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  }