"os"
"path"
"runtime"
+ "strings"
"sync"
"syscall"
return GetNS(getCurrentThreadNetNSPath())
}
-// Returns an object representing the namespace referred to by @path
-func GetNS(nspath string) (NetNS, error) {
- fd, err := os.Open(nspath)
- if err != nil {
- return nil, fmt.Errorf("Failed to open %v: %v", nspath, err)
+const (
+ // https://github.com/torvalds/linux/blob/master/include/uapi/linux/magic.h
+ NSFS_MAGIC = 0x6e736673
+ PROCFS_MAGIC = 0x9fa0
+)
+
+func IsNS(nspath string) (isNS bool, msg string, err error) {
+ stat := syscall.Statfs_t{}
+ if err = syscall.Statfs(nspath, &stat); err != nil {
+ err = fmt.Errorf("failed to Statfs %s: %v", nspath, err)
+ return
+ }
+
+ switch stat.Type {
+ case PROCFS_MAGIC:
+ // Kernel < 3.19
+
+ validPathContent := "ns/"
+ validName := strings.Contains(nspath, validPathContent)
+ if !validName {
+ msg = fmt.Sprintf("path doesn't contain %q", validPathContent)
+ return
+ }
+ isNS = true
+ case NSFS_MAGIC:
+ // Kernel >= 3.19
+
+ isNS = true
+ default:
+ msg = fmt.Sprintf("unknown FS magic: %x", stat.Type)
}
+ return
+}
- isNSFS, err := IsNSFS(nspath)
+// Returns an object representing the namespace referred to by @path
+func GetNS(nspath string) (NetNS, error) {
+ isNS, msg, err := IsNS(nspath)
if err != nil {
- fd.Close()
return nil, err
}
- if !isNSFS {
- fd.Close()
- return nil, fmt.Errorf("%v is not of type NSFS", nspath)
+ if !isNS {
+ return nil, fmt.Errorf("no network namespace detected on %s: %s", nspath, msg)
}
- return &netNS{file: fd}, nil
-}
-
-// Returns whether or not the nspath argument points to a network namespace
-func IsNSFS(nspath string) (bool, error) {
- const NSFS_MAGIC = 0x6e736673
-
- stat := syscall.Statfs_t{}
- if err := syscall.Statfs(nspath, &stat); err != nil {
- return false, fmt.Errorf("failed to Statfs %q: %v", nspath, err)
+ fd, err := os.Open(nspath)
+ if err != nil {
+ return nil, fmt.Errorf("Failed to open %v: %v", nspath, err)
}
- return stat.Type == NSFS_MAGIC, nil
+ return &netNS{file: fd}, nil
}
// Creates a new persistent network namespace and returns an object
defer os.Remove(nspath)
_, err = ns.GetNS(nspath)
- Expect(err).To(MatchError(fmt.Sprintf("%v is not of type NSFS", nspath)))
+ Expect(err).To(HaveOccurred())
+ errString := fmt.Sprintf("%v", err)
+ Expect(errString).To(HavePrefix("no network namespace detected on %s", nspath))
})
})
})
})
- Describe("IsNSFS", func() {
+ Describe("IsNS", func() {
It("should detect a namespace", func() {
createdNetNS, err := ns.NewNS()
- isNSFS, err := ns.IsNSFS(createdNetNS.Path())
+ isNSFS, msg, err := ns.IsNS(createdNetNS.Path())
Expect(err).NotTo(HaveOccurred())
+ Expect(msg).To(Equal(""))
Expect(isNSFS).To(Equal(true))
})
nspath := tempFile.Name()
defer os.Remove(nspath)
- isNSFS, err := ns.IsNSFS(nspath)
+ isNSFS, _, err := ns.IsNS(nspath)
Expect(err).NotTo(HaveOccurred())
Expect(isNSFS).To(Equal(false))
})