Пример #1
0
// preferred nodes are nodes that are not on the same host as the local node
func (j *joinSender) CollectPreferredNodes() []string {
	var preferredNodes []string

	for host, hostports := range j.node.bootstrapHosts {
		if host != util.CaptureHost(j.node.address) {
			preferredNodes = append(preferredNodes, hostports...)
		}
	}

	return preferredNodes
}
Пример #2
0
// non-preferred nodes are everyone else
func (j *joinSender) CollectNonPreferredNodes() []string {
	if len(j.preferredNodes) == 0 {
		return j.potentialNodes
	}

	var nonPreferredNodes []string

	for _, host := range j.node.bootstrapHosts[util.CaptureHost(j.node.address)] {
		if host != j.node.address {
			nonPreferredNodes = append(nonPreferredNodes, host)
		}
	}
	return nonPreferredNodes
}
Пример #3
0
func (n *Node) seedBootstrapHosts(opts *BootstrapOptions) (err error) {
	var hostports []string

	n.bootstrapHosts = make(map[string][]string)

	if opts.Hosts != nil {
		hostports = opts.Hosts
	} else {
		switch true {
		case true:
			if opts.File != "" {
				hostports, err = util.ReadHostsFile(opts.File)
				if err == nil {
					break
				}
				n.log.WithField("file", opts.File).Warnf("could not read host file: %v", err)
			}
			fallthrough
		case true:
			if n.bootstrapFile != "" {
				hostports, err = util.ReadHostsFile(n.bootstrapFile)
				if err == nil {
					break
				}
				n.log.WithField("file", n.bootstrapFile).Warnf("could not read host file: %v", err)
			}
			fallthrough
		case true:
			hostports, err = util.ReadHostsFile("./hosts.json")
			if err == nil {
				break
			}
			n.log.WithField("file", "./hosts.json").Warnf("could not read host file: %v", err)
			return errors.New("unable to read hosts file")
		}
	}

	for _, hostport := range hostports {
		host := util.CaptureHost(hostport)
		if host != "" {
			n.bootstrapHosts[host] = append(n.bootstrapHosts[host], hostport)
		}
	}

	return
}
Пример #4
0
// Bootstrap joins a node to a cluster. The channel provided to the node must be
// listening for the bootstrap to complete.
func (n *Node) Bootstrap(opts *BootstrapOptions) ([]string, error) {
	if n.channel == nil {
		return nil, errors.New("channel required")
	}

	if opts == nil {
		opts = &BootstrapOptions{}
	}

	if err := n.seedBootstrapHosts(opts); err != nil {
		return nil, err
	}

	if len(n.bootstrapHosts) == 0 {
		return nil, errors.New("bootstrap hosts required, but none found")
	}

	err := util.CheckLocalMissing(n.address, n.bootstrapHosts[util.CaptureHost(n.address)])
	if err != nil {
		n.log.Warn(err.Error())
	}

	mismatched, err := util.CheckHostnameIPMismatch(n.address, n.bootstrapHosts)
	if err != nil {
		n.log.WithField("mismatched", mismatched).Warn(err.Error())
	}

	n.memberlist.MakeAlive(n.address, util.TimeNowMS())

	joinOpts := &joinOpts{
		timeout:           opts.JoinTimeout,
		size:              opts.JoinSize,
		maxJoinDuration:   opts.MaxJoinDuration,
		parallelismFactor: opts.ParallelismFactor,
	}

	joined, err := sendJoin(n, joinOpts)
	if err != nil {
		n.log.WithFields(log.Fields{
			"err": err.Error(),
		}).Error("bootstrap failed")
		return nil, err
	}

	if n.Destroyed() {
		n.log.Error("destroyed during bootstrap process")
		return nil, errors.New("destroyed during bootstrap process")
	}

	if !opts.Stopped {
		n.gossip.Start()
	}

	n.state.Lock()
	n.state.ready = true
	n.state.Unlock()

	n.startTime = time.Now()

	return joined, nil
}