sandbox_store.go 6.9 KB

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