Beispiel #1
0
// Campaign handles leader election. Basically this just acquires a lock on the LeadershipKey and whoever gets the lock
// is the leader. A re-election occurs when there are changes in the LeadershipKey.
func (c *Candidate) campaign() {
	c.retrieveNode()
	c.retrieveSession()
	consul := c.consulClient()

	logrus.Debugf("%s is running for election with session %s.", c.node, c.session)

	kvpair := &consulapi.KVPair{
		Key:     c.LeadershipKey,
		Value:   []byte(c.node),
		Session: c.session,
	}
	acquired, _, err := consul.KV().Acquire(kvpair, nil)
	if err != nil {
		logrus.Errorln("Failed to run Consul KV Acquire:", err)
	}

	if acquired {
		logrus.Infof("%s has become the leader.", c.node)
	}

	kv, _, _ := consul.KV().Get(c.LeadershipKey, nil)

	if kv != nil && kv.Session != "" {
		logrus.Debugf("%s is the current leader.", string(kv.Value))
		logrus.Debugf("%s is waiting for changes in '%s'.", c.node, c.LeadershipKey)
		latestIndex := kv.ModifyIndex
		options := &consulapi.QueryOptions{
			WaitIndex: latestIndex,
		}
		consul.KV().Get(c.LeadershipKey, options)
	}
	time.Sleep(15 * time.Second)
	c.campaign()
}
Beispiel #2
0
// IsLeader returns true if the current agent is the leader.
func (c *Candidate) IsLeader() bool {
	consul := c.consulClient()
	c.retrieveNode()
	c.retrieveSession()
	kv, _, err := consul.KV().Get(c.LeadershipKey, nil)
	if err != nil {
		logrus.Errorln("Unable to check for leadership:", err)
		return false
	}
	if kv == nil {
		logrus.Warnf("Leadership key '%s' is missing in Consuk KV.", c.LeadershipKey)
		return false
	}
	return c.node == string(kv.Value) && c.session == kv.Session
}
Beispiel #3
0
// RetrieveSession retrieves the existing session needed to run leader election. If a session does not exist, a new
// session is created with the LeadershipKey as the name.
func (c *Candidate) retrieveSession() {
	consul := c.consulClient()

	if sessions, _, err := consul.Session().List(nil); err != nil {
		logrus.Warnln("Unable to retrieve list of sessions.")
	} else {
		for _, session := range sessions {
			if session.Name == c.LeadershipKey && session.Node == c.node {
				c.session = session.ID
				return
			}
		}
	}

	newSession := &consulapi.SessionEntry{
		Name: c.LeadershipKey,
	}
	if sessionId, _, err := consul.Session().Create(newSession, nil); err != nil {
		logrus.Errorln("Unable to create new sessions:", err)
	} else {
		c.session = sessionId
	}
}