func runReboot(args []string) int { if os.Geteuid() != 0 { fmt.Fprintln(os.Stderr, "Must be root to initiate reboot.") return 1 } elc, err := getClient() if err != nil { fmt.Fprintln(os.Stderr, "Error initializing etcd client:", err) return 1 } lgn, err := login1.New() if err != nil { fmt.Fprintln(os.Stderr, "Error initializing login connection:", err) return 1 } mID := machineid.MachineID("/") if mID == "" { fmt.Fprintln(os.Stderr, "Cannot read machine-id") return 1 } l := lock.New(mID, elc) err = l.Lock() if err != nil { fmt.Fprintln(os.Stderr, "Error locking:", err) return 1 } lgn.Reboot(false) // TODO(philips): Unlock if the reboot fails. return 0 }
// runDaemon waits for the reboot needed signal coming out of update engine and // 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 == "" { strategy = StrategyBestEffort } if strategy == StrategyOff { fmt.Fprintf(os.Stderr, "Reboot strategy is %q - shutting down.\n", strategy) 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 == "") { fmt.Fprintln(os.Stderr, "either both or neither $REBOOT_WINDOW_START and $REBOOT_WINDOW_LENGTH must be set") return 1 } if startw != "" && lengthw != "" { p, err := timeutil.ParsePeriodic(startw, lengthw) if err != nil { fmt.Fprintf(os.Stderr, "error parsing reboot window: %s\n", err) return 1 } period = p } shutdown := make(chan os.Signal, 1) stop := make(chan struct{}, 1) go func() { <-shutdown fmt.Fprintln(os.Stderr, "Received interrupt/termination signal - shutting down.") os.Exit(0) }() signal.Notify(shutdown, syscall.SIGINT, syscall.SIGTERM) ue, err := updateengine.New() if err != nil { fmt.Fprintln(os.Stderr, "Error initializing update1 client:", err) return 1 } lgn, err := login1.New() if err != nil { fmt.Fprintln(os.Stderr, "Error initializing login1 client:", err) return 1 } var wg sync.WaitGroup if strategy != StrategyReboot { wg.Add(1) go unlockHeldLocks(strategy, stop, &wg) } ch := make(chan updateengine.Status, 1) go ue.RebootNeededSignal(ch, stop) r := rebooter{strategy, lgn} result, err := ue.GetStatus() if err != nil { fmt.Fprintln(os.Stderr, "Cannot get update engine status:", err) return 1 } fmt.Printf("locksmithd starting currentOperation=%q strategy=%q\n", result.CurrentOperation, strategy, ) if result.CurrentOperation != updateengine.UpdateStatusUpdatedNeedReboot { <-ch } close(stop) wg.Wait() if period != nil { now := time.Now() sleeptime := period.DurationToStart(now) if sleeptime > 0 { fmt.Printf("Waiting for %s to reboot.\n", sleeptime) time.Sleep(sleeptime) } } return r.reboot() }