github.com/rawahars/moby@v24.0.4+incompatible/libnetwork/sandbox_store.go (about)

     1  package libnetwork
     2  
     3  import (
     4  	"encoding/json"
     5  	"sync"
     6  
     7  	"github.com/docker/docker/libnetwork/datastore"
     8  	"github.com/docker/docker/libnetwork/osl"
     9  	"github.com/sirupsen/logrus"
    10  )
    11  
    12  const (
    13  	sandboxPrefix = "sandbox"
    14  )
    15  
    16  type epState struct {
    17  	Eid string
    18  	Nid string
    19  }
    20  
    21  type sbState struct {
    22  	ID         string
    23  	Cid        string
    24  	c          *Controller
    25  	dbIndex    uint64
    26  	dbExists   bool
    27  	Eps        []epState
    28  	EpPriority map[string]int
    29  	// external servers have to be persisted so that on restart of a live-restore
    30  	// enabled daemon we get the external servers for the running containers.
    31  	//
    32  	// It is persisted as "ExtDNS2" for historical reasons. ExtDNS2 was used to
    33  	// handle migration between docker < 1.14 and >= 1.14. Before version 1.14 we
    34  	// used ExtDNS but with a []string. As it's unlikely that installations still
    35  	// have state from before 1.14, we've dropped the migration code.
    36  	ExtDNS []extDNSEntry `json:"ExtDNS2"`
    37  }
    38  
    39  func (sbs *sbState) Key() []string {
    40  	return []string{sandboxPrefix, sbs.ID}
    41  }
    42  
    43  func (sbs *sbState) KeyPrefix() []string {
    44  	return []string{sandboxPrefix}
    45  }
    46  
    47  func (sbs *sbState) Value() []byte {
    48  	b, err := json.Marshal(sbs)
    49  	if err != nil {
    50  		return nil
    51  	}
    52  	return b
    53  }
    54  
    55  func (sbs *sbState) SetValue(value []byte) error {
    56  	return json.Unmarshal(value, sbs)
    57  }
    58  
    59  func (sbs *sbState) Index() uint64 {
    60  	sb, err := sbs.c.SandboxByID(sbs.ID)
    61  	if err != nil {
    62  		return sbs.dbIndex
    63  	}
    64  
    65  	maxIndex := sb.dbIndex
    66  	if sbs.dbIndex > maxIndex {
    67  		maxIndex = sbs.dbIndex
    68  	}
    69  
    70  	return maxIndex
    71  }
    72  
    73  func (sbs *sbState) SetIndex(index uint64) {
    74  	sbs.dbIndex = index
    75  	sbs.dbExists = true
    76  
    77  	sb, err := sbs.c.SandboxByID(sbs.ID)
    78  	if err != nil {
    79  		return
    80  	}
    81  
    82  	sb.dbIndex = index
    83  	sb.dbExists = true
    84  }
    85  
    86  func (sbs *sbState) Exists() bool {
    87  	if sbs.dbExists {
    88  		return sbs.dbExists
    89  	}
    90  
    91  	sb, err := sbs.c.SandboxByID(sbs.ID)
    92  	if err != nil {
    93  		return false
    94  	}
    95  
    96  	return sb.dbExists
    97  }
    98  
    99  func (sbs *sbState) Skip() bool {
   100  	return false
   101  }
   102  
   103  func (sbs *sbState) New() datastore.KVObject {
   104  	return &sbState{c: sbs.c}
   105  }
   106  
   107  func (sbs *sbState) CopyTo(o datastore.KVObject) error {
   108  	dstSbs := o.(*sbState)
   109  	dstSbs.c = sbs.c
   110  	dstSbs.ID = sbs.ID
   111  	dstSbs.Cid = sbs.Cid
   112  	dstSbs.dbIndex = sbs.dbIndex
   113  	dstSbs.dbExists = sbs.dbExists
   114  	dstSbs.EpPriority = sbs.EpPriority
   115  
   116  	dstSbs.Eps = append(dstSbs.Eps, sbs.Eps...)
   117  	dstSbs.ExtDNS = append(dstSbs.ExtDNS, sbs.ExtDNS...)
   118  
   119  	return nil
   120  }
   121  
   122  func (sbs *sbState) DataScope() string {
   123  	return datastore.LocalScope
   124  }
   125  
   126  func (sb *Sandbox) storeUpdate() error {
   127  	sbs := &sbState{
   128  		c:          sb.controller,
   129  		ID:         sb.id,
   130  		Cid:        sb.containerID,
   131  		EpPriority: sb.epPriority,
   132  		ExtDNS:     sb.extDNS,
   133  	}
   134  
   135  retry:
   136  	sbs.Eps = nil
   137  	for _, ep := range sb.Endpoints() {
   138  		// If the endpoint is not persisted then do not add it to
   139  		// the sandbox checkpoint
   140  		if ep.Skip() {
   141  			continue
   142  		}
   143  
   144  		eps := epState{
   145  			Nid: ep.getNetwork().ID(),
   146  			Eid: ep.ID(),
   147  		}
   148  
   149  		sbs.Eps = append(sbs.Eps, eps)
   150  	}
   151  
   152  	err := sb.controller.updateToStore(sbs)
   153  	if err == datastore.ErrKeyModified {
   154  		// When we get ErrKeyModified it is sufficient to just
   155  		// go back and retry.  No need to get the object from
   156  		// the store because we always regenerate the store
   157  		// state from in memory sandbox state
   158  		goto retry
   159  	}
   160  
   161  	return err
   162  }
   163  
   164  func (sb *Sandbox) storeDelete() error {
   165  	sbs := &sbState{
   166  		c:        sb.controller,
   167  		ID:       sb.id,
   168  		Cid:      sb.containerID,
   169  		dbIndex:  sb.dbIndex,
   170  		dbExists: sb.dbExists,
   171  	}
   172  
   173  	return sb.controller.deleteFromStore(sbs)
   174  }
   175  
   176  func (c *Controller) sandboxCleanup(activeSandboxes map[string]interface{}) {
   177  	store := c.getStore()
   178  	if store == nil {
   179  		logrus.Error("Could not find local scope store while trying to cleanup sandboxes")
   180  		return
   181  	}
   182  
   183  	kvol, err := store.List(datastore.Key(sandboxPrefix), &sbState{c: c})
   184  	if err != nil && err != datastore.ErrKeyNotFound {
   185  		logrus.Errorf("failed to get sandboxes for scope %s: %v", store.Scope(), err)
   186  		return
   187  	}
   188  
   189  	// It's normal for no sandboxes to be found. Just bail out.
   190  	if err == datastore.ErrKeyNotFound {
   191  		return
   192  	}
   193  
   194  	for _, kvo := range kvol {
   195  		sbs := kvo.(*sbState)
   196  
   197  		sb := &Sandbox{
   198  			id:                 sbs.ID,
   199  			controller:         sbs.c,
   200  			containerID:        sbs.Cid,
   201  			extDNS:             sbs.ExtDNS,
   202  			endpoints:          []*Endpoint{},
   203  			populatedEndpoints: map[string]struct{}{},
   204  			dbIndex:            sbs.dbIndex,
   205  			isStub:             true,
   206  			dbExists:           true,
   207  		}
   208  
   209  		msg := " for cleanup"
   210  		create := true
   211  		isRestore := false
   212  		if val, ok := activeSandboxes[sb.ID()]; ok {
   213  			msg = ""
   214  			sb.isStub = false
   215  			isRestore = true
   216  			opts := val.([]SandboxOption)
   217  			sb.processOptions(opts...)
   218  			sb.restorePath()
   219  			create = !sb.config.useDefaultSandBox
   220  		}
   221  		sb.osSbox, err = osl.NewSandbox(sb.Key(), create, isRestore)
   222  		if err != nil {
   223  			logrus.Errorf("failed to create osl sandbox while trying to restore sandbox %.7s%s: %v", sb.ID(), msg, err)
   224  			continue
   225  		}
   226  
   227  		c.mu.Lock()
   228  		c.sandboxes[sb.id] = sb
   229  		c.mu.Unlock()
   230  
   231  		for _, eps := range sbs.Eps {
   232  			n, err := c.getNetworkFromStore(eps.Nid)
   233  			var ep *Endpoint
   234  			if err != nil {
   235  				logrus.Errorf("getNetworkFromStore for nid %s failed while trying to build sandbox for cleanup: %v", eps.Nid, err)
   236  				n = &network{id: eps.Nid, ctrlr: c, drvOnce: &sync.Once{}, persist: true}
   237  				ep = &Endpoint{id: eps.Eid, network: n, sandboxID: sbs.ID}
   238  			} else {
   239  				ep, err = n.getEndpointFromStore(eps.Eid)
   240  				if err != nil {
   241  					logrus.Errorf("getEndpointFromStore for eid %s failed while trying to build sandbox for cleanup: %v", eps.Eid, err)
   242  					ep = &Endpoint{id: eps.Eid, network: n, sandboxID: sbs.ID}
   243  				}
   244  			}
   245  			if _, ok := activeSandboxes[sb.ID()]; ok && err != nil {
   246  				logrus.Errorf("failed to restore endpoint %s in %s for container %s due to %v", eps.Eid, eps.Nid, sb.ContainerID(), err)
   247  				continue
   248  			}
   249  			sb.addEndpoint(ep)
   250  		}
   251  
   252  		if _, ok := activeSandboxes[sb.ID()]; !ok {
   253  			logrus.Infof("Removing stale sandbox %s (%s)", sb.id, sb.containerID)
   254  			if err := sb.delete(true); err != nil {
   255  				logrus.Errorf("Failed to delete sandbox %s while trying to cleanup: %v", sb.id, err)
   256  			}
   257  			continue
   258  		}
   259  
   260  		// reconstruct osl sandbox field
   261  		if !sb.config.useDefaultSandBox {
   262  			if err := sb.restoreOslSandbox(); err != nil {
   263  				logrus.Errorf("failed to populate fields for osl sandbox %s: %v", sb.ID(), err)
   264  				continue
   265  			}
   266  		} else {
   267  			c.sboxOnce.Do(func() {
   268  				c.defOsSbox = sb.osSbox
   269  			})
   270  		}
   271  
   272  		for _, ep := range sb.endpoints {
   273  			// Watch for service records
   274  			if !c.isAgent() {
   275  				c.watchSvcRecord(ep)
   276  			}
   277  		}
   278  	}
   279  }