From e744b0dcbacd5e226fd79aba5a2e83f432d2d13f Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Fri, 16 Jan 2015 14:48:25 -0500 Subject: [PATCH] Fix volume ref restore process Fixes #9629 #9768 A couple of issues: 1) Volume config is not restored if we couldn't find it with the graph driver, but bind-mounts would never be found by the graph driver since they aren't in that dir 2) container volumes were only being restored if they were found in the volumes repo, but volumes created by old daemons wouldn't be in the repo until the container is at least started. Signed-off-by: Brian Goff --- daemon/daemon.go | 9 +++---- daemon/volumes.go | 19 +++++++++++-- integration-cli/docker_cli_daemon_test.go | 33 +++++++++++++++++++++++ volumes/repository.go | 6 ----- 4 files changed, 54 insertions(+), 13 deletions(-) diff --git a/daemon/daemon.go b/daemon/daemon.go index ef25960c52..1b2d13bb6d 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "os" "path" + "path/filepath" "regexp" "runtime" "strings" @@ -237,6 +238,8 @@ func (daemon *Daemon) register(container *Container, updateSuffixarray bool) err // we'll waste time if we update it for every container daemon.idIndex.Add(container.ID) + container.registerVolumes() + // FIXME: if the container is supposed to be running but is not, auto restart it? // if so, then we need to restart monitor and init a new lock // If the container is supposed to be running, make sure of it @@ -400,10 +403,6 @@ func (daemon *Daemon) restore() error { } } - for _, c := range registeredContainers { - c.registerVolumes() - } - if !debug { fmt.Println() log.Infof("Loading containers: done.") @@ -890,7 +889,7 @@ func NewDaemonFromDirectory(config *Config, eng *engine.Engine) (*Daemon, error) return nil, err } - volumes, err := volumes.NewRepository(path.Join(config.Root, "volumes"), volumesDriver) + volumes, err := volumes.NewRepository(filepath.Join(config.Root, "volumes"), volumesDriver) if err != nil { return nil, err } diff --git a/daemon/volumes.go b/daemon/volumes.go index fa38b253fa..7b49733839 100644 --- a/daemon/volumes.go +++ b/daemon/volumes.go @@ -119,8 +119,23 @@ func (container *Container) VolumePaths() map[string]struct{} { } func (container *Container) registerVolumes() { - for _, mnt := range container.VolumeMounts() { - mnt.volume.AddContainer(container.ID) + for path := range container.VolumePaths() { + if v := container.daemon.volumes.Get(path); v != nil { + v.AddContainer(container.ID) + continue + } + + // if container was created with an old daemon, this volume may not be registered so we need to make sure it gets registered + writable := true + if rw, exists := container.VolumesRW[path]; exists { + writable = rw + } + v, err := container.daemon.volumes.FindOrCreateVolume(path, writable) + if err != nil { + log.Debugf("error registering volume %s: %v", path, err) + continue + } + v.AddContainer(container.ID) } } diff --git a/integration-cli/docker_cli_daemon_test.go b/integration-cli/docker_cli_daemon_test.go index dbc4d232b6..b7db552b62 100644 --- a/integration-cli/docker_cli_daemon_test.go +++ b/integration-cli/docker_cli_daemon_test.go @@ -317,3 +317,36 @@ func TestDaemonAllocatesListeningPort(t *testing.T) { logDone("daemon - daemon listening port is allocated") } + +// #9629 +func TestDaemonVolumesBindsRefs(t *testing.T) { + d := NewDaemon(t) + + if err := d.StartWithBusybox(); err != nil { + t.Fatal(err) + } + + tmp, err := ioutil.TempDir(os.TempDir(), "") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmp) + + if err := ioutil.WriteFile(tmp+"/test", []byte("testing"), 0655); err != nil { + t.Fatal(err) + } + + if out, err := d.Cmd("create", "-v", tmp+":/foo", "--name=voltest", "busybox"); err != nil { + t.Fatal(err, out) + } + + if err := d.Restart(); err != nil { + t.Fatal(err) + } + + if out, err := d.Cmd("run", "--volumes-from=voltest", "--name=consumer", "busybox", "/bin/sh", "-c", "[ -f /foo/test ]"); err != nil { + t.Fatal(err, out) + } + + logDone("daemon - bind refs in data-containers survive daemon restart") +} diff --git a/volumes/repository.go b/volumes/repository.go index 225148b60e..8219952243 100644 --- a/volumes/repository.go +++ b/volumes/repository.go @@ -87,16 +87,10 @@ func (r *Repository) restore() error { for _, v := range dir { id := v.Name() - 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) {