github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/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/clock" 10 "github.com/juju/errors" 11 "github.com/juju/mgo/v3" 12 "github.com/juju/replicaset/v3" 13 "github.com/juju/retry" 14 15 "github.com/juju/juju/agent" 16 "github.com/juju/juju/mongo" 17 ) 18 19 // InitiateMongoParams holds parameters for the MaybeInitiateMongo call. 20 type InitiateMongoParams struct { 21 // DialInfo specifies how to connect to the mongo server. 22 DialInfo *mgo.DialInfo 23 24 // MemberHostPort provides the address to use for 25 // the first replica set member. 26 MemberHostPort string 27 28 // User holds the user to log as in to the mongo server. 29 // If it is empty, no login will take place. 30 User string 31 Password string 32 } 33 34 // InitiateMongoServer checks for an existing mongo configuration. 35 // If no existing configuration is found one is created using Initiate. 36 func InitiateMongoServer(p InitiateMongoParams) error { 37 logger.Debugf("Initiating mongo replicaset; dialInfo %#v; memberHostport %q; user %q; password %q", p.DialInfo, p.MemberHostPort, p.User, p.Password) 38 defer logger.Infof("finished InitiateMongoServer") 39 40 if len(p.DialInfo.Addrs) > 1 { 41 logger.Infof("more than one member; replica set must be already initiated") 42 return nil 43 } 44 p.DialInfo.Direct = true 45 46 // Initiate may fail while mongo is initialising, so we retry until 47 // we successfully populate the replicaset config. 48 retryCallArgs := retry.CallArgs{ 49 Clock: clock.WallClock, 50 MaxDuration: 60 * time.Second, 51 Delay: 5 * time.Second, 52 Func: func() error { 53 return attemptInitiateMongoServer(p.DialInfo, p.MemberHostPort) 54 }, 55 NotifyFunc: func(lastError error, attempt int) { 56 logger.Debugf("replica set initiation attempt %d failed: %v", attempt, lastError) 57 }, 58 } 59 err := retry.Call(retryCallArgs) 60 if retry.IsAttemptsExceeded(err) || retry.IsDurationExceeded(err) { 61 err = retry.LastError(err) 62 logger.Debugf("replica set initiation failed: %v", err) 63 } 64 if err == nil { 65 logger.Infof("replica set initiated") 66 return nil 67 } 68 return errors.Annotatef(err, "cannot initiate replica set") 69 } 70 71 // attemptInitiateMongoServer attempts to initiate the replica set. 72 func attemptInitiateMongoServer(dialInfo *mgo.DialInfo, memberHostPort string) error { 73 session, err := mgo.DialWithInfo(dialInfo) 74 if err != nil { 75 return errors.Annotatef(err, "cannot dial mongo to initiate replicaset") 76 } 77 defer session.Close() 78 session.SetSocketTimeout(mongo.SocketTimeout) 79 80 return replicaset.Initiate( 81 session, 82 memberHostPort, 83 mongo.ReplicaSetName, 84 map[string]string{ 85 jujuNodeKey: agent.BootstrapControllerId, 86 }, 87 ) 88 }