Fix stale sandbox from store problem
At times, when checkpointed sandbox from store cannot be cleaned up properly we still retain the sandbox in both the store and in memory. But this sandbox store may not contain important configuration information from docker. So when docker requests a new sandbox, instead of using it as is, reconcile the sandbox state from store with the the configuration information provided by docker. To do this mark the sandbox from store as stub and never reveal it to external searches. When docker requests a new sandbox, update the stub sandbox and clear the stub flag. Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
This commit is contained in:
parent
e557f4a67d
commit
670302e66b
|
@ -100,6 +100,9 @@ type NetworkController interface {
|
||||||
// SandboxByID returns the Sandbox which has the passed id. If not found, a types.NotFoundError is returned.
|
// SandboxByID returns the Sandbox which has the passed id. If not found, a types.NotFoundError is returned.
|
||||||
SandboxByID(id string) (Sandbox, error)
|
SandboxByID(id string) (Sandbox, error)
|
||||||
|
|
||||||
|
// SandboxDestroy destroys a sandbox given a container ID
|
||||||
|
SandboxDestroy(id string) error
|
||||||
|
|
||||||
// Stop network controller
|
// Stop network controller
|
||||||
Stop()
|
Stop()
|
||||||
}
|
}
|
||||||
|
@ -478,21 +481,37 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (S
|
||||||
return nil, types.BadRequestErrorf("invalid container ID")
|
return nil, types.BadRequestErrorf("invalid container ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
var existing Sandbox
|
var sb *sandbox
|
||||||
look := SandboxContainerWalker(&existing, containerID)
|
c.Lock()
|
||||||
c.WalkSandboxes(look)
|
for _, s := range c.sandboxes {
|
||||||
if existing != nil {
|
if s.containerID == containerID {
|
||||||
return nil, types.BadRequestErrorf("container %s is already present: %v", containerID, existing)
|
// If not a stub, then we already have a complete sandbox.
|
||||||
|
if !s.isStub {
|
||||||
|
c.Unlock()
|
||||||
|
return nil, types.BadRequestErrorf("container %s is already present: %v", containerID, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We already have a stub sandbox from the
|
||||||
|
// store. Make use of it so that we don't lose
|
||||||
|
// the endpoints from store but reset the
|
||||||
|
// isStub flag.
|
||||||
|
sb = s
|
||||||
|
sb.isStub = false
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
c.Unlock()
|
||||||
|
|
||||||
// Create sandbox and process options first. Key generation depends on an option
|
// Create sandbox and process options first. Key generation depends on an option
|
||||||
sb := &sandbox{
|
if sb == nil {
|
||||||
id: stringid.GenerateRandomID(),
|
sb = &sandbox{
|
||||||
containerID: containerID,
|
id: stringid.GenerateRandomID(),
|
||||||
endpoints: epHeap{},
|
containerID: containerID,
|
||||||
epPriority: map[string]int{},
|
endpoints: epHeap{},
|
||||||
config: containerConfig{},
|
epPriority: map[string]int{},
|
||||||
controller: c,
|
config: containerConfig{},
|
||||||
|
controller: c,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
heap.Init(&sb.endpoints)
|
heap.Init(&sb.endpoints)
|
||||||
|
@ -547,6 +566,11 @@ func (c *controller) Sandboxes() []Sandbox {
|
||||||
|
|
||||||
list := make([]Sandbox, 0, len(c.sandboxes))
|
list := make([]Sandbox, 0, len(c.sandboxes))
|
||||||
for _, s := range c.sandboxes {
|
for _, s := range c.sandboxes {
|
||||||
|
// Hide stub sandboxes from libnetwork users
|
||||||
|
if s.isStub {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
list = append(list, s)
|
list = append(list, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,6 +598,26 @@ func (c *controller) SandboxByID(id string) (Sandbox, error) {
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SandboxDestroy destroys a sandbox given a container ID
|
||||||
|
func (c *controller) SandboxDestroy(id string) error {
|
||||||
|
var sb *sandbox
|
||||||
|
c.Lock()
|
||||||
|
for _, s := range c.sandboxes {
|
||||||
|
if s.containerID == id {
|
||||||
|
sb = s
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.Unlock()
|
||||||
|
|
||||||
|
// It is not an error if sandbox is not available
|
||||||
|
if sb == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.Delete()
|
||||||
|
}
|
||||||
|
|
||||||
// SandboxContainerWalker returns a Sandbox Walker function which looks for an existing Sandbox with the passed containerID
|
// SandboxContainerWalker returns a Sandbox Walker function which looks for an existing Sandbox with the passed containerID
|
||||||
func SandboxContainerWalker(out *Sandbox, containerID string) SandboxWalker {
|
func SandboxContainerWalker(out *Sandbox, containerID string) SandboxWalker {
|
||||||
return func(sb Sandbox) bool {
|
return func(sb Sandbox) bool {
|
||||||
|
|
|
@ -68,6 +68,7 @@ type sandbox struct {
|
||||||
joinLeaveDone chan struct{}
|
joinLeaveDone chan struct{}
|
||||||
dbIndex uint64
|
dbIndex uint64
|
||||||
dbExists bool
|
dbExists bool
|
||||||
|
isStub bool
|
||||||
inDelete bool
|
inDelete bool
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,6 +188,7 @@ func (c *controller) sandboxCleanup() {
|
||||||
endpoints: epHeap{},
|
endpoints: epHeap{},
|
||||||
epPriority: map[string]int{},
|
epPriority: map[string]int{},
|
||||||
dbIndex: sbs.dbIndex,
|
dbIndex: sbs.dbIndex,
|
||||||
|
isStub: true,
|
||||||
dbExists: true,
|
dbExists: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue