namespaces_linux.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package configs
  2. import (
  3. "fmt"
  4. "os"
  5. "sync"
  6. )
  7. const (
  8. NEWNET NamespaceType = "NEWNET"
  9. NEWPID NamespaceType = "NEWPID"
  10. NEWNS NamespaceType = "NEWNS"
  11. NEWUTS NamespaceType = "NEWUTS"
  12. NEWIPC NamespaceType = "NEWIPC"
  13. NEWUSER NamespaceType = "NEWUSER"
  14. )
  15. var (
  16. nsLock sync.Mutex
  17. supportedNamespaces = make(map[NamespaceType]bool)
  18. )
  19. // NsName converts the namespace type to its filename
  20. func NsName(ns NamespaceType) string {
  21. switch ns {
  22. case NEWNET:
  23. return "net"
  24. case NEWNS:
  25. return "mnt"
  26. case NEWPID:
  27. return "pid"
  28. case NEWIPC:
  29. return "ipc"
  30. case NEWUSER:
  31. return "user"
  32. case NEWUTS:
  33. return "uts"
  34. }
  35. return ""
  36. }
  37. // IsNamespaceSupported returns whether a namespace is available or
  38. // not
  39. func IsNamespaceSupported(ns NamespaceType) bool {
  40. nsLock.Lock()
  41. defer nsLock.Unlock()
  42. supported, ok := supportedNamespaces[ns]
  43. if ok {
  44. return supported
  45. }
  46. nsFile := NsName(ns)
  47. // if the namespace type is unknown, just return false
  48. if nsFile == "" {
  49. return false
  50. }
  51. _, err := os.Stat(fmt.Sprintf("/proc/self/ns/%s", nsFile))
  52. // a namespace is supported if it exists and we have permissions to read it
  53. supported = err == nil
  54. supportedNamespaces[ns] = supported
  55. return supported
  56. }
  57. func NamespaceTypes() []NamespaceType {
  58. return []NamespaceType{
  59. NEWUSER, // Keep user NS always first, don't move it.
  60. NEWIPC,
  61. NEWUTS,
  62. NEWNET,
  63. NEWPID,
  64. NEWNS,
  65. }
  66. }
  67. // Namespace defines configuration for each namespace. It specifies an
  68. // alternate path that is able to be joined via setns.
  69. type Namespace struct {
  70. Type NamespaceType `json:"type"`
  71. Path string `json:"path"`
  72. }
  73. func (n *Namespace) GetPath(pid int) string {
  74. return fmt.Sprintf("/proc/%d/ns/%s", pid, NsName(n.Type))
  75. }
  76. func (n *Namespaces) Remove(t NamespaceType) bool {
  77. i := n.index(t)
  78. if i == -1 {
  79. return false
  80. }
  81. *n = append((*n)[:i], (*n)[i+1:]...)
  82. return true
  83. }
  84. func (n *Namespaces) Add(t NamespaceType, path string) {
  85. i := n.index(t)
  86. if i == -1 {
  87. *n = append(*n, Namespace{Type: t, Path: path})
  88. return
  89. }
  90. (*n)[i].Path = path
  91. }
  92. func (n *Namespaces) index(t NamespaceType) int {
  93. for i, ns := range *n {
  94. if ns.Type == t {
  95. return i
  96. }
  97. }
  98. return -1
  99. }
  100. func (n *Namespaces) Contains(t NamespaceType) bool {
  101. return n.index(t) != -1
  102. }
  103. func (n *Namespaces) PathOf(t NamespaceType) string {
  104. i := n.index(t)
  105. if i == -1 {
  106. return ""
  107. }
  108. return (*n)[i].Path
  109. }