sandbox_store.go 6.5 KB

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