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