github.com/reds/docker@v1.11.2-rc1/pkg/sysinfo/sysinfo_linux.go (about) 1 package sysinfo 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path" 8 "strings" 9 "syscall" 10 11 "github.com/Sirupsen/logrus" 12 "github.com/opencontainers/runc/libcontainer/cgroups" 13 ) 14 15 const ( 16 // SeccompModeFilter refers to the syscall argument SECCOMP_MODE_FILTER. 17 SeccompModeFilter = uintptr(2) 18 ) 19 20 func findCgroupMountpoints() (map[string]string, error) { 21 cgMounts, err := cgroups.GetCgroupMounts() 22 if err != nil { 23 return nil, fmt.Errorf("Failed to parse cgroup information: %v", err) 24 } 25 mps := make(map[string]string) 26 for _, m := range cgMounts { 27 for _, ss := range m.Subsystems { 28 mps[ss] = m.Mountpoint 29 } 30 } 31 return mps, nil 32 } 33 34 // New returns a new SysInfo, using the filesystem to detect which features 35 // the kernel supports. If `quiet` is `false` warnings are printed in logs 36 // whenever an error occurs or misconfigurations are present. 37 func New(quiet bool) *SysInfo { 38 sysInfo := &SysInfo{} 39 cgMounts, err := findCgroupMountpoints() 40 if err != nil { 41 logrus.Warnf("Failed to parse cgroup information: %v", err) 42 } else { 43 sysInfo.cgroupMemInfo = checkCgroupMem(cgMounts, quiet) 44 sysInfo.cgroupCPUInfo = checkCgroupCPU(cgMounts, quiet) 45 sysInfo.cgroupBlkioInfo = checkCgroupBlkioInfo(cgMounts, quiet) 46 sysInfo.cgroupCpusetInfo = checkCgroupCpusetInfo(cgMounts, quiet) 47 sysInfo.cgroupPids = checkCgroupPids(quiet) 48 } 49 50 _, ok := cgMounts["devices"] 51 sysInfo.CgroupDevicesEnabled = ok 52 53 sysInfo.IPv4ForwardingDisabled = !readProcBool("/proc/sys/net/ipv4/ip_forward") 54 sysInfo.BridgeNFCallIPTablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-iptables") 55 sysInfo.BridgeNFCallIP6TablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-ip6tables") 56 57 // Check if AppArmor is supported. 58 if _, err := os.Stat("/sys/kernel/security/apparmor"); !os.IsNotExist(err) { 59 sysInfo.AppArmor = true 60 } 61 62 // Check if Seccomp is supported, via CONFIG_SECCOMP. 63 if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_GET_SECCOMP, 0, 0); err != syscall.EINVAL { 64 // Make sure the kernel has CONFIG_SECCOMP_FILTER. 65 if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_SECCOMP, SeccompModeFilter, 0); err != syscall.EINVAL { 66 sysInfo.Seccomp = true 67 } 68 } 69 70 return sysInfo 71 } 72 73 // checkCgroupMem reads the memory information from the memory cgroup mount point. 74 func checkCgroupMem(cgMounts map[string]string, quiet bool) cgroupMemInfo { 75 mountPoint, ok := cgMounts["memory"] 76 if !ok { 77 if !quiet { 78 logrus.Warnf("Your kernel does not support cgroup memory limit") 79 } 80 return cgroupMemInfo{} 81 } 82 83 swapLimit := cgroupEnabled(mountPoint, "memory.memsw.limit_in_bytes") 84 if !quiet && !swapLimit { 85 logrus.Warn("Your kernel does not support swap memory limit.") 86 } 87 memoryReservation := cgroupEnabled(mountPoint, "memory.soft_limit_in_bytes") 88 if !quiet && !memoryReservation { 89 logrus.Warn("Your kernel does not support memory reservation.") 90 } 91 oomKillDisable := cgroupEnabled(mountPoint, "memory.oom_control") 92 if !quiet && !oomKillDisable { 93 logrus.Warnf("Your kernel does not support oom control.") 94 } 95 memorySwappiness := cgroupEnabled(mountPoint, "memory.swappiness") 96 if !quiet && !memorySwappiness { 97 logrus.Warnf("Your kernel does not support memory swappiness.") 98 } 99 kernelMemory := cgroupEnabled(mountPoint, "memory.kmem.limit_in_bytes") 100 if !quiet && !kernelMemory { 101 logrus.Warnf("Your kernel does not support kernel memory limit.") 102 } 103 104 return cgroupMemInfo{ 105 MemoryLimit: true, 106 SwapLimit: swapLimit, 107 MemoryReservation: memoryReservation, 108 OomKillDisable: oomKillDisable, 109 MemorySwappiness: memorySwappiness, 110 KernelMemory: kernelMemory, 111 } 112 } 113 114 // checkCgroupCPU reads the cpu information from the cpu cgroup mount point. 115 func checkCgroupCPU(cgMounts map[string]string, quiet bool) cgroupCPUInfo { 116 mountPoint, ok := cgMounts["cpu"] 117 if !ok { 118 if !quiet { 119 logrus.Warnf("Unable to find cpu cgroup in mounts") 120 } 121 return cgroupCPUInfo{} 122 } 123 124 cpuShares := cgroupEnabled(mountPoint, "cpu.shares") 125 if !quiet && !cpuShares { 126 logrus.Warn("Your kernel does not support cgroup cpu shares") 127 } 128 129 cpuCfsPeriod := cgroupEnabled(mountPoint, "cpu.cfs_period_us") 130 if !quiet && !cpuCfsPeriod { 131 logrus.Warn("Your kernel does not support cgroup cfs period") 132 } 133 134 cpuCfsQuota := cgroupEnabled(mountPoint, "cpu.cfs_quota_us") 135 if !quiet && !cpuCfsQuota { 136 logrus.Warn("Your kernel does not support cgroup cfs quotas") 137 } 138 return cgroupCPUInfo{ 139 CPUShares: cpuShares, 140 CPUCfsPeriod: cpuCfsPeriod, 141 CPUCfsQuota: cpuCfsQuota, 142 } 143 } 144 145 // checkCgroupBlkioInfo reads the blkio information from the blkio cgroup mount point. 146 func checkCgroupBlkioInfo(cgMounts map[string]string, quiet bool) cgroupBlkioInfo { 147 mountPoint, ok := cgMounts["blkio"] 148 if !ok { 149 if !quiet { 150 logrus.Warnf("Unable to find blkio cgroup in mounts") 151 } 152 return cgroupBlkioInfo{} 153 } 154 155 weight := cgroupEnabled(mountPoint, "blkio.weight") 156 if !quiet && !weight { 157 logrus.Warn("Your kernel does not support cgroup blkio weight") 158 } 159 160 weightDevice := cgroupEnabled(mountPoint, "blkio.weight_device") 161 if !quiet && !weightDevice { 162 logrus.Warn("Your kernel does not support cgroup blkio weight_device") 163 } 164 165 readBpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.read_bps_device") 166 if !quiet && !readBpsDevice { 167 logrus.Warn("Your kernel does not support cgroup blkio throttle.read_bps_device") 168 } 169 170 writeBpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.write_bps_device") 171 if !quiet && !writeBpsDevice { 172 logrus.Warn("Your kernel does not support cgroup blkio throttle.write_bps_device") 173 } 174 readIOpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.read_iops_device") 175 if !quiet && !readIOpsDevice { 176 logrus.Warn("Your kernel does not support cgroup blkio throttle.read_iops_device") 177 } 178 179 writeIOpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.write_iops_device") 180 if !quiet && !writeIOpsDevice { 181 logrus.Warn("Your kernel does not support cgroup blkio throttle.write_iops_device") 182 } 183 return cgroupBlkioInfo{ 184 BlkioWeight: weight, 185 BlkioWeightDevice: weightDevice, 186 BlkioReadBpsDevice: readBpsDevice, 187 BlkioWriteBpsDevice: writeBpsDevice, 188 BlkioReadIOpsDevice: readIOpsDevice, 189 BlkioWriteIOpsDevice: writeIOpsDevice, 190 } 191 } 192 193 // checkCgroupCpusetInfo reads the cpuset information from the cpuset cgroup mount point. 194 func checkCgroupCpusetInfo(cgMounts map[string]string, quiet bool) cgroupCpusetInfo { 195 mountPoint, ok := cgMounts["cpuset"] 196 if !ok { 197 if !quiet { 198 logrus.Warnf("Unable to find cpuset cgroup in mounts") 199 } 200 return cgroupCpusetInfo{} 201 } 202 203 cpus, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.cpus")) 204 if err != nil { 205 return cgroupCpusetInfo{} 206 } 207 208 mems, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.mems")) 209 if err != nil { 210 return cgroupCpusetInfo{} 211 } 212 213 return cgroupCpusetInfo{ 214 Cpuset: true, 215 Cpus: strings.TrimSpace(string(cpus)), 216 Mems: strings.TrimSpace(string(mems)), 217 } 218 } 219 220 // checkCgroupPids reads the pids information from the pids cgroup mount point. 221 func checkCgroupPids(quiet bool) cgroupPids { 222 _, err := cgroups.FindCgroupMountpoint("pids") 223 if err != nil { 224 if !quiet { 225 logrus.Warn(err) 226 } 227 return cgroupPids{} 228 } 229 230 return cgroupPids{ 231 PidsLimit: true, 232 } 233 } 234 235 func cgroupEnabled(mountPoint, name string) bool { 236 _, err := os.Stat(path.Join(mountPoint, name)) 237 return err == nil 238 } 239 240 func readProcBool(path string) bool { 241 val, err := ioutil.ReadFile(path) 242 if err != nil { 243 return false 244 } 245 return strings.TrimSpace(string(val)) == "1" 246 }