sandbox_store.go 6.7 KB

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