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  }