github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/worker/peergrouper/initiate.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package peergrouper 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 "github.com/juju/replicaset" 11 "github.com/juju/utils" 12 "gopkg.in/mgo.v2" 13 14 "github.com/juju/juju/agent" 15 "github.com/juju/juju/mongo" 16 ) 17 18 var initiateAttemptStrategy = utils.AttemptStrategy{ 19 Total: 60 * time.Second, 20 Delay: 5 * time.Second, 21 } 22 23 // InitiateMongoParams holds parameters for the MaybeInitiateMongo call. 24 type InitiateMongoParams struct { 25 // DialInfo specifies how to connect to the mongo server. 26 DialInfo *mgo.DialInfo 27 28 // MemberHostPort provides the address to use for 29 // the first replica set member. 30 MemberHostPort string 31 32 // User holds the user to log as in to the mongo server. 33 // If it is empty, no login will take place. 34 User string 35 Password string 36 } 37 38 // InitiateMongoServer checks for an existing mongo configuration. 39 // If no existing configuration is found one is created using Initiate. 40 func InitiateMongoServer(p InitiateMongoParams) error { 41 logger.Debugf("Initiating mongo replicaset; dialInfo %#v; memberHostport %q; user %q; password %q", p.DialInfo, p.MemberHostPort, p.User, p.Password) 42 defer logger.Infof("finished InitiateMongoServer") 43 44 if len(p.DialInfo.Addrs) > 1 { 45 logger.Infof("more than one member; replica set must be already initiated") 46 return nil 47 } 48 p.DialInfo.Direct = true 49 50 // Initiate may fail while mongo is initialising, so we retry until 51 // we successfully populate the replicaset config. 52 var err error 53 for attempt := initiateAttemptStrategy.Start(); attempt.Next(); { 54 err = attemptInitiateMongoServer(p.DialInfo, p.MemberHostPort) 55 if err == nil { 56 logger.Infof("replica set initiated") 57 return err 58 } 59 if attempt.HasNext() { 60 logger.Debugf("replica set initiation failed, will retry: %v", err) 61 } 62 } 63 return errors.Annotatef(err, "cannot initiate replica set") 64 } 65 66 // attemptInitiateMongoServer attempts to initiate the replica set. 67 func attemptInitiateMongoServer(dialInfo *mgo.DialInfo, memberHostPort string) error { 68 session, err := mgo.DialWithInfo(dialInfo) 69 if err != nil { 70 return errors.Annotatef(err, "cannot dial mongo to initiate replicaset") 71 } 72 defer session.Close() 73 session.SetSocketTimeout(mongo.SocketTimeout) 74 75 return replicaset.Initiate( 76 session, 77 memberHostPort, 78 mongo.ReplicaSetName, 79 map[string]string{ 80 jujuMachineKey: agent.BootstrapMachineId, 81 }, 82 ) 83 }