Ensure that state always contains pathes to all namespaces

Thanks coolljit0725 for initial fix.

Closes #512

Signed-off-by: Alexander Morozov <lk4d4@docker.com>
This commit is contained in:
Alexander Morozov 2015-04-07 14:16:29 -07:00
parent 6012d1056d
commit cbc8dee085
4 changed files with 93 additions and 1 deletions

View File

@ -16,6 +16,17 @@ const (
NEWUSER NamespaceType = "NEWUSER" NEWUSER NamespaceType = "NEWUSER"
) )
func NamespaceTypes() []NamespaceType {
return []NamespaceType{
NEWNET,
NEWPID,
NEWNS,
NEWUTS,
NEWIPC,
NEWUSER,
}
}
// Namespace defines configuration for each namespace. It specifies an // Namespace defines configuration for each namespace. It specifies an
// alternate path that is able to be joined via setns. // alternate path that is able to be joined via setns.
type Namespace struct { type Namespace struct {

View File

@ -306,5 +306,11 @@ func (c *linuxContainer) currentState() (*State, error) {
for _, ns := range c.config.Namespaces { for _, ns := range c.config.Namespaces {
state.NamespacePaths[ns.Type] = ns.GetPath(c.initProcess.pid()) 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 return state, nil
} }

View File

@ -130,7 +130,8 @@ func TestGetContainerState(t *testing.T) {
{Type: configs.NEWNS}, {Type: configs.NEWNS},
{Type: configs.NEWNET, Path: expectedNetworkPath}, {Type: configs.NEWNET, Path: expectedNetworkPath},
{Type: configs.NEWUTS}, {Type: configs.NEWUTS},
{Type: configs.NEWIPC}, // emulate host for IPC
//{Type: configs.NEWIPC},
}, },
}, },
initProcess: &mockProcess{ initProcess: &mockProcess{

View File

@ -574,3 +574,77 @@ func testFreeze(t *testing.T, systemd bool) {
t.Fatal(s.String()) 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()
}