// 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 }
// 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 }
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 }
// 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 }