From 153b47b46a06a0409e1451e8c7682b2176c0d836 Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Wed, 8 Oct 2014 13:13:32 -0400 Subject: [PATCH] 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 Upstream-commit: 9acf7c765c7e074f6c75eaf162ca06ecfe40d692 Component: engine --- components/engine/daemon/daemon.go | 4 +-- components/engine/daemon/volumes.go | 6 ++++ .../integration-cli/docker_cli_daemon_test.go | 34 +++++++++++++++++++ components/engine/volumes/repository.go | 29 +++++++++++++--- 4 files changed, 66 insertions(+), 7 deletions(-) diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go index 1757b4fea1..524143945b 100644 --- a/components/engine/daemon/daemon.go +++ b/components/engine/daemon/daemon.go @@ -400,9 +400,7 @@ func (daemon *Daemon) restore() error { } for _, c := range registeredContainers { - for _, mnt := range c.VolumeMounts() { - daemon.volumes.Add(mnt.volume) - } + c.registerVolumes() } if !debug { diff --git a/components/engine/daemon/volumes.go b/components/engine/daemon/volumes.go index b9d622990d..03981f337a 100644 --- a/components/engine/daemon/volumes.go +++ b/components/engine/daemon/volumes.go @@ -92,6 +92,12 @@ func (container *Container) VolumePaths() map[string]struct{} { return paths } +func (container *Container) registerVolumes() { + for _, mnt := range container.VolumeMounts() { + mnt.volume.AddContainer(container.ID) + } +} + func (container *Container) derefVolumes() { for path := range container.VolumePaths() { vol := container.daemon.volumes.Get(path) diff --git a/components/engine/integration-cli/docker_cli_daemon_test.go b/components/engine/integration-cli/docker_cli_daemon_test.go index da9724c492..906680dc6d 100644 --- a/components/engine/integration-cli/docker_cli_daemon_test.go +++ b/components/engine/integration-cli/docker_cli_daemon_test.go @@ -1,6 +1,8 @@ package main import ( + "encoding/json" + "os" "strings" "testing" ) @@ -48,3 +50,35 @@ func TestDaemonRestartWithRunningContainersPorts(t *testing.T) { 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") +} diff --git a/components/engine/volumes/repository.go b/components/engine/volumes/repository.go index 7e095b8fe0..e765d944c2 100644 --- a/components/engine/volumes/repository.go +++ b/components/engine/volumes/repository.go @@ -8,6 +8,7 @@ import ( "sync" "github.com/docker/docker/daemon/graphdriver" + "github.com/docker/docker/pkg/log" "github.com/docker/docker/utils" ) @@ -83,11 +84,31 @@ func (r *Repository) restore() error { return err } - var ids []string for _, v := range dir { id := v.Name() - if r.driver.Exists(id) { - ids = append(ids, id) + path, err := r.driver.Get(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 @@ -173,7 +194,7 @@ func (r *Repository) createNewVolumePath(id string) (string, error) { path, err := r.driver.Get(id, "") 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