github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/reboot/reboot.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package reboot 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 "github.com/juju/loggo" 11 "github.com/juju/mutex" 12 "github.com/juju/utils/clock" 13 "gopkg.in/juju/names.v2" 14 "gopkg.in/tomb.v1" 15 16 "github.com/juju/juju/agent" 17 "github.com/juju/juju/api/reboot" 18 "github.com/juju/juju/apiserver/params" 19 "github.com/juju/juju/watcher" 20 "github.com/juju/juju/worker" 21 ) 22 23 var logger = loggo.GetLogger("juju.worker.reboot") 24 25 // The reboot worker listens for changes to the reboot flag and 26 // exists with worker.ErrRebootMachine if the machine should reboot or 27 // with worker.ErrShutdownMachine if it should shutdown. This will be picked 28 // up by the machine agent as a fatal error and will do the 29 // right thing (reboot or shutdown) 30 type Reboot struct { 31 tomb tomb.Tomb 32 st reboot.State 33 tag names.MachineTag 34 machineLockName string 35 clock clock.Clock 36 } 37 38 func NewReboot(st reboot.State, agentConfig agent.Config, machineLockName string, clock clock.Clock) (worker.Worker, error) { 39 tag, ok := agentConfig.Tag().(names.MachineTag) 40 if !ok { 41 return nil, errors.Errorf("Expected names.MachineTag, got %T: %v", agentConfig.Tag(), agentConfig.Tag()) 42 } 43 r := &Reboot{ 44 st: st, 45 tag: tag, 46 machineLockName: machineLockName, 47 clock: clock, 48 } 49 w, err := watcher.NewNotifyWorker(watcher.NotifyConfig{ 50 Handler: r, 51 }) 52 return w, errors.Trace(err) 53 } 54 55 func (r *Reboot) SetUp() (watcher.NotifyWatcher, error) { 56 watcher, err := r.st.WatchForRebootEvent() 57 return watcher, errors.Trace(err) 58 } 59 60 func (r *Reboot) Handle(_ <-chan struct{}) error { 61 rAction, err := r.st.GetRebootAction() 62 if err != nil { 63 return errors.Trace(err) 64 } 65 logger.Debugf("Reboot worker got action: %v", rAction) 66 // NOTE: Here we explicitly avoid stopping on the abort channel as we are 67 // wanting to make sure that we grab the lock and return an error 68 // sufficiently heavyweight to get the agent to restart. 69 spec := mutex.Spec{ 70 Name: r.machineLockName, 71 Clock: r.clock, 72 Delay: 250 * time.Millisecond, 73 } 74 75 switch rAction { 76 case params.ShouldReboot: 77 logger.Debugf("acquiring mutex %q for reboot", r.machineLockName) 78 if _, err := mutex.Acquire(spec); err != nil { 79 return errors.Trace(err) 80 } 81 logger.Debugf("mutex %q acquired, won't release", r.machineLockName) 82 return worker.ErrRebootMachine 83 case params.ShouldShutdown: 84 logger.Debugf("acquiring mutex %q for shutdown", r.machineLockName) 85 if _, err := mutex.Acquire(spec); err != nil { 86 return errors.Trace(err) 87 } 88 logger.Debugf("mutex %q acquired, won't release", r.machineLockName) 89 return worker.ErrShutdownMachine 90 default: 91 return nil 92 } 93 } 94 95 func (r *Reboot) TearDown() error { 96 // nothing to teardown. 97 return nil 98 }