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