github.com/moby/docker@v26.1.3+incompatible/libnetwork/store.go (about)

     1  package libnetwork
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/containerd/log"
     9  	"github.com/docker/docker/libnetwork/datastore"
    10  	"github.com/docker/docker/libnetwork/scope"
    11  )
    12  
    13  func (c *Controller) initStores() error {
    14  	if c.cfg == nil {
    15  		return nil
    16  	}
    17  	var err error
    18  	c.store, err = datastore.New(c.cfg.Scope)
    19  	if err != nil {
    20  		return err
    21  	}
    22  
    23  	return nil
    24  }
    25  
    26  func (c *Controller) closeStores() {
    27  	if store := c.store; store != nil {
    28  		store.Close()
    29  	}
    30  }
    31  
    32  func (c *Controller) getStore() *datastore.Store {
    33  	return c.store
    34  }
    35  
    36  func (c *Controller) getNetworkFromStore(nid string) (*Network, error) {
    37  	for _, n := range c.getNetworksFromStore(context.TODO()) {
    38  		if n.id == nid {
    39  			return n, nil
    40  		}
    41  	}
    42  	return nil, ErrNoSuchNetwork(nid)
    43  }
    44  
    45  func (c *Controller) getNetworks() ([]*Network, error) {
    46  	var nl []*Network
    47  
    48  	store := c.getStore()
    49  	if store == nil {
    50  		return nil, nil
    51  	}
    52  
    53  	kvol, err := store.List(&Network{ctrlr: c})
    54  	if err != nil && err != datastore.ErrKeyNotFound {
    55  		return nil, fmt.Errorf("failed to get networks: %w", err)
    56  	}
    57  
    58  	for _, kvo := range kvol {
    59  		n := kvo.(*Network)
    60  		n.ctrlr = c
    61  
    62  		ec := &endpointCnt{n: n}
    63  		err = store.GetObject(ec)
    64  		if err != nil && !n.inDelete {
    65  			log.G(context.TODO()).Warnf("Could not find endpoint count key %s for network %s while listing: %v", datastore.Key(ec.Key()...), n.Name(), err)
    66  			continue
    67  		}
    68  
    69  		n.epCnt = ec
    70  		if n.scope == "" {
    71  			n.scope = scope.Local
    72  		}
    73  		nl = append(nl, n)
    74  	}
    75  
    76  	return nl, nil
    77  }
    78  
    79  func (c *Controller) getNetworksFromStore(ctx context.Context) []*Network { // FIXME: unify with c.getNetworks()
    80  	var nl []*Network
    81  
    82  	store := c.getStore()
    83  	kvol, err := store.List(&Network{ctrlr: c})
    84  	if err != nil {
    85  		if err != datastore.ErrKeyNotFound {
    86  			log.G(ctx).Debugf("failed to get networks from store: %v", err)
    87  		}
    88  		return nil
    89  	}
    90  
    91  	kvep, err := store.Map(datastore.Key(epCntKeyPrefix), &endpointCnt{})
    92  	if err != nil && err != datastore.ErrKeyNotFound {
    93  		log.G(ctx).Warnf("failed to get endpoint_count map from store: %v", err)
    94  	}
    95  
    96  	for _, kvo := range kvol {
    97  		n := kvo.(*Network)
    98  		n.mu.Lock()
    99  		n.ctrlr = c
   100  		ec := &endpointCnt{n: n}
   101  		// Trim the leading & trailing "/" to make it consistent across all stores
   102  		if val, ok := kvep[strings.Trim(datastore.Key(ec.Key()...), "/")]; ok {
   103  			ec = val.(*endpointCnt)
   104  			ec.n = n
   105  			n.epCnt = ec
   106  		}
   107  		if n.scope == "" {
   108  			n.scope = scope.Local
   109  		}
   110  		n.mu.Unlock()
   111  		nl = append(nl, n)
   112  	}
   113  
   114  	return nl
   115  }
   116  
   117  func (n *Network) getEndpointFromStore(eid string) (*Endpoint, error) {
   118  	store := n.ctrlr.getStore()
   119  	ep := &Endpoint{id: eid, network: n}
   120  	err := store.GetObject(ep)
   121  	if err != nil {
   122  		return nil, fmt.Errorf("could not find endpoint %s: %w", eid, err)
   123  	}
   124  	return ep, nil
   125  }
   126  
   127  func (n *Network) getEndpointsFromStore() ([]*Endpoint, error) {
   128  	var epl []*Endpoint
   129  
   130  	store := n.getController().getStore()
   131  	kvol, err := store.List(&Endpoint{network: n})
   132  	if err != nil {
   133  		if err != datastore.ErrKeyNotFound {
   134  			return nil, fmt.Errorf("failed to get endpoints for network %s: %w",
   135  				n.Name(), err)
   136  		}
   137  		return nil, nil
   138  	}
   139  
   140  	for _, kvo := range kvol {
   141  		ep := kvo.(*Endpoint)
   142  		epl = append(epl, ep)
   143  	}
   144  
   145  	return epl, nil
   146  }
   147  
   148  func (c *Controller) updateToStore(kvObject datastore.KVObject) error {
   149  	cs := c.getStore()
   150  	if cs == nil {
   151  		return fmt.Errorf("datastore is not initialized")
   152  	}
   153  
   154  	if err := cs.PutObjectAtomic(kvObject); err != nil {
   155  		if err == datastore.ErrKeyModified {
   156  			return err
   157  		}
   158  		return fmt.Errorf("failed to update store for object type %T: %v", kvObject, err)
   159  	}
   160  
   161  	return nil
   162  }
   163  
   164  func (c *Controller) deleteFromStore(kvObject datastore.KVObject) error {
   165  	cs := c.getStore()
   166  	if cs == nil {
   167  		return fmt.Errorf("datastore is not initialized")
   168  	}
   169  
   170  retry:
   171  	if err := cs.DeleteObjectAtomic(kvObject); err != nil {
   172  		if err == datastore.ErrKeyModified {
   173  			if err := cs.GetObject(kvObject); err != nil {
   174  				return fmt.Errorf("could not update the kvobject to latest when trying to delete: %v", err)
   175  			}
   176  			log.G(context.TODO()).Warnf("Error (%v) deleting object %v, retrying....", err, kvObject.Key())
   177  			goto retry
   178  		}
   179  		return err
   180  	}
   181  
   182  	return nil
   183  }
   184  
   185  func (c *Controller) networkCleanup() {
   186  	for _, n := range c.getNetworksFromStore(context.TODO()) {
   187  		if n.inDelete {
   188  			log.G(context.TODO()).Infof("Removing stale network %s (%s)", n.Name(), n.ID())
   189  			if err := n.delete(true, true); err != nil {
   190  				log.G(context.TODO()).Debugf("Error while removing stale network: %v", err)
   191  			}
   192  		}
   193  	}
   194  }