Signed-off-by: David Calavera <david.calavera@gmail.com>
David Calavera authored on 2015/05/23 02:37:00... | ... |
@@ -346,6 +346,8 @@ func (container *Container) cleanup() { |
346 | 346 |
for _, eConfig := range container.execCommands.s { |
347 | 347 |
container.daemon.unregisterExecCommand(eConfig) |
348 | 348 |
} |
349 |
+ |
|
350 |
+ container.UnmountVolumes(true) |
|
349 | 351 |
} |
350 | 352 |
|
351 | 353 |
func (container *Container) KillSig(sig int) error { |
... | ... |
@@ -469,6 +471,7 @@ func (container *Container) Stop(seconds int) error { |
469 | 469 |
return err |
470 | 470 |
} |
471 | 471 |
} |
472 |
+ |
|
472 | 473 |
return nil |
473 | 474 |
} |
474 | 475 |
|
... | ... |
@@ -564,16 +567,10 @@ func (container *Container) Copy(resource string) (io.ReadCloser, error) { |
564 | 564 |
if err := container.Mount(); err != nil { |
565 | 565 |
return nil, err |
566 | 566 |
} |
567 |
- var paths []string |
|
568 |
- unmount := func() { |
|
569 |
- for _, p := range paths { |
|
570 |
- syscall.Unmount(p, 0) |
|
571 |
- } |
|
572 |
- } |
|
573 | 567 |
defer func() { |
574 | 568 |
if err != nil { |
575 | 569 |
// unmount any volumes |
576 |
- unmount() |
|
570 |
+ container.UnmountVolumes(true) |
|
577 | 571 |
// unmount the container's rootfs |
578 | 572 |
container.Unmount() |
579 | 573 |
} |
... | ... |
@@ -587,7 +584,6 @@ func (container *Container) Copy(resource string) (io.ReadCloser, error) { |
587 | 587 |
if err != nil { |
588 | 588 |
return nil, err |
589 | 589 |
} |
590 |
- paths = append(paths, dest) |
|
591 | 590 |
if err := mount.Mount(m.Source, dest, "bind", "rbind,ro"); err != nil { |
592 | 591 |
return nil, err |
593 | 592 |
} |
... | ... |
@@ -618,7 +614,7 @@ func (container *Container) Copy(resource string) (io.ReadCloser, error) { |
618 | 618 |
} |
619 | 619 |
return ioutils.NewReadCloserWrapper(archive, func() error { |
620 | 620 |
err := archive.Close() |
621 |
- unmount() |
|
621 |
+ container.UnmountVolumes(true) |
|
622 | 622 |
container.Unmount() |
623 | 623 |
return err |
624 | 624 |
}), |
... | ... |
@@ -1090,3 +1086,48 @@ func (container *Container) shouldRestart() bool { |
1090 | 1090 |
return container.hostConfig.RestartPolicy.Name == "always" || |
1091 | 1091 |
(container.hostConfig.RestartPolicy.Name == "on-failure" && container.ExitCode != 0) |
1092 | 1092 |
} |
1093 |
+ |
|
1094 |
+func (container *Container) UnmountVolumes(forceSyscall bool) error { |
|
1095 |
+ for _, m := range container.MountPoints { |
|
1096 |
+ dest, err := container.GetResourcePath(m.Destination) |
|
1097 |
+ if err != nil { |
|
1098 |
+ return err |
|
1099 |
+ } |
|
1100 |
+ |
|
1101 |
+ if forceSyscall { |
|
1102 |
+ syscall.Unmount(dest, 0) |
|
1103 |
+ } |
|
1104 |
+ |
|
1105 |
+ if m.Volume != nil { |
|
1106 |
+ if err := m.Volume.Unmount(); err != nil { |
|
1107 |
+ return err |
|
1108 |
+ } |
|
1109 |
+ } |
|
1110 |
+ } |
|
1111 |
+ return nil |
|
1112 |
+} |
|
1113 |
+ |
|
1114 |
+func (container *Container) copyImagePathContent(v volume.Volume, destination string) error { |
|
1115 |
+ rootfs, err := symlink.FollowSymlinkInScope(filepath.Join(container.basefs, destination), container.basefs) |
|
1116 |
+ if err != nil { |
|
1117 |
+ return err |
|
1118 |
+ } |
|
1119 |
+ |
|
1120 |
+ if _, err = ioutil.ReadDir(rootfs); err != nil { |
|
1121 |
+ if os.IsNotExist(err) { |
|
1122 |
+ return nil |
|
1123 |
+ } |
|
1124 |
+ return err |
|
1125 |
+ } |
|
1126 |
+ |
|
1127 |
+ path, err := v.Mount() |
|
1128 |
+ if err != nil { |
|
1129 |
+ return err |
|
1130 |
+ } |
|
1131 |
+ |
|
1132 |
+ if err := copyExistingContents(rootfs, path); err != nil { |
|
1133 |
+ return err |
|
1134 |
+ } |
|
1135 |
+ |
|
1136 |
+ return v.Unmount() |
|
1137 |
+} |
... | ... |
@@ -10,7 +10,6 @@ import ( |
10 | 10 |
"github.com/docker/docker/image" |
11 | 11 |
"github.com/docker/docker/pkg/parsers" |
12 | 12 |
"github.com/docker/docker/pkg/stringid" |
13 |
- "github.com/docker/docker/pkg/symlink" |
|
14 | 13 |
"github.com/docker/docker/runconfig" |
15 | 14 |
"github.com/docker/libcontainer/label" |
16 | 15 |
) |
... | ... |
@@ -120,21 +119,20 @@ func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.Hos |
120 | 120 |
if err != nil { |
121 | 121 |
return nil, nil, err |
122 | 122 |
} |
123 |
- if stat, err := os.Stat(path); err == nil && !stat.IsDir() { |
|
123 |
+ |
|
124 |
+ stat, err := os.Stat(path) |
|
125 |
+ if err == nil && !stat.IsDir() { |
|
124 | 126 |
return nil, nil, fmt.Errorf("cannot mount volume over existing file, file exists %s", path) |
125 | 127 |
} |
128 |
+ |
|
126 | 129 |
v, err := createVolume(name, config.VolumeDriver) |
127 | 130 |
if err != nil { |
128 | 131 |
return nil, nil, err |
129 | 132 |
} |
130 |
- rootfs, err := symlink.FollowSymlinkInScope(filepath.Join(container.basefs, destination), container.basefs) |
|
131 |
- if err != nil { |
|
132 |
- return nil, nil, err |
|
133 |
- } |
|
134 |
- if path, err = v.Mount(); err != nil { |
|
133 |
+ |
|
134 |
+ if err := container.copyImagePathContent(v, destination); err != nil { |
|
135 | 135 |
return nil, nil, err |
136 | 136 |
} |
137 |
- copyExistingContents(rootfs, path) |
|
138 | 137 |
|
139 | 138 |
container.addMountPointWithVolume(destination, v, true) |
140 | 139 |
} |
... | ... |
@@ -440,14 +440,6 @@ func (s *DockerSuite) TestRunCreateVolumesInSymlinkDir(c *check.C) { |
440 | 440 |
} |
441 | 441 |
} |
442 | 442 |
|
443 |
-// Regression test for #4830 |
|
444 |
-func (s *DockerSuite) TestRunWithRelativePath(c *check.C) { |
|
445 |
- runCmd := exec.Command(dockerBinary, "run", "-v", "tmp:/other-tmp", "busybox", "true") |
|
446 |
- if _, _, _, err := runCommandWithStdoutStderr(runCmd); err == nil { |
|
447 |
- c.Fatalf("relative path should result in an error") |
|
448 |
- } |
|
449 |
-} |
|
450 |
- |
|
451 | 443 |
func (s *DockerSuite) TestRunVolumesMountedAsReadonly(c *check.C) { |
452 | 444 |
cmd := exec.Command(dockerBinary, "run", "-v", "/test:/test:ro", "busybox", "touch", "/test/somefile") |
453 | 445 |
if code, err := runCommand(cmd); err == nil || code == 0 { |
... | ... |
@@ -10,7 +10,6 @@ import ( |
10 | 10 |
"net/http" |
11 | 11 |
"net/http/httptest" |
12 | 12 |
"os" |
13 |
- "os/exec" |
|
14 | 13 |
"path/filepath" |
15 | 14 |
"strings" |
16 | 15 |
|
... | ... |
@@ -18,25 +17,40 @@ import ( |
18 | 18 |
) |
19 | 19 |
|
20 | 20 |
func init() { |
21 |
- check.Suite(&ExternalVolumeSuite{ |
|
21 |
+ check.Suite(&DockerExternalVolumeSuite{ |
|
22 | 22 |
ds: &DockerSuite{}, |
23 | 23 |
}) |
24 | 24 |
} |
25 | 25 |
|
26 |
-type ExternalVolumeSuite struct { |
|
26 |
+type eventCounter struct { |
|
27 |
+ activations int |
|
28 |
+ creations int |
|
29 |
+ removals int |
|
30 |
+ mounts int |
|
31 |
+ unmounts int |
|
32 |
+ paths int |
|
33 |
+} |
|
34 |
+ |
|
35 |
+type DockerExternalVolumeSuite struct { |
|
27 | 36 |
server *httptest.Server |
28 | 37 |
ds *DockerSuite |
38 |
+ d *Daemon |
|
39 |
+ ec *eventCounter |
|
29 | 40 |
} |
30 | 41 |
|
31 |
-func (s *ExternalVolumeSuite) SetUpTest(c *check.C) { |
|
42 |
+func (s *DockerExternalVolumeSuite) SetUpTest(c *check.C) { |
|
43 |
+ s.d = NewDaemon(c) |
|
32 | 44 |
s.ds.SetUpTest(c) |
45 |
+ s.ec = &eventCounter{} |
|
46 |
+ |
|
33 | 47 |
} |
34 | 48 |
|
35 |
-func (s *ExternalVolumeSuite) TearDownTest(c *check.C) { |
|
49 |
+func (s *DockerExternalVolumeSuite) TearDownTest(c *check.C) { |
|
50 |
+ s.d.Stop() |
|
36 | 51 |
s.ds.TearDownTest(c) |
37 | 52 |
} |
38 | 53 |
|
39 |
-func (s *ExternalVolumeSuite) SetUpSuite(c *check.C) { |
|
54 |
+func (s *DockerExternalVolumeSuite) SetUpSuite(c *check.C) { |
|
40 | 55 |
mux := http.NewServeMux() |
41 | 56 |
s.server = httptest.NewServer(mux) |
42 | 57 |
|
... | ... |
@@ -44,26 +58,30 @@ func (s *ExternalVolumeSuite) SetUpSuite(c *check.C) { |
44 | 44 |
name string |
45 | 45 |
} |
46 | 46 |
|
47 |
- hostVolumePath := func(name string) string { |
|
48 |
- return fmt.Sprintf("/var/lib/docker/volumes/%s", name) |
|
49 |
- } |
|
50 |
- |
|
51 | 47 |
mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) { |
48 |
+ s.ec.activations++ |
|
49 |
+ |
|
52 | 50 |
w.Header().Set("Content-Type", "appplication/vnd.docker.plugins.v1+json") |
53 | 51 |
fmt.Fprintln(w, `{"Implements": ["VolumeDriver"]}`) |
54 | 52 |
}) |
55 | 53 |
|
56 | 54 |
mux.HandleFunc("/VolumeDriver.Create", func(w http.ResponseWriter, r *http.Request) { |
55 |
+ s.ec.creations++ |
|
56 |
+ |
|
57 | 57 |
w.Header().Set("Content-Type", "appplication/vnd.docker.plugins.v1+json") |
58 | 58 |
fmt.Fprintln(w, `{}`) |
59 | 59 |
}) |
60 | 60 |
|
61 | 61 |
mux.HandleFunc("/VolumeDriver.Remove", func(w http.ResponseWriter, r *http.Request) { |
62 |
+ s.ec.removals++ |
|
63 |
+ |
|
62 | 64 |
w.Header().Set("Content-Type", "appplication/vnd.docker.plugins.v1+json") |
63 | 65 |
fmt.Fprintln(w, `{}`) |
64 | 66 |
}) |
65 | 67 |
|
66 | 68 |
mux.HandleFunc("/VolumeDriver.Path", func(w http.ResponseWriter, r *http.Request) { |
69 |
+ s.ec.paths++ |
|
70 |
+ |
|
67 | 71 |
var pr pluginRequest |
68 | 72 |
if err := json.NewDecoder(r.Body).Decode(&pr); err != nil { |
69 | 73 |
http.Error(w, err.Error(), 500) |
... | ... |
@@ -76,6 +94,8 @@ func (s *ExternalVolumeSuite) SetUpSuite(c *check.C) { |
76 | 76 |
}) |
77 | 77 |
|
78 | 78 |
mux.HandleFunc("/VolumeDriver.Mount", func(w http.ResponseWriter, r *http.Request) { |
79 |
+ s.ec.mounts++ |
|
80 |
+ |
|
79 | 81 |
var pr pluginRequest |
80 | 82 |
if err := json.NewDecoder(r.Body).Decode(&pr); err != nil { |
81 | 83 |
http.Error(w, err.Error(), 500) |
... | ... |
@@ -94,7 +114,9 @@ func (s *ExternalVolumeSuite) SetUpSuite(c *check.C) { |
94 | 94 |
fmt.Fprintln(w, fmt.Sprintf("{\"Mountpoint\": \"%s\"}", p)) |
95 | 95 |
}) |
96 | 96 |
|
97 |
- mux.HandleFunc("/VolumeDriver.Umount", func(w http.ResponseWriter, r *http.Request) { |
|
97 |
+ mux.HandleFunc("/VolumeDriver.Unmount", func(w http.ResponseWriter, r *http.Request) { |
|
98 |
+ s.ec.unmounts++ |
|
99 |
+ |
|
98 | 100 |
var pr pluginRequest |
99 | 101 |
if err := json.NewDecoder(r.Body).Decode(&pr); err != nil { |
100 | 102 |
http.Error(w, err.Error(), 500) |
... | ... |
@@ -118,7 +140,7 @@ func (s *ExternalVolumeSuite) SetUpSuite(c *check.C) { |
118 | 118 |
} |
119 | 119 |
} |
120 | 120 |
|
121 |
-func (s *ExternalVolumeSuite) TearDownSuite(c *check.C) { |
|
121 |
+func (s *DockerExternalVolumeSuite) TearDownSuite(c *check.C) { |
|
122 | 122 |
s.server.Close() |
123 | 123 |
|
124 | 124 |
if err := os.RemoveAll("/usr/share/docker/plugins"); err != nil { |
... | ... |
@@ -126,14 +148,102 @@ func (s *ExternalVolumeSuite) TearDownSuite(c *check.C) { |
126 | 126 |
} |
127 | 127 |
} |
128 | 128 |
|
129 |
-func (s *ExternalVolumeSuite) TestStartExternalVolumeDriver(c *check.C) { |
|
130 |
- runCmd := exec.Command(dockerBinary, "run", "--name", "test-data", "-v", "external-volume-test:/tmp/external-volume-test", "--volume-driver", "test-external-volume-driver", "busybox:latest", "cat", "/tmp/external-volume-test/test") |
|
131 |
- out, stderr, exitCode, err := runCommandWithStdoutStderr(runCmd) |
|
132 |
- if err != nil && exitCode != 0 { |
|
133 |
- c.Fatal(out, stderr, err) |
|
129 |
+func (s *DockerExternalVolumeSuite) TestStartExternalNamedVolumeDriver(c *check.C) { |
|
130 |
+ if err := s.d.StartWithBusybox(); err != nil { |
|
131 |
+ c.Fatal(err) |
|
132 |
+ } |
|
133 |
+ |
|
134 |
+ out, err := s.d.Cmd("run", "--rm", "--name", "test-data", "-v", "external-volume-test:/tmp/external-volume-test", "--volume-driver", "test-external-volume-driver", "busybox:latest", "cat", "/tmp/external-volume-test/test") |
|
135 |
+ if err != nil { |
|
136 |
+ c.Fatal(err) |
|
134 | 137 |
} |
135 | 138 |
|
136 | 139 |
if !strings.Contains(out, s.server.URL) { |
137 | 140 |
c.Fatalf("External volume mount failed. Output: %s\n", out) |
138 | 141 |
} |
142 |
+ |
|
143 |
+ p := hostVolumePath("external-volume-test") |
|
144 |
+ _, err = os.Lstat(p) |
|
145 |
+ if err == nil { |
|
146 |
+ c.Fatalf("Expected error checking volume path in host: %s\n", p) |
|
147 |
+ } |
|
148 |
+ |
|
149 |
+ if !os.IsNotExist(err) { |
|
150 |
+ c.Fatalf("Expected volume path in host to not exist: %s, %v\n", p, err) |
|
151 |
+ } |
|
152 |
+ |
|
153 |
+ c.Assert(s.ec.activations, check.Equals, 1) |
|
154 |
+ c.Assert(s.ec.creations, check.Equals, 1) |
|
155 |
+ c.Assert(s.ec.removals, check.Equals, 1) |
|
156 |
+ c.Assert(s.ec.mounts, check.Equals, 1) |
|
157 |
+ c.Assert(s.ec.unmounts, check.Equals, 1) |
|
158 |
+} |
|
159 |
+ |
|
160 |
+func (s *DockerExternalVolumeSuite) TestStartExternalVolumeUnnamedDriver(c *check.C) { |
|
161 |
+ if err := s.d.StartWithBusybox(); err != nil { |
|
162 |
+ c.Fatal(err) |
|
163 |
+ } |
|
164 |
+ |
|
165 |
+ out, err := s.d.Cmd("run", "--rm", "--name", "test-data", "-v", "/tmp/external-volume-test", "--volume-driver", "test-external-volume-driver", "busybox:latest", "cat", "/tmp/external-volume-test/test") |
|
166 |
+ if err != nil { |
|
167 |
+ c.Fatal(err) |
|
168 |
+ } |
|
169 |
+ |
|
170 |
+ if !strings.Contains(out, s.server.URL) { |
|
171 |
+ c.Fatalf("External volume mount failed. Output: %s\n", out) |
|
172 |
+ } |
|
173 |
+ |
|
174 |
+ c.Assert(s.ec.activations, check.Equals, 1) |
|
175 |
+ c.Assert(s.ec.creations, check.Equals, 1) |
|
176 |
+ c.Assert(s.ec.removals, check.Equals, 1) |
|
177 |
+ c.Assert(s.ec.mounts, check.Equals, 1) |
|
178 |
+ c.Assert(s.ec.unmounts, check.Equals, 1) |
|
179 |
+} |
|
180 |
+ |
|
181 |
+func (s DockerExternalVolumeSuite) TestStartExternalVolumeDriverVolumesFrom(c *check.C) { |
|
182 |
+ if err := s.d.StartWithBusybox(); err != nil { |
|
183 |
+ c.Fatal(err) |
|
184 |
+ } |
|
185 |
+ |
|
186 |
+ if _, err := s.d.Cmd("run", "-d", "--name", "vol-test1", "-v", "/foo", "--volume-driver", "test-external-volume-driver", "busybox:latest"); err != nil { |
|
187 |
+ c.Fatal(err) |
|
188 |
+ } |
|
189 |
+ |
|
190 |
+ if _, err := s.d.Cmd("run", "--rm", "--volumes-from", "vol-test1", "--name", "vol-test2", "busybox", "ls", "/tmp"); err != nil { |
|
191 |
+ c.Fatal(err) |
|
192 |
+ } |
|
193 |
+ |
|
194 |
+ if _, err := s.d.Cmd("rm", "-f", "vol-test1"); err != nil { |
|
195 |
+ c.Fatal(err) |
|
196 |
+ } |
|
197 |
+ |
|
198 |
+ c.Assert(s.ec.activations, check.Equals, 1) |
|
199 |
+ c.Assert(s.ec.creations, check.Equals, 2) |
|
200 |
+ c.Assert(s.ec.removals, check.Equals, 1) |
|
201 |
+ c.Assert(s.ec.mounts, check.Equals, 2) |
|
202 |
+ c.Assert(s.ec.unmounts, check.Equals, 2) |
|
203 |
+} |
|
204 |
+ |
|
205 |
+func (s DockerExternalVolumeSuite) TestStartExternalVolumeDriverDeleteContainer(c *check.C) { |
|
206 |
+ if err := s.d.StartWithBusybox(); err != nil { |
|
207 |
+ c.Fatal(err) |
|
208 |
+ } |
|
209 |
+ |
|
210 |
+ if _, err := s.d.Cmd("run", "-d", "--name", "vol-test1", "-v", "/foo", "--volume-driver", "test-external-volume-driver", "busybox:latest"); err != nil { |
|
211 |
+ c.Fatal(err) |
|
212 |
+ } |
|
213 |
+ |
|
214 |
+ if _, err := s.d.Cmd("rm", "-fv", "vol-test1"); err != nil { |
|
215 |
+ c.Fatal(err) |
|
216 |
+ } |
|
217 |
+ |
|
218 |
+ c.Assert(s.ec.activations, check.Equals, 1) |
|
219 |
+ c.Assert(s.ec.creations, check.Equals, 1) |
|
220 |
+ c.Assert(s.ec.removals, check.Equals, 1) |
|
221 |
+ c.Assert(s.ec.mounts, check.Equals, 1) |
|
222 |
+ c.Assert(s.ec.unmounts, check.Equals, 1) |
|
223 |
+} |
|
224 |
+ |
|
225 |
+func hostVolumePath(name string) string { |
|
226 |
+ return fmt.Sprintf("/var/lib/docker/volumes/%s", name) |
|
139 | 227 |
} |
... | ... |
@@ -16,7 +16,10 @@ func (a *volumeDriverAdapter) Create(name string) (volume.Volume, error) { |
16 | 16 |
if err != nil { |
17 | 17 |
return nil, err |
18 | 18 |
} |
19 |
- return &volumeAdapter{a.proxy, name, a.name}, nil |
|
19 |
+ return &volumeAdapter{ |
|
20 |
+ proxy: a.proxy, |
|
21 |
+ name: name, |
|
22 |
+ driverName: a.name}, nil |
|
20 | 23 |
} |
21 | 24 |
|
22 | 25 |
func (a *volumeDriverAdapter) Remove(v volume.Volume) error { |
... | ... |
@@ -27,6 +30,7 @@ type volumeAdapter struct { |
27 | 27 |
proxy *volumeDriverProxy |
28 | 28 |
name string |
29 | 29 |
driverName string |
30 |
+ eMount string // ephemeral host volume path |
|
30 | 31 |
} |
31 | 32 |
|
32 | 33 |
func (a *volumeAdapter) Name() string { |
... | ... |
@@ -38,12 +42,17 @@ func (a *volumeAdapter) DriverName() string { |
38 | 38 |
} |
39 | 39 |
|
40 | 40 |
func (a *volumeAdapter) Path() string { |
41 |
+ if len(a.eMount) > 0 { |
|
42 |
+ return a.eMount |
|
43 |
+ } |
|
41 | 44 |
m, _ := a.proxy.Path(a.name) |
42 | 45 |
return m |
43 | 46 |
} |
44 | 47 |
|
45 | 48 |
func (a *volumeAdapter) Mount() (string, error) { |
46 |
- return a.proxy.Mount(a.name) |
|
49 |
+ var err error |
|
50 |
+ a.eMount, err = a.proxy.Mount(a.name) |
|
51 |
+ return a.eMount, err |
|
47 | 52 |
} |
48 | 53 |
|
49 | 54 |
func (a *volumeAdapter) Unmount() error { |
... | ... |
@@ -1,9 +1,9 @@ |
1 | 1 |
package volumedrivers |
2 | 2 |
|
3 | 3 |
import ( |
4 |
+ "fmt" |
|
4 | 5 |
"sync" |
5 | 6 |
|
6 |
- "github.com/Sirupsen/logrus" |
|
7 | 7 |
"github.com/docker/docker/pkg/plugins" |
8 | 8 |
"github.com/docker/docker/volume" |
9 | 9 |
) |
... | ... |
@@ -52,9 +52,9 @@ func Lookup(name string) (volume.Driver, error) { |
52 | 52 |
} |
53 | 53 |
pl, err := plugins.Get(name, "VolumeDriver") |
54 | 54 |
if err != nil { |
55 |
- logrus.Errorf("Error: %v", err) |
|
56 |
- return nil, err |
|
55 |
+ return nil, fmt.Errorf("Error looking up volume plugin %s: %v", name, err) |
|
57 | 56 |
} |
57 |
+ |
|
58 | 58 |
d := NewVolumeDriver(name, pl.Client) |
59 | 59 |
drivers.extensions[name] = d |
60 | 60 |
return d, nil |
... | ... |
@@ -1,5 +1,7 @@ |
1 | 1 |
package volumedrivers |
2 | 2 |
|
3 |
+import "fmt" |
|
4 |
+ |
|
3 | 5 |
// currently created by hand. generation tool would generate this like: |
4 | 6 |
// $ rpc-gen volume/drivers/api.go VolumeDriver > volume/drivers/proxy.go |
5 | 7 |
|
... | ... |
@@ -21,9 +23,9 @@ func (pp *volumeDriverProxy) Create(name string) error { |
21 | 21 |
var ret volumeDriverResponse |
22 | 22 |
err := pp.c.Call("VolumeDriver.Create", args, &ret) |
23 | 23 |
if err != nil { |
24 |
- return err |
|
24 |
+ return pp.fmtError(name, err) |
|
25 | 25 |
} |
26 |
- return ret.Err |
|
26 |
+ return pp.fmtError(name, ret.Err) |
|
27 | 27 |
} |
28 | 28 |
|
29 | 29 |
func (pp *volumeDriverProxy) Remove(name string) error { |
... | ... |
@@ -31,27 +33,27 @@ func (pp *volumeDriverProxy) Remove(name string) error { |
31 | 31 |
var ret volumeDriverResponse |
32 | 32 |
err := pp.c.Call("VolumeDriver.Remove", args, &ret) |
33 | 33 |
if err != nil { |
34 |
- return err |
|
34 |
+ return pp.fmtError(name, err) |
|
35 | 35 |
} |
36 |
- return ret.Err |
|
36 |
+ return pp.fmtError(name, ret.Err) |
|
37 | 37 |
} |
38 | 38 |
|
39 | 39 |
func (pp *volumeDriverProxy) Path(name string) (string, error) { |
40 | 40 |
args := volumeDriverRequest{name} |
41 | 41 |
var ret volumeDriverResponse |
42 | 42 |
if err := pp.c.Call("VolumeDriver.Path", args, &ret); err != nil { |
43 |
- return "", err |
|
43 |
+ return "", pp.fmtError(name, err) |
|
44 | 44 |
} |
45 |
- return ret.Mountpoint, ret.Err |
|
45 |
+ return ret.Mountpoint, pp.fmtError(name, ret.Err) |
|
46 | 46 |
} |
47 | 47 |
|
48 | 48 |
func (pp *volumeDriverProxy) Mount(name string) (string, error) { |
49 | 49 |
args := volumeDriverRequest{name} |
50 | 50 |
var ret volumeDriverResponse |
51 | 51 |
if err := pp.c.Call("VolumeDriver.Mount", args, &ret); err != nil { |
52 |
- return "", err |
|
52 |
+ return "", pp.fmtError(name, err) |
|
53 | 53 |
} |
54 |
- return ret.Mountpoint, ret.Err |
|
54 |
+ return ret.Mountpoint, pp.fmtError(name, ret.Err) |
|
55 | 55 |
} |
56 | 56 |
|
57 | 57 |
func (pp *volumeDriverProxy) Unmount(name string) error { |
... | ... |
@@ -59,7 +61,14 @@ func (pp *volumeDriverProxy) Unmount(name string) error { |
59 | 59 |
var ret volumeDriverResponse |
60 | 60 |
err := pp.c.Call("VolumeDriver.Unmount", args, &ret) |
61 | 61 |
if err != nil { |
62 |
- return err |
|
62 |
+ return pp.fmtError(name, err) |
|
63 |
+ } |
|
64 |
+ return pp.fmtError(name, ret.Err) |
|
65 |
+} |
|
66 |
+ |
|
67 |
+func (pp *volumeDriverProxy) fmtError(name string, err error) error { |
|
68 |
+ if err == nil { |
|
69 |
+ return nil |
|
63 | 70 |
} |
64 |
- return ret.Err |
|
71 |
+ return fmt.Errorf("External volume driver request failed for %s: %v", name, err) |
|
65 | 72 |
} |