From cbc8dee085ac04921c7b56474ce1fc6a554f077a Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Tue, 7 Apr 2015 14:16:29 -0700 Subject: [PATCH] Ensure that state always contains pathes to all namespaces Thanks coolljit0725 for initial fix. Closes #512 Signed-off-by: Alexander Morozov --- configs/namespaces.go | 11 ++++++ container_linux.go | 6 ++++ container_linux_test.go | 3 +- integration/exec_test.go | 74 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 1 deletion(-) diff --git a/configs/namespaces.go b/configs/namespaces.go index 9078e6ab..ac6a7fa2 100644 --- a/configs/namespaces.go +++ b/configs/namespaces.go @@ -16,6 +16,17 @@ const ( NEWUSER NamespaceType = "NEWUSER" ) +func NamespaceTypes() []NamespaceType { + return []NamespaceType{ + NEWNET, + NEWPID, + NEWNS, + NEWUTS, + NEWIPC, + NEWUSER, + } +} + // Namespace defines configuration for each namespace. It specifies an // alternate path that is able to be joined via setns. type Namespace struct { diff --git a/container_linux.go b/container_linux.go index 3c077afb..d52610f0 100644 --- a/container_linux.go +++ b/container_linux.go @@ -306,5 +306,11 @@ func (c *linuxContainer) currentState() (*State, error) { for _, ns := range c.config.Namespaces { state.NamespacePaths[ns.Type] = ns.GetPath(c.initProcess.pid()) } + for _, nsType := range configs.NamespaceTypes() { + if _, ok := state.NamespacePaths[nsType]; !ok { + ns := configs.Namespace{Type: nsType} + state.NamespacePaths[ns.Type] = ns.GetPath(c.initProcess.pid()) + } + } return state, nil } diff --git a/container_linux_test.go b/container_linux_test.go index 5ee46ab1..b05733e5 100644 --- a/container_linux_test.go +++ b/container_linux_test.go @@ -130,7 +130,8 @@ func TestGetContainerState(t *testing.T) { {Type: configs.NEWNS}, {Type: configs.NEWNET, Path: expectedNetworkPath}, {Type: configs.NEWUTS}, - {Type: configs.NEWIPC}, + // emulate host for IPC + //{Type: configs.NEWIPC}, }, }, initProcess: &mockProcess{ diff --git a/integration/exec_test.go b/integration/exec_test.go index b5a34b5e..12457ba1 100644 --- a/integration/exec_test.go +++ b/integration/exec_test.go @@ -574,3 +574,77 @@ func testFreeze(t *testing.T, systemd bool) { t.Fatal(s.String()) } } + +func TestContainerState(t *testing.T) { + if testing.Short() { + return + } + root, err := newTestRoot() + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(root) + + rootfs, err := newRootfs() + if err != nil { + t.Fatal(err) + } + defer remove(rootfs) + + l, err := os.Readlink("/proc/1/ns/ipc") + if err != nil { + t.Fatal(err) + } + + config := newTemplateConfig(rootfs) + config.Namespaces = configs.Namespaces([]configs.Namespace{ + {Type: configs.NEWNS}, + {Type: configs.NEWUTS}, + // host for IPC + //{Type: configs.NEWIPC}, + {Type: configs.NEWPID}, + {Type: configs.NEWNET}, + }) + + factory, err := libcontainer.New(root, libcontainer.Cgroupfs) + if err != nil { + t.Fatal(err) + } + + container, err := factory.Create("test", config) + if err != nil { + t.Fatal(err) + } + defer container.Destroy() + + stdinR, stdinW, err := os.Pipe() + if err != nil { + t.Fatal(err) + } + p := &libcontainer.Process{ + Args: []string{"cat"}, + Env: standardEnvironment, + Stdin: stdinR, + } + err = container.Start(p) + if err != nil { + t.Fatal(err) + } + stdinR.Close() + defer p.Signal(os.Kill) + + st, err := container.State() + if err != nil { + t.Fatal(err) + } + + l1, err := os.Readlink(st.NamespacePaths[configs.NEWIPC]) + if err != nil { + t.Fatal(err) + } + if l1 != l { + t.Fatal("Container using non-host ipc namespace") + } + stdinW.Close() + p.Wait() +}