123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- package libnetwork
- import (
- "container/heap"
- "encoding/json"
- "sync"
- "github.com/Sirupsen/logrus"
- "github.com/docker/libnetwork/datastore"
- "github.com/docker/libnetwork/osl"
- )
- const (
- sandboxPrefix = "sandbox"
- )
- type epState struct {
- Eid string
- Nid string
- }
- type sbState struct {
- ID string
- Cid string
- c *controller
- dbIndex uint64
- dbExists bool
- Eps []epState
- EpPriority map[string]int
- // external servers have to be persisted so that on restart of a live-restore
- // enabled daemon we get the external servers for the running containers.
- // We have two versions of ExtDNS to support upgrade & downgrade of the daemon
- // between >=1.14 and <1.14 versions.
- ExtDNS []string
- ExtDNS2 []extDNSEntry
- }
- func (sbs *sbState) Key() []string {
- return []string{sandboxPrefix, sbs.ID}
- }
- func (sbs *sbState) KeyPrefix() []string {
- return []string{sandboxPrefix}
- }
- func (sbs *sbState) Value() []byte {
- b, err := json.Marshal(sbs)
- if err != nil {
- return nil
- }
- return b
- }
- func (sbs *sbState) SetValue(value []byte) error {
- return json.Unmarshal(value, sbs)
- }
- func (sbs *sbState) Index() uint64 {
- sbi, err := sbs.c.SandboxByID(sbs.ID)
- if err != nil {
- return sbs.dbIndex
- }
- sb := sbi.(*sandbox)
- maxIndex := sb.dbIndex
- if sbs.dbIndex > maxIndex {
- maxIndex = sbs.dbIndex
- }
- return maxIndex
- }
- func (sbs *sbState) SetIndex(index uint64) {
- sbs.dbIndex = index
- sbs.dbExists = true
- sbi, err := sbs.c.SandboxByID(sbs.ID)
- if err != nil {
- return
- }
- sb := sbi.(*sandbox)
- sb.dbIndex = index
- sb.dbExists = true
- }
- func (sbs *sbState) Exists() bool {
- if sbs.dbExists {
- return sbs.dbExists
- }
- sbi, err := sbs.c.SandboxByID(sbs.ID)
- if err != nil {
- return false
- }
- sb := sbi.(*sandbox)
- return sb.dbExists
- }
- func (sbs *sbState) Skip() bool {
- return false
- }
- func (sbs *sbState) New() datastore.KVObject {
- return &sbState{c: sbs.c}
- }
- func (sbs *sbState) CopyTo(o datastore.KVObject) error {
- dstSbs := o.(*sbState)
- dstSbs.c = sbs.c
- dstSbs.ID = sbs.ID
- dstSbs.Cid = sbs.Cid
- dstSbs.dbIndex = sbs.dbIndex
- dstSbs.dbExists = sbs.dbExists
- dstSbs.EpPriority = sbs.EpPriority
- for _, eps := range sbs.Eps {
- dstSbs.Eps = append(dstSbs.Eps, eps)
- }
- if len(sbs.ExtDNS2) > 0 {
- for _, dns := range sbs.ExtDNS2 {
- dstSbs.ExtDNS2 = append(dstSbs.ExtDNS2, dns)
- dstSbs.ExtDNS = append(dstSbs.ExtDNS, dns.IPStr)
- }
- return nil
- }
- for _, dns := range sbs.ExtDNS {
- dstSbs.ExtDNS = append(dstSbs.ExtDNS, dns)
- dstSbs.ExtDNS2 = append(dstSbs.ExtDNS2, extDNSEntry{IPStr: dns})
- }
- return nil
- }
- func (sbs *sbState) DataScope() string {
- return datastore.LocalScope
- }
- func (sb *sandbox) storeUpdate() error {
- sbs := &sbState{
- c: sb.controller,
- ID: sb.id,
- Cid: sb.containerID,
- EpPriority: sb.epPriority,
- ExtDNS2: sb.extDNS,
- }
- for _, ext := range sb.extDNS {
- sbs.ExtDNS = append(sbs.ExtDNS, ext.IPStr)
- }
- retry:
- sbs.Eps = nil
- for _, ep := range sb.getConnectedEndpoints() {
- // If the endpoint is not persisted then do not add it to
- // the sandbox checkpoint
- if ep.Skip() {
- continue
- }
- eps := epState{
- Nid: ep.getNetwork().ID(),
- Eid: ep.ID(),
- }
- sbs.Eps = append(sbs.Eps, eps)
- }
- err := sb.controller.updateToStore(sbs)
- if err == datastore.ErrKeyModified {
- // When we get ErrKeyModified it is sufficient to just
- // go back and retry. No need to get the object from
- // the store because we always regenerate the store
- // state from in memory sandbox state
- goto retry
- }
- return err
- }
- func (sb *sandbox) storeDelete() error {
- sbs := &sbState{
- c: sb.controller,
- ID: sb.id,
- Cid: sb.containerID,
- dbIndex: sb.dbIndex,
- dbExists: sb.dbExists,
- }
- return sb.controller.deleteFromStore(sbs)
- }
- func (c *controller) sandboxCleanup(activeSandboxes map[string]interface{}) {
- store := c.getStore(datastore.LocalScope)
- if store == nil {
- logrus.Error("Could not find local scope store while trying to cleanup sandboxes")
- return
- }
- kvol, err := store.List(datastore.Key(sandboxPrefix), &sbState{c: c})
- if err != nil && err != datastore.ErrKeyNotFound {
- logrus.Errorf("failed to get sandboxes for scope %s: %v", store.Scope(), err)
- return
- }
- // It's normal for no sandboxes to be found. Just bail out.
- if err == datastore.ErrKeyNotFound {
- return
- }
- for _, kvo := range kvol {
- sbs := kvo.(*sbState)
- sb := &sandbox{
- id: sbs.ID,
- controller: sbs.c,
- containerID: sbs.Cid,
- endpoints: epHeap{},
- populatedEndpoints: map[string]struct{}{},
- dbIndex: sbs.dbIndex,
- isStub: true,
- dbExists: true,
- }
- // If we are restoring from a older version extDNSEntry won't have the
- // HostLoopback field
- if len(sbs.ExtDNS2) > 0 {
- sb.extDNS = sbs.ExtDNS2
- } else {
- for _, dns := range sbs.ExtDNS {
- sb.extDNS = append(sb.extDNS, extDNSEntry{IPStr: dns})
- }
- }
- msg := " for cleanup"
- create := true
- isRestore := false
- if val, ok := activeSandboxes[sb.ID()]; ok {
- msg = ""
- sb.isStub = false
- isRestore = true
- opts := val.([]SandboxOption)
- sb.processOptions(opts...)
- sb.restorePath()
- create = !sb.config.useDefaultSandBox
- heap.Init(&sb.endpoints)
- }
- sb.osSbox, err = osl.NewSandbox(sb.Key(), create, isRestore)
- if err != nil {
- logrus.Errorf("failed to create osl sandbox while trying to restore sandbox %s%s: %v", sb.ID()[0:7], msg, err)
- continue
- }
- c.Lock()
- c.sandboxes[sb.id] = sb
- c.Unlock()
- for _, eps := range sbs.Eps {
- n, err := c.getNetworkFromStore(eps.Nid)
- var ep *endpoint
- if err != nil {
- logrus.Errorf("getNetworkFromStore for nid %s failed while trying to build sandbox for cleanup: %v", eps.Nid, err)
- n = &network{id: eps.Nid, ctrlr: c, drvOnce: &sync.Once{}, persist: true}
- ep = &endpoint{id: eps.Eid, network: n, sandboxID: sbs.ID}
- } else {
- ep, err = n.getEndpointFromStore(eps.Eid)
- if err != nil {
- logrus.Errorf("getEndpointFromStore for eid %s failed while trying to build sandbox for cleanup: %v", eps.Eid, err)
- ep = &endpoint{id: eps.Eid, network: n, sandboxID: sbs.ID}
- }
- }
- if _, ok := activeSandboxes[sb.ID()]; ok && err != nil {
- logrus.Errorf("failed to restore endpoint %s in %s for container %s due to %v", eps.Eid, eps.Nid, sb.ContainerID(), err)
- continue
- }
- heap.Push(&sb.endpoints, ep)
- }
- if _, ok := activeSandboxes[sb.ID()]; !ok {
- logrus.Infof("Removing stale sandbox %s (%s)", sb.id, sb.containerID)
- if err := sb.delete(true); err != nil {
- logrus.Errorf("Failed to delete sandbox %s while trying to cleanup: %v", sb.id, err)
- }
- continue
- }
- // reconstruct osl sandbox field
- if !sb.config.useDefaultSandBox {
- if err := sb.restoreOslSandbox(); err != nil {
- logrus.Errorf("failed to populate fields for osl sandbox %s", sb.ID())
- continue
- }
- } else {
- c.sboxOnce.Do(func() {
- c.defOsSbox = sb.osSbox
- })
- }
- for _, ep := range sb.endpoints {
- // Watch for service records
- if !c.isAgent() {
- c.watchSvcRecord(ep)
- }
- }
- }
- }
|