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:
Brian Goff 2014-10-08 13:13:32 -04:00
parent 0d5daa4a8f
commit 9acf7c765c
4 changed files with 66 additions and 7 deletions

View file

@ -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 {

View file

@ -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)

View file

@ -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")
}

View file

@ -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