Procházet zdrojové kódy

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 <cpuguy83@gmail.com>
Brian Goff před 10 roky
rodič
revize
e744b0dcba

+ 4 - 5
daemon/daemon.go

@@ -7,6 +7,7 @@ import (
 	"io/ioutil"
 	"io/ioutil"
 	"os"
 	"os"
 	"path"
 	"path"
+	"path/filepath"
 	"regexp"
 	"regexp"
 	"runtime"
 	"runtime"
 	"strings"
 	"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
 	// we'll waste time if we update it for every container
 	daemon.idIndex.Add(container.ID)
 	daemon.idIndex.Add(container.ID)
 
 
+	container.registerVolumes()
+
 	// FIXME: if the container is supposed to be running but is not, auto restart it?
 	// 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 so, then we need to restart monitor and init a new lock
 	// If the container is supposed to be running, make sure of it
 	// 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 {
 	if !debug {
 		fmt.Println()
 		fmt.Println()
 		log.Infof("Loading containers: done.")
 		log.Infof("Loading containers: done.")
@@ -890,7 +889,7 @@ func NewDaemonFromDirectory(config *Config, eng *engine.Engine) (*Daemon, error)
 		return nil, err
 		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 {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 17 - 2
daemon/volumes.go

@@ -119,8 +119,23 @@ func (container *Container) VolumePaths() map[string]struct{} {
 }
 }
 
 
 func (container *Container) registerVolumes() {
 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)
 	}
 	}
 }
 }
 
 

+ 33 - 0
integration-cli/docker_cli_daemon_test.go

@@ -317,3 +317,36 @@ func TestDaemonAllocatesListeningPort(t *testing.T) {
 
 
 	logDone("daemon - daemon listening port is allocated")
 	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")
+}

+ 0 - 6
volumes/repository.go

@@ -87,16 +87,10 @@ func (r *Repository) restore() error {
 
 
 	for _, v := range dir {
 	for _, v := range dir {
 		id := v.Name()
 		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{
 		vol := &Volume{
 			ID:         id,
 			ID:         id,
 			configPath: r.configPath + "/" + id,
 			configPath: r.configPath + "/" + id,
 			containers: make(map[string]struct{}),
 			containers: make(map[string]struct{}),
-			Path:       path,
 		}
 		}
 		if err := vol.FromDisk(); err != nil {
 		if err := vol.FromDisk(); err != nil {
 			if !os.IsNotExist(err) {
 			if !os.IsNotExist(err) {