Skip to content

Commit

Permalink
Fix volume ref restore process
Browse files Browse the repository at this point in the history
Fixes moby#9629 moby#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 <[email protected]>
  • Loading branch information
cpuguy83 committed Jan 20, 2015
1 parent 9305020 commit e744b0d
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 13 deletions.
9 changes: 4 additions & 5 deletions daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io/ioutil"
"os"
"path"
"path/filepath"
"regexp"
"runtime"
"strings"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -400,10 +403,6 @@ func (daemon *Daemon) restore() error {
}
}

for _, c := range registeredContainers {
c.registerVolumes()
}

if !debug {
fmt.Println()
log.Infof("Loading containers: done.")
Expand Down Expand Up @@ -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
}
Expand Down
19 changes: 17 additions & 2 deletions daemon/volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down
33 changes: 33 additions & 0 deletions integration-cli/docker_cli_daemon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
6 changes: 0 additions & 6 deletions volumes/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit e744b0d

Please sign in to comment.