// watchKeys creates a new Watcher and adds all configured keys func watchKeys(config Config, etcdClient *etcd.Client) *watcher.Watcher { w, err := watcher.New(etcdClient) if err != nil { log.WithField("error", err).Fatal("failed to create watcher") } // start watching etcd prefixs for prefix := range config { if err := w.Add(prefix); err != nil { log.WithFields(log.Fields{ "prefix": prefix, "error": err, "errorMsg": err.Error(), }).Fatal("failed to add watch prefix") } } return w }
func main() { eaddr := "http://localhost:4001" hn := "" rules := "/etc/nftables.conf" flag.StringVarP(&eaddr, "etcd", "e", eaddr, "etcd cluster address") flag.StringVarP(&hn, "id", "i", hn, "hypervisor id") flag.StringVarP(&rules, "file", "f", rules, "nft configuration file") flag.Parse() rules = canonicalizeRules(rules) cleanStaleFiles(rules) e := etcd.NewClient([]string{eaddr}) c := ln.NewContext(e) hv := getHV(hn, e, c) watcher, err := watcher.New(e) if err != nil { log.WithFields(log.Fields{ "error": err, "func": "watcher.New", }).Fatal("failed to start watcher") } if err = watcher.Add("/lochness/guests"); err != nil { log.WithFields(log.Fields{ "error": err, "func": "watcher.Add", "prefix": "/lochness/guests", }).Fatal("failed to add prefix to watch list") } if err := watcher.Add("/lochness/fwgroups"); err != nil { log.WithFields(log.Fields{ "error": err, "func": "watcher.Add", "prefix": "/lochness/fwgroups", }).Fatal("failed to add prefix to watch list") } // load rules at startup td, err := genRules(hv, c) if err != nil { log.WithField("error", err).Fatal("could not load intial rules") } if err := applyRules(rules, td); err != nil { log.WithField("error", err).Fatal("could not apply intial rules") } for watcher.Next() { td, err := genRules(hv, c) if err != nil { continue } if err := applyRules(rules, td); err != nil { log.WithField("error", err).Fatal("could not apply rules") } } if err := watcher.Err(); err != nil { log.Fatal(err) } }
func main() { // Command line options var etcdAddress, domain, confPath, logLevel string flag.StringVarP(&domain, "domain", "d", "", "domain for lochness; required") flag.StringVarP(&etcdAddress, "etcd", "e", "http://127.0.0.1:4001", "address of etcd server") flag.StringVarP(&confPath, "conf-dir", "c", "/etc/dhcp/", "dhcpd configuration directory") flag.StringVarP(&logLevel, "log-level", "l", "warning", "log level: debug/info/warning/error/critical/fatal") flag.Parse() // Domain is required if domain == "" { flag.PrintDefaults() os.Exit(1) } // Logging if err := logx.DefaultSetup(logLevel); err != nil { log.WithFields(log.Fields{ "error": err, "func": "logx.DefaultSetup", }).Fatal("Could not set up logrus") } hconfPath := path.Join(confPath, "hypervisors.conf") gconfPath := path.Join(confPath, "guests.conf") // Set up fetcher and refresher f := NewFetcher(etcdAddress) r := NewRefresher(domain) err := f.FetchAll() if err != nil { os.Exit(1) } // Update at the start of each run restart, err := updateConfigs(f, r, hconfPath, gconfPath) if restart { restartDhcpd() } if err != nil { os.Exit(1) } // Create the watcher w, err := watcher.New(f.etcdClient) if err != nil { log.WithFields(log.Fields{ "error": err, "func": "watcher.New", }).Fatal("Could not create watcher") } // Start watching the necessary etcd prefixs prefixes := [...]string{"/lochness/hypervisors", "/lochness/guests", "/lochness/subnets"} for _, prefix := range prefixes { if err := w.Add(prefix); err != nil { log.WithFields(log.Fields{ "error": err, "func": "watcher.Add", "prefix": prefix, }).Fatal("Could not add watch prefix") } } // Channel for indicating work in progress // (to coordinate clean exiting between the consumer and the signal handler) ready := make(chan struct{}, 1) ready <- struct{}{} for w.Next() { // Remove item to indicate processing has begun done := <-ready // Integrate the response and update the configs if necessary refresh, err := f.IntegrateResponse(w.Response()) if err != nil { log.Info("Error on integration; re-fetching") err := f.FetchAll() if err != nil { os.Exit(1) } refresh = true } if refresh { restart, err := updateConfigs(f, r, hconfPath, gconfPath) if restart { restartDhcpd() } if err != nil { log.WithFields(log.Fields{ "error": err, "func": "updateConfigs", }).Warn("Could not create watcher") } } // Return item to indicate processing has completed ready <- done } if err := w.Err(); err != nil { log.WithField("error", err).Fatal("Watcher encountered an error") } // Handle signals for clean shutdown sigs := make(chan os.Signal) signal.Notify(sigs, os.Interrupt, syscall.SIGTERM) s := <-sigs log.WithField("signal", s).Info("Signal received; waiting for current task to process") <-ready // wait until any current processing is finished _ = w.Close() log.Info("Exiting") }