func (sb *sandbox) Delete() error { sb.Lock() if sb.inDelete { sb.Unlock() return types.ForbiddenErrorf("another sandbox delete in progress") } // Set the inDelete flag. This will ensure that we don't // update the store until we have completed all the endpoint // leaves and deletes. And when endpoint leaves and deletes // are completed then we can finally delete the sandbox object // altogether from the data store. If the daemon exits // ungracefully in the middle of a sandbox delete this way we // will have all the references to the endpoints in the // sandbox so that we can clean them up when we restart sb.inDelete = true sb.Unlock() c := sb.controller // Detach from all endpoints for _, ep := range sb.getConnectedEndpoints() { // endpoint in the Gateway network will be cleaned up // when when sandbox no longer needs external connectivity if ep.endpointInGWNetwork() { continue } if err := ep.Leave(sb); err != nil { log.Warnf("Failed detaching sandbox %s from endpoint %s: %v\n", sb.ID(), ep.ID(), err) } if err := ep.Delete(); err != nil { log.Warnf("Failed deleting endpoint %s: %v\n", ep.ID(), err) } } // Container is going away. Path cache in etchosts is most // likely not required any more. Drop it. etchosts.Drop(sb.config.hostsPath) if sb.osSbox != nil { sb.osSbox.Destroy() } if err := sb.storeDelete(); err != nil { log.Warnf("Failed to delete sandbox %s from store: %v", sb.ID(), err) } c.Lock() delete(c.sandboxes, sb.ID()) c.Unlock() return nil }
func (sb *sandbox) delete(force bool) error { sb.Lock() if sb.inDelete { sb.Unlock() return types.ForbiddenErrorf("another sandbox delete in progress") } // Set the inDelete flag. This will ensure that we don't // update the store until we have completed all the endpoint // leaves and deletes. And when endpoint leaves and deletes // are completed then we can finally delete the sandbox object // altogether from the data store. If the daemon exits // ungracefully in the middle of a sandbox delete this way we // will have all the references to the endpoints in the // sandbox so that we can clean them up when we restart sb.inDelete = true sb.Unlock() c := sb.controller // Detach from all endpoints retain := false for _, ep := range sb.getConnectedEndpoints() { // Retain the sanbdox if we can't obtain the network from store. if _, err := c.getNetworkFromStore(ep.getNetwork().ID()); err != nil { retain = true log.Warnf("Failed getting network for ep %s during sandbox %s delete: %v", ep.ID(), sb.ID(), err) continue } if !force { if err := ep.Leave(sb); err != nil { log.Warnf("Failed detaching sandbox %s from endpoint %s: %v\n", sb.ID(), ep.ID(), err) } } if err := ep.Delete(force); err != nil { log.Warnf("Failed deleting endpoint %s: %v\n", ep.ID(), err) } } if retain { sb.Lock() sb.inDelete = false sb.Unlock() return fmt.Errorf("could not cleanup all the endpoints in container %s / sandbox %s", sb.containerID, sb.id) } // Container is going away. Path cache in etchosts is most // likely not required any more. Drop it. etchosts.Drop(sb.config.hostsPath) if sb.resolver != nil { sb.resolver.Stop() } if sb.osSbox != nil && !sb.config.useDefaultSandBox { sb.osSbox.Destroy() } if err := sb.storeDelete(); err != nil { log.Warnf("Failed to delete sandbox %s from store: %v", sb.ID(), err) } c.Lock() delete(c.sandboxes, sb.ID()) c.Unlock() return nil }