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>
| ... | ... |
@@ -92,6 +92,12 @@ func (container *Container) VolumePaths() map[string]struct{} {
|
| 92 | 92 |
return paths |
| 93 | 93 |
} |
| 94 | 94 |
|
| 95 |
+func (container *Container) registerVolumes() {
|
|
| 96 |
+ for _, mnt := range container.VolumeMounts() {
|
|
| 97 |
+ mnt.volume.AddContainer(container.ID) |
|
| 98 |
+ } |
|
| 99 |
+} |
|
| 100 |
+ |
|
| 95 | 101 |
func (container *Container) derefVolumes() {
|
| 96 | 102 |
for path := range container.VolumePaths() {
|
| 97 | 103 |
vol := container.daemon.volumes.Get(path) |
| ... | ... |
@@ -1,6 +1,8 @@ |
| 1 | 1 |
package main |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "encoding/json" |
|
| 5 |
+ "os" |
|
| 4 | 6 |
"strings" |
| 5 | 7 |
"testing" |
| 6 | 8 |
) |
| ... | ... |
@@ -48,3 +50,35 @@ func TestDaemonRestartWithRunningContainersPorts(t *testing.T) {
|
| 48 | 48 |
|
| 49 | 49 |
logDone("daemon - running containers on daemon restart")
|
| 50 | 50 |
} |
| 51 |
+ |
|
| 52 |
+func TestDaemonRestartWithVolumesRefs(t *testing.T) {
|
|
| 53 |
+ d := NewDaemon(t) |
|
| 54 |
+ if err := d.StartWithBusybox(); err != nil {
|
|
| 55 |
+ t.Fatal(err) |
|
| 56 |
+ } |
|
| 57 |
+ defer d.Stop() |
|
| 58 |
+ |
|
| 59 |
+ if out, err := d.Cmd("run", "-d", "--name", "volrestarttest1", "-v", "/foo", "busybox"); err != nil {
|
|
| 60 |
+ t.Fatal(err, out) |
|
| 61 |
+ } |
|
| 62 |
+ if err := d.Restart(); err != nil {
|
|
| 63 |
+ t.Fatal(err) |
|
| 64 |
+ } |
|
| 65 |
+ if _, err := d.Cmd("run", "-d", "--volumes-from", "volrestarttest1", "--name", "volrestarttest2", "busybox"); err != nil {
|
|
| 66 |
+ t.Fatal(err) |
|
| 67 |
+ } |
|
| 68 |
+ if out, err := d.Cmd("rm", "-fv", "volrestarttest2"); err != nil {
|
|
| 69 |
+ t.Fatal(err, out) |
|
| 70 |
+ } |
|
| 71 |
+ v, err := d.Cmd("inspect", "--format", "{{ json .Volumes }}", "volrestarttest1")
|
|
| 72 |
+ if err != nil {
|
|
| 73 |
+ t.Fatal(err) |
|
| 74 |
+ } |
|
| 75 |
+ volumes := make(map[string]string) |
|
| 76 |
+ json.Unmarshal([]byte(v), &volumes) |
|
| 77 |
+ if _, err := os.Stat(volumes["/foo"]); err != nil {
|
|
| 78 |
+ t.Fatalf("Expected volume to exist: %s - %s", volumes["/foo"], err)
|
|
| 79 |
+ } |
|
| 80 |
+ |
|
| 81 |
+ logDone("daemon - volume refs are restored")
|
|
| 82 |
+} |
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
"sync" |
| 9 | 9 |
|
| 10 | 10 |
"github.com/docker/docker/daemon/graphdriver" |
| 11 |
+ "github.com/docker/docker/pkg/log" |
|
| 11 | 12 |
"github.com/docker/docker/utils" |
| 12 | 13 |
) |
| 13 | 14 |
|
| ... | ... |
@@ -83,11 +84,31 @@ func (r *Repository) restore() error {
|
| 83 | 83 |
return err |
| 84 | 84 |
} |
| 85 | 85 |
|
| 86 |
- var ids []string |
|
| 87 | 86 |
for _, v := range dir {
|
| 88 | 87 |
id := v.Name() |
| 89 |
- if r.driver.Exists(id) {
|
|
| 90 |
- ids = append(ids, id) |
|
| 88 |
+ path, err := r.driver.Get(id, "") |
|
| 89 |
+ if err != nil {
|
|
| 90 |
+ log.Debugf("Could not find volume for %s: %v", id, err)
|
|
| 91 |
+ continue |
|
| 92 |
+ } |
|
| 93 |
+ vol := &Volume{
|
|
| 94 |
+ ID: id, |
|
| 95 |
+ configPath: r.configPath + "/" + id, |
|
| 96 |
+ containers: make(map[string]struct{}),
|
|
| 97 |
+ Path: path, |
|
| 98 |
+ } |
|
| 99 |
+ if err := vol.FromDisk(); err != nil {
|
|
| 100 |
+ if !os.IsNotExist(err) {
|
|
| 101 |
+ log.Debugf("Error restoring volume: %v", err)
|
|
| 102 |
+ continue |
|
| 103 |
+ } |
|
| 104 |
+ if err := vol.initialize(); err != nil {
|
|
| 105 |
+ log.Debugf("%s", err)
|
|
| 106 |
+ continue |
|
| 107 |
+ } |
|
| 108 |
+ } |
|
| 109 |
+ if err := r.add(vol); err != nil {
|
|
| 110 |
+ log.Debugf("Error restoring volume: %v", err)
|
|
| 91 | 111 |
} |
| 92 | 112 |
} |
| 93 | 113 |
return nil |
| ... | ... |
@@ -173,7 +194,7 @@ func (r *Repository) createNewVolumePath(id string) (string, error) {
|
| 173 | 173 |
|
| 174 | 174 |
path, err := r.driver.Get(id, "") |
| 175 | 175 |
if err != nil {
|
| 176 |
- return "", fmt.Errorf("Driver %s failed to get volume rootfs %s: %s", r.driver, id, err)
|
|
| 176 |
+ return "", fmt.Errorf("Driver %s failed to get volume rootfs %s: %v", r.driver, id, err)
|
|
| 177 | 177 |
} |
| 178 | 178 |
|
| 179 | 179 |
return path, nil |