github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/libnetwork/drivers/overlay/ov_serf.go (about)

     1  //go:build linux
     2  // +build linux
     3  
     4  package overlay
     5  
     6  import (
     7  	"fmt"
     8  	"net"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/hashicorp/serf/serf"
    13  	"github.com/sirupsen/logrus"
    14  )
    15  
    16  type ovNotify struct {
    17  	action string
    18  	ep     *endpoint
    19  	nw     *network
    20  }
    21  
    22  type logWriter struct{}
    23  
    24  func (l *logWriter) Write(p []byte) (int, error) {
    25  	str := string(p)
    26  
    27  	switch {
    28  	case strings.Contains(str, "[WARN]"):
    29  		logrus.Warn(str)
    30  	case strings.Contains(str, "[DEBUG]"):
    31  		logrus.Debug(str)
    32  	case strings.Contains(str, "[INFO]"):
    33  		logrus.Info(str)
    34  	case strings.Contains(str, "[ERR]"):
    35  		logrus.Error(str)
    36  	}
    37  
    38  	return len(p), nil
    39  }
    40  
    41  func (d *driver) serfInit() error {
    42  	var err error
    43  
    44  	config := serf.DefaultConfig()
    45  	config.Init()
    46  	config.MemberlistConfig.BindAddr = d.advertiseAddress
    47  
    48  	d.eventCh = make(chan serf.Event, 4)
    49  	config.EventCh = d.eventCh
    50  	config.UserCoalescePeriod = 1 * time.Second
    51  	config.UserQuiescentPeriod = 50 * time.Millisecond
    52  
    53  	config.LogOutput = &logWriter{}
    54  	config.MemberlistConfig.LogOutput = config.LogOutput
    55  
    56  	s, err := serf.Create(config)
    57  	if err != nil {
    58  		return fmt.Errorf("failed to create cluster node: %v", err)
    59  	}
    60  	defer func() {
    61  		if err != nil {
    62  			s.Shutdown()
    63  		}
    64  	}()
    65  
    66  	d.serfInstance = s
    67  
    68  	d.notifyCh = make(chan ovNotify)
    69  	d.exitCh = make(chan chan struct{})
    70  
    71  	go d.startSerfLoop(d.eventCh, d.notifyCh, d.exitCh)
    72  	return nil
    73  }
    74  
    75  func (d *driver) serfJoin(neighIP string) error {
    76  	if neighIP == "" {
    77  		return fmt.Errorf("no neighbor to join")
    78  	}
    79  	if _, err := d.serfInstance.Join([]string{neighIP}, true); err != nil {
    80  		return fmt.Errorf("Failed to join the cluster at neigh IP %s: %v",
    81  			neighIP, err)
    82  	}
    83  	return nil
    84  }
    85  
    86  func (d *driver) notifyEvent(event ovNotify) {
    87  	ep := event.ep
    88  
    89  	ePayload := fmt.Sprintf("%s %s %s %s", event.action, ep.addr.IP.String(),
    90  		net.IP(ep.addr.Mask).String(), ep.mac.String())
    91  	eName := fmt.Sprintf("jl %s %s %s", d.serfInstance.LocalMember().Addr.String(),
    92  		event.nw.id, ep.id)
    93  
    94  	if err := d.serfInstance.UserEvent(eName, []byte(ePayload), true); err != nil {
    95  		logrus.Errorf("Sending user event failed: %v\n", err)
    96  	}
    97  }
    98  
    99  func (d *driver) processEvent(u serf.UserEvent) {
   100  	logrus.Debugf("Received user event name:%s, payload:%s LTime:%d \n", u.Name,
   101  		string(u.Payload), uint64(u.LTime))
   102  
   103  	var dummy, action, vtepStr, nid, eid, ipStr, maskStr, macStr string
   104  	if _, err := fmt.Sscan(u.Name, &dummy, &vtepStr, &nid, &eid); err != nil {
   105  		fmt.Printf("Failed to scan name string: %v\n", err)
   106  	}
   107  
   108  	if _, err := fmt.Sscan(string(u.Payload), &action,
   109  		&ipStr, &maskStr, &macStr); err != nil {
   110  		fmt.Printf("Failed to scan value string: %v\n", err)
   111  	}
   112  
   113  	logrus.Debugf("Parsed data = %s/%s/%s/%s/%s/%s\n", nid, eid, vtepStr, ipStr, maskStr, macStr)
   114  
   115  	mac, err := net.ParseMAC(macStr)
   116  	if err != nil {
   117  		logrus.Errorf("Failed to parse mac: %v\n", err)
   118  	}
   119  
   120  	if d.serfInstance.LocalMember().Addr.String() == vtepStr {
   121  		return
   122  	}
   123  
   124  	switch action {
   125  	case "join":
   126  		d.peerAdd(nid, eid, net.ParseIP(ipStr), net.IPMask(net.ParseIP(maskStr).To4()), mac, net.ParseIP(vtepStr), false, false, false)
   127  	case "leave":
   128  		d.peerDelete(nid, eid, net.ParseIP(ipStr), net.IPMask(net.ParseIP(maskStr).To4()), mac, net.ParseIP(vtepStr), false)
   129  	}
   130  }
   131  
   132  func (d *driver) processQuery(q *serf.Query) {
   133  	logrus.Debugf("Received query name:%s, payload:%s\n", q.Name,
   134  		string(q.Payload))
   135  
   136  	var nid, ipStr string
   137  	if _, err := fmt.Sscan(string(q.Payload), &nid, &ipStr); err != nil {
   138  		fmt.Printf("Failed to scan query payload string: %v\n", err)
   139  	}
   140  
   141  	pKey, pEntry, err := d.peerDbSearch(nid, net.ParseIP(ipStr))
   142  	if err != nil {
   143  		return
   144  	}
   145  
   146  	logrus.Debugf("Sending peer query resp mac %v, mask %s, vtep %s", pKey.peerMac, net.IP(pEntry.peerIPMask).String(), pEntry.vtep)
   147  	q.Respond([]byte(fmt.Sprintf("%s %s %s", pKey.peerMac.String(), net.IP(pEntry.peerIPMask).String(), pEntry.vtep.String())))
   148  }
   149  
   150  func (d *driver) resolvePeer(nid string, peerIP net.IP) (net.HardwareAddr, net.IPMask, net.IP, error) {
   151  	if d.serfInstance == nil {
   152  		return nil, nil, nil, fmt.Errorf("could not resolve peer: serf instance not initialized")
   153  	}
   154  
   155  	qPayload := fmt.Sprintf("%s %s", nid, peerIP.String())
   156  	resp, err := d.serfInstance.Query("peerlookup", []byte(qPayload), nil)
   157  	if err != nil {
   158  		return nil, nil, nil, fmt.Errorf("resolving peer by querying the cluster failed: %v", err)
   159  	}
   160  
   161  	respCh := resp.ResponseCh()
   162  	select {
   163  	case r := <-respCh:
   164  		var macStr, maskStr, vtepStr string
   165  		if _, err := fmt.Sscan(string(r.Payload), &macStr, &maskStr, &vtepStr); err != nil {
   166  			return nil, nil, nil, fmt.Errorf("bad response %q for the resolve query: %v", string(r.Payload), err)
   167  		}
   168  
   169  		mac, err := net.ParseMAC(macStr)
   170  		if err != nil {
   171  			return nil, nil, nil, fmt.Errorf("failed to parse mac: %v", err)
   172  		}
   173  
   174  		logrus.Debugf("Received peer query response, mac %s, vtep %s, mask %s", macStr, vtepStr, maskStr)
   175  		return mac, net.IPMask(net.ParseIP(maskStr).To4()), net.ParseIP(vtepStr), nil
   176  
   177  	case <-time.After(time.Second):
   178  		return nil, nil, nil, fmt.Errorf("timed out resolving peer by querying the cluster")
   179  	}
   180  }
   181  
   182  func (d *driver) startSerfLoop(eventCh chan serf.Event, notifyCh chan ovNotify, exitCh chan chan struct{}) {
   183  	for {
   184  		select {
   185  		case notify, ok := <-notifyCh:
   186  			if !ok {
   187  				break
   188  			}
   189  
   190  			d.notifyEvent(notify)
   191  		case ch, ok := <-exitCh:
   192  			if !ok {
   193  				break
   194  			}
   195  
   196  			if err := d.serfInstance.Leave(); err != nil {
   197  				logrus.Errorf("failed leaving the cluster: %v\n", err)
   198  			}
   199  
   200  			d.serfInstance.Shutdown()
   201  			close(ch)
   202  			return
   203  		case e, ok := <-eventCh:
   204  			if !ok {
   205  				break
   206  			}
   207  
   208  			if e.EventType() == serf.EventQuery {
   209  				d.processQuery(e.(*serf.Query))
   210  				break
   211  			}
   212  
   213  			u, ok := e.(serf.UserEvent)
   214  			if !ok {
   215  				break
   216  			}
   217  			d.processEvent(u)
   218  		}
   219  	}
   220  }
   221  
   222  func (d *driver) isSerfAlive() bool {
   223  	d.Lock()
   224  	serfInstance := d.serfInstance
   225  	d.Unlock()
   226  	if serfInstance == nil || serfInstance.State() != serf.SerfAlive {
   227  		return false
   228  	}
   229  	return true
   230  }