pkg/sysinfo/sysinfo_linux.go
Antonio Murdaca 826c468f2c Move sysinfo out of daemon struct
sysinfo struct was initialized at daemon startup to make sure
kernel configs such as device cgroup are present and error out if not.
The struct was embedded in daemon struct making impossible to detect
if some system config is changed at daemon runtime (i.e. someone
umount the memory cgroup). This leads to container's starts failure if
some config is changed at daemon runtime.
This patch moves sysinfo out of daemon and initilize and check it when
needed (daemon startup, containers creation, contaienrs startup for
now).

Signed-off-by: Antonio Murdaca <runcom@linux.com>
(cherry picked from commit 472b6f66e03f9a85fe8d23098dac6f55a87456d8)
2015-08-06 15:46:09 -07:00

134 lines
3.6 KiB
Go

package sysinfo
import (
"io/ioutil"
"os"
"path"
"strings"
"github.com/Sirupsen/logrus"
"github.com/opencontainers/runc/libcontainer/cgroups"
)
// New returns a new SysInfo, using the filesystem to detect which features
// the kernel supports. If `quiet` is `false` warnings are printed in logs
// whenever an error occurs or misconfigurations are present.
func New(quiet bool) *SysInfo {
sysInfo := &SysInfo{}
sysInfo.cgroupMemInfo = checkCgroupMem(quiet)
sysInfo.cgroupCPUInfo = checkCgroupCPU(quiet)
sysInfo.cgroupBlkioInfo = checkCgroupBlkioInfo(quiet)
sysInfo.cgroupCpusetInfo = checkCgroupCpusetInfo(quiet)
_, err := cgroups.FindCgroupMountpoint("devices")
sysInfo.CgroupDevicesEnabled = err == nil
sysInfo.IPv4ForwardingDisabled = !readProcBool("/proc/sys/net/ipv4/ip_forward")
sysInfo.BridgeNfCallIptablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-iptables")
sysInfo.BridgeNfCallIP6tablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-ip6tables")
// Check if AppArmor is supported.
if _, err := os.Stat("/sys/kernel/security/apparmor"); !os.IsNotExist(err) {
sysInfo.AppArmor = true
}
return sysInfo
}
func checkCgroupMem(quiet bool) *cgroupMemInfo {
info := &cgroupMemInfo{}
mountPoint, err := cgroups.FindCgroupMountpoint("memory")
if err != nil {
if !quiet {
logrus.Warnf("Your kernel does not support cgroup memory limit: %v", err)
}
return info
}
info.MemoryLimit = true
info.SwapLimit = cgroupEnabled(mountPoint, "memory.memsw.limit_in_bytes")
if !quiet && !info.SwapLimit {
logrus.Warn("Your kernel does not support swap memory limit.")
}
info.OomKillDisable = cgroupEnabled(mountPoint, "memory.oom_control")
if !quiet && !info.OomKillDisable {
logrus.Warnf("Your kernel does not support oom control.")
}
info.MemorySwappiness = cgroupEnabled(mountPoint, "memory.swappiness")
if !quiet && !info.MemorySwappiness {
logrus.Warnf("Your kernel does not support memory swappiness.")
}
return info
}
func checkCgroupCPU(quiet bool) *cgroupCPUInfo {
info := &cgroupCPUInfo{}
mountPoint, err := cgroups.FindCgroupMountpoint("cpu")
if err != nil {
if !quiet {
logrus.Warn(err)
}
return info
}
info.CPUShares = cgroupEnabled(mountPoint, "cpu.shares")
if !quiet && !info.CPUShares {
logrus.Warn("Your kernel does not support cgroup cpu shares")
}
info.CPUCfsPeriod = cgroupEnabled(mountPoint, "cpu.cfs_period_us")
if !quiet && !info.CPUCfsPeriod {
logrus.Warn("Your kernel does not support cgroup cfs period")
}
info.CPUCfsQuota = cgroupEnabled(mountPoint, "cpu.cfs_quota_us")
if !quiet && !info.CPUCfsQuota {
logrus.Warn("Your kernel does not support cgroup cfs quotas")
}
return info
}
func checkCgroupBlkioInfo(quiet bool) *cgroupBlkioInfo {
info := &cgroupBlkioInfo{}
mountPoint, err := cgroups.FindCgroupMountpoint("blkio")
if err != nil {
if !quiet {
logrus.Warn(err)
}
return info
}
info.BlkioWeight = cgroupEnabled(mountPoint, "blkio.weight")
if !quiet && !info.BlkioWeight {
logrus.Warn("Your kernel does not support cgroup blkio weight")
}
return info
}
func checkCgroupCpusetInfo(quiet bool) *cgroupCpusetInfo {
info := &cgroupCpusetInfo{}
_, err := cgroups.FindCgroupMountpoint("cpuset")
if err != nil {
if !quiet {
logrus.Warn(err)
}
return info
}
info.Cpuset = true
return info
}
func cgroupEnabled(mountPoint, name string) bool {
_, err := os.Stat(path.Join(mountPoint, name))
return err == nil
}
func readProcBool(path string) bool {
val, err := ioutil.ReadFile(path)
if err != nil {
return false
}
return strings.TrimSpace(string(val)) == "1"
}