namespaces_linux.go 2.4 KB

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