Example #1
0
// Open connects to the server described by the given
// info, waits for it to be initialized, and returns a new State
// representing the environment connected to.
//
// A policy may be provided, which will be used to validate and
// modify behaviour of certain operations in state. A nil policy
// may be provided.
//
// Open returns unauthorizedError if access is unauthorized.
func Open(info *Info, opts mongo.DialOpts, policy Policy) (*State, error) {
	logger.Infof("opening state, mongo addresses: %q; entity %q", info.Addrs, info.Tag)
	di, err := mongo.DialInfo(info.Info, opts)
	if err != nil {
		return nil, err
	}
	logger.Debugf("dialing mongo")
	session, err := mgo.DialWithInfo(di)
	if err != nil {
		return nil, err
	}
	logger.Debugf("connection established")

	_, err = replicaset.CurrentConfig(session)
	safe := &mgo.Safe{J: true}
	if err == nil {
		// set mongo to write-majority (writes only returned after replicated
		// to a majority of replica-set members)
		safe.WMode = "majority"
	}
	session.SetSafe(safe)

	st, err := newState(session, info, policy)
	if err != nil {
		session.Close()
		return nil, err
	}
	session.SetSocketTimeout(mongo.SocketTimeout)
	return st, nil
}
Example #2
0
// attemptInitiateMongoServer attempts to initiate the replica set.
func attemptInitiateMongoServer(dialInfo *mgo.DialInfo, memberHostPort string) error {
	session, err := mgo.DialWithInfo(dialInfo)
	if err != nil {
		return fmt.Errorf("can't dial mongo to initiate replicaset: %v", err)
	}
	defer session.Close()
	session.SetSocketTimeout(mongo.SocketTimeout)

	var cfg *replicaset.Config
	cfg, err = replicaset.CurrentConfig(session)
	if err == nil && len(cfg.Members) > 0 {
		logger.Infof("replica set configuration already found: %#v", cfg)
		return nil
	}
	if err != nil && err != mgo.ErrNotFound {
		return fmt.Errorf("cannot get replica set configuration: %v", err)
	}
	return replicaset.Initiate(
		session,
		memberHostPort,
		mongo.ReplicaSetName,
		map[string]string{
			jujuMachineTag: agent.BootstrapMachineId,
		},
	)
}
Example #3
0
// MaybeInitiateMongoServer checks for an existing mongo configuration.
// If no existing configuration is found one is created using Initiate.
func MaybeInitiateMongoServer(p InitiateMongoParams) error {
	logger.Debugf("Initiating mongo replicaset; dialInfo %#v; memberHostport %q; user %q; password %q", p.DialInfo, p.MemberHostPort, p.User, p.Password)
	defer logger.Infof("finished MaybeInitiateMongoServer")

	if len(p.DialInfo.Addrs) > 1 {
		logger.Infof("more than one member; replica set must be already initiated")
		return nil
	}
	p.DialInfo.Direct = true

	// TODO(rog) remove this code when we no longer need to upgrade
	// from pre-HA-capable environments.
	if p.User != "" {
		p.DialInfo.Username = p.User
		p.DialInfo.Password = p.Password
	}

	session, err := mgo.DialWithInfo(p.DialInfo)
	if err != nil {
		return fmt.Errorf("can't dial mongo to initiate replicaset: %v", err)
	}
	defer session.Close()

	// Initiate may fail while mongo is initialising, so we retry until
	// we succssfully populate the replicaset config.
	for attempt := initiateAttemptStrategy.Start(); attempt.Next(); {
		var cfg *replicaset.Config
		cfg, err = replicaset.CurrentConfig(session)
		if err == nil && len(cfg.Members) > 0 {
			logger.Infof("replica set configuration already found: %#v", cfg)
			return nil
		}
		if err != nil && err != mgo.ErrNotFound {
			return fmt.Errorf("cannot get replica set configuration: %v", err)
		}
		err = replicaset.Initiate(
			session,
			p.MemberHostPort,
			mongo.ReplicaSetName,
			map[string]string{
				jujuMachineTag: agent.BootstrapMachineId,
			},
		)
		if err == nil {
			logger.Infof("replica set initiated")
			return nil
		}
		if attempt.HasNext() {
			logger.Debugf("replica set initiation failed, will retry: %v", err)
		}
		// Release sockets, which may have been closed by mgo.
		session.Refresh()
	}
	return fmt.Errorf("cannot initiate replica set: %v", err)
}
Example #4
0
func init() {
	stateWorkerDialOpts = mongo.DefaultDialOpts()
	stateWorkerDialOpts.PostDial = func(session *mgo.Session) error {
		safe := mgo.Safe{
			// Wait for group commit if journaling is enabled,
			// which is always true in production.
			J: true,
		}
		_, err := replicaset.CurrentConfig(session)
		if err == nil {
			// set mongo to write-majority (writes only returned after
			// replicated to a majority of replica-set members).
			safe.WMode = "majority"
		}
		session.SetSafe(&safe)
		return nil
	}
}