sysinfo_linux.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. package sysinfo
  2. import (
  3. "io/ioutil"
  4. "os"
  5. "path"
  6. "strings"
  7. "github.com/Sirupsen/logrus"
  8. "github.com/opencontainers/runc/libcontainer/cgroups"
  9. )
  10. // New returns a new SysInfo, using the filesystem to detect which features
  11. // the kernel supports. If `quiet` is `false` warnings are printed in logs
  12. // whenever an error occurs or misconfigurations are present.
  13. func New(quiet bool) *SysInfo {
  14. sysInfo := &SysInfo{}
  15. sysInfo.cgroupMemInfo = checkCgroupMem(quiet)
  16. sysInfo.cgroupCPUInfo = checkCgroupCPU(quiet)
  17. sysInfo.cgroupBlkioInfo = checkCgroupBlkioInfo(quiet)
  18. sysInfo.cgroupCpusetInfo = checkCgroupCpusetInfo(quiet)
  19. _, err := cgroups.FindCgroupMountpoint("devices")
  20. sysInfo.CgroupDevicesEnabled = err == nil
  21. sysInfo.IPv4ForwardingDisabled = !readProcBool("/proc/sys/net/ipv4/ip_forward")
  22. sysInfo.BridgeNfCallIptablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-iptables")
  23. sysInfo.BridgeNfCallIP6tablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-ip6tables")
  24. // Check if AppArmor is supported.
  25. if _, err := os.Stat("/sys/kernel/security/apparmor"); !os.IsNotExist(err) {
  26. sysInfo.AppArmor = true
  27. }
  28. return sysInfo
  29. }
  30. // checkCgroupMem reads the memory information from the memory cgroup mount point.
  31. func checkCgroupMem(quiet bool) cgroupMemInfo {
  32. mountPoint, err := cgroups.FindCgroupMountpoint("memory")
  33. if err != nil {
  34. if !quiet {
  35. logrus.Warnf("Your kernel does not support cgroup memory limit: %v", err)
  36. }
  37. return cgroupMemInfo{}
  38. }
  39. swapLimit := cgroupEnabled(mountPoint, "memory.memsw.limit_in_bytes")
  40. if !quiet && !swapLimit {
  41. logrus.Warn("Your kernel does not support swap memory limit.")
  42. }
  43. memoryReservation := cgroupEnabled(mountPoint, "memory.soft_limit_in_bytes")
  44. if !quiet && !memoryReservation {
  45. logrus.Warn("Your kernel does not support memory reservation.")
  46. }
  47. oomKillDisable := cgroupEnabled(mountPoint, "memory.oom_control")
  48. if !quiet && !oomKillDisable {
  49. logrus.Warnf("Your kernel does not support oom control.")
  50. }
  51. memorySwappiness := cgroupEnabled(mountPoint, "memory.swappiness")
  52. if !quiet && !memorySwappiness {
  53. logrus.Warnf("Your kernel does not support memory swappiness.")
  54. }
  55. kernelMemory := cgroupEnabled(mountPoint, "memory.kmem.limit_in_bytes")
  56. if !quiet && !kernelMemory {
  57. logrus.Warnf("Your kernel does not support kernel memory limit.")
  58. }
  59. return cgroupMemInfo{
  60. MemoryLimit: true,
  61. SwapLimit: swapLimit,
  62. MemoryReservation: memoryReservation,
  63. OomKillDisable: oomKillDisable,
  64. MemorySwappiness: memorySwappiness,
  65. KernelMemory: kernelMemory,
  66. }
  67. }
  68. // checkCgroupCPU reads the cpu information from the cpu cgroup mount point.
  69. func checkCgroupCPU(quiet bool) cgroupCPUInfo {
  70. mountPoint, err := cgroups.FindCgroupMountpoint("cpu")
  71. if err != nil {
  72. if !quiet {
  73. logrus.Warn(err)
  74. }
  75. return cgroupCPUInfo{}
  76. }
  77. cpuShares := cgroupEnabled(mountPoint, "cpu.shares")
  78. if !quiet && !cpuShares {
  79. logrus.Warn("Your kernel does not support cgroup cpu shares")
  80. }
  81. cpuCfsPeriod := cgroupEnabled(mountPoint, "cpu.cfs_period_us")
  82. if !quiet && !cpuCfsPeriod {
  83. logrus.Warn("Your kernel does not support cgroup cfs period")
  84. }
  85. cpuCfsQuota := cgroupEnabled(mountPoint, "cpu.cfs_quota_us")
  86. if !quiet && !cpuCfsQuota {
  87. logrus.Warn("Your kernel does not support cgroup cfs quotas")
  88. }
  89. return cgroupCPUInfo{
  90. CPUShares: cpuShares,
  91. CPUCfsPeriod: cpuCfsPeriod,
  92. CPUCfsQuota: cpuCfsQuota,
  93. }
  94. }
  95. // checkCgroupBlkioInfo reads the blkio information from the blkio cgroup mount point.
  96. func checkCgroupBlkioInfo(quiet bool) cgroupBlkioInfo {
  97. mountPoint, err := cgroups.FindCgroupMountpoint("blkio")
  98. if err != nil {
  99. if !quiet {
  100. logrus.Warn(err)
  101. }
  102. return cgroupBlkioInfo{}
  103. }
  104. w := cgroupEnabled(mountPoint, "blkio.weight")
  105. if !quiet && !w {
  106. logrus.Warn("Your kernel does not support cgroup blkio weight")
  107. }
  108. return cgroupBlkioInfo{BlkioWeight: w}
  109. }
  110. // checkCgroupCpusetInfo reads the cpuset information from the cpuset cgroup mount point.
  111. func checkCgroupCpusetInfo(quiet bool) cgroupCpusetInfo {
  112. _, err := cgroups.FindCgroupMountpoint("cpuset")
  113. if err != nil {
  114. if !quiet {
  115. logrus.Warn(err)
  116. }
  117. return cgroupCpusetInfo{}
  118. }
  119. return cgroupCpusetInfo{Cpuset: true}
  120. }
  121. func cgroupEnabled(mountPoint, name string) bool {
  122. _, err := os.Stat(path.Join(mountPoint, name))
  123. return err == nil
  124. }
  125. func readProcBool(path string) bool {
  126. val, err := ioutil.ReadFile(path)
  127. if err != nil {
  128. return false
  129. }
  130. return strings.TrimSpace(string(val)) == "1"
  131. }