Browse code

Refactor pkg/sysinfo

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2019/02/04 04:51:04
Showing 1 changed files
... ...
@@ -26,225 +26,241 @@ func findCgroupMountpoints() (map[string]string, error) {
26 26
 	return mps, nil
27 27
 }
28 28
 
29
+type infoCollector func(info *SysInfo, cgMounts map[string]string) (warnings []string)
30
+
29 31
 // New returns a new SysInfo, using the filesystem to detect which features
30 32
 // the kernel supports. If `quiet` is `false` warnings are printed in logs
31 33
 // whenever an error occurs or misconfigurations are present.
32 34
 func New(quiet bool) *SysInfo {
35
+	var ops []infoCollector
36
+	var warnings []string
33 37
 	sysInfo := &SysInfo{}
34 38
 	cgMounts, err := findCgroupMountpoints()
35 39
 	if err != nil {
36
-		logrus.Warnf("Failed to parse cgroup information: %v", err)
40
+		logrus.Warn(err)
37 41
 	} else {
38
-		sysInfo.cgroupMemInfo = checkCgroupMem(cgMounts, quiet)
39
-		sysInfo.cgroupCPUInfo = checkCgroupCPU(cgMounts, quiet)
40
-		sysInfo.cgroupBlkioInfo = checkCgroupBlkioInfo(cgMounts, quiet)
41
-		sysInfo.cgroupCpusetInfo = checkCgroupCpusetInfo(cgMounts, quiet)
42
-		sysInfo.cgroupPids = checkCgroupPids(quiet)
43
-	}
44
-
45
-	_, ok := cgMounts["devices"]
46
-	sysInfo.CgroupDevicesEnabled = ok
47
-
48
-	sysInfo.IPv4ForwardingDisabled = !readProcBool("/proc/sys/net/ipv4/ip_forward")
49
-	sysInfo.BridgeNFCallIPTablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-iptables")
50
-	sysInfo.BridgeNFCallIP6TablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-ip6tables")
51
-
52
-	// Check if AppArmor is supported.
53
-	if _, err := os.Stat("/sys/kernel/security/apparmor"); !os.IsNotExist(err) {
54
-		if _, err := ioutil.ReadFile("/sys/kernel/security/apparmor/profiles"); err == nil {
55
-			sysInfo.AppArmor = true
42
+		ops = append(ops, []infoCollector{
43
+			applyMemoryCgroupInfo,
44
+			applyCPUCgroupInfo,
45
+			applyBlkioCgroupInfo,
46
+			applyCPUSetCgroupInfo,
47
+			applyPIDSCgroupInfo,
48
+			applyDevicesCgroupInfo,
49
+		}...)
50
+	}
51
+
52
+	ops = append(ops, []infoCollector{
53
+		applyNetworkingInfo,
54
+		applyAppArmorInfo,
55
+		applySeccompInfo,
56
+	}...)
57
+
58
+	for _, o := range ops {
59
+		w := o(sysInfo, cgMounts)
60
+		warnings = append(warnings, w...)
61
+	}
62
+	if !quiet {
63
+		for _, w := range warnings {
64
+			logrus.Warn(w)
56 65
 		}
57 66
 	}
58
-
59
-	// Check if Seccomp is supported, via CONFIG_SECCOMP.
60
-	if err := unix.Prctl(unix.PR_GET_SECCOMP, 0, 0, 0, 0); err != unix.EINVAL {
61
-		// Make sure the kernel has CONFIG_SECCOMP_FILTER.
62
-		if err := unix.Prctl(unix.PR_SET_SECCOMP, unix.SECCOMP_MODE_FILTER, 0, 0, 0); err != unix.EINVAL {
63
-			sysInfo.Seccomp = true
64
-		}
65
-	}
66
-
67 67
 	return sysInfo
68 68
 }
69 69
 
70
-// checkCgroupMem reads the memory information from the memory cgroup mount point.
71
-func checkCgroupMem(cgMounts map[string]string, quiet bool) cgroupMemInfo {
70
+// applyMemoryCgroupInfo reads the memory information from the memory cgroup mount point.
71
+func applyMemoryCgroupInfo(info *SysInfo, cgMounts map[string]string) []string {
72
+	var warnings []string
72 73
 	mountPoint, ok := cgMounts["memory"]
73 74
 	if !ok {
74
-		if !quiet {
75
-			logrus.Warn("Your kernel does not support cgroup memory limit")
76
-		}
77
-		return cgroupMemInfo{}
75
+		warnings = append(warnings, "Your kernel does not support cgroup memory limit")
76
+		return warnings
78 77
 	}
78
+	info.MemoryLimit = ok
79 79
 
80
-	swapLimit := cgroupEnabled(mountPoint, "memory.memsw.limit_in_bytes")
81
-	if !quiet && !swapLimit {
82
-		logrus.Warn("Your kernel does not support swap memory limit")
80
+	info.SwapLimit = cgroupEnabled(mountPoint, "memory.memsw.limit_in_bytes")
81
+	if !info.SwapLimit {
82
+		warnings = append(warnings, "Your kernel does not support swap memory limit")
83 83
 	}
84
-	memoryReservation := cgroupEnabled(mountPoint, "memory.soft_limit_in_bytes")
85
-	if !quiet && !memoryReservation {
86
-		logrus.Warn("Your kernel does not support memory reservation")
84
+	info.MemoryReservation = cgroupEnabled(mountPoint, "memory.soft_limit_in_bytes")
85
+	if !info.MemoryReservation {
86
+		warnings = append(warnings, "Your kernel does not support memory reservation")
87 87
 	}
88
-	oomKillDisable := cgroupEnabled(mountPoint, "memory.oom_control")
89
-	if !quiet && !oomKillDisable {
90
-		logrus.Warn("Your kernel does not support oom control")
88
+	info.OomKillDisable = cgroupEnabled(mountPoint, "memory.oom_control")
89
+	if !info.OomKillDisable {
90
+		warnings = append(warnings, "Your kernel does not support oom control")
91 91
 	}
92
-	memorySwappiness := cgroupEnabled(mountPoint, "memory.swappiness")
93
-	if !quiet && !memorySwappiness {
94
-		logrus.Warn("Your kernel does not support memory swappiness")
92
+	info.MemorySwappiness = cgroupEnabled(mountPoint, "memory.swappiness")
93
+	if !info.MemorySwappiness {
94
+		warnings = append(warnings, "Your kernel does not support memory swappiness")
95 95
 	}
96
-	kernelMemory := cgroupEnabled(mountPoint, "memory.kmem.limit_in_bytes")
97
-	if !quiet && !kernelMemory {
98
-		logrus.Warn("Your kernel does not support kernel memory limit")
96
+	info.KernelMemory = cgroupEnabled(mountPoint, "memory.kmem.limit_in_bytes")
97
+	if !info.KernelMemory {
98
+		warnings = append(warnings, "Your kernel does not support kernel memory limit")
99 99
 	}
100
-	kernelMemoryTCP := cgroupEnabled(mountPoint, "memory.kmem.tcp.limit_in_bytes")
101
-	if !quiet && !kernelMemoryTCP {
102
-		logrus.Warn("Your kernel does not support kernel memory TCP limit")
100
+	info.KernelMemoryTCP = cgroupEnabled(mountPoint, "memory.kmem.tcp.limit_in_bytes")
101
+	if !info.KernelMemoryTCP {
102
+		warnings = append(warnings, "Your kernel does not support kernel memory TCP limit")
103 103
 	}
104 104
 
105
-	return cgroupMemInfo{
106
-		MemoryLimit:       true,
107
-		SwapLimit:         swapLimit,
108
-		MemoryReservation: memoryReservation,
109
-		OomKillDisable:    oomKillDisable,
110
-		MemorySwappiness:  memorySwappiness,
111
-		KernelMemory:      kernelMemory,
112
-		KernelMemoryTCP:   kernelMemoryTCP,
113
-	}
105
+	return warnings
114 106
 }
115 107
 
116
-// checkCgroupCPU reads the cpu information from the cpu cgroup mount point.
117
-func checkCgroupCPU(cgMounts map[string]string, quiet bool) cgroupCPUInfo {
108
+// applyCPUCgroupInfo reads the cpu information from the cpu cgroup mount point.
109
+func applyCPUCgroupInfo(info *SysInfo, cgMounts map[string]string) []string {
110
+	var warnings []string
118 111
 	mountPoint, ok := cgMounts["cpu"]
119 112
 	if !ok {
120
-		if !quiet {
121
-			logrus.Warn("Unable to find cpu cgroup in mounts")
122
-		}
123
-		return cgroupCPUInfo{}
113
+		warnings = append(warnings, "Unable to find cpu cgroup in mounts")
114
+		return warnings
124 115
 	}
125 116
 
126
-	cpuShares := cgroupEnabled(mountPoint, "cpu.shares")
127
-	if !quiet && !cpuShares {
128
-		logrus.Warn("Your kernel does not support cgroup cpu shares")
117
+	info.CPUShares = cgroupEnabled(mountPoint, "cpu.shares")
118
+	if !info.CPUShares {
119
+		warnings = append(warnings, "Your kernel does not support cgroup cpu shares")
129 120
 	}
130 121
 
131
-	cpuCfsPeriod := cgroupEnabled(mountPoint, "cpu.cfs_period_us")
132
-	if !quiet && !cpuCfsPeriod {
133
-		logrus.Warn("Your kernel does not support cgroup cfs period")
122
+	info.CPUCfsPeriod = cgroupEnabled(mountPoint, "cpu.cfs_period_us")
123
+	if !info.CPUCfsPeriod {
124
+		warnings = append(warnings, "Your kernel does not support cgroup cfs period")
134 125
 	}
135 126
 
136
-	cpuCfsQuota := cgroupEnabled(mountPoint, "cpu.cfs_quota_us")
137
-	if !quiet && !cpuCfsQuota {
138
-		logrus.Warn("Your kernel does not support cgroup cfs quotas")
127
+	info.CPUCfsQuota = cgroupEnabled(mountPoint, "cpu.cfs_quota_us")
128
+	if !info.CPUCfsQuota {
129
+		warnings = append(warnings, "Your kernel does not support cgroup cfs quotas")
139 130
 	}
140 131
 
141
-	cpuRealtimePeriod := cgroupEnabled(mountPoint, "cpu.rt_period_us")
142
-	if !quiet && !cpuRealtimePeriod {
143
-		logrus.Warn("Your kernel does not support cgroup rt period")
132
+	info.CPURealtimePeriod = cgroupEnabled(mountPoint, "cpu.rt_period_us")
133
+	if !info.CPURealtimePeriod {
134
+		warnings = append(warnings, "Your kernel does not support cgroup rt period")
144 135
 	}
145 136
 
146
-	cpuRealtimeRuntime := cgroupEnabled(mountPoint, "cpu.rt_runtime_us")
147
-	if !quiet && !cpuRealtimeRuntime {
148
-		logrus.Warn("Your kernel does not support cgroup rt runtime")
137
+	info.CPURealtimeRuntime = cgroupEnabled(mountPoint, "cpu.rt_runtime_us")
138
+	if !info.CPURealtimeRuntime {
139
+		warnings = append(warnings, "Your kernel does not support cgroup rt runtime")
149 140
 	}
150 141
 
151
-	return cgroupCPUInfo{
152
-		CPUShares:          cpuShares,
153
-		CPUCfsPeriod:       cpuCfsPeriod,
154
-		CPUCfsQuota:        cpuCfsQuota,
155
-		CPURealtimePeriod:  cpuRealtimePeriod,
156
-		CPURealtimeRuntime: cpuRealtimeRuntime,
157
-	}
142
+	return warnings
158 143
 }
159 144
 
160
-// checkCgroupBlkioInfo reads the blkio information from the blkio cgroup mount point.
161
-func checkCgroupBlkioInfo(cgMounts map[string]string, quiet bool) cgroupBlkioInfo {
145
+// applyBlkioCgroupInfo reads the blkio information from the blkio cgroup mount point.
146
+func applyBlkioCgroupInfo(info *SysInfo, cgMounts map[string]string) []string {
147
+	var warnings []string
162 148
 	mountPoint, ok := cgMounts["blkio"]
163 149
 	if !ok {
164
-		if !quiet {
165
-			logrus.Warn("Unable to find blkio cgroup in mounts")
166
-		}
167
-		return cgroupBlkioInfo{}
150
+		warnings = append(warnings, "Unable to find blkio cgroup in mounts")
151
+		return warnings
168 152
 	}
169 153
 
170
-	weight := cgroupEnabled(mountPoint, "blkio.weight")
171
-	if !quiet && !weight {
172
-		logrus.Warn("Your kernel does not support cgroup blkio weight")
154
+	info.BlkioWeight = cgroupEnabled(mountPoint, "blkio.weight")
155
+	if !info.BlkioWeight {
156
+		warnings = append(warnings, "Your kernel does not support cgroup blkio weight")
173 157
 	}
174 158
 
175
-	weightDevice := cgroupEnabled(mountPoint, "blkio.weight_device")
176
-	if !quiet && !weightDevice {
177
-		logrus.Warn("Your kernel does not support cgroup blkio weight_device")
159
+	info.BlkioWeightDevice = cgroupEnabled(mountPoint, "blkio.weight_device")
160
+	if !info.BlkioWeightDevice {
161
+		warnings = append(warnings, "Your kernel does not support cgroup blkio weight_device")
178 162
 	}
179 163
 
180
-	readBpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.read_bps_device")
181
-	if !quiet && !readBpsDevice {
182
-		logrus.Warn("Your kernel does not support cgroup blkio throttle.read_bps_device")
164
+	info.BlkioReadBpsDevice = cgroupEnabled(mountPoint, "blkio.throttle.read_bps_device")
165
+	if !info.BlkioReadBpsDevice {
166
+		warnings = append(warnings, "Your kernel does not support cgroup blkio throttle.read_bps_device")
183 167
 	}
184 168
 
185
-	writeBpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.write_bps_device")
186
-	if !quiet && !writeBpsDevice {
187
-		logrus.Warn("Your kernel does not support cgroup blkio throttle.write_bps_device")
169
+	info.BlkioWriteBpsDevice = cgroupEnabled(mountPoint, "blkio.throttle.write_bps_device")
170
+	if !info.BlkioWriteBpsDevice {
171
+		warnings = append(warnings, "Your kernel does not support cgroup blkio throttle.write_bps_device")
188 172
 	}
189
-	readIOpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.read_iops_device")
190
-	if !quiet && !readIOpsDevice {
191
-		logrus.Warn("Your kernel does not support cgroup blkio throttle.read_iops_device")
173
+	info.BlkioReadIOpsDevice = cgroupEnabled(mountPoint, "blkio.throttle.read_iops_device")
174
+	if !info.BlkioReadIOpsDevice {
175
+		warnings = append(warnings, "Your kernel does not support cgroup blkio throttle.read_iops_device")
192 176
 	}
193 177
 
194
-	writeIOpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.write_iops_device")
195
-	if !quiet && !writeIOpsDevice {
196
-		logrus.Warn("Your kernel does not support cgroup blkio throttle.write_iops_device")
197
-	}
198
-	return cgroupBlkioInfo{
199
-		BlkioWeight:          weight,
200
-		BlkioWeightDevice:    weightDevice,
201
-		BlkioReadBpsDevice:   readBpsDevice,
202
-		BlkioWriteBpsDevice:  writeBpsDevice,
203
-		BlkioReadIOpsDevice:  readIOpsDevice,
204
-		BlkioWriteIOpsDevice: writeIOpsDevice,
178
+	info.BlkioWriteIOpsDevice = cgroupEnabled(mountPoint, "blkio.throttle.write_iops_device")
179
+	if !info.BlkioWriteIOpsDevice {
180
+		warnings = append(warnings, "Your kernel does not support cgroup blkio throttle.write_iops_device")
205 181
 	}
182
+
183
+	return warnings
206 184
 }
207 185
 
208
-// checkCgroupCpusetInfo reads the cpuset information from the cpuset cgroup mount point.
209
-func checkCgroupCpusetInfo(cgMounts map[string]string, quiet bool) cgroupCpusetInfo {
186
+// applyCPUSetCgroupInfo reads the cpuset information from the cpuset cgroup mount point.
187
+func applyCPUSetCgroupInfo(info *SysInfo, cgMounts map[string]string) []string {
188
+	var warnings []string
210 189
 	mountPoint, ok := cgMounts["cpuset"]
211 190
 	if !ok {
212
-		if !quiet {
213
-			logrus.Warn("Unable to find cpuset cgroup in mounts")
214
-		}
215
-		return cgroupCpusetInfo{}
191
+		warnings = append(warnings, "Unable to find cpuset cgroup in mounts")
192
+		return warnings
216 193
 	}
194
+	info.Cpuset = ok
195
+
196
+	var err error
217 197
 
218 198
 	cpus, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.cpus"))
219 199
 	if err != nil {
220
-		return cgroupCpusetInfo{}
200
+		return warnings
221 201
 	}
202
+	info.Cpus = strings.TrimSpace(string(cpus))
222 203
 
223 204
 	mems, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.mems"))
224 205
 	if err != nil {
225
-		return cgroupCpusetInfo{}
206
+		return warnings
226 207
 	}
208
+	info.Mems = strings.TrimSpace(string(mems))
227 209
 
228
-	return cgroupCpusetInfo{
229
-		Cpuset: true,
230
-		Cpus:   strings.TrimSpace(string(cpus)),
231
-		Mems:   strings.TrimSpace(string(mems)),
232
-	}
210
+	return warnings
233 211
 }
234 212
 
235
-// checkCgroupPids reads the pids information from the pids cgroup mount point.
236
-func checkCgroupPids(quiet bool) cgroupPids {
213
+// applyPIDSCgroupInfo reads the pids information from the pids cgroup mount point.
214
+func applyPIDSCgroupInfo(info *SysInfo, _ map[string]string) []string {
215
+	var warnings []string
237 216
 	_, err := cgroups.FindCgroupMountpoint("", "pids")
238 217
 	if err != nil {
239
-		if !quiet {
240
-			logrus.Warn(err)
218
+		warnings = append(warnings, err.Error())
219
+		return warnings
220
+	}
221
+	info.PidsLimit = true
222
+	return warnings
223
+}
224
+
225
+// applyDevicesCgroupInfo reads the pids information from the devices cgroup mount point.
226
+func applyDevicesCgroupInfo(info *SysInfo, cgMounts map[string]string) []string {
227
+	var warnings []string
228
+	_, ok := cgMounts["devices"]
229
+	info.CgroupDevicesEnabled = ok
230
+	return warnings
231
+}
232
+
233
+// applyNetworkingInfo adds networking information to the info.
234
+func applyNetworkingInfo(info *SysInfo, _ map[string]string) []string {
235
+	var warnings []string
236
+	info.IPv4ForwardingDisabled = !readProcBool("/proc/sys/net/ipv4/ip_forward")
237
+	info.BridgeNFCallIPTablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-iptables")
238
+	info.BridgeNFCallIP6TablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-ip6tables")
239
+	return warnings
240
+}
241
+
242
+// applyAppArmorInfo adds AppArmor information to the info.
243
+func applyAppArmorInfo(info *SysInfo, _ map[string]string) []string {
244
+	var warnings []string
245
+	if _, err := os.Stat("/sys/kernel/security/apparmor"); !os.IsNotExist(err) {
246
+		if _, err := ioutil.ReadFile("/sys/kernel/security/apparmor/profiles"); err == nil {
247
+			info.AppArmor = true
241 248
 		}
242
-		return cgroupPids{}
243 249
 	}
250
+	return warnings
251
+}
244 252
 
245
-	return cgroupPids{
246
-		PidsLimit: true,
253
+// applySeccompInfo checks if Seccomp is supported, via CONFIG_SECCOMP.
254
+func applySeccompInfo(info *SysInfo, _ map[string]string) []string {
255
+	var warnings []string
256
+	// Check if Seccomp is supported, via CONFIG_SECCOMP.
257
+	if err := unix.Prctl(unix.PR_GET_SECCOMP, 0, 0, 0, 0); err != unix.EINVAL {
258
+		// Make sure the kernel has CONFIG_SECCOMP_FILTER.
259
+		if err := unix.Prctl(unix.PR_SET_SECCOMP, unix.SECCOMP_MODE_FILTER, 0, 0, 0); err != unix.EINVAL {
260
+			info.Seccomp = true
261
+		}
247 262
 	}
263
+	return warnings
248 264
 }
249 265
 
250 266
 func cgroupEnabled(mountPoint, name string) bool {