Restore volume refs after daemon restart
Volume refs were not being restored on daemon restart. This made it possible to remove a volume being used by other containers after a daemon restart. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
parent
0d5daa4a8f
commit
9acf7c765c
|
|
@ -400,9 +400,7 @@ func (daemon *Daemon) restore() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range registeredContainers {
|
for _, c := range registeredContainers {
|
||||||
for _, mnt := range c.VolumeMounts() {
|
c.registerVolumes()
|
||||||
daemon.volumes.Add(mnt.volume)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !debug {
|
if !debug {
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,12 @@ func (container *Container) VolumePaths() map[string]struct{} {
|
||||||
return paths
|
return paths
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (container *Container) registerVolumes() {
|
||||||
|
for _, mnt := range container.VolumeMounts() {
|
||||||
|
mnt.volume.AddContainer(container.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (container *Container) derefVolumes() {
|
func (container *Container) derefVolumes() {
|
||||||
for path := range container.VolumePaths() {
|
for path := range container.VolumePaths() {
|
||||||
vol := container.daemon.volumes.Get(path)
|
vol := container.daemon.volumes.Get(path)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
@ -48,3 +50,35 @@ func TestDaemonRestartWithRunningContainersPorts(t *testing.T) {
|
||||||
|
|
||||||
logDone("daemon - running containers on daemon restart")
|
logDone("daemon - running containers on daemon restart")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDaemonRestartWithVolumesRefs(t *testing.T) {
|
||||||
|
d := NewDaemon(t)
|
||||||
|
if err := d.StartWithBusybox(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer d.Stop()
|
||||||
|
|
||||||
|
if out, err := d.Cmd("run", "-d", "--name", "volrestarttest1", "-v", "/foo", "busybox"); err != nil {
|
||||||
|
t.Fatal(err, out)
|
||||||
|
}
|
||||||
|
if err := d.Restart(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := d.Cmd("run", "-d", "--volumes-from", "volrestarttest1", "--name", "volrestarttest2", "busybox"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if out, err := d.Cmd("rm", "-fv", "volrestarttest2"); err != nil {
|
||||||
|
t.Fatal(err, out)
|
||||||
|
}
|
||||||
|
v, err := d.Cmd("inspect", "--format", "{{ json .Volumes }}", "volrestarttest1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
volumes := make(map[string]string)
|
||||||
|
json.Unmarshal([]byte(v), &volumes)
|
||||||
|
if _, err := os.Stat(volumes["/foo"]); err != nil {
|
||||||
|
t.Fatalf("Expected volume to exist: %s - %s", volumes["/foo"], err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logDone("daemon - volume refs are restored")
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/docker/docker/daemon/graphdriver"
|
"github.com/docker/docker/daemon/graphdriver"
|
||||||
|
"github.com/docker/docker/pkg/log"
|
||||||
"github.com/docker/docker/utils"
|
"github.com/docker/docker/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -83,11 +84,31 @@ func (r *Repository) restore() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var ids []string
|
|
||||||
for _, v := range dir {
|
for _, v := range dir {
|
||||||
id := v.Name()
|
id := v.Name()
|
||||||
if r.driver.Exists(id) {
|
path, err := r.driver.Get(id, "")
|
||||||
ids = append(ids, id)
|
if err != nil {
|
||||||
|
log.Debugf("Could not find volume for %s: %v", id, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
vol := &Volume{
|
||||||
|
ID: id,
|
||||||
|
configPath: r.configPath + "/" + id,
|
||||||
|
containers: make(map[string]struct{}),
|
||||||
|
Path: path,
|
||||||
|
}
|
||||||
|
if err := vol.FromDisk(); err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
log.Debugf("Error restoring volume: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := vol.initialize(); err != nil {
|
||||||
|
log.Debugf("%s", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := r.add(vol); err != nil {
|
||||||
|
log.Debugf("Error restoring volume: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -173,7 +194,7 @@ func (r *Repository) createNewVolumePath(id string) (string, error) {
|
||||||
|
|
||||||
path, err := r.driver.Get(id, "")
|
path, err := r.driver.Get(id, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("Driver %s failed to get volume rootfs %s: %s", r.driver, id, err)
|
return "", fmt.Errorf("Driver %s failed to get volume rootfs %s: %v", r.driver, id, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return path, nil
|
return path, nil
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue