// DefaultConfig is used to return a sane default configuration func DefaultConfig() *Config { hostname, err := os.Hostname() if err != nil { panic(err) } conf := &Config{ Datacenter: DefaultDC, NodeName: hostname, RPCAddr: DefaultRPCAddr, RaftConfig: raft.DefaultConfig(), SerfLANConfig: serf.DefaultConfig(), SerfWANConfig: serf.DefaultConfig(), ReconcileInterval: 60 * time.Second, ProtocolVersion: ProtocolVersionMax, } // Increase our reap interval to 3 days instead of 24h. conf.SerfLANConfig.ReconnectTimeout = 3 * 24 * time.Hour conf.SerfWANConfig.ReconnectTimeout = 3 * 24 * time.Hour // WAN Serf should use the WAN timing, since we are using it // to communicate between DC's conf.SerfWANConfig.MemberlistConfig = memberlist.DefaultWANConfig() // Ensure we don't have port conflicts conf.SerfLANConfig.MemberlistConfig.BindPort = DefaultLANSerfPort conf.SerfWANConfig.MemberlistConfig.BindPort = DefaultWANSerfPort // Disable shutdown on removal conf.RaftConfig.ShutdownOnRemove = false return conf }
// DefaultConfig is used to return a sane default configuration func DefaultConfig() *Config { hostname, err := os.Hostname() if err != nil { panic(err) } conf := &Config{ Datacenter: DefaultDC, NodeName: hostname, RPCAddr: DefaultRPCAddr, RaftConfig: raft.DefaultConfig(), SerfLANConfig: serf.DefaultConfig(), SerfWANConfig: serf.DefaultConfig(), ReconcileInterval: 60 * time.Second, ProtocolVersion: ProtocolVersion2Compatible, ACLTTL: 30 * time.Second, ACLDefaultPolicy: "allow", ACLDownPolicy: "extend-cache", ACLReplicationInterval: 30 * time.Second, ACLReplicationApplyLimit: 100, // ops / sec TombstoneTTL: 15 * time.Minute, TombstoneTTLGranularity: 30 * time.Second, SessionTTLMin: 10 * time.Second, DisableCoordinates: false, // These are tuned to provide a total throughput of 128 updates // per second. If you update these, you should update the client- // side SyncCoordinateRateTarget parameter accordingly. CoordinateUpdatePeriod: 5 * time.Second, CoordinateUpdateBatchSize: 128, CoordinateUpdateMaxBatches: 5, // Hold an RPC for up to 5 seconds by default RPCHoldTimeout: 5 * time.Second, } // Increase our reap interval to 3 days instead of 24h. conf.SerfLANConfig.ReconnectTimeout = 3 * 24 * time.Hour conf.SerfWANConfig.ReconnectTimeout = 3 * 24 * time.Hour // WAN Serf should use the WAN timing, since we are using it // to communicate between DC's conf.SerfWANConfig.MemberlistConfig = memberlist.DefaultWANConfig() // Ensure we don't have port conflicts conf.SerfLANConfig.MemberlistConfig.BindPort = DefaultLANSerfPort conf.SerfWANConfig.MemberlistConfig.BindPort = DefaultWANSerfPort // Enable interoperability with unversioned Raft library, and don't // start using new ID-based features yet. conf.RaftConfig.ProtocolVersion = 1 // Disable shutdown on removal conf.RaftConfig.ShutdownOnRemove = false return conf }
// DefaultConfig is used to return a sane default configuration func DefaultConfig() *Config { hostname, err := os.Hostname() if err != nil { panic(err) } conf := &Config{ Datacenter: DefaultDC, NodeName: hostname, RPCAddr: DefaultRPCAddr, RaftConfig: raft.DefaultConfig(), SerfLANConfig: serf.DefaultConfig(), SerfWANConfig: serf.DefaultConfig(), ReconcileInterval: 60 * time.Second, ProtocolVersion: ProtocolVersion2Compatible, ACLTTL: 30 * time.Second, ACLDefaultPolicy: "allow", ACLDownPolicy: "extend-cache", TombstoneTTL: 15 * time.Minute, TombstoneTTLGranularity: 30 * time.Second, SessionTTLMin: 10 * time.Second, DisableCoordinates: false, // These are tuned to provide a total throughput of 128 updates // per second. If you update these, you should update the client- // side SyncCoordinateRateTarget parameter accordingly. CoordinateUpdatePeriod: 5 * time.Second, CoordinateUpdateBatchSize: 128, CoordinateUpdateMaxBatches: 5, } // Increase our reap interval to 3 days instead of 24h. conf.SerfLANConfig.ReconnectTimeout = 3 * 24 * time.Hour conf.SerfWANConfig.ReconnectTimeout = 3 * 24 * time.Hour // WAN Serf should use the WAN timing, since we are using it // to communicate between DC's conf.SerfWANConfig.MemberlistConfig = memberlist.DefaultWANConfig() // Turn LAN Serf to run globally conf.SerfLANConfig.MemberlistConfig = memberlist.DefaultWANConfig() // Ensure we don't have port conflicts conf.SerfLANConfig.MemberlistConfig.BindPort = DefaultLANSerfPort conf.SerfWANConfig.MemberlistConfig.BindPort = DefaultWANSerfPort // Disable shutdown on removal conf.RaftConfig.ShutdownOnRemove = false // Make Raft more WAN friendly conf.RaftConfig.HeartbeatTimeout = 5000 * time.Millisecond conf.RaftConfig.ElectionTimeout = 5000 * time.Millisecond conf.RaftConfig.CommitTimeout = 100 * time.Millisecond conf.RaftConfig.LeaderLeaseTimeout = 2500 * time.Millisecond return conf }
func TestAgentTagsFile(t *testing.T) { tags := map[string]string{ "role": "webserver", "datacenter": "us-east", } td, err := ioutil.TempDir("", "serf") if err != nil { t.Fatalf("err: %s", err) } defer os.RemoveAll(td) agentConfig := DefaultConfig() agentConfig.TagsFile = filepath.Join(td, "tags.json") a1 := testAgentWithConfig(agentConfig, serf.DefaultConfig(), nil) if err := a1.Start(); err != nil { t.Fatalf("err: %s", err) } defer a1.Shutdown() defer a1.Leave() testutil.Yield() err = a1.SetTags(tags) if err != nil { t.Fatalf("err: %s", err) } testutil.Yield() a2 := testAgentWithConfig(agentConfig, serf.DefaultConfig(), nil) if err := a2.Start(); err != nil { t.Fatalf("err: %s", err) } defer a2.Shutdown() defer a2.Leave() testutil.Yield() m := a2.Serf().LocalMember() if !reflect.DeepEqual(m.Tags, tags) { t.Fatalf("tags not restored: %#v", m.Tags) } }
func Create() (*Agent, error) { conf := serf.DefaultConfig() conf.Init() conf.NodeName = os.Getenv("HOST") conf.Tags["DOCKER_HOST"] = Os.Getenv("DOCKER_HOST") logOutput := log.StandardLogger().Out // Setup the underlying loggers conf.MemberlistConfig.LogOutput = logOutput conf.LogOutput = logOutput // Create a channel to listen for events from Serf eventCh := make(chan serf.Event, 64) conf.EventCh = eventCh // support only LAN configuration at the moment conf.MemberlistConfig = memberlist.DefaultLANConfig() conf.MemberlistConfig.BindAddr = "0.0.0.0" conf.MemberlistConfig.BindPort = 3388 // Setup the agent agent := &Agent{ conf: conf, eventCh: eventCh, isManager: false, shutdownCh: make(chan struct{}), } return agent, nil }
func (a *Agent) Start() error { conf := serf.DefaultConfig() conf.Init() conf.Tags["role"] = "agent" conf.Tags["info"] = a.getInfo() bindAddr, err := a.config.GetIpByInterface() if err != nil { log.Fatal(err) } conf.NodeName = a.config.Name conf.MemberlistConfig.BindAddr = bindAddr conf.EventCh = a.eventCh serf, err := serf.Create(conf) if err != nil { return err } a.serf = serf go a.handleEvents() return nil }
func (n *Node) createSerfAgent(iface string) { serfConfig := serf.DefaultConfig() serfConfig.Tags = n.tags serfConfig.MemberlistConfig.BindAddr = iface serfConfig.MemberlistConfig.BindPort = getRandomPort(iface) serfConfig.NodeName = fmt.Sprintf("%s@%s", n.UUID, iface) serfConfig.Tags = n.tags serfConfig.LogOutput = ioutil.Discard // serfConfig.MemberlistConfig.GossipInterval = 5 * time.Millisecond // serfConfig.MemberlistConfig.ProbeInterval = 50 * time.Millisecond // serfConfig.MemberlistConfig.ProbeTimeout = 25 * time.Millisecond // serfConfig.MemberlistConfig.SuspicionMult = 1 serfConfig.Init() agentConfig := agent.DefaultConfig() agentConfig.Tags = n.tags agentConfig.LogLevel = "INFO" agt, err := agent.Create(agentConfig, serfConfig, ioutil.Discard) // agt, err := agent.Create(agentConfig, serfConfig, n.cfg.Logger()) if n.handleErr(err) { eventHandler := newEventHandler() n.join.Join(eventHandler.join.WhereNot(n.isSelf)) n.leave.Join(eventHandler.leave.WhereNot(n.isSelf).Transform(toLeaveEvent())) n.query.Join(eventHandler.query.Transform(toQueryEvent(iface))) agt.RegisterEventHandler(eventHandler) n.agents[iface] = agt n.logger.Println("Agent Created On Port", agt.SerfConfig().MemberlistConfig.BindPort) } else { n.logger.Println("Failed to create Agent") } }
func main() { InitLogger(logrus.DebugLevel.String(), "yws1") serfConfig := serf.DefaultConfig() serfConfig.NodeName = "yws1" serfConfig.MemberlistConfig = memberlist.DefaultLANConfig() serfConfig.MemberlistConfig.BindAddr = "127.0.0.1" serfConfig.MemberlistConfig.BindPort = 7373 serfConfig.MemberlistConfig.AdvertiseAddr = "127.0.0.1" serfConfig.MemberlistConfig.AdvertisePort = 5000 eventCh := make(chan serf.Event, 64) serfConfig.EventCh = eventCh serfConfig.LogOutput = ioutil.Discard serfConfig.MemberlistConfig.LogOutput = ioutil.Discard s, err := serf.Create(serfConfig) if err != nil { fmt.Println(err) } go func() { serfShutdownCh := s.ShutdownCh() log.Info("agent: Listen for events") for { select { case e := <-eventCh: log.WithFields(logrus.Fields{ "event": e.String(), }).Debug("agent: Received event") // Log all member events if failed, ok := e.(serf.MemberEvent); ok { for _, member := range failed.Members { log.WithFields(logrus.Fields{ "node": "yang", "member": member.Name, "event": e.EventType(), }).Debug("agent: Member event") } } if e.EventType() == serf.EventQuery { query := e.(*serf.Query) fmt.Println(query) } case <-serfShutdownCh: log.Warn("agent: Serf shutdown detected, quitting") return } } }() fmt.Println(s) wait := make(chan int) <-wait }
func (d *driver) serfInit() error { var err error config := serf.DefaultConfig() config.Init() config.MemberlistConfig.BindAddr = d.bindAddress d.eventCh = make(chan serf.Event, 4) config.EventCh = d.eventCh config.UserCoalescePeriod = 1 * time.Second config.UserQuiescentPeriod = 50 * time.Millisecond config.LogOutput = &logWriter{} config.MemberlistConfig.LogOutput = config.LogOutput s, err := serf.Create(config) if err != nil { return fmt.Errorf("failed to create cluster node: %v", err) } defer func() { if err != nil { s.Shutdown() } }() d.serfInstance = s d.notifyCh = make(chan ovNotify) d.exitCh = make(chan chan struct{}) go d.startSerfLoop(d.eventCh, d.notifyCh, d.exitCh) return nil }
// setupAgent is used to create the agent we use func (c *Command) setupAgent(config *Config, logOutput io.Writer) *Agent { bindIP, bindPort, err := config.AddrParts(config.BindAddr) if err != nil { c.Ui.Error(fmt.Sprintf("Invalid bind address: %s", err)) return nil } var advertiseIP string var advertisePort int if config.AdvertiseAddr != "" { advertiseIP, advertisePort, err = config.AddrParts(config.AdvertiseAddr) if err != nil { c.Ui.Error(fmt.Sprintf("Invalid advertise address: %s", err)) return nil } } encryptKey, err := config.EncryptBytes() if err != nil { c.Ui.Error(fmt.Sprintf("Invalid encryption key: %s", err)) return nil } serfConfig := serf.DefaultConfig() switch config.Profile { case "lan": serfConfig.MemberlistConfig = memberlist.DefaultLANConfig() case "wan": serfConfig.MemberlistConfig = memberlist.DefaultWANConfig() case "local": serfConfig.MemberlistConfig = memberlist.DefaultLocalConfig() default: c.Ui.Error(fmt.Sprintf("Unknown profile: %s", config.Profile)) return nil } serfConfig.MemberlistConfig.BindAddr = bindIP serfConfig.MemberlistConfig.BindPort = bindPort serfConfig.MemberlistConfig.AdvertiseAddr = advertiseIP serfConfig.MemberlistConfig.AdvertisePort = advertisePort serfConfig.MemberlistConfig.SecretKey = encryptKey serfConfig.NodeName = config.NodeName serfConfig.Tags = config.Tags serfConfig.SnapshotPath = config.SnapshotPath serfConfig.ProtocolVersion = uint8(config.Protocol) serfConfig.CoalescePeriod = 3 * time.Second serfConfig.QuiescentPeriod = time.Second serfConfig.UserCoalescePeriod = 3 * time.Second serfConfig.UserQuiescentPeriod = time.Second // Start Serf c.Ui.Output("Starting Serf agent...") agent, err := Create(serfConfig, logOutput) if err != nil { c.Ui.Error(fmt.Sprintf("Failed to start the Serf agent: %v", err)) return nil } return agent }
// DefaultNodeConfig returns a reasonable default to use. func DefaultNodeConfig() *NodeConfig { return &NodeConfig{ Replicas: 2, RpcPort: 11211, SerfConfig: serf.DefaultConfig(), MaxMemoryUsage: 1 << 30, // 1 GB } }
// DefaultConfig returns the default configuration func DefaultConfig() *Config { hostname, err := os.Hostname() if err != nil { panic(err) } c := &Config{ Region: DefaultRegion, Datacenter: DefaultDC, NodeName: hostname, ProtocolVersion: ProtocolVersionMax, RaftConfig: raft.DefaultConfig(), RaftTimeout: 10 * time.Second, LogOutput: os.Stderr, RPCAddr: DefaultRPCAddr, SerfConfig: serf.DefaultConfig(), NumSchedulers: 1, ReconcileInterval: 60 * time.Second, EvalGCInterval: 5 * time.Minute, EvalGCThreshold: 1 * time.Hour, JobGCInterval: 5 * time.Minute, JobGCThreshold: 4 * time.Hour, NodeGCInterval: 5 * time.Minute, NodeGCThreshold: 24 * time.Hour, EvalNackTimeout: 60 * time.Second, EvalDeliveryLimit: 3, MinHeartbeatTTL: 10 * time.Second, MaxHeartbeatsPerSecond: 50.0, HeartbeatGrace: 10 * time.Second, FailoverHeartbeatTTL: 300 * time.Second, ConsulConfig: config.DefaultConsulConfig(), VaultConfig: config.DefaultVaultConfig(), RPCHoldTimeout: 5 * time.Second, TLSConfig: &config.TLSConfig{}, } // Enable all known schedulers by default c.EnabledSchedulers = make([]string, 0, len(scheduler.BuiltinSchedulers)) for name := range scheduler.BuiltinSchedulers { c.EnabledSchedulers = append(c.EnabledSchedulers, name) } c.EnabledSchedulers = append(c.EnabledSchedulers, structs.JobTypeCore) // Default the number of schedulers to match the coores c.NumSchedulers = runtime.NumCPU() // Increase our reap interval to 3 days instead of 24h. c.SerfConfig.ReconnectTimeout = 3 * 24 * time.Hour // Serf should use the WAN timing, since we are using it // to communicate between DC's c.SerfConfig.MemberlistConfig = memberlist.DefaultWANConfig() c.SerfConfig.MemberlistConfig.BindPort = DefaultSerfPort // Disable shutdown on removal c.RaftConfig.ShutdownOnRemove = false return c }
func serfInit() *serf.Serf { conf := serf.DefaultConfig() serfin, err := serf.Create(conf) if err != nil { log.Fatal(err) } return serfin }
func TestAgentKeyringFile_BadOptions(t *testing.T) { agentConfig := DefaultConfig() agentConfig.KeyringFile = "/some/path" agentConfig.EncryptKey = "pL4owv4IE1x+ZXCyd5vLLg==" _, err := Create(agentConfig, serf.DefaultConfig(), nil) if err == nil || !strings.Contains(err.Error(), "not allowed") { t.Fatalf("err: %s", err) } }
// DefaultConfig returns a Config with sane default values. func DefaultConfig() Config { return Config{ Partitions: 512, Redundancy: 3, SerfConfig: serf.DefaultConfig(), Events: make(chan Event), LogOutput: os.Stderr, LogLevel: 2, } }
func TestAgentTagsFile_BadOptions(t *testing.T) { agentConfig := DefaultConfig() agentConfig.TagsFile = "/some/path" agentConfig.Tags = map[string]string{ "tag1": "val1", } _, err := Create(agentConfig, serf.DefaultConfig(), nil) if err == nil || !strings.Contains(err.Error(), "not allowed") { t.Fatalf("err: %s", err) } }
func testAgent() *Agent { config := serf.DefaultConfig() config.MemberlistConfig.BindAddr = testutil.GetBindAddr().String() config.NodeName = config.MemberlistConfig.BindAddr agent := &Agent{ RPCAddr: getRPCAddr(), SerfConfig: config, } return agent }
func (s *Server) setupSerf() (*serf.Serf, error) { conf := serf.DefaultConfig() // Generate NodeName if missing id, err := uuid.UUID4() if err != nil { return nil, err } // Get SSH server port port := s.sshServer.Addr.Port // Initialize serf conf.Init() // s.logger.Info("local port", "port", conf.MemberlistConfig.BindPort) conf.NodeName = s.config.NodeName conf.MemberlistConfig.BindAddr = s.config.GossipBindAddr conf.MemberlistConfig.BindPort = s.config.GossipBindPort conf.MemberlistConfig.AdvertiseAddr = s.config.GossipAdvertiseAddr conf.MemberlistConfig.AdvertisePort = s.config.GossipAdvertisePort s.logger.Info("Gossip", "BindAddr", conf.MemberlistConfig.BindAddr, "BindPort", conf.MemberlistConfig.BindPort, "AdvertiseAddr", conf.MemberlistConfig.AdvertiseAddr, "AdvertisePort", conf.MemberlistConfig.AdvertisePort) conf.Tags["id"] = id conf.Tags["role"] = "kappa-server" conf.Tags["cluster"] = s.config.ClusterName conf.Tags["build"] = s.config.Build conf.Tags["port"] = fmt.Sprintf("%d", port) if s.config.Bootstrap { conf.Tags["bootstrap"] = "1" } if s.config.BootstrapExpect != 0 { conf.Tags["expect"] = fmt.Sprintf("%d", s.config.BootstrapExpect) } conf.MemberlistConfig.LogOutput = s.config.LogOutput conf.LogOutput = s.config.LogOutput conf.EventCh = s.serfEventCh conf.SnapshotPath = filepath.Join(s.config.DataPath, serfSnapshot) conf.ProtocolVersion = conf.ProtocolVersion conf.RejoinAfterLeave = true conf.EnableNameConflictResolution = false conf.Merge = &mergeDelegate{name: s.config.ClusterName} if err := ensurePath(conf.SnapshotPath, false); err != nil { return nil, err } return serf.Create(conf) }
func testAgent(logOutput io.Writer) *Agent { if logOutput == nil { logOutput = os.Stderr } config := serf.DefaultConfig() config.MemberlistConfig.ProbeInterval = 100 * time.Millisecond config.MemberlistConfig.BindAddr = testutil.GetBindAddr().String() config.NodeName = config.MemberlistConfig.BindAddr agent, err := Create(config, logOutput) if err != nil { panic(err) } return agent }
func testAgent(t *testing.T) *agent.Agent { config := serf.DefaultConfig() config.MemberlistConfig.BindAddr = testutil.GetBindAddr().String() config.NodeName = config.MemberlistConfig.BindAddr agent := &agent.Agent{ RPCAddr: getRPCAddr(), SerfConfig: config, } if err := agent.Start(); err != nil { t.Fatalf("err: %s", err) } return agent }
func (d *driver) serfInit() error { var err error config := serf.DefaultConfig() config.Init() if d.ifaceName != "" { bindAddr, err := getBindAddr(d.ifaceName) if err != nil { return fmt.Errorf("getBindAddr error: %v", err) } config.MemberlistConfig.BindAddr = bindAddr } d.eventCh = make(chan serf.Event, 4) config.EventCh = d.eventCh config.UserCoalescePeriod = 1 * time.Second config.UserQuiescentPeriod = 50 * time.Millisecond config.LogOutput = logrus.StandardLogger().Out s, err := serf.Create(config) if err != nil { return fmt.Errorf("failed to create cluster node: %v", err) } defer func() { if err != nil { s.Shutdown() } }() if d.neighIP != "" { if _, err = s.Join([]string{d.neighIP}, false); err != nil { return fmt.Errorf("Failed to join the cluster at neigh IP %s: %v", d.neighIP, err) } } d.serfInstance = s d.notifyCh = make(chan ovNotify) d.exitCh = make(chan chan struct{}) go d.startSerfLoop(d.eventCh, d.notifyCh, d.exitCh) return nil }
func testAgent(t *testing.T) *agent.Agent { config := serf.DefaultConfig() config.MemberlistConfig.BindAddr = testutil.GetBindAddr().String() config.MemberlistConfig.ProbeInterval = 50 * time.Millisecond config.MemberlistConfig.ProbeTimeout = 25 * time.Millisecond config.MemberlistConfig.SuspicionMult = 1 config.NodeName = config.MemberlistConfig.BindAddr agent := &agent.Agent{ RPCAddr: getRPCAddr(), SerfConfig: config, } if err := agent.Start(); err != nil { t.Fatalf("err: %s", err) } return agent }
func TestAgentKeyringFile(t *testing.T) { keys := []string{ "enjTwAFRe4IE71bOFhirzQ==", "csT9mxI7aTf9ap3HLBbdmA==", "noha2tVc0OyD/2LtCBoAOQ==", } td, err := ioutil.TempDir("", "serf") if err != nil { t.Fatalf("err: %s", err) } defer os.RemoveAll(td) keyringFile := filepath.Join(td, "keyring.json") serfConfig := serf.DefaultConfig() agentConfig := DefaultConfig() agentConfig.KeyringFile = keyringFile encodedKeys, err := json.Marshal(keys) if err != nil { t.Fatalf("err: %s", err) } if err := ioutil.WriteFile(keyringFile, encodedKeys, 0600); err != nil { t.Fatalf("err: %s", err) } a1 := testAgentWithConfig(agentConfig, serfConfig, nil) if err := a1.Start(); err != nil { t.Fatalf("err: %s", err) } defer a1.Shutdown() testutil.Yield() totalLoadedKeys := len(serfConfig.MemberlistConfig.Keyring.GetKeys()) if totalLoadedKeys != 3 { t.Fatalf("Expected to load 3 keys but got %d", totalLoadedKeys) } }
func testAgent(t *testing.T) *agent.Agent { config := serf.DefaultConfig() config.MemberlistConfig.BindAddr = testutil.GetBindAddr().String() config.MemberlistConfig.ProbeInterval = 50 * time.Millisecond config.MemberlistConfig.ProbeTimeout = 25 * time.Millisecond config.MemberlistConfig.SuspicionMult = 1 config.NodeName = config.MemberlistConfig.BindAddr config.Tags = map[string]string{"role": "test", "tag1": "foo", "tag2": "bar"} agent, err := agent.Create(config, nil) if err != nil { t.Fatalf("err: %s", err) } if err := agent.Start(); err != nil { t.Fatalf("err: %s", err) } return agent }
func testKeysCommandAgent(t *testing.T) *agent.Agent { key1, err := base64.StdEncoding.DecodeString("SNCg1bQSoCdGVlEx+TgfBw==") if err != nil { t.Fatalf("err: %s", err) } key2, err := base64.StdEncoding.DecodeString("vbitCcJNwNP4aEWHgofjMg==") if err != nil { t.Fatalf("err: %s", err) } keyring, err := memberlist.NewKeyring([][]byte{key1, key2}, key1) if err != nil { t.Fatalf("err: %s", err) } agentConf := agent.DefaultConfig() serfConf := serf.DefaultConfig() serfConf.MemberlistConfig.Keyring = keyring a1 := testAgentWithConfig(t, agentConf, serfConf) return a1 }
func DefaultConfig() (*Config, error) { hostname, err := os.Hostname() if err != nil { return nil, err } ambariConfig, err := DefaultAmbariConfig() if err != nil { return nil, err } c := &Config{ NodeName: hostname, SerfConfig: serf.DefaultConfig(), RPCAddr: DefaultRPCAddr, AmbariConfig: ambariConfig, HostsFile: "/etc/hosts", HostsUpdateInterval: 10 * time.Second, } c.setupSerfConfig() return c, nil }
func TestAgentKeyringFile_NoKeys(t *testing.T) { dir, err := ioutil.TempDir("", "serf") if err != nil { t.Fatalf("err: %s", err) } defer os.RemoveAll(dir) keysFile := filepath.Join(dir, "keyring") if err := ioutil.WriteFile(keysFile, []byte("[]"), 0600); err != nil { t.Fatalf("err: %s", err) } agentConfig := DefaultConfig() agentConfig.KeyringFile = keysFile _, err = Create(agentConfig, serf.DefaultConfig(), nil) if err == nil { t.Fatalf("should have errored") } if !strings.Contains(err.Error(), "contains no keys") { t.Fatalf("bad: %s", err) } }
func (c *cerebrum) setupSerf() (*serf.Serf, error) { // Get serf config conf := serf.DefaultConfig() // Initialize serf conf.Init() conf.NodeName = c.config.NodeName conf.MemberlistConfig.BindAddr = c.config.GossipBindAddr conf.MemberlistConfig.BindPort = c.config.GossipBindPort conf.MemberlistConfig.AdvertiseAddr = c.config.GossipAdvertiseAddr conf.MemberlistConfig.AdvertisePort = c.config.GossipAdvertisePort c.logger.Info("Gossip", "BindAddr", conf.MemberlistConfig.BindAddr, "BindPort", conf.MemberlistConfig.BindPort, "AdvertiseAddr", conf.MemberlistConfig.AdvertiseAddr, "AdvertisePort", conf.MemberlistConfig.AdvertisePort) conf.Tags["id"] = c.config.NodeID conf.Tags["role"] = "cerebrum-server" conf.Tags["dc"] = c.config.DataCenter // conf.Tags["port"] = fmt.Sprintf("%d", port) conf.MemberlistConfig.LogOutput = c.config.LogOutput conf.LogOutput = c.config.LogOutput conf.EventCh = c.serfEventCh conf.SnapshotPath = filepath.Join(c.config.DataPath, SerfSnapshotDir) conf.ProtocolVersion = conf.ProtocolVersion conf.RejoinAfterLeave = true conf.EnableNameConflictResolution = false conf.Merge = &mergeDelegate{c.logger} if err := os.MkdirAll(conf.SnapshotPath, 0755); err != nil { return nil, err } return serf.Create(conf) }
func (c *Command) Run(args []string) int { ui := &cli.PrefixedUi{ OutputPrefix: "==> ", InfoPrefix: " ", ErrorPrefix: "==> ", Ui: c.Ui, } var cmdConfig Config var configFiles []string cmdFlags := flag.NewFlagSet("agent", flag.ContinueOnError) cmdFlags.Usage = func() { ui.Output(c.Help()) } cmdFlags.StringVar(&cmdConfig.BindAddr, "bind", "", "address to bind listeners to") cmdFlags.Var((*AppendSliceValue)(&configFiles), "config-file", "json file to read config from") cmdFlags.Var((*AppendSliceValue)(&configFiles), "config-dir", "directory of json files to read") cmdFlags.StringVar(&cmdConfig.EncryptKey, "encrypt", "", "encryption key") cmdFlags.Var((*AppendSliceValue)(&cmdConfig.EventHandlers), "event-handler", "command to execute when events occur") cmdFlags.Var((*AppendSliceValue)(&cmdConfig.StartJoin), "join", "address of agent to join on startup") cmdFlags.StringVar(&cmdConfig.LogLevel, "log-level", "", "log level") cmdFlags.StringVar(&cmdConfig.NodeName, "node", "", "node name") cmdFlags.IntVar(&cmdConfig.Protocol, "protocol", -1, "protocol version") cmdFlags.StringVar(&cmdConfig.Role, "role", "", "role name") cmdFlags.StringVar(&cmdConfig.RPCAddr, "rpc-addr", "", "address to bind RPC listener to") if err := cmdFlags.Parse(args); err != nil { return 1 } config := DefaultConfig if len(configFiles) > 0 { fileConfig, err := ReadConfigPaths(configFiles) if err != nil { c.Ui.Error(err.Error()) return 1 } config = MergeConfig(config, fileConfig) } config = MergeConfig(config, &cmdConfig) if config.NodeName == "" { hostname, err := os.Hostname() if err != nil { c.Ui.Error(fmt.Sprintf("Error determining hostname: %s", err)) return 1 } config.NodeName = hostname } eventScripts, err := config.EventScripts() if err != nil { c.Ui.Error(err.Error()) return 1 } for _, script := range eventScripts { if !script.Valid() { c.Ui.Error(fmt.Sprintf("Invalid event script: %s", script.String())) return 1 } } bindIP, bindPort, err := config.BindAddrParts() if err != nil { c.Ui.Error(fmt.Sprintf("Invalid bind address: %s", err)) return 1 } encryptKey, err := config.EncryptBytes() if err != nil { c.Ui.Error(fmt.Sprintf("Invalid encryption key: %s", err)) return 1 } // Setup logging. First create the gated log writer, which will // store logs until we're ready to show them. Then create the level // filter, filtering logs of the specified level. logGate := &GatedWriter{ Writer: &cli.UiWriter{Ui: c.Ui}, } logLevelFilter := LevelFilter() logLevelFilter.MinLevel = logutils.LogLevel(strings.ToUpper(config.LogLevel)) logLevelFilter.Writer = logGate if !ValidateLevelFilter(logLevelFilter) { ui.Error(fmt.Sprintf( "Invalid log level: %s. Valid log levels are: %v", logLevelFilter.MinLevel, logLevelFilter.Levels)) return 1 } serfConfig := serf.DefaultConfig() serfConfig.MemberlistConfig.BindAddr = bindIP serfConfig.MemberlistConfig.Port = bindPort serfConfig.MemberlistConfig.SecretKey = encryptKey serfConfig.NodeName = config.NodeName serfConfig.Role = config.Role serfConfig.ProtocolVersion = uint8(config.Protocol) serfConfig.CoalescePeriod = 3 * time.Second serfConfig.QuiescentPeriod = time.Second serfConfig.UserCoalescePeriod = 3 * time.Second serfConfig.UserQuiescentPeriod = time.Second agent := &Agent{ EventHandler: &ScriptEventHandler{ Self: serf.Member{ Name: serfConfig.NodeName, Role: serfConfig.Role, }, Scripts: eventScripts, }, LogOutput: logLevelFilter, RPCAddr: config.RPCAddr, SerfConfig: serfConfig, } ui.Output("Starting Serf agent...") if err := agent.Start(); err != nil { ui.Error(err.Error()) return 1 } defer agent.Shutdown() bindAddr := (&net.TCPAddr{IP: net.ParseIP(bindIP), Port: bindPort}).String() ui.Output("Serf agent running!") ui.Info(fmt.Sprintf("Node name: '%s'", config.NodeName)) ui.Info(fmt.Sprintf("Bind addr: '%s'", bindAddr)) ui.Info(fmt.Sprintf(" RPC addr: '%s'", config.RPCAddr)) ui.Info(fmt.Sprintf("Encrypted: %#v", config.EncryptKey != "")) if len(config.StartJoin) > 0 { ui.Output("Joining cluster...") n, err := agent.Join(config.StartJoin, true) if err != nil { ui.Error(err.Error()) return 1 } ui.Info(fmt.Sprintf("Join completed. Synced with %d initial agents", n)) } ui.Info("") ui.Output("Log data will now stream in as it occurs:\n") logGate.Flush() graceful, forceful := c.startShutdownWatcher(agent, ui) select { case <-graceful: case <-forceful: // Forcefully shut down, return a bad exit status. return 1 } return 0 }
// setupAgent is used to create the agent we use func (c *Command) setupAgent(config *Config, logOutput io.Writer) *Agent { bindIP, bindPort, err := config.AddrParts(config.BindAddr) if err != nil { c.Ui.Error(fmt.Sprintf("Invalid bind address: %s", err)) return nil } // Check if we have an interface if iface, _ := config.NetworkInterface(); iface != nil { addrs, err := iface.Addrs() if err != nil { c.Ui.Error(fmt.Sprintf("Failed to get interface addresses: %s", err)) return nil } if len(addrs) == 0 { c.Ui.Error(fmt.Sprintf("Interface '%s' has no addresses", config.Interface)) return nil } // If there is no bind IP, pick an address if bindIP == "0.0.0.0" { found := false for _, a := range addrs { addr, ok := a.(*net.IPNet) if !ok { continue } // Skip self-assigned IPs if addr.IP.IsLinkLocalUnicast() { continue } // Found an IP found = true bindIP = addr.IP.String() c.Ui.Output(fmt.Sprintf("Using interface '%s' address '%s'", config.Interface, bindIP)) // Update the configuration bindAddr := &net.TCPAddr{ IP: net.ParseIP(bindIP), Port: bindPort, } config.BindAddr = bindAddr.String() break } if !found { c.Ui.Error(fmt.Sprintf("Failed to find usable address for interface '%s'", config.Interface)) return nil } } else { // If there is a bind IP, ensure it is available found := false for _, a := range addrs { addr, ok := a.(*net.IPNet) if !ok { continue } if addr.IP.String() == bindIP { found = true break } } if !found { c.Ui.Error(fmt.Sprintf("Interface '%s' has no '%s' address", config.Interface, bindIP)) return nil } } } var advertiseIP string var advertisePort int if config.AdvertiseAddr != "" { advertiseIP, advertisePort, err = config.AddrParts(config.AdvertiseAddr) if err != nil { c.Ui.Error(fmt.Sprintf("Invalid advertise address: %s", err)) return nil } } encryptKey, err := config.EncryptBytes() if err != nil { c.Ui.Error(fmt.Sprintf("Invalid encryption key: %s", err)) return nil } serfConfig := serf.DefaultConfig() switch config.Profile { case "lan": serfConfig.MemberlistConfig = memberlist.DefaultLANConfig() case "wan": serfConfig.MemberlistConfig = memberlist.DefaultWANConfig() case "local": serfConfig.MemberlistConfig = memberlist.DefaultLocalConfig() default: c.Ui.Error(fmt.Sprintf("Unknown profile: %s", config.Profile)) return nil } serfConfig.MemberlistConfig.BindAddr = bindIP serfConfig.MemberlistConfig.BindPort = bindPort serfConfig.MemberlistConfig.AdvertiseAddr = advertiseIP serfConfig.MemberlistConfig.AdvertisePort = advertisePort serfConfig.MemberlistConfig.SecretKey = encryptKey serfConfig.NodeName = config.NodeName serfConfig.Tags = config.Tags serfConfig.SnapshotPath = config.SnapshotPath serfConfig.ProtocolVersion = uint8(config.Protocol) serfConfig.CoalescePeriod = 3 * time.Second serfConfig.QuiescentPeriod = time.Second serfConfig.UserCoalescePeriod = 3 * time.Second serfConfig.UserQuiescentPeriod = time.Second if config.ReconnectInterval != 0 { serfConfig.ReconnectInterval = config.ReconnectInterval } if config.ReconnectTimeout != 0 { serfConfig.ReconnectTimeout = config.ReconnectTimeout } if config.TombstoneTimeout != 0 { serfConfig.TombstoneTimeout = config.TombstoneTimeout } serfConfig.EnableNameConflictResolution = !config.DisableNameResolution if config.KeyringFile != "" { serfConfig.KeyringFile = config.KeyringFile } serfConfig.RejoinAfterLeave = config.RejoinAfterLeave // Start Serf c.Ui.Output("Starting Serf agent...") agent, err := Create(config, serfConfig, logOutput) if err != nil { c.Ui.Error(fmt.Sprintf("Failed to start the Serf agent: %v", err)) return nil } return agent }