Esempio n. 1
0
// 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
}
Esempio n. 2
0
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)
	}
}
Esempio n. 3
0
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")
}