예제 #1
0
// Daemon is the top-level entrypoint for the volsupervisor from the CLI.
func Daemon(ctx *cli.Context) {
	cfg, err := config.NewClient(ctx.String("prefix"), ctx.StringSlice("etcd"))
	if err != nil {
		logrus.Fatal(err)
	}

retry:
	global, err := cfg.GetGlobal()
	if err != nil {
		logrus.Errorf("Could not retrieve global configuration: %v. Retrying in 1 second", err)
		time.Sleep(time.Second)
		goto retry
	}

	dc := &DaemonConfig{Config: cfg, Global: global, Hostname: ctx.String("host-label")}
	dc.setDebug()

	globalChan := make(chan *watch.Watch)
	dc.Config.WatchGlobal(globalChan)
	go dc.watchAndSetGlobal(globalChan)
	go info.HandleDebugSignal()

	stopChan, err := lock.NewDriver(dc.Config).AcquireWithTTLRefresh(&config.UseVolsupervisor{Hostname: dc.Hostname}, dc.Global.TTL, dc.Global.Timeout)
	if err != nil {
		logrus.Fatal("Could not start volsupervisor: already in use")
	}

	sigChan := make(chan os.Signal, 1)

	go func() {
		<-sigChan
		logrus.Infof("Removing volsupervisor global lock; waiting %v for lock to clear", dc.Global.TTL)
		stopChan <- struct{}{}
		time.Sleep(wait.Jitter(dc.Global.TTL+time.Second, 0)) // give us enough time to try to clear the lock
		os.Exit(0)
	}()

	signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)

	dc.signalSnapshot()
	dc.updateVolumes()
	// doing it here ensures the goroutine is created when the first poll completes.
	go func() {
		for {
			time.Sleep(wait.Jitter(time.Second, 0))
			dc.updateVolumes()
		}
	}()

	dc.loop()
}
예제 #2
0
// AcquireAndRefresh starts a goroutine to refresh the key every 1/4
// (jittered) of the TTL. A stop channel is returned which, when sent a
// struct, will terminate the refresh. Error is returned for anything that
// might occur while setting up the goroutine.
//
// Do not use Free to free these locks, it will not work! Use the stop
// channel.
func (c *Client) AcquireAndRefresh(lock db.Lock, ttl time.Duration) (chan struct{}, error) {
	logrus.Debugf("In refresh, performing preliminary permanent lock on %v", lock)
	if err := c.Acquire(lock); err != nil {
		return nil, err
	}

	stopChan := make(chan struct{})

	go func() {
		for {
			select {
			case <-stopChan:
				if err := c.Free(lock, false); err != nil {
					logrus.Errorf("Error freeing lock %q: %v", lock, err)
				}

				return
			default:
				time.Sleep(wait.Jitter(ttl/4, 0))
				if err := c.AcquireWithTTL(lock, ttl); err != nil {
					logrus.Errorf("Could not acquire lock %v: %v", lock, err)
				}
			}
		}
	}()

	return stopChan, nil
}