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