sysinfo_linux.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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. weight := cgroupEnabled(mountPoint, "blkio.weight")
  105. if !quiet && !weight {
  106. logrus.Warn("Your kernel does not support cgroup blkio weight")
  107. }
  108. weightDevice := cgroupEnabled(mountPoint, "blkio.weight_device")
  109. if !quiet && !weightDevice {
  110. logrus.Warn("Your kernel does not support cgroup blkio weight_device")
  111. }
  112. readBpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.read_bps_device")
  113. if !quiet && !readBpsDevice {
  114. logrus.Warn("Your kernel does not support cgroup blkio throttle.read_bps_device")
  115. }
  116. writeBpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.write_bps_device")
  117. if !quiet && !writeBpsDevice {
  118. logrus.Warn("Your kernel does not support cgroup blkio throttle.write_bps_device")
  119. }
  120. return cgroupBlkioInfo{
  121. BlkioWeight: weight,
  122. BlkioWeightDevice: weightDevice,
  123. BlkioReadBpsDevice: readBpsDevice,
  124. BlkioWriteBpsDevice: writeBpsDevice,
  125. }
  126. }
  127. // checkCgroupCpusetInfo reads the cpuset information from the cpuset cgroup mount point.
  128. func checkCgroupCpusetInfo(quiet bool) cgroupCpusetInfo {
  129. mountPoint, err := cgroups.FindCgroupMountpoint("cpuset")
  130. if err != nil {
  131. if !quiet {
  132. logrus.Warn(err)
  133. }
  134. return cgroupCpusetInfo{}
  135. }
  136. cpus, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.cpus"))
  137. if err != nil {
  138. return cgroupCpusetInfo{}
  139. }
  140. mems, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.mems"))
  141. if err != nil {
  142. return cgroupCpusetInfo{}
  143. }
  144. return cgroupCpusetInfo{
  145. Cpuset: true,
  146. Cpus: strings.TrimSpace(string(cpus)),
  147. Mems: strings.TrimSpace(string(mems)),
  148. }
  149. }
  150. func cgroupEnabled(mountPoint, name string) bool {
  151. _, err := os.Stat(path.Join(mountPoint, name))
  152. return err == nil
  153. }
  154. func readProcBool(path string) bool {
  155. val, err := ioutil.ReadFile(path)
  156. if err != nil {
  157. return false
  158. }
  159. return strings.TrimSpace(string(val)) == "1"
  160. }