github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/libnetwork/store.go (about) 1 package libnetwork 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/docker/libkv/store/boltdb" 8 "github.com/docker/libkv/store/consul" 9 "github.com/docker/libkv/store/etcd" 10 "github.com/docker/libkv/store/zookeeper" 11 "github.com/docker/libnetwork/datastore" 12 "github.com/sirupsen/logrus" 13 ) 14 15 func registerKVStores() { 16 consul.Register() 17 zookeeper.Register() 18 etcd.Register() 19 boltdb.Register() 20 } 21 22 func (c *controller) initScopedStore(scope string, scfg *datastore.ScopeCfg) error { 23 store, err := datastore.NewDataStore(scope, scfg) 24 if err != nil { 25 return err 26 } 27 c.Lock() 28 c.stores = append(c.stores, store) 29 c.Unlock() 30 31 return nil 32 } 33 34 func (c *controller) initStores() error { 35 registerKVStores() 36 37 c.Lock() 38 if c.cfg == nil { 39 c.Unlock() 40 return nil 41 } 42 scopeConfigs := c.cfg.Scopes 43 c.stores = nil 44 c.Unlock() 45 46 for scope, scfg := range scopeConfigs { 47 if err := c.initScopedStore(scope, scfg); err != nil { 48 return err 49 } 50 } 51 52 c.startWatch() 53 return nil 54 } 55 56 func (c *controller) closeStores() { 57 for _, store := range c.getStores() { 58 store.Close() 59 } 60 } 61 62 func (c *controller) getStore(scope string) datastore.DataStore { 63 c.Lock() 64 defer c.Unlock() 65 66 for _, store := range c.stores { 67 if store.Scope() == scope { 68 return store 69 } 70 } 71 72 return nil 73 } 74 75 func (c *controller) getStores() []datastore.DataStore { 76 c.Lock() 77 defer c.Unlock() 78 79 return c.stores 80 } 81 82 func (c *controller) getNetworkFromStore(nid string) (*network, error) { 83 for _, n := range c.getNetworksFromStore() { 84 if n.id == nid { 85 return n, nil 86 } 87 } 88 return nil, ErrNoSuchNetwork(nid) 89 } 90 91 func (c *controller) getNetworksForScope(scope string) ([]*network, error) { 92 var nl []*network 93 94 store := c.getStore(scope) 95 if store == nil { 96 return nil, nil 97 } 98 99 kvol, err := store.List(datastore.Key(datastore.NetworkKeyPrefix), 100 &network{ctrlr: c}) 101 if err != nil && err != datastore.ErrKeyNotFound { 102 return nil, fmt.Errorf("failed to get networks for scope %s: %v", 103 scope, err) 104 } 105 106 for _, kvo := range kvol { 107 n := kvo.(*network) 108 n.ctrlr = c 109 110 ec := &endpointCnt{n: n} 111 err = store.GetObject(datastore.Key(ec.Key()...), ec) 112 if err != nil && !n.inDelete { 113 logrus.Warnf("Could not find endpoint count key %s for network %s while listing: %v", datastore.Key(ec.Key()...), n.Name(), err) 114 continue 115 } 116 117 n.epCnt = ec 118 if n.scope == "" { 119 n.scope = scope 120 } 121 nl = append(nl, n) 122 } 123 124 return nl, nil 125 } 126 127 func (c *controller) getNetworksFromStore() []*network { 128 var nl []*network 129 130 for _, store := range c.getStores() { 131 kvol, err := store.List(datastore.Key(datastore.NetworkKeyPrefix), &network{ctrlr: c}) 132 // Continue searching in the next store if no keys found in this store 133 if err != nil { 134 if err != datastore.ErrKeyNotFound { 135 logrus.Debugf("failed to get networks for scope %s: %v", store.Scope(), err) 136 } 137 continue 138 } 139 140 kvep, err := store.Map(datastore.Key(epCntKeyPrefix), &endpointCnt{}) 141 if err != nil && err != datastore.ErrKeyNotFound { 142 logrus.Warnf("failed to get endpoint_count map for scope %s: %v", store.Scope(), err) 143 } 144 145 for _, kvo := range kvol { 146 n := kvo.(*network) 147 n.Lock() 148 n.ctrlr = c 149 ec := &endpointCnt{n: n} 150 // Trim the leading & trailing "/" to make it consistent across all stores 151 if val, ok := kvep[strings.Trim(datastore.Key(ec.Key()...), "/")]; ok { 152 ec = val.(*endpointCnt) 153 ec.n = n 154 n.epCnt = ec 155 } 156 if n.scope == "" { 157 n.scope = store.Scope() 158 } 159 n.Unlock() 160 nl = append(nl, n) 161 } 162 } 163 164 return nl 165 } 166 167 func (n *network) getEndpointFromStore(eid string) (*endpoint, error) { 168 var errors []string 169 for _, store := range n.ctrlr.getStores() { 170 ep := &endpoint{id: eid, network: n} 171 err := store.GetObject(datastore.Key(ep.Key()...), ep) 172 // Continue searching in the next store if the key is not found in this store 173 if err != nil { 174 if err != datastore.ErrKeyNotFound { 175 errors = append(errors, fmt.Sprintf("{%s:%v}, ", store.Scope(), err)) 176 logrus.Debugf("could not find endpoint %s in %s: %v", eid, store.Scope(), err) 177 } 178 continue 179 } 180 return ep, nil 181 } 182 return nil, fmt.Errorf("could not find endpoint %s: %v", eid, errors) 183 } 184 185 func (n *network) getEndpointsFromStore() ([]*endpoint, error) { 186 var epl []*endpoint 187 188 tmp := endpoint{network: n} 189 for _, store := range n.getController().getStores() { 190 kvol, err := store.List(datastore.Key(tmp.KeyPrefix()...), &endpoint{network: n}) 191 // Continue searching in the next store if no keys found in this store 192 if err != nil { 193 if err != datastore.ErrKeyNotFound { 194 logrus.Debugf("failed to get endpoints for network %s scope %s: %v", 195 n.Name(), store.Scope(), err) 196 } 197 continue 198 } 199 200 for _, kvo := range kvol { 201 ep := kvo.(*endpoint) 202 epl = append(epl, ep) 203 } 204 } 205 206 return epl, nil 207 } 208 209 func (c *controller) updateToStore(kvObject datastore.KVObject) error { 210 cs := c.getStore(kvObject.DataScope()) 211 if cs == nil { 212 return ErrDataStoreNotInitialized(kvObject.DataScope()) 213 } 214 215 if err := cs.PutObjectAtomic(kvObject); err != nil { 216 if err == datastore.ErrKeyModified { 217 return err 218 } 219 return fmt.Errorf("failed to update store for object type %T: %v", kvObject, err) 220 } 221 222 return nil 223 } 224 225 func (c *controller) deleteFromStore(kvObject datastore.KVObject) error { 226 cs := c.getStore(kvObject.DataScope()) 227 if cs == nil { 228 return ErrDataStoreNotInitialized(kvObject.DataScope()) 229 } 230 231 retry: 232 if err := cs.DeleteObjectAtomic(kvObject); err != nil { 233 if err == datastore.ErrKeyModified { 234 if err := cs.GetObject(datastore.Key(kvObject.Key()...), kvObject); err != nil { 235 return fmt.Errorf("could not update the kvobject to latest when trying to delete: %v", err) 236 } 237 logrus.Warnf("Error (%v) deleting object %v, retrying....", err, kvObject.Key()) 238 goto retry 239 } 240 return err 241 } 242 243 return nil 244 } 245 246 type netWatch struct { 247 localEps map[string]*endpoint 248 remoteEps map[string]*endpoint 249 stopCh chan struct{} 250 } 251 252 func (c *controller) getLocalEps(nw *netWatch) []*endpoint { 253 c.Lock() 254 defer c.Unlock() 255 256 var epl []*endpoint 257 for _, ep := range nw.localEps { 258 epl = append(epl, ep) 259 } 260 261 return epl 262 } 263 264 func (c *controller) watchSvcRecord(ep *endpoint) { 265 c.watchCh <- ep 266 } 267 268 func (c *controller) unWatchSvcRecord(ep *endpoint) { 269 c.unWatchCh <- ep 270 } 271 272 func (c *controller) networkWatchLoop(nw *netWatch, ep *endpoint, ecCh <-chan datastore.KVObject) { 273 for { 274 select { 275 case <-nw.stopCh: 276 return 277 case o := <-ecCh: 278 ec := o.(*endpointCnt) 279 280 epl, err := ec.n.getEndpointsFromStore() 281 if err != nil { 282 break 283 } 284 285 c.Lock() 286 var addEp []*endpoint 287 288 delEpMap := make(map[string]*endpoint) 289 renameEpMap := make(map[string]bool) 290 for k, v := range nw.remoteEps { 291 delEpMap[k] = v 292 } 293 294 for _, lEp := range epl { 295 if _, ok := nw.localEps[lEp.ID()]; ok { 296 continue 297 } 298 299 if ep, ok := nw.remoteEps[lEp.ID()]; ok { 300 // On a container rename EP ID will remain 301 // the same but the name will change. service 302 // records should reflect the change. 303 // Keep old EP entry in the delEpMap and add 304 // EP from the store (which has the new name) 305 // into the new list 306 if lEp.name == ep.name { 307 delete(delEpMap, lEp.ID()) 308 continue 309 } 310 renameEpMap[lEp.ID()] = true 311 } 312 nw.remoteEps[lEp.ID()] = lEp 313 addEp = append(addEp, lEp) 314 } 315 316 // EPs whose name are to be deleted from the svc records 317 // should also be removed from nw's remote EP list, except 318 // the ones that are getting renamed. 319 for _, lEp := range delEpMap { 320 if !renameEpMap[lEp.ID()] { 321 delete(nw.remoteEps, lEp.ID()) 322 } 323 } 324 c.Unlock() 325 326 for _, lEp := range delEpMap { 327 ep.getNetwork().updateSvcRecord(lEp, c.getLocalEps(nw), false) 328 329 } 330 for _, lEp := range addEp { 331 ep.getNetwork().updateSvcRecord(lEp, c.getLocalEps(nw), true) 332 } 333 } 334 } 335 } 336 337 func (c *controller) processEndpointCreate(nmap map[string]*netWatch, ep *endpoint) { 338 n := ep.getNetwork() 339 if !c.isDistributedControl() && n.Scope() == datastore.SwarmScope && n.driverIsMultihost() { 340 return 341 } 342 343 networkID := n.ID() 344 endpointID := ep.ID() 345 346 c.Lock() 347 nw, ok := nmap[networkID] 348 c.Unlock() 349 350 if ok { 351 // Update the svc db for the local endpoint join right away 352 n.updateSvcRecord(ep, c.getLocalEps(nw), true) 353 354 c.Lock() 355 nw.localEps[endpointID] = ep 356 357 // If we had learned that from the kv store remove it 358 // from remote ep list now that we know that this is 359 // indeed a local endpoint 360 delete(nw.remoteEps, endpointID) 361 c.Unlock() 362 return 363 } 364 365 nw = &netWatch{ 366 localEps: make(map[string]*endpoint), 367 remoteEps: make(map[string]*endpoint), 368 } 369 370 // Update the svc db for the local endpoint join right away 371 // Do this before adding this ep to localEps so that we don't 372 // try to update this ep's container's svc records 373 n.updateSvcRecord(ep, c.getLocalEps(nw), true) 374 375 c.Lock() 376 nw.localEps[endpointID] = ep 377 nmap[networkID] = nw 378 nw.stopCh = make(chan struct{}) 379 c.Unlock() 380 381 store := c.getStore(n.DataScope()) 382 if store == nil { 383 return 384 } 385 386 if !store.Watchable() { 387 return 388 } 389 390 ch, err := store.Watch(n.getEpCnt(), nw.stopCh) 391 if err != nil { 392 logrus.Warnf("Error creating watch for network: %v", err) 393 return 394 } 395 396 go c.networkWatchLoop(nw, ep, ch) 397 } 398 399 func (c *controller) processEndpointDelete(nmap map[string]*netWatch, ep *endpoint) { 400 n := ep.getNetwork() 401 if !c.isDistributedControl() && n.Scope() == datastore.SwarmScope && n.driverIsMultihost() { 402 return 403 } 404 405 c.Lock() 406 nw, ok := nmap[n.ID()] 407 408 if ok { 409 delete(nw.localEps, ep.ID()) 410 c.Unlock() 411 412 // Update the svc db about local endpoint leave right away 413 // Do this after we remove this ep from localEps so that we 414 // don't try to remove this svc record from this ep's container. 415 n.updateSvcRecord(ep, c.getLocalEps(nw), false) 416 417 c.Lock() 418 if len(nw.localEps) == 0 { 419 close(nw.stopCh) 420 421 // This is the last container going away for the network. Destroy 422 // this network's svc db entry 423 delete(c.svcRecords, n.ID()) 424 425 delete(nmap, n.ID()) 426 } 427 } 428 c.Unlock() 429 } 430 431 func (c *controller) watchLoop() { 432 for { 433 select { 434 case ep := <-c.watchCh: 435 c.processEndpointCreate(c.nmap, ep) 436 case ep := <-c.unWatchCh: 437 c.processEndpointDelete(c.nmap, ep) 438 } 439 } 440 } 441 442 func (c *controller) startWatch() { 443 if c.watchCh != nil { 444 return 445 } 446 c.watchCh = make(chan *endpoint) 447 c.unWatchCh = make(chan *endpoint) 448 c.nmap = make(map[string]*netWatch) 449 450 go c.watchLoop() 451 } 452 453 func (c *controller) networkCleanup() { 454 for _, n := range c.getNetworksFromStore() { 455 if n.inDelete { 456 logrus.Infof("Removing stale network %s (%s)", n.Name(), n.ID()) 457 if err := n.delete(true, true); err != nil { 458 logrus.Debugf("Error while removing stale network: %v", err) 459 } 460 } 461 } 462 } 463 464 var populateSpecial NetworkWalker = func(nw Network) bool { 465 if n := nw.(*network); n.hasSpecialDriver() && !n.ConfigOnly() { 466 if err := n.getController().addNetwork(n); err != nil { 467 logrus.Warnf("Failed to populate network %q with driver %q", nw.Name(), nw.Type()) 468 } 469 } 470 return false 471 }