github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/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  	// We have two versions of ExtDNS to support upgrade & downgrade of the daemon
    32  	// between >=1.14 and <1.14 versions.
    33  	ExtDNS  []string
    34  	ExtDNS2 []extDNSEntry
    35  }
    36  
    37  func (sbs *sbState) Key() []string {
    38  	return []string{sandboxPrefix, sbs.ID}
    39  }
    40  
    41  func (sbs *sbState) KeyPrefix() []string {
    42  	return []string{sandboxPrefix}
    43  }
    44  
    45  func (sbs *sbState) Value() []byte {
    46  	b, err := json.Marshal(sbs)
    47  	if err != nil {
    48  		return nil
    49  	}
    50  	return b
    51  }
    52  
    53  func (sbs *sbState) SetValue(value []byte) error {
    54  	return json.Unmarshal(value, sbs)
    55  }
    56  
    57  func (sbs *sbState) Index() uint64 {
    58  	sbi, err := sbs.c.SandboxByID(sbs.ID)
    59  	if err != nil {
    60  		return sbs.dbIndex
    61  	}
    62  
    63  	sb := sbi.(*sandbox)
    64  	maxIndex := sb.dbIndex
    65  	if sbs.dbIndex > maxIndex {
    66  		maxIndex = sbs.dbIndex
    67  	}
    68  
    69  	return maxIndex
    70  }
    71  
    72  func (sbs *sbState) SetIndex(index uint64) {
    73  	sbs.dbIndex = index
    74  	sbs.dbExists = true
    75  
    76  	sbi, err := sbs.c.SandboxByID(sbs.ID)
    77  	if err != nil {
    78  		return
    79  	}
    80  
    81  	sb := sbi.(*sandbox)
    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  	sbi, err := sbs.c.SandboxByID(sbs.ID)
    92  	if err != nil {
    93  		return false
    94  	}
    95  
    96  	sb := sbi.(*sandbox)
    97  	return sb.dbExists
    98  }
    99  
   100  func (sbs *sbState) Skip() bool {
   101  	return false
   102  }
   103  
   104  func (sbs *sbState) New() datastore.KVObject {
   105  	return &sbState{c: sbs.c}
   106  }
   107  
   108  func (sbs *sbState) CopyTo(o datastore.KVObject) error {
   109  	dstSbs := o.(*sbState)
   110  	dstSbs.c = sbs.c
   111  	dstSbs.ID = sbs.ID
   112  	dstSbs.Cid = sbs.Cid
   113  	dstSbs.dbIndex = sbs.dbIndex
   114  	dstSbs.dbExists = sbs.dbExists
   115  	dstSbs.EpPriority = sbs.EpPriority
   116  
   117  	dstSbs.Eps = append(dstSbs.Eps, sbs.Eps...)
   118  
   119  	if len(sbs.ExtDNS2) > 0 {
   120  		for _, dns := range sbs.ExtDNS2 {
   121  			dstSbs.ExtDNS2 = append(dstSbs.ExtDNS2, dns)
   122  			dstSbs.ExtDNS = append(dstSbs.ExtDNS, dns.IPStr)
   123  		}
   124  		return nil
   125  	}
   126  	for _, dns := range sbs.ExtDNS {
   127  		dstSbs.ExtDNS = append(dstSbs.ExtDNS, dns)
   128  		dstSbs.ExtDNS2 = append(dstSbs.ExtDNS2, extDNSEntry{IPStr: dns})
   129  	}
   130  
   131  	return nil
   132  }
   133  
   134  func (sbs *sbState) DataScope() string {
   135  	return datastore.LocalScope
   136  }
   137  
   138  func (sb *sandbox) storeUpdate() error {
   139  	sbs := &sbState{
   140  		c:          sb.controller,
   141  		ID:         sb.id,
   142  		Cid:        sb.containerID,
   143  		EpPriority: sb.epPriority,
   144  		ExtDNS2:    sb.extDNS,
   145  	}
   146  
   147  	for _, ext := range sb.extDNS {
   148  		sbs.ExtDNS = append(sbs.ExtDNS, ext.IPStr)
   149  	}
   150  
   151  retry:
   152  	sbs.Eps = nil
   153  	for _, ep := range sb.getConnectedEndpoints() {
   154  		// If the endpoint is not persisted then do not add it to
   155  		// the sandbox checkpoint
   156  		if ep.Skip() {
   157  			continue
   158  		}
   159  
   160  		eps := epState{
   161  			Nid: ep.getNetwork().ID(),
   162  			Eid: ep.ID(),
   163  		}
   164  
   165  		sbs.Eps = append(sbs.Eps, eps)
   166  	}
   167  
   168  	err := sb.controller.updateToStore(sbs)
   169  	if err == datastore.ErrKeyModified {
   170  		// When we get ErrKeyModified it is sufficient to just
   171  		// go back and retry.  No need to get the object from
   172  		// the store because we always regenerate the store
   173  		// state from in memory sandbox state
   174  		goto retry
   175  	}
   176  
   177  	return err
   178  }
   179  
   180  func (sb *sandbox) storeDelete() error {
   181  	sbs := &sbState{
   182  		c:        sb.controller,
   183  		ID:       sb.id,
   184  		Cid:      sb.containerID,
   185  		dbIndex:  sb.dbIndex,
   186  		dbExists: sb.dbExists,
   187  	}
   188  
   189  	return sb.controller.deleteFromStore(sbs)
   190  }
   191  
   192  func (c *controller) sandboxCleanup(activeSandboxes map[string]interface{}) {
   193  	store := c.getStore(datastore.LocalScope)
   194  	if store == nil {
   195  		logrus.Error("Could not find local scope store while trying to cleanup sandboxes")
   196  		return
   197  	}
   198  
   199  	kvol, err := store.List(datastore.Key(sandboxPrefix), &sbState{c: c})
   200  	if err != nil && err != datastore.ErrKeyNotFound {
   201  		logrus.Errorf("failed to get sandboxes for scope %s: %v", store.Scope(), err)
   202  		return
   203  	}
   204  
   205  	// It's normal for no sandboxes to be found. Just bail out.
   206  	if err == datastore.ErrKeyNotFound {
   207  		return
   208  	}
   209  
   210  	for _, kvo := range kvol {
   211  		sbs := kvo.(*sbState)
   212  
   213  		sb := &sandbox{
   214  			id:                 sbs.ID,
   215  			controller:         sbs.c,
   216  			containerID:        sbs.Cid,
   217  			endpoints:          []*endpoint{},
   218  			populatedEndpoints: map[string]struct{}{},
   219  			dbIndex:            sbs.dbIndex,
   220  			isStub:             true,
   221  			dbExists:           true,
   222  		}
   223  		// If we are restoring from a older version extDNSEntry won't have the
   224  		// HostLoopback field
   225  		if len(sbs.ExtDNS2) > 0 {
   226  			sb.extDNS = sbs.ExtDNS2
   227  		} else {
   228  			for _, dns := range sbs.ExtDNS {
   229  				sb.extDNS = append(sb.extDNS, extDNSEntry{IPStr: dns})
   230  			}
   231  		}
   232  
   233  		msg := " for cleanup"
   234  		create := true
   235  		isRestore := false
   236  		if val, ok := activeSandboxes[sb.ID()]; ok {
   237  			msg = ""
   238  			sb.isStub = false
   239  			isRestore = true
   240  			opts := val.([]SandboxOption)
   241  			sb.processOptions(opts...)
   242  			sb.restorePath()
   243  			create = !sb.config.useDefaultSandBox
   244  		}
   245  		sb.osSbox, err = osl.NewSandbox(sb.Key(), create, isRestore)
   246  		if err != nil {
   247  			logrus.Errorf("failed to create osl sandbox while trying to restore sandbox %.7s%s: %v", sb.ID(), msg, err)
   248  			continue
   249  		}
   250  
   251  		c.Lock()
   252  		c.sandboxes[sb.id] = sb
   253  		c.Unlock()
   254  
   255  		for _, eps := range sbs.Eps {
   256  			n, err := c.getNetworkFromStore(eps.Nid)
   257  			var ep *endpoint
   258  			if err != nil {
   259  				logrus.Errorf("getNetworkFromStore for nid %s failed while trying to build sandbox for cleanup: %v", eps.Nid, err)
   260  				n = &network{id: eps.Nid, ctrlr: c, drvOnce: &sync.Once{}, persist: true}
   261  				ep = &endpoint{id: eps.Eid, network: n, sandboxID: sbs.ID}
   262  			} else {
   263  				ep, err = n.getEndpointFromStore(eps.Eid)
   264  				if err != nil {
   265  					logrus.Errorf("getEndpointFromStore for eid %s failed while trying to build sandbox for cleanup: %v", eps.Eid, err)
   266  					ep = &endpoint{id: eps.Eid, network: n, sandboxID: sbs.ID}
   267  				}
   268  			}
   269  			if _, ok := activeSandboxes[sb.ID()]; ok && err != nil {
   270  				logrus.Errorf("failed to restore endpoint %s in %s for container %s due to %v", eps.Eid, eps.Nid, sb.ContainerID(), err)
   271  				continue
   272  			}
   273  			sb.addEndpoint(ep)
   274  		}
   275  
   276  		if _, ok := activeSandboxes[sb.ID()]; !ok {
   277  			logrus.Infof("Removing stale sandbox %s (%s)", sb.id, sb.containerID)
   278  			if err := sb.delete(true); err != nil {
   279  				logrus.Errorf("Failed to delete sandbox %s while trying to cleanup: %v", sb.id, err)
   280  			}
   281  			continue
   282  		}
   283  
   284  		// reconstruct osl sandbox field
   285  		if !sb.config.useDefaultSandBox {
   286  			if err := sb.restoreOslSandbox(); err != nil {
   287  				logrus.Errorf("failed to populate fields for osl sandbox %s", sb.ID())
   288  				continue
   289  			}
   290  		} else {
   291  			c.sboxOnce.Do(func() {
   292  				c.defOsSbox = sb.osSbox
   293  			})
   294  		}
   295  
   296  		for _, ep := range sb.endpoints {
   297  			// Watch for service records
   298  			if !c.isAgent() {
   299  				c.watchSvcRecord(ep)
   300  			}
   301  		}
   302  	}
   303  }