github.com/ncdc/docker@v0.10.1-0.20160129113957-6c6729ef5b74/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 } 48 49 _, ok := cgMounts["devices"] 50 sysInfo.CgroupDevicesEnabled = ok 51 52 sysInfo.IPv4ForwardingDisabled = !readProcBool("/proc/sys/net/ipv4/ip_forward") 53 sysInfo.BridgeNfCallIptablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-iptables") 54 sysInfo.BridgeNfCallIP6tablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-ip6tables") 55 56 // Check if AppArmor is supported. 57 if _, err := os.Stat("/sys/kernel/security/apparmor"); !os.IsNotExist(err) { 58 sysInfo.AppArmor = true 59 } 60 61 // Check if Seccomp is supported, via CONFIG_SECCOMP. 62 if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_GET_SECCOMP, 0, 0); err != syscall.EINVAL { 63 // Make sure the kernel has CONFIG_SECCOMP_FILTER. 64 if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_SECCOMP, SeccompModeFilter, 0); err != syscall.EINVAL { 65 sysInfo.Seccomp = true 66 } 67 } 68 69 return sysInfo 70 } 71 72 // checkCgroupMem reads the memory information from the memory cgroup mount point. 73 func checkCgroupMem(cgMounts map[string]string, quiet bool) cgroupMemInfo { 74 mountPoint, ok := cgMounts["memory"] 75 if !ok { 76 if !quiet { 77 logrus.Warnf("Your kernel does not support cgroup memory limit") 78 } 79 return cgroupMemInfo{} 80 } 81 82 swapLimit := cgroupEnabled(mountPoint, "memory.memsw.limit_in_bytes") 83 if !quiet && !swapLimit { 84 logrus.Warn("Your kernel does not support swap memory limit.") 85 } 86 memoryReservation := cgroupEnabled(mountPoint, "memory.soft_limit_in_bytes") 87 if !quiet && !memoryReservation { 88 logrus.Warn("Your kernel does not support memory reservation.") 89 } 90 oomKillDisable := cgroupEnabled(mountPoint, "memory.oom_control") 91 if !quiet && !oomKillDisable { 92 logrus.Warnf("Your kernel does not support oom control.") 93 } 94 memorySwappiness := cgroupEnabled(mountPoint, "memory.swappiness") 95 if !quiet && !memorySwappiness { 96 logrus.Warnf("Your kernel does not support memory swappiness.") 97 } 98 kernelMemory := cgroupEnabled(mountPoint, "memory.kmem.limit_in_bytes") 99 if !quiet && !kernelMemory { 100 logrus.Warnf("Your kernel does not support kernel memory limit.") 101 } 102 103 return cgroupMemInfo{ 104 MemoryLimit: true, 105 SwapLimit: swapLimit, 106 MemoryReservation: memoryReservation, 107 OomKillDisable: oomKillDisable, 108 MemorySwappiness: memorySwappiness, 109 KernelMemory: kernelMemory, 110 } 111 } 112 113 // checkCgroupCPU reads the cpu information from the cpu cgroup mount point. 114 func checkCgroupCPU(cgMounts map[string]string, quiet bool) cgroupCPUInfo { 115 mountPoint, ok := cgMounts["cpu"] 116 if !ok { 117 if !quiet { 118 logrus.Warnf("Unable to find cpu cgroup in mounts") 119 } 120 return cgroupCPUInfo{} 121 } 122 123 cpuShares := cgroupEnabled(mountPoint, "cpu.shares") 124 if !quiet && !cpuShares { 125 logrus.Warn("Your kernel does not support cgroup cpu shares") 126 } 127 128 cpuCfsPeriod := cgroupEnabled(mountPoint, "cpu.cfs_period_us") 129 if !quiet && !cpuCfsPeriod { 130 logrus.Warn("Your kernel does not support cgroup cfs period") 131 } 132 133 cpuCfsQuota := cgroupEnabled(mountPoint, "cpu.cfs_quota_us") 134 if !quiet && !cpuCfsQuota { 135 logrus.Warn("Your kernel does not support cgroup cfs quotas") 136 } 137 return cgroupCPUInfo{ 138 CPUShares: cpuShares, 139 CPUCfsPeriod: cpuCfsPeriod, 140 CPUCfsQuota: cpuCfsQuota, 141 } 142 } 143 144 // checkCgroupBlkioInfo reads the blkio information from the blkio cgroup mount point. 145 func checkCgroupBlkioInfo(cgMounts map[string]string, quiet bool) cgroupBlkioInfo { 146 mountPoint, ok := cgMounts["blkio"] 147 if !ok { 148 if !quiet { 149 logrus.Warnf("Unable to find blkio cgroup in mounts") 150 } 151 return cgroupBlkioInfo{} 152 } 153 154 weight := cgroupEnabled(mountPoint, "blkio.weight") 155 if !quiet && !weight { 156 logrus.Warn("Your kernel does not support cgroup blkio weight") 157 } 158 159 weightDevice := cgroupEnabled(mountPoint, "blkio.weight_device") 160 if !quiet && !weightDevice { 161 logrus.Warn("Your kernel does not support cgroup blkio weight_device") 162 } 163 164 readBpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.read_bps_device") 165 if !quiet && !readBpsDevice { 166 logrus.Warn("Your kernel does not support cgroup blkio throttle.read_bps_device") 167 } 168 169 writeBpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.write_bps_device") 170 if !quiet && !writeBpsDevice { 171 logrus.Warn("Your kernel does not support cgroup blkio throttle.write_bps_device") 172 } 173 readIOpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.read_iops_device") 174 if !quiet && !readIOpsDevice { 175 logrus.Warn("Your kernel does not support cgroup blkio throttle.read_iops_device") 176 } 177 178 writeIOpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.write_iops_device") 179 if !quiet && !writeIOpsDevice { 180 logrus.Warn("Your kernel does not support cgroup blkio throttle.write_iops_device") 181 } 182 return cgroupBlkioInfo{ 183 BlkioWeight: weight, 184 BlkioWeightDevice: weightDevice, 185 BlkioReadBpsDevice: readBpsDevice, 186 BlkioWriteBpsDevice: writeBpsDevice, 187 BlkioReadIOpsDevice: readIOpsDevice, 188 BlkioWriteIOpsDevice: writeIOpsDevice, 189 } 190 } 191 192 // checkCgroupCpusetInfo reads the cpuset information from the cpuset cgroup mount point. 193 func checkCgroupCpusetInfo(cgMounts map[string]string, quiet bool) cgroupCpusetInfo { 194 mountPoint, ok := cgMounts["cpuset"] 195 if !ok { 196 if !quiet { 197 logrus.Warnf("Unable to find cpuset cgroup in mounts") 198 } 199 return cgroupCpusetInfo{} 200 } 201 202 cpus, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.cpus")) 203 if err != nil { 204 return cgroupCpusetInfo{} 205 } 206 207 mems, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.mems")) 208 if err != nil { 209 return cgroupCpusetInfo{} 210 } 211 212 return cgroupCpusetInfo{ 213 Cpuset: true, 214 Cpus: strings.TrimSpace(string(cpus)), 215 Mems: strings.TrimSpace(string(mems)), 216 } 217 } 218 219 func cgroupEnabled(mountPoint, name string) bool { 220 _, err := os.Stat(path.Join(mountPoint, name)) 221 return err == nil 222 } 223 224 func readProcBool(path string) bool { 225 val, err := ioutil.ReadFile(path) 226 if err != nil { 227 return false 228 } 229 return strings.TrimSpace(string(val)) == "1" 230 }