launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/worker/machiner/machiner.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 package machiner 4 5 import ( 6 "net" 7 8 "github.com/loggo/loggo" 9 10 "launchpad.net/errgo/errors" 11 "launchpad.net/juju-core/agent" 12 "launchpad.net/juju-core/instance" 13 "launchpad.net/juju-core/state/api/machiner" 14 "launchpad.net/juju-core/state/api/params" 15 "launchpad.net/juju-core/state/api/watcher" 16 "launchpad.net/juju-core/worker" 17 ) 18 19 var logger = loggo.GetLogger("juju.worker.machiner") 20 21 var mask = errors.Mask 22 23 // Machiner is responsible for a machine agent's lifecycle. 24 type Machiner struct { 25 st *machiner.State 26 tag string 27 machine *machiner.Machine 28 } 29 30 // NewMachiner returns a Worker that will wait for the identified machine 31 // to become Dying and make it Dead; or until the machine becomes Dead by 32 // other means. 33 func NewMachiner(st *machiner.State, agentConfig agent.Config) worker.Worker { 34 mr := &Machiner{st: st, tag: agentConfig.Tag()} 35 return worker.NewNotifyWorker(mr) 36 } 37 38 func (mr *Machiner) SetUp() (watcher.NotifyWatcher, error) { 39 // Find which machine we're responsible for. 40 m, err := mr.st.Machine(mr.tag) 41 if params.IsCodeNotFoundOrCodeUnauthorized(err) { 42 return nil, worker.ErrTerminateAgent 43 } else if err != nil { 44 return nil, mask(err) 45 } 46 mr.machine = m 47 48 // Set the addresses in state to the host's addresses. 49 if err := setMachineAddresses(m); err != nil { 50 return nil, mask(err) 51 } 52 53 // Mark the machine as started and log it. 54 if err := m.SetStatus(params.StatusStarted, "", nil); err != nil { 55 return nil, errors.Notef(err, "%s failed to set status started", mr.tag) 56 } 57 logger.Infof("%q started", mr.tag) 58 59 return m.Watch() 60 } 61 62 var interfaceAddrs = net.InterfaceAddrs 63 64 // setMachineAddresses sets the addresses for this machine to all of the 65 // host's non-loopback interface IP addresses. 66 func setMachineAddresses(m *machiner.Machine) error { 67 addrs, err := interfaceAddrs() 68 if err != nil { 69 return mask(err) 70 } 71 var hostAddresses []instance.Address 72 for _, addr := range addrs { 73 var ip net.IP 74 switch addr := addr.(type) { 75 case *net.IPAddr: 76 ip = addr.IP 77 case *net.IPNet: 78 ip = addr.IP 79 default: 80 continue 81 } 82 if ip.IsLoopback() { 83 continue 84 } 85 hostAddresses = append(hostAddresses, instance.NewAddress(ip.String())) 86 } 87 if len(hostAddresses) == 0 { 88 return nil 89 } 90 logger.Infof("setting addresses for %v to %q", m.Tag(), hostAddresses) 91 return m.SetMachineAddresses(hostAddresses) 92 } 93 94 func (mr *Machiner) Handle() error { 95 if err := mr.machine.Refresh(); params.IsCodeNotFoundOrCodeUnauthorized(err) { 96 return worker.ErrTerminateAgent 97 } else if err != nil { 98 return mask(err) 99 } 100 if mr.machine.Life() == params.Alive { 101 return nil 102 } 103 logger.Debugf("%q is now %s", mr.tag, mr.machine.Life()) 104 if err := mr.machine.SetStatus(params.StatusStopped, "", nil); err != nil { 105 return errors.Notef(err, "%s failed to set status stopped", mr.tag) 106 } 107 108 // If the machine is Dying, it has no units, 109 // and can be safely set to Dead. 110 if err := mr.machine.EnsureDead(); err != nil { 111 return errors.Notef(err, "%s failed to set machine to dead", mr.tag) 112 } 113 return worker.ErrTerminateAgent 114 } 115 116 func (mr *Machiner) TearDown() error { 117 // Nothing to do here. 118 return nil 119 }