From 623ebf203bc4f4e6ddefdd494f201a1401ab72a6 Mon Sep 17 00:00:00 2001 From: Alexandr Morozov Date: Wed, 10 Sep 2014 11:34:38 +0400 Subject: [PATCH 1/2] Persistent directory for container in execdriver This is needed for persistent namespaces Signed-off-by: Alexandr Morozov --- daemon/delete.go | 4 ++++ daemon/execdriver/driver.go | 1 + daemon/execdriver/lxc/driver.go | 5 +++++ daemon/execdriver/native/driver.go | 17 ++++++++++------- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/daemon/delete.go b/daemon/delete.go index 95cb567188..4501d91e22 100644 --- a/daemon/delete.go +++ b/daemon/delete.go @@ -115,6 +115,10 @@ func (daemon *Daemon) Destroy(container *Container) error { return fmt.Errorf("Unable to remove filesystem for %v: %v", container.ID, err) } + if err := daemon.execDriver.Clean(container.ID); err != nil { + return fmt.Errorf("Unable to remove execdriver data for %s: %s", container.ID, err) + } + selinuxFreeLxcContexts(container.ProcessLabel) return nil diff --git a/daemon/execdriver/driver.go b/daemon/execdriver/driver.go index cd65a2c7e1..3cd2877185 100644 --- a/daemon/execdriver/driver.go +++ b/daemon/execdriver/driver.go @@ -51,6 +51,7 @@ type Driver interface { Info(id string) Info // "temporary" hack (until we move state from core to plugins) GetPidsForContainer(id string) ([]int, error) // Returns a list of pids for the given container. Terminate(c *Command) error // kill it with fire + Clean(id string) error // clean all traces of container exec } // Network settings of the container diff --git a/daemon/execdriver/lxc/driver.go b/daemon/execdriver/lxc/driver.go index 13884fc699..9ddf673191 100644 --- a/daemon/execdriver/lxc/driver.go +++ b/daemon/execdriver/lxc/driver.go @@ -457,6 +457,11 @@ func (d *driver) generateEnvConfig(c *execdriver.Command) error { return ioutil.WriteFile(p, data, 0600) } +// Clean not implemented for lxc +func (d *driver) Clean(id string) error { + return nil +} + type TtyConsole struct { MasterPty *os.File SlavePty *os.File diff --git a/daemon/execdriver/native/driver.go b/daemon/execdriver/native/driver.go index ef3dc95818..3367fad1f2 100644 --- a/daemon/execdriver/native/driver.go +++ b/daemon/execdriver/native/driver.go @@ -94,7 +94,7 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba if err := d.createContainerRoot(c.ID); err != nil { return -1, err } - defer d.removeContainerRoot(c.ID) + defer d.cleanContainer(c.ID) if err := d.writeContainerFile(container, c.ID); err != nil { return -1, err @@ -186,7 +186,7 @@ func (d *driver) Terminate(p *execdriver.Command) error { err = syscall.Kill(p.ProcessConfig.Process.Pid, 9) syscall.Wait4(p.ProcessConfig.Process.Pid, nil, 0, nil) } - d.removeContainerRoot(p.ID) + d.cleanContainer(p.ID) return err @@ -227,15 +227,18 @@ func (d *driver) writeContainerFile(container *libcontainer.Config, id string) e return ioutil.WriteFile(filepath.Join(d.root, id, "container.json"), data, 0655) } +func (d *driver) cleanContainer(id string) error { + d.Lock() + delete(d.activeContainers, id) + d.Unlock() + return os.RemoveAll(filepath.Join(d.root, id, "container.json")) +} + func (d *driver) createContainerRoot(id string) error { return os.MkdirAll(filepath.Join(d.root, id), 0655) } -func (d *driver) removeContainerRoot(id string) error { - d.Lock() - delete(d.activeContainers, id) - d.Unlock() - +func (d *driver) Clean(id string) error { return os.RemoveAll(filepath.Join(d.root, id)) } From 652cd6a842377ec55b53333c7ddc0fc50b587a99 Mon Sep 17 00:00:00 2001 From: Alexandr Morozov Date: Wed, 10 Sep 2014 20:43:16 +0400 Subject: [PATCH 2/2] Test on execdriver dir behavior Signed-off-by: Alexandr Morozov --- integration-cli/docker_cli_run_test.go | 100 +++++++++++++++++++++++++ integration-cli/docker_test_vars.go | 2 + 2 files changed, 102 insertions(+) diff --git a/integration-cli/docker_cli_run_test.go b/integration-cli/docker_cli_run_test.go index df49f0f4ba..be9e081a4e 100644 --- a/integration-cli/docker_cli_run_test.go +++ b/integration-cli/docker_cli_run_test.go @@ -2062,3 +2062,103 @@ func TestRunMountOrdering(t *testing.T) { deleteAllContainers() logDone("run - volumes are mounted in the correct order") } + +func TestRunExecDir(t *testing.T) { + cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top") + out, _, err := runCommandWithOutput(cmd) + if err != nil { + t.Fatal(err, out) + } + id := strings.TrimSpace(out) + execDir := filepath.Join(execDriverPath, id) + stateFile := filepath.Join(execDir, "state.json") + contFile := filepath.Join(execDir, "container.json") + + { + fi, err := os.Stat(execDir) + if err != nil { + t.Fatal(err) + } + if !fi.IsDir() { + t.Fatalf("%q must be a directory", execDir) + } + fi, err = os.Stat(stateFile) + if err != nil { + t.Fatal(err) + } + fi, err = os.Stat(contFile) + if err != nil { + t.Fatal(err) + } + } + + stopCmd := exec.Command(dockerBinary, "stop", id) + out, _, err = runCommandWithOutput(stopCmd) + if err != nil { + t.Fatal(err, out) + } + { + fi, err := os.Stat(execDir) + if err != nil { + t.Fatal(err) + } + if !fi.IsDir() { + t.Fatalf("%q must be a directory", execDir) + } + fi, err = os.Stat(stateFile) + if err == nil { + t.Fatalf("Statefile %q is exists for stopped container!", stateFile) + } + if !os.IsNotExist(err) { + t.Fatalf("Error should be about non-existing, got %s", err) + } + fi, err = os.Stat(contFile) + if err == nil { + t.Fatalf("Container file %q is exists for stopped container!", contFile) + } + if !os.IsNotExist(err) { + t.Fatalf("Error should be about non-existing, got %s", err) + } + } + startCmd := exec.Command(dockerBinary, "start", id) + out, _, err = runCommandWithOutput(startCmd) + if err != nil { + t.Fatal(err, out) + } + { + fi, err := os.Stat(execDir) + if err != nil { + t.Fatal(err) + } + if !fi.IsDir() { + t.Fatalf("%q must be a directory", execDir) + } + fi, err = os.Stat(stateFile) + if err != nil { + t.Fatal(err) + } + fi, err = os.Stat(contFile) + if err != nil { + t.Fatal(err) + } + } + rmCmd := exec.Command(dockerBinary, "rm", "-f", id) + out, _, err = runCommandWithOutput(rmCmd) + if err != nil { + t.Fatal(err, out) + } + { + _, err := os.Stat(execDir) + if err == nil { + t.Fatal(err) + } + if err == nil { + t.Fatalf("Exec directory %q is exists for removed container!", execDir) + } + if !os.IsNotExist(err) { + t.Fatalf("Error should be about non-existing, got %s", err) + } + } + + logDone("run - check execdriver dir behavior") +} diff --git a/integration-cli/docker_test_vars.go b/integration-cli/docker_test_vars.go index 78e0685a9d..87bca92e9c 100644 --- a/integration-cli/docker_test_vars.go +++ b/integration-cli/docker_test_vars.go @@ -15,6 +15,8 @@ var registryImageName = "registry" // the private registry to use for tests var privateRegistryURL = "127.0.0.1:5000" +var execDriverPath = "/var/lib/docker/execdriver/native" + var workingDirectory string func init() {