diff --git a/daemon/mgr/container_storage.go b/daemon/mgr/container_storage.go index 15297004a..9fe00637e 100644 --- a/daemon/mgr/container_storage.go +++ b/daemon/mgr/container_storage.go @@ -8,6 +8,7 @@ import ( "path" "path/filepath" "regexp" + "sort" "strconv" "github.com/alibaba/pouch/apis/opts" @@ -359,6 +360,12 @@ func (mgr *ContainerManager) getMountPointFromContainers(ctx context.Context, co } func (mgr *ContainerManager) populateVolumes(ctx context.Context, c *Container) error { + // sort mounts by destination directory string shortest length. + // the reason is: there are two mounts: /home/admin and /home/admin/log, + // when do copy data with dr mode, if the data of /home/admin/log is copied first, + // it will cause /home/admin don't copy data since the destination directory is not empty. + c.Mounts = sortMountPoint(c.Mounts) + for _, mp := range c.Mounts { if mp.Driver == "tmpfs" { continue @@ -719,6 +726,17 @@ func (mgr *ContainerManager) SetupWorkingDirectory(ctx context.Context, c *Conta return nil } +func sortMountPoint(mounts []*types.MountPoint) []*types.MountPoint { + sort.Slice(mounts, func(i, j int) bool { + if len(mounts[i].Destination) < len(mounts[j].Destination) { + return true + } + return false + }) + + return mounts +} + func copyImageContent(source, destination string) error { fi, err := os.Stat(source) if err != nil { diff --git a/daemon/mgr/container_storage_test.go b/daemon/mgr/container_storage_test.go new file mode 100644 index 000000000..1ffccf926 --- /dev/null +++ b/daemon/mgr/container_storage_test.go @@ -0,0 +1,71 @@ +package mgr + +import ( + "testing" + + "github.com/alibaba/pouch/apis/types" +) + +func TestSortMountPoint(t *testing.T) { + mounts := []*types.MountPoint{ + { + Destination: "/home/admin/log", + Source: "/pouch/volume1", + }, + { + Destination: "/var/lib", + Source: "/pouch/volume2", + }, + { + Destination: "/home/admin", + Source: "/pouch/volume3", + }, + { + Destination: "/home", + Source: "/pouch/volume4", + }, + { + Destination: "/opt", + Source: "/pouch/volume5", + }, + { + Destination: "/var/log", + Source: "/pouch/volume6", + }, + } + + expectMounts := []*types.MountPoint{ + { + Destination: "/opt", + Source: "/pouch/volume5", + }, + { + Destination: "/home", + Source: "/pouch/volume4", + }, + { + Destination: "/var/lib", + Source: "/pouch/volume2", + }, + { + Destination: "/var/log", + Source: "/pouch/volume6", + }, + { + Destination: "/home/admin", + Source: "/pouch/volume3", + }, + { + Destination: "/home/admin/log", + Source: "/pouch/volume1", + }, + } + + mounts = sortMountPoint(mounts) + for i := range mounts { + if mounts[i].Destination != expectMounts[i].Destination || + mounts[i].Source != expectMounts[i].Source { + t.Fatalf("got unexpect sort: %v, expect: %v", *mounts[i], *expectMounts[i]) + } + } +} diff --git a/test/cli_run_volume_test.go b/test/cli_run_volume_test.go index 36cb79e73..ed14a2d1b 100644 --- a/test/cli_run_volume_test.go +++ b/test/cli_run_volume_test.go @@ -395,3 +395,30 @@ func (suite *PouchRunVolumeSuite) TestRunWithDiskQuota(c *check.C) { c.Assert(found, check.Equals, true) } + +func (suite *PouchRunVolumeSuite) TestRunCopyDataWithDR(c *check.C) { + cname := "TestRunCopyDataWithDR_Container" + vname := "TestRunCopyDataWithDR_Volume" + + command.PouchRun("volume", "create", "-n", vname).Assert(c, icmd.Success) + defer command.PouchRun("volume", "rm", vname) + + command.PouchRun("run", "-d", "--name", cname, + "-v", vname+":/var/spool:dr", + "-v", vname+":/var:dr", + "-v", vname+":/data", busyboxImage, "top").Assert(c, icmd.Success) + defer command.PouchRun("rm", "-vf", cname) + + res := command.PouchRun("exec", cname, "ls", "/var") + res.Assert(c, icmd.Success) + if !strings.Contains(res.Stdout(), "spool") || + !strings.Contains(res.Stdout(), "www") { + c.Fatal("no copy image data, miss spool and www directory") + } + + res = command.PouchRun("exec", cname, "ls", "/var/spool") + res.Assert(c, icmd.Success) + if !strings.Contains(res.Stdout(), "mail") { + c.Fatal("no copy image data, miss mail directory") + } +}