sandbox_store.go 6.9 KB

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