From f376cf84b9becafbcb27604f1ae232b0564326e6 Mon Sep 17 00:00:00 2001 From: "Daniel, Dao Quang Minh" Date: Mon, 14 Sep 2015 00:31:33 +0000 Subject: [PATCH] Check if a namespace is supported This adds `configs.IsNamespaceSupported(nsType)` to check if the host supports a namespace type. Signed-off-by: Daniel, Dao Quang Minh --- libcontainer/configs/namespaces_unix.go | 72 +++++++++++++++++-------- 1 file changed, 51 insertions(+), 21 deletions(-) diff --git a/libcontainer/configs/namespaces_unix.go b/libcontainer/configs/namespaces_unix.go index 7bc908546..60707e369 100644 --- a/libcontainer/configs/namespaces_unix.go +++ b/libcontainer/configs/namespaces_unix.go @@ -2,7 +2,11 @@ package configs -import "fmt" +import ( + "fmt" + "os" + "sync" +) const ( NEWNET NamespaceType = "NEWNET" @@ -13,6 +17,51 @@ const ( NEWUSER NamespaceType = "NEWUSER" ) +var ( + nsLock sync.Mutex + supportedNamespaces = make(map[NamespaceType]bool) +) + +// nsToFile converts the namespace type to its filename +func nsToFile(ns NamespaceType) string { + switch ns { + case NEWNET: + return "net" + case NEWNS: + return "mnt" + case NEWPID: + return "pid" + case NEWIPC: + return "ipc" + case NEWUSER: + return "user" + case NEWUTS: + return "uts" + } + return "" +} + +// IsNamespaceSupported returns whether a namespace is available or +// not +func IsNamespaceSupported(ns NamespaceType) bool { + nsLock.Lock() + defer nsLock.Unlock() + supported, ok := supportedNamespaces[ns] + if ok { + return supported + } + nsFile := nsToFile(ns) + // if the namespace type is unknown, just return false + if nsFile == "" { + return false + } + _, err := os.Stat(fmt.Sprintf("/proc/self/ns/%s", nsFile)) + // a namespace is supported if it exists and we have permissions to read it + supported = err == nil + supportedNamespaces[ns] = supported + return supported +} + func NamespaceTypes() []NamespaceType { return []NamespaceType{ NEWNET, @@ -35,26 +84,7 @@ func (n *Namespace) GetPath(pid int) string { if n.Path != "" { return n.Path } - return fmt.Sprintf("/proc/%d/ns/%s", pid, n.file()) -} - -func (n *Namespace) file() string { - file := "" - switch n.Type { - case NEWNET: - file = "net" - case NEWNS: - file = "mnt" - case NEWPID: - file = "pid" - case NEWIPC: - file = "ipc" - case NEWUSER: - file = "user" - case NEWUTS: - file = "uts" - } - return file + return fmt.Sprintf("/proc/%d/ns/%s", pid, nsToFile(n.Type)) } func (n *Namespaces) Remove(t NamespaceType) bool {