Browse code

Merge pull request #16162 from cpuguy83/16071_fix_lstat_errors

Ignore stat errors on volume rm.

Jess Frazelle authored on 2015/09/10 03:55:14
Showing 3 changed files
... ...
@@ -155,7 +155,7 @@ func (daemon *Daemon) VolumeRm(name string) error {
155 155
 		if err == ErrVolumeInUse {
156 156
 			return fmt.Errorf("Conflict: %v", err)
157 157
 		}
158
-		return err
158
+		return fmt.Errorf("Error while removing volume %s: %v", name, err)
159 159
 	}
160 160
 	return nil
161 161
 }
... ...
@@ -126,6 +126,7 @@ func (r *Root) Create(name string, _ map[string]string) (volume.Volume, error) {
126 126
 func (r *Root) Remove(v volume.Volume) error {
127 127
 	r.m.Lock()
128 128
 	defer r.m.Unlock()
129
+
129 130
 	lv, ok := v.(*localVolume)
130 131
 	if !ok {
131 132
 		return errors.New("unknown volume type")
... ...
@@ -133,18 +134,32 @@ func (r *Root) Remove(v volume.Volume) error {
133 133
 
134 134
 	realPath, err := filepath.EvalSymlinks(lv.path)
135 135
 	if err != nil {
136
-		return err
136
+		if !os.IsNotExist(err) {
137
+			return err
138
+		}
139
+		realPath = filepath.Dir(lv.path)
137 140
 	}
141
+
138 142
 	if !r.scopedPath(realPath) {
139
-		return fmt.Errorf("Unable to remove a directory of out the Docker root: %s", realPath)
143
+		return fmt.Errorf("Unable to remove a directory of out the Docker root %s: %s", r.scope, realPath)
140 144
 	}
141 145
 
142
-	if err := os.RemoveAll(realPath); err != nil {
146
+	if err := removePath(realPath); err != nil {
143 147
 		return err
144 148
 	}
145 149
 
146 150
 	delete(r.volumes, lv.name)
147
-	return os.RemoveAll(filepath.Dir(lv.path))
151
+	return removePath(filepath.Dir(lv.path))
152
+}
153
+
154
+func removePath(path string) error {
155
+	if err := os.RemoveAll(path); err != nil {
156
+		if os.IsNotExist(err) {
157
+			return nil
158
+		}
159
+		return err
160
+	}
161
+	return nil
148 162
 }
149 163
 
150 164
 // Get looks up the volume for the given name and returns it if found
... ...
@@ -162,7 +177,7 @@ func (r *Root) Get(name string) (volume.Volume, error) {
162 162
 // is under Docker's root and the valid local paths.
163 163
 func (r *Root) scopedPath(realPath string) bool {
164 164
 	// Volumes path for Docker version >= 1.7
165
-	if strings.HasPrefix(realPath, filepath.Join(r.scope, volumesPathName)) {
165
+	if strings.HasPrefix(realPath, filepath.Join(r.scope, volumesPathName)) && realPath != filepath.Join(r.scope, volumesPathName) {
166 166
 		return true
167 167
 	}
168 168
 
169 169
new file mode 100644
... ...
@@ -0,0 +1,81 @@
0
+package local
1
+
2
+import (
3
+	"io/ioutil"
4
+	"os"
5
+	"testing"
6
+)
7
+
8
+func TestRemove(t *testing.T) {
9
+	rootDir, err := ioutil.TempDir("", "local-volume-test")
10
+	if err != nil {
11
+		t.Fatal(err)
12
+	}
13
+	defer os.RemoveAll(rootDir)
14
+
15
+	r, err := New(rootDir)
16
+	if err != nil {
17
+		t.Fatal(err)
18
+	}
19
+
20
+	vol, err := r.Create("testing", nil)
21
+	if err != nil {
22
+		t.Fatal(err)
23
+	}
24
+
25
+	if err := r.Remove(vol); err != nil {
26
+		t.Fatal(err)
27
+	}
28
+
29
+	vol, err = r.Create("testing2", nil)
30
+	if err != nil {
31
+		t.Fatal(err)
32
+	}
33
+	if err := os.RemoveAll(vol.Path()); err != nil {
34
+		t.Fatal(err)
35
+	}
36
+
37
+	if err := r.Remove(vol); err != nil {
38
+		t.Fatal(err)
39
+	}
40
+
41
+	if _, err := os.Stat(vol.Path()); err != nil && !os.IsNotExist(err) {
42
+		t.Fatal("volume dir not removed")
43
+	}
44
+
45
+	if len(r.List()) != 0 {
46
+		t.Fatal("expected there to be no volumes")
47
+	}
48
+}
49
+
50
+func TestInitializeWithVolumes(t *testing.T) {
51
+	rootDir, err := ioutil.TempDir("", "local-volume-test")
52
+	if err != nil {
53
+		t.Fatal(err)
54
+	}
55
+	defer os.RemoveAll(rootDir)
56
+
57
+	r, err := New(rootDir)
58
+	if err != nil {
59
+		t.Fatal(err)
60
+	}
61
+
62
+	vol, err := r.Create("testing", nil)
63
+	if err != nil {
64
+		t.Fatal(err)
65
+	}
66
+
67
+	r, err = New(rootDir)
68
+	if err != nil {
69
+		t.Fatal(err)
70
+	}
71
+
72
+	v, err := r.Get(vol.Name())
73
+	if err != nil {
74
+		t.Fatal(err)
75
+	}
76
+
77
+	if v.Path() != vol.Path() {
78
+		t.Fatal("expected to re-initialize root with existing volumes")
79
+	}
80
+}