diff --git a/api.go b/api.go index cfef7a50ce..83b749b217 100644 --- a/api.go +++ b/api.go @@ -657,16 +657,16 @@ func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r for scanner.Scan() { out.Warnings = append(out.Warnings, scanner.Text()) } - if job.GetenvInt("Memory") > 0 && !srv.runtime.capabilities.MemoryLimit { + if job.GetenvInt("Memory") > 0 && !srv.runtime.sysInfo.MemoryLimit { log.Println("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.") out.Warnings = append(out.Warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.") } - if job.GetenvInt("Memory") > 0 && !srv.runtime.capabilities.SwapLimit { + if job.GetenvInt("Memory") > 0 && !srv.runtime.sysInfo.SwapLimit { log.Println("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.") out.Warnings = append(out.Warnings, "Your kernel does not support memory swap capabilities. Limitation discarded.") } - if !job.GetenvBool("NetworkDisabled") && srv.runtime.capabilities.IPv4ForwardingDisabled { + if !job.GetenvBool("NetworkDisabled") && srv.runtime.sysInfo.IPv4ForwardingDisabled { log.Println("Warning: IPv4 forwarding is disabled.") out.Warnings = append(out.Warnings, "IPv4 forwarding is disabled.") } diff --git a/commands.go b/commands.go index 09b65ad163..d23c7a9da5 100644 --- a/commands.go +++ b/commands.go @@ -12,6 +12,7 @@ import ( "github.com/dotcloud/docker/auth" "github.com/dotcloud/docker/engine" flag "github.com/dotcloud/docker/pkg/mflag" + "github.com/dotcloud/docker/pkg/sysinfo" "github.com/dotcloud/docker/pkg/term" "github.com/dotcloud/docker/registry" "github.com/dotcloud/docker/utils" @@ -1745,14 +1746,14 @@ func (cli *DockerCli) CmdTag(args ...string) error { } //FIXME Only used in tests -func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig, *flag.FlagSet, error) { +func ParseRun(args []string, sysInfo *sysinfo.SysInfo) (*Config, *HostConfig, *flag.FlagSet, error) { cmd := flag.NewFlagSet("run", flag.ContinueOnError) cmd.SetOutput(ioutil.Discard) cmd.Usage = nil - return parseRun(cmd, args, capabilities) + return parseRun(cmd, args, sysInfo) } -func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Config, *HostConfig, *flag.FlagSet, error) { +func parseRun(cmd *flag.FlagSet, args []string, sysInfo *sysinfo.SysInfo) (*Config, *HostConfig, *flag.FlagSet, error) { var ( // FIXME: use utils.ListOpts for attach and volumes? flAttach = NewListOpts(ValidateAttach) @@ -1802,7 +1803,7 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co } // Check if the kernel supports memory limit cgroup. - if capabilities != nil && *flMemoryString != "" && !capabilities.MemoryLimit { + if sysInfo != nil && *flMemoryString != "" && !sysInfo.MemoryLimit { *flMemoryString = "" } @@ -1934,7 +1935,7 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co PublishAllPorts: *flPublishAll, } - if capabilities != nil && flMemory > 0 && !capabilities.SwapLimit { + if sysInfo != nil && flMemory > 0 && !sysInfo.SwapLimit { //fmt.Fprintf(stdout, "WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n") config.MemorySwap = -1 } diff --git a/container.go b/container.go index 257925fdda..23a3c05335 100644 --- a/container.go +++ b/container.go @@ -527,16 +527,16 @@ func (container *Container) Start() (err error) { } // Make sure the config is compatible with the current kernel - if container.Config.Memory > 0 && !container.runtime.capabilities.MemoryLimit { + if container.Config.Memory > 0 && !container.runtime.sysInfo.MemoryLimit { log.Printf("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.\n") container.Config.Memory = 0 } - if container.Config.Memory > 0 && !container.runtime.capabilities.SwapLimit { + if container.Config.Memory > 0 && !container.runtime.sysInfo.SwapLimit { log.Printf("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n") container.Config.MemorySwap = -1 } - if container.runtime.capabilities.IPv4ForwardingDisabled { + if container.runtime.sysInfo.IPv4ForwardingDisabled { log.Printf("WARNING: IPv4 forwarding is disabled. Networking will not work") } diff --git a/lxc_template.go b/lxc_template.go index f96323b5ea..4e1aece94b 100644 --- a/lxc_template.go +++ b/lxc_template.go @@ -1,6 +1,7 @@ package docker import ( + "github.com/dotcloud/docker/pkg/sysinfo" "strings" "text/template" ) @@ -31,7 +32,7 @@ lxc.console = none lxc.tty = 1 {{if (getHostConfig .).Privileged}} -lxc.cgroup.devices.allow = a +lxc.cgroup.devices.allow = a {{else}} # no implicit access to devices lxc.cgroup.devices.deny = a @@ -82,7 +83,7 @@ lxc.mount.entry = devpts {{escapeFstabSpaces $ROOTFS}}/dev/pts devpts newinstanc lxc.mount.entry = shm {{escapeFstabSpaces $ROOTFS}}/dev/shm tmpfs size=65536k,nosuid,nodev,noexec 0 0 {{if (getHostConfig .).Privileged}} -{{if (getCapabilities .).AppArmor}} +{{if (getSysInfo .).AppArmor}} lxc.aa_profile = unconfined {{else}} #lxc.aa_profile = unconfined @@ -129,8 +130,8 @@ func getHostConfig(container *Container) *HostConfig { return container.hostConfig } -func getCapabilities(container *Container) *Capabilities { - return container.runtime.capabilities +func getSysInfo(container *Container) *sysinfo.SysInfo { + return container.runtime.sysInfo } func init() { @@ -138,7 +139,7 @@ func init() { funcMap := template.FuncMap{ "getMemorySwap": getMemorySwap, "getHostConfig": getHostConfig, - "getCapabilities": getCapabilities, + "getSysInfo": getSysInfo, "escapeFstabSpaces": escapeFstabSpaces, } LxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate) diff --git a/pkg/sysinfo/sysinfo.go b/pkg/sysinfo/sysinfo.go new file mode 100644 index 0000000000..884fcbde7c --- /dev/null +++ b/pkg/sysinfo/sysinfo.go @@ -0,0 +1,55 @@ +package sysinfo + +import ( + "github.com/dotcloud/docker/cgroups" + "github.com/dotcloud/docker/utils" + "io/ioutil" + "log" + "os" + "path" +) + +type SysInfo struct { + MemoryLimit bool + SwapLimit bool + IPv4ForwardingDisabled bool + AppArmor bool +} + +func New(quiet bool) *SysInfo { + sysInfo := &SysInfo{} + if cgroupMemoryMountpoint, err := cgroups.FindCgroupMountpoint("memory"); err != nil { + if !quiet { + log.Printf("WARNING: %s\n", err) + } + } else { + _, err1 := ioutil.ReadFile(path.Join(cgroupMemoryMountpoint, "memory.limit_in_bytes")) + _, err2 := ioutil.ReadFile(path.Join(cgroupMemoryMountpoint, "memory.soft_limit_in_bytes")) + sysInfo.MemoryLimit = err1 == nil && err2 == nil + if !sysInfo.MemoryLimit && !quiet { + log.Printf("WARNING: Your kernel does not support cgroup memory limit.") + } + + _, err = ioutil.ReadFile(path.Join(cgroupMemoryMountpoint, "memory.memsw.limit_in_bytes")) + sysInfo.SwapLimit = err == nil + if !sysInfo.SwapLimit && !quiet { + log.Printf("WARNING: Your kernel does not support cgroup swap limit.") + } + } + + content, err3 := ioutil.ReadFile("/proc/sys/net/ipv4/ip_forward") + sysInfo.IPv4ForwardingDisabled = err3 != nil || len(content) == 0 || content[0] != '1' + if sysInfo.IPv4ForwardingDisabled && !quiet { + log.Printf("WARNING: IPv4 forwarding is disabled.") + } + + // Check if AppArmor seems to be enabled on this system. + if _, err := os.Stat("/sys/kernel/security/apparmor"); os.IsNotExist(err) { + utils.Debugf("/sys/kernel/security/apparmor not found; assuming AppArmor is not enabled.") + sysInfo.AppArmor = false + } else { + utils.Debugf("/sys/kernel/security/apparmor found; assuming AppArmor is enabled.") + sysInfo.AppArmor = true + } + return sysInfo +} diff --git a/runtime.go b/runtime.go index 5a11faec9f..52f03f84be 100644 --- a/runtime.go +++ b/runtime.go @@ -4,7 +4,6 @@ import ( "container/list" "fmt" "github.com/dotcloud/docker/archive" - "github.com/dotcloud/docker/cgroups" "github.com/dotcloud/docker/execdriver" "github.com/dotcloud/docker/execdriver/chroot" "github.com/dotcloud/docker/execdriver/lxc" @@ -13,10 +12,10 @@ import ( _ "github.com/dotcloud/docker/graphdriver/devmapper" _ "github.com/dotcloud/docker/graphdriver/vfs" "github.com/dotcloud/docker/pkg/graphdb" + "github.com/dotcloud/docker/pkg/sysinfo" "github.com/dotcloud/docker/utils" "io" "io/ioutil" - "log" "os" "path" "regexp" @@ -37,13 +36,6 @@ var ( validContainerNamePattern = regexp.MustCompile(`^/?` + validContainerNameChars + `+$`) ) -type Capabilities struct { - MemoryLimit bool - SwapLimit bool - IPv4ForwardingDisabled bool - AppArmor bool -} - type Runtime struct { repository string sysInitPath string @@ -52,7 +44,7 @@ type Runtime struct { graph *Graph repositories *TagStore idIndex *utils.TruncIndex - capabilities *Capabilities + sysInfo *sysinfo.SysInfo volumes *Graph srv *Server config *DaemonConfig @@ -332,44 +324,6 @@ func (runtime *Runtime) restore() error { return nil } -func NewRuntimeCapabilities(quiet bool) *Capabilities { - capabilities := &Capabilities{} - if cgroupMemoryMountpoint, err := cgroups.FindCgroupMountpoint("memory"); err != nil { - if !quiet { - log.Printf("WARNING: %s\n", err) - } - } else { - _, err1 := ioutil.ReadFile(path.Join(cgroupMemoryMountpoint, "memory.limit_in_bytes")) - _, err2 := ioutil.ReadFile(path.Join(cgroupMemoryMountpoint, "memory.soft_limit_in_bytes")) - capabilities.MemoryLimit = err1 == nil && err2 == nil - if !capabilities.MemoryLimit && !quiet { - log.Printf("WARNING: Your kernel does not support cgroup memory limit.") - } - - _, err = ioutil.ReadFile(path.Join(cgroupMemoryMountpoint, "memory.memsw.limit_in_bytes")) - capabilities.SwapLimit = err == nil - if !capabilities.SwapLimit && !quiet { - log.Printf("WARNING: Your kernel does not support cgroup swap limit.") - } - } - - content, err3 := ioutil.ReadFile("/proc/sys/net/ipv4/ip_forward") - capabilities.IPv4ForwardingDisabled = err3 != nil || len(content) == 0 || content[0] != '1' - if capabilities.IPv4ForwardingDisabled && !quiet { - log.Printf("WARNING: IPv4 forwarding is disabled.") - } - - // Check if AppArmor seems to be enabled on this system. - if _, err := os.Stat("/sys/kernel/security/apparmor"); os.IsNotExist(err) { - utils.Debugf("/sys/kernel/security/apparmor not found; assuming AppArmor is not enabled.") - capabilities.AppArmor = false - } else { - utils.Debugf("/sys/kernel/security/apparmor found; assuming AppArmor is enabled.") - capabilities.AppArmor = true - } - return capabilities -} - // Create creates a new container from the given configuration with a given name. func (runtime *Runtime) Create(config *Config, name string) (*Container, []string, error) { // Lookup image @@ -732,7 +686,7 @@ func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) { sysInitPath = localCopy } - capabilities := NewRuntimeCapabilities(false) + sysInfo := sysinfo.New(false) /* temporarilly disabled. @@ -740,14 +694,14 @@ func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) { if false { var ed execdriver.Driver if driver := os.Getenv("EXEC_DRIVER"); driver == "lxc" { - ed, err = lxc.NewDriver(config.Root, capabilities.AppArmor) + ed, err = lxc.NewDriver(config.Root, sysInfo.AppArmor) } else { ed, err = chroot.NewDriver() } if ed != nil { } } - ed, err := lxc.NewDriver(config.Root, capabilities.AppArmor) + ed, err := lxc.NewDriver(config.Root, sysInfo.AppArmor) if err != nil { return nil, err } @@ -759,7 +713,7 @@ func NewRuntimeFromDirectory(config *DaemonConfig) (*Runtime, error) { graph: g, repositories: repositories, idIndex: utils.NewTruncIndex(), - capabilities: capabilities, + sysInfo: sysInfo, volumes: volumes, config: config, containerGraph: graph, diff --git a/server.go b/server.go index a9c83575e4..bc8a86ef2f 100644 --- a/server.go +++ b/server.go @@ -516,7 +516,7 @@ func (srv *Server) ImageInsert(job *engine.Job) engine.Status { } defer file.Body.Close() - config, _, _, err := ParseRun([]string{img.ID, "echo", "insert", url, path}, srv.runtime.capabilities) + config, _, _, err := ParseRun([]string{img.ID, "echo", "insert", url, path}, srv.runtime.sysInfo) if err != nil { job.Error(err) return engine.StatusErr @@ -678,9 +678,9 @@ func (srv *Server) DockerInfo(job *engine.Job) engine.Status { v.SetInt("Images", imgcount) v.Set("Driver", srv.runtime.driver.String()) v.SetJson("DriverStatus", srv.runtime.driver.Status()) - v.SetBool("MemoryLimit", srv.runtime.capabilities.MemoryLimit) - v.SetBool("SwapLimit", srv.runtime.capabilities.SwapLimit) - v.SetBool("IPv4Forwarding", !srv.runtime.capabilities.IPv4ForwardingDisabled) + v.SetBool("MemoryLimit", srv.runtime.sysInfo.MemoryLimit) + v.SetBool("SwapLimit", srv.runtime.sysInfo.SwapLimit) + v.SetBool("IPv4Forwarding", !srv.runtime.sysInfo.IPv4ForwardingDisabled) v.SetBool("Debug", os.Getenv("DEBUG") != "") v.SetInt("NFd", utils.GetTotalUsedFds()) v.SetInt("NGoroutines", runtime.NumGoroutine()) @@ -1470,10 +1470,10 @@ func (srv *Server) ContainerCreate(job *engine.Job) engine.Status { job.Errorf("Minimum memory limit allowed is 512k") return engine.StatusErr } - if config.Memory > 0 && !srv.runtime.capabilities.MemoryLimit { + if config.Memory > 0 && !srv.runtime.sysInfo.MemoryLimit { config.Memory = 0 } - if config.Memory > 0 && !srv.runtime.capabilities.SwapLimit { + if config.Memory > 0 && !srv.runtime.sysInfo.SwapLimit { config.MemorySwap = -1 } container, buildWarnings, err := srv.runtime.Create(&config, name)