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:
parent
0d5daa4a8f
commit
9acf7c765c
4 changed files with 66 additions and 7 deletions
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue