Signed-off-by: David Calavera <david.calavera@gmail.com>
| ... | ... |
@@ -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 |
} |