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