github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/worker/mongoupgrader/worker.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package mongoupgrader 5 6 import ( 7 "net" 8 "strconv" 9 10 "github.com/juju/errors" 11 12 "github.com/juju/juju/mongo" 13 "github.com/juju/juju/state" 14 "github.com/juju/juju/worker" 15 "github.com/juju/replicaset" 16 ) 17 18 // StopMongo represents a function that can issue a stop 19 // to a running mongo service. 20 type StopMongo func(mongo.Version, bool) error 21 22 // New returns a worker or err in case of failure. 23 // this worker takes care of watching the state of machine's upgrade 24 // mongo information and change agent conf accordingly. 25 func New(st *state.State, machineID string, maybeStopMongo StopMongo) (worker.Worker, error) { 26 upgradeWorker := func(stopch <-chan struct{}) error { 27 return upgradeMongoWatcher(st, stopch, machineID, maybeStopMongo) 28 } 29 return worker.NewSimpleWorker(upgradeWorker), nil 30 } 31 32 func upgradeMongoWatcher(st *state.State, stopch <-chan struct{}, machineID string, maybeStopMongo StopMongo) error { 33 m, err := st.Machine(machineID) 34 if err != nil { 35 return errors.Annotatef(err, "cannot start watcher for machine %q", machineID) 36 } 37 watch := m.Watch() 38 defer func() { 39 watch.Kill() 40 watch.Wait() 41 }() 42 43 for { 44 select { 45 case <-watch.Changes(): 46 if err := m.Refresh(); err != nil { 47 return errors.Annotate(err, "cannot refresh machine information") 48 } 49 if !m.IsManager() { 50 continue 51 } 52 expectedVersion, err := m.StopMongoUntilVersion() 53 if err != nil { 54 return errors.Annotate(err, "cannot obtain minimum version of mongo") 55 } 56 if expectedVersion == mongo.Mongo24 { 57 continue 58 } 59 var isMaster bool 60 isMaster, err = mongo.IsMaster(st.MongoSession(), m) 61 if err != nil { 62 return errors.Annotatef(err, "cannot determine if machine %q is master", machineID) 63 } 64 65 err = maybeStopMongo(expectedVersion, isMaster) 66 if err != nil { 67 return errors.Annotate(err, "cannot determine if mongo must be stopped") 68 } 69 if !isMaster { 70 addrs := make([]string, len(m.Addresses())) 71 ssi, err := st.StateServingInfo() 72 if err != nil { 73 return errors.Annotate(err, "cannot obtain state serving info to stop mongo") 74 } 75 for i, addr := range m.Addresses() { 76 addrs[i] = net.JoinHostPort(addr.Value, strconv.Itoa(ssi.StatePort)) 77 } 78 if err := replicaset.Remove(st.MongoSession(), addrs...); err != nil { 79 return errors.Annotatef(err, "cannot remove %q from replicaset", m.Id()) 80 } 81 if err := m.SetStopMongoUntilVersion(mongo.Mongo24); err != nil { 82 return errors.Annotate(err, "cannot reset stop mongo flag") 83 } 84 } 85 case <-stopch: 86 return nil 87 } 88 } 89 }