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