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