github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/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 "github.com/juju/names" 11 12 "github.com/juju/juju/agent" 13 "github.com/juju/juju/api/watcher" 14 "github.com/juju/juju/apiserver/params" 15 "github.com/juju/juju/network" 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 MachineAccessor 24 tag names.MachineTag 25 machine 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 MachineAccessor, agentConfig agent.Config) worker.Worker { 32 mr := &Machiner{st: st, tag: agentConfig.Tag().(names.MachineTag)} 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(mr.tag, 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(tag names.MachineTag, m Machine) error { 65 addrs, err := interfaceAddrs() 66 if err != nil { 67 return err 68 } 69 var hostAddresses []network.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 := network.NewAddress(ip.String()) 81 // Filter out link-local addresses as we cannot reliably use them. 82 if address.Scope == network.ScopeLinkLocal { 83 continue 84 } 85 hostAddresses = append(hostAddresses, address) 86 } 87 if len(hostAddresses) == 0 { 88 return nil 89 } 90 // Filter out any LXC bridge addresses. 91 hostAddresses = network.FilterLXCAddresses(hostAddresses) 92 logger.Infof("setting addresses for %v to %q", tag, hostAddresses) 93 return m.SetMachineAddresses(hostAddresses) 94 } 95 96 func (mr *Machiner) Handle(_ <-chan struct{}) error { 97 if err := mr.machine.Refresh(); params.IsCodeNotFoundOrCodeUnauthorized(err) { 98 return worker.ErrTerminateAgent 99 } else if err != nil { 100 return err 101 } 102 life := mr.machine.Life() 103 if life == params.Alive { 104 return nil 105 } 106 logger.Debugf("%q is now %s", mr.tag, life) 107 if err := mr.machine.SetStatus(params.StatusStopped, "", nil); err != nil { 108 return fmt.Errorf("%s failed to set status stopped: %v", mr.tag, err) 109 } 110 111 // Attempt to mark the machine Dead. If the machine still has units 112 // assigned, or storage attached, this will fail with 113 // CodeHasAssignedUnits or CodeMachineHasAttachedStorage respectively. 114 // Once units or storage are removed, the watcher will trigger again 115 // and we'll reattempt. 116 if err := mr.machine.EnsureDead(); err != nil { 117 if params.IsCodeHasAssignedUnits(err) { 118 return nil 119 } 120 if params.IsCodeMachineHasAttachedStorage(err) { 121 logger.Tracef("machine still has storage attached") 122 return nil 123 } 124 return fmt.Errorf("%s failed to set machine to dead: %v", mr.tag, err) 125 } 126 return worker.ErrTerminateAgent 127 } 128 129 func (mr *Machiner) TearDown() error { 130 // Nothing to do here. 131 return nil 132 }