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