// returns an array of the mgtports and the tribe port for the last node func startTribes(count int, seed string) ([]int, int) { var wg sync.WaitGroup var tribePort int var mgtPorts []int for i := 0; i < count; i++ { mgtPort := getAvailablePort() mgtPorts = append(mgtPorts, mgtPort) tribePort = getAvailablePort() conf := tribe.DefaultConfig(fmt.Sprintf("member-%v", mgtPort), "127.0.0.1", tribePort, seed, mgtPort) // conf.MemberlistConfig.PushPullInterval = 5 * time.Second conf.MemberlistConfig.RetransmitMult = conf.MemberlistConfig.RetransmitMult * 2 if seed == "" { seed = fmt.Sprintf("%s:%d", "127.0.0.1", tribePort) } t, err := tribe.New(conf) if err != nil { panic(err) } c := control.New() c.RegisterEventHandler("tribe", t) c.Start() s := scheduler.New() s.SetMetricManager(c) s.RegisterEventHandler("tribe", t) s.Start() t.SetPluginCatalog(c) t.SetTaskManager(s) t.Start() r, _ := New(false, "", "") r.BindMetricManager(c) r.BindTaskManager(s) r.BindTribeManager(t) r.Start(":" + strconv.Itoa(mgtPort)) wg.Add(1) timer := time.After(10 * time.Second) go func(port int) { defer wg.Done() for { select { case <-timer: panic("timed out") default: time.Sleep(100 * time.Millisecond) resp := getMembers(port) if resp.Meta.Code == 200 && len(resp.Body.(*rbody.TribeMemberList).Members) >= count { restLogger.Infof("num of members %v", len(resp.Body.(*rbody.TribeMemberList).Members)) return } } } }(mgtPort) } wg.Wait() return mgtPorts, tribePort }
func action(ctx *cli.Context) { // If logPath is set, we verify the logPath and set it so that all logging // goes to the log file instead of stdout. logPath := ctx.String("log-path") if logPath != "" { f, err := os.Stat(logPath) if err != nil { log.Fatal(err) } if !f.IsDir() { log.Fatal("log path provided must be a directory") } file, err := os.OpenFile(fmt.Sprintf("%s/snap.log", logPath), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err != nil { log.Fatal(err) } defer file.Close() log.SetOutput(file) } var l = map[int]string{ 1: "debug", 2: "info", 3: "warning", 4: "error", 5: "fatal", } var t = map[int]string{ 0: "disabled", 1: "enabled", 2: "warning", } logLevel := ctx.Int("log-level") maxProcs := ctx.Int("max-procs") disableAPI := ctx.Bool("disable-api") apiPort := ctx.Int("api-port") autodiscoverPath := ctx.String("auto-discover") maxRunning := ctx.Int("max-running-plugins") pluginTrust := ctx.Int("plugin-trust") keyringPaths := ctx.String("keyring-files") cachestr := ctx.String("cache-expiration") isTribeEnabled := ctx.Bool("tribe") tribeSeed := ctx.String("tribe-seed") tribeNodeName := ctx.String("tribe-node-name") tribeAddr := ctx.String("tribe-addr") tribePort := ctx.Int("tribe-port") cache, err := time.ParseDuration(cachestr) if err != nil { log.Fatal(fmt.Sprintf("invalid cache-expiration format: %s", cachestr)) } config := ctx.String("config") restHttps := ctx.Bool("rest-https") restKey := ctx.String("rest-key") restCert := ctx.String("rest-cert") log.Info("Starting snapd (version: ", gitversion, ")") // Set Max Processors for snapd. setMaxProcs(maxProcs) // Validate log level and trust level settings for snapd validateLevelSettings(logLevel, pluginTrust) controlOpts := []control.PluginControlOpt{ control.MaxRunningPlugins(maxRunning), control.CacheExpiration(cache), } if config != "" { b, err := ioutil.ReadFile(config) if err != nil { log.WithFields(log.Fields{ "block": "main", "_module": "snapd", "error": err.Error(), "path": config, }).Fatal("unable to read config") } cfg := control.NewConfig() err = json.Unmarshal(b, &cfg) if err != nil { log.WithFields(log.Fields{ "block": "main", "_module": "snapd", "error": err.Error(), "path": config, }).Fatal("invalid config") } controlOpts = append(controlOpts, control.OptSetConfig(cfg)) } c := control.New( controlOpts..., ) coreModules = []coreModule{} coreModules = append(coreModules, c) s := scheduler.New( scheduler.CollectQSizeOption(defaultQueueSize), scheduler.CollectWkrSizeOption(defaultPoolSize), scheduler.PublishQSizeOption(defaultQueueSize), scheduler.PublishWkrSizeOption(defaultPoolSize), scheduler.ProcessQSizeOption(defaultQueueSize), scheduler.ProcessWkrSizeOption(defaultPoolSize), ) s.SetMetricManager(c) coreModules = append(coreModules, s) var tr managesTribe if isTribeEnabled { log.Info("Tribe is enabled") tc := tribe.DefaultConfig(tribeNodeName, tribeAddr, tribePort, tribeSeed, apiPort) t, err := tribe.New(tc) if err != nil { printErrorAndExit(t.Name(), err) } c.RegisterEventHandler("tribe", t) t.SetPluginCatalog(c) s.RegisterEventHandler("tribe", t) t.SetTaskManager(s) coreModules = append(coreModules, t) tr = t } // Set interrupt handling so we can die gracefully. startInterruptHandling(coreModules...) // Start our modules var started []coreModule for _, m := range coreModules { if err := startModule(m); err != nil { for _, m := range started { m.Stop() } printErrorAndExit(m.Name(), err) } started = append(started, m) } //Plugin Trust c.SetPluginTrustLevel(pluginTrust) log.Info("setting plugin trust level to: ", t[pluginTrust]) //Keyring checking for trust levels 1 and 2 if pluginTrust > 0 { keyrings := filepath.SplitList(keyringPaths) if len(keyrings) == 0 { log.WithFields( log.Fields{ "block": "main", "_module": "snapd", }).Fatal("need keyring file when trust is on (--keyring-file or -k)") } for _, k := range keyrings { keyringPath, err := filepath.Abs(k) if err != nil { log.WithFields( log.Fields{ "block": "main", "_module": "snapd", "error": err.Error(), "keyringPath": keyringPath, }).Fatal("Unable to determine absolute path to keyring file") } f, err := os.Stat(keyringPath) if err != nil { log.WithFields( log.Fields{ "block": "main", "_module": "snapd", "error": err.Error(), "keyringPath": keyringPath, }).Fatal("bad keyring file") } if f.IsDir() { log.Info("Adding keyrings from: ", keyringPath) files, err := ioutil.ReadDir(keyringPath) if err != nil { log.WithFields( log.Fields{ "_block": "main", "_module": "snapd", "error": err.Error(), "keyringPath": keyringPath, }).Fatal(err) } if len(files) == 0 { log.Fatal(fmt.Sprintf("given keyring path [%s] is an empty directory!", keyringPath)) } for _, keyringFile := range files { if keyringFile.IsDir() { continue } if strings.HasSuffix(keyringFile.Name(), ".gpg") || (strings.HasSuffix(keyringFile.Name(), ".pub")) || (strings.HasSuffix(keyringFile.Name(), ".pubring")) { f, err := os.Open(keyringPath) if err != nil { log.WithFields( log.Fields{ "block": "main", "_module": "snapd", "error": err.Error(), "keyringPath": keyringPath, }).Warning("unable to open keyring file. not adding to keyring path") continue } f.Close() log.Info("adding keyring file: ", keyringPath+"/"+keyringFile.Name()) c.SetKeyringFile(keyringPath + "/" + keyringFile.Name()) } } } else { f, err := os.Open(keyringPath) if err != nil { log.WithFields( log.Fields{ "block": "main", "_module": "snapd", "error": err.Error(), "keyringPath": keyringPath, }).Fatal("unable to open keyring file.") } f.Close() log.Info("adding keyring file ", keyringPath) c.SetKeyringFile(keyringPath) } } } //Autodiscover if autodiscoverPath != "" { log.Info("auto discover path is enabled") paths := filepath.SplitList(autodiscoverPath) c.SetAutodiscoverPaths(paths) for _, p := range paths { fullPath, err := filepath.Abs(p) if err != nil { log.WithFields( log.Fields{ "_block": "main", "_module": "snapd", "autodiscoverpath": p, }).Fatal(err) } log.Info("autoloading plugins from: ", fullPath) files, err := ioutil.ReadDir(fullPath) if err != nil { log.WithFields( log.Fields{ "_block": "main", "_module": "snapd", "autodiscoverpath": fullPath, }).Fatal(err) } for _, file := range files { if file.IsDir() { continue } if strings.HasSuffix(file.Name(), ".aci") || !(strings.HasSuffix(file.Name(), ".asc")) { rp, err := core.NewRequestedPlugin(path.Join(fullPath, file.Name())) if err != nil { log.WithFields(log.Fields{ "_block": "main", "_module": "snapd", "autodiscoverpath": fullPath, "plugin": file, }).Error(err) } signatureFile := file.Name() + ".asc" if _, err := os.Stat(path.Join(fullPath, signatureFile)); err == nil { err = rp.ReadSignatureFile(path.Join(fullPath, signatureFile)) if err != nil { log.WithFields(log.Fields{ "_block": "main", "_module": "snapd", "autodiscoverpath": fullPath, "plugin": file.Name() + ".asc", }).Error(err) } } pl, err := c.Load(rp) if err != nil { log.WithFields(log.Fields{ "_block": "main", "_module": "snapd", "autodiscoverpath": fullPath, "plugin": file, }).Error(err) } else { log.WithFields(log.Fields{ "_block": "main", "_module": "snapd", "autodiscoverpath": fullPath, "plugin": file, "plugin-name": pl.Name(), "plugin-version": pl.Version(), "plugin-type": pl.TypeName(), }).Info("Loading plugin") } } } } } else { log.Info("auto discover path is disabled") } //API if !disableAPI { r, err := rest.New(restHttps, restCert, restKey) if err != nil { log.Fatal(err) return } r.BindMetricManager(c) r.BindConfigManager(c.Config) r.BindTaskManager(s) if tr != nil { r.BindTribeManager(tr) } r.Start(fmt.Sprintf(":%d", apiPort)) go monitorErrors(r.Err()) log.Info("Rest API is enabled") } else { log.Info("Rest API is disabled") } log.WithFields( log.Fields{ "block": "main", "_module": "snapd", }).Info("snapd started") // Switch log level to user defined log.Info("setting log level to: ", l[logLevel]) log.SetLevel(getLevel(logLevel)) select {} //run forever and ever }