Browse Source

Merge pull request #15381 from calavera/carry_15275

[Carry 15275] Runtime sysinfo check
David Calavera 10 years ago
parent
commit
6168a992c7
6 changed files with 42 additions and 34 deletions
  1. 0 6
      daemon/daemon.go
  2. 18 11
      daemon/daemon_unix.go
  3. 11 8
      daemon/info.go
  4. 6 4
      daemon/start.go
  5. 3 1
      pkg/sysinfo/sysinfo_linux.go
  6. 4 4
      runconfig/parse.go

+ 0 - 6
daemon/daemon.go

@@ -92,7 +92,6 @@ type Daemon struct {
 	graph            *graph.Graph
 	graph            *graph.Graph
 	repositories     *graph.TagStore
 	repositories     *graph.TagStore
 	idIndex          *truncindex.TruncIndex
 	idIndex          *truncindex.TruncIndex
-	sysInfo          *sysinfo.SysInfo
 	config           *Config
 	config           *Config
 	containerGraph   *graphdb.Database
 	containerGraph   *graphdb.Database
 	driver           graphdriver.Driver
 	driver           graphdriver.Driver
@@ -725,7 +724,6 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
 	d.graph = g
 	d.graph = g
 	d.repositories = repositories
 	d.repositories = repositories
 	d.idIndex = truncindex.NewTruncIndex([]string{})
 	d.idIndex = truncindex.NewTruncIndex([]string{})
-	d.sysInfo = sysInfo
 	d.config = config
 	d.config = config
 	d.sysInitPath = sysInitPath
 	d.sysInitPath = sysInitPath
 	d.execDriver = ed
 	d.execDriver = ed
@@ -858,10 +856,6 @@ func (daemon *Daemon) Config() *Config {
 	return daemon.config
 	return daemon.config
 }
 }
 
 
-func (daemon *Daemon) SystemConfig() *sysinfo.SysInfo {
-	return daemon.sysInfo
-}
-
 func (daemon *Daemon) SystemInitPath() string {
 func (daemon *Daemon) SystemInitPath() string {
 	return daemon.sysInitPath
 	return daemon.sysInitPath
 }
 }

+ 18 - 11
daemon/daemon_unix.go

@@ -18,6 +18,7 @@ import (
 	"github.com/docker/docker/pkg/fileutils"
 	"github.com/docker/docker/pkg/fileutils"
 	"github.com/docker/docker/pkg/parsers"
 	"github.com/docker/docker/pkg/parsers"
 	"github.com/docker/docker/pkg/parsers/kernel"
 	"github.com/docker/docker/pkg/parsers/kernel"
+	"github.com/docker/docker/pkg/sysinfo"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/utils"
 	"github.com/docker/docker/utils"
@@ -148,20 +149,24 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *runconfig.HostConfig, a
 // verifyPlatformContainerSettings performs platform-specific validation of the
 // verifyPlatformContainerSettings performs platform-specific validation of the
 // hostconfig and config structures.
 // hostconfig and config structures.
 func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) {
 func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) {
-	var warnings []string
+	warnings := []string{}
+	sysInfo := sysinfo.New(false)
 
 
 	if hostConfig.LxcConf.Len() > 0 && !strings.Contains(daemon.ExecutionDriver().Name(), "lxc") {
 	if hostConfig.LxcConf.Len() > 0 && !strings.Contains(daemon.ExecutionDriver().Name(), "lxc") {
 		return warnings, fmt.Errorf("Cannot use --lxc-conf with execdriver: %s", daemon.ExecutionDriver().Name())
 		return warnings, fmt.Errorf("Cannot use --lxc-conf with execdriver: %s", daemon.ExecutionDriver().Name())
 	}
 	}
+
+	// memory subsystem checks and adjustments
 	if hostConfig.Memory != 0 && hostConfig.Memory < 4194304 {
 	if hostConfig.Memory != 0 && hostConfig.Memory < 4194304 {
 		return warnings, fmt.Errorf("Minimum memory limit allowed is 4MB")
 		return warnings, fmt.Errorf("Minimum memory limit allowed is 4MB")
 	}
 	}
-	if hostConfig.Memory > 0 && !daemon.SystemConfig().MemoryLimit {
+	if hostConfig.Memory > 0 && !sysInfo.MemoryLimit {
 		warnings = append(warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.")
 		warnings = append(warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.")
 		logrus.Warnf("Your kernel does not support memory limit capabilities. Limitation discarded.")
 		logrus.Warnf("Your kernel does not support memory limit capabilities. Limitation discarded.")
 		hostConfig.Memory = 0
 		hostConfig.Memory = 0
+		hostConfig.MemorySwap = -1
 	}
 	}
-	if hostConfig.Memory > 0 && hostConfig.MemorySwap != -1 && !daemon.SystemConfig().SwapLimit {
+	if hostConfig.Memory > 0 && hostConfig.MemorySwap != -1 && !sysInfo.SwapLimit {
 		warnings = append(warnings, "Your kernel does not support swap limit capabilities, memory limited without swap.")
 		warnings = append(warnings, "Your kernel does not support swap limit capabilities, memory limited without swap.")
 		logrus.Warnf("Your kernel does not support swap limit capabilities, memory limited without swap.")
 		logrus.Warnf("Your kernel does not support swap limit capabilities, memory limited without swap.")
 		hostConfig.MemorySwap = -1
 		hostConfig.MemorySwap = -1
@@ -172,7 +177,7 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostC
 	if hostConfig.Memory == 0 && hostConfig.MemorySwap > 0 {
 	if hostConfig.Memory == 0 && hostConfig.MemorySwap > 0 {
 		return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.")
 		return warnings, fmt.Errorf("You should always set the Memory limit when using Memoryswap limit, see usage.")
 	}
 	}
-	if hostConfig.MemorySwappiness != nil && !daemon.SystemConfig().MemorySwappiness {
+	if hostConfig.MemorySwappiness != nil && *hostConfig.MemorySwappiness != -1 && !sysInfo.MemorySwappiness {
 		warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, memory swappiness discarded.")
 		warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, memory swappiness discarded.")
 		logrus.Warnf("Your kernel does not support memory swappiness capabilities, memory swappiness discarded.")
 		logrus.Warnf("Your kernel does not support memory swappiness capabilities, memory swappiness discarded.")
 		hostConfig.MemorySwappiness = nil
 		hostConfig.MemorySwappiness = nil
@@ -183,28 +188,28 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostC
 			return warnings, fmt.Errorf("Invalid value: %v, valid memory swappiness range is 0-100.", swappiness)
 			return warnings, fmt.Errorf("Invalid value: %v, valid memory swappiness range is 0-100.", swappiness)
 		}
 		}
 	}
 	}
-	if hostConfig.CPUShares > 0 && !daemon.SystemConfig().CPUShares {
+	if hostConfig.CPUShares > 0 && !sysInfo.CPUShares {
 		warnings = append(warnings, "Your kernel does not support CPU shares. Shares discarded.")
 		warnings = append(warnings, "Your kernel does not support CPU shares. Shares discarded.")
 		logrus.Warnf("Your kernel does not support CPU shares. Shares discarded.")
 		logrus.Warnf("Your kernel does not support CPU shares. Shares discarded.")
 		hostConfig.CPUShares = 0
 		hostConfig.CPUShares = 0
 	}
 	}
-	if hostConfig.CPUPeriod > 0 && !daemon.SystemConfig().CPUCfsPeriod {
+	if hostConfig.CPUPeriod > 0 && !sysInfo.CPUCfsPeriod {
 		warnings = append(warnings, "Your kernel does not support CPU cfs period. Period discarded.")
 		warnings = append(warnings, "Your kernel does not support CPU cfs period. Period discarded.")
 		logrus.Warnf("Your kernel does not support CPU cfs period. Period discarded.")
 		logrus.Warnf("Your kernel does not support CPU cfs period. Period discarded.")
 		hostConfig.CPUPeriod = 0
 		hostConfig.CPUPeriod = 0
 	}
 	}
-	if hostConfig.CPUQuota > 0 && !daemon.SystemConfig().CPUCfsQuota {
+	if hostConfig.CPUQuota > 0 && !sysInfo.CPUCfsQuota {
 		warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.")
 		warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.")
 		logrus.Warnf("Your kernel does not support CPU cfs quota. Quota discarded.")
 		logrus.Warnf("Your kernel does not support CPU cfs quota. Quota discarded.")
 		hostConfig.CPUQuota = 0
 		hostConfig.CPUQuota = 0
 	}
 	}
-	if (hostConfig.CpusetCpus != "" || hostConfig.CpusetMems != "") && !daemon.SystemConfig().Cpuset {
+	if (hostConfig.CpusetCpus != "" || hostConfig.CpusetMems != "") && !sysInfo.Cpuset {
 		warnings = append(warnings, "Your kernel does not support cpuset. Cpuset discarded.")
 		warnings = append(warnings, "Your kernel does not support cpuset. Cpuset discarded.")
 		logrus.Warnf("Your kernel does not support cpuset. Cpuset discarded.")
 		logrus.Warnf("Your kernel does not support cpuset. Cpuset discarded.")
 		hostConfig.CpusetCpus = ""
 		hostConfig.CpusetCpus = ""
 		hostConfig.CpusetMems = ""
 		hostConfig.CpusetMems = ""
 	}
 	}
-	if hostConfig.BlkioWeight > 0 && !daemon.SystemConfig().BlkioWeight {
+	if hostConfig.BlkioWeight > 0 && !sysInfo.BlkioWeight {
 		warnings = append(warnings, "Your kernel does not support Block I/O weight. Weight discarded.")
 		warnings = append(warnings, "Your kernel does not support Block I/O weight. Weight discarded.")
 		logrus.Warnf("Your kernel does not support Block I/O weight. Weight discarded.")
 		logrus.Warnf("Your kernel does not support Block I/O weight. Weight discarded.")
 		hostConfig.BlkioWeight = 0
 		hostConfig.BlkioWeight = 0
@@ -212,11 +217,13 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostC
 	if hostConfig.BlkioWeight > 0 && (hostConfig.BlkioWeight < 10 || hostConfig.BlkioWeight > 1000) {
 	if hostConfig.BlkioWeight > 0 && (hostConfig.BlkioWeight < 10 || hostConfig.BlkioWeight > 1000) {
 		return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.")
 		return warnings, fmt.Errorf("Range of blkio weight is from 10 to 1000.")
 	}
 	}
-	if hostConfig.OomKillDisable && !daemon.SystemConfig().OomKillDisable {
+
+	if hostConfig.OomKillDisable && !sysInfo.OomKillDisable {
 		hostConfig.OomKillDisable = false
 		hostConfig.OomKillDisable = false
 		return warnings, fmt.Errorf("Your kernel does not support oom kill disable.")
 		return warnings, fmt.Errorf("Your kernel does not support oom kill disable.")
 	}
 	}
-	if daemon.SystemConfig().IPv4ForwardingDisabled {
+
+	if sysInfo.IPv4ForwardingDisabled {
 		warnings = append(warnings, "IPv4 forwarding is disabled. Networking will not work.")
 		warnings = append(warnings, "IPv4 forwarding is disabled. Networking will not work.")
 		logrus.Warnf("IPv4 forwarding is disabled. Networking will not work")
 		logrus.Warnf("IPv4 forwarding is disabled. Networking will not work")
 	}
 	}

+ 11 - 8
daemon/info.go

@@ -11,6 +11,7 @@ import (
 	"github.com/docker/docker/pkg/fileutils"
 	"github.com/docker/docker/pkg/fileutils"
 	"github.com/docker/docker/pkg/parsers/kernel"
 	"github.com/docker/docker/pkg/parsers/kernel"
 	"github.com/docker/docker/pkg/parsers/operatingsystem"
 	"github.com/docker/docker/pkg/parsers/operatingsystem"
+	"github.com/docker/docker/pkg/sysinfo"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/registry"
 	"github.com/docker/docker/registry"
 	"github.com/docker/docker/utils"
 	"github.com/docker/docker/utils"
@@ -56,15 +57,17 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
 		initPath = daemon.SystemInitPath()
 		initPath = daemon.SystemInitPath()
 	}
 	}
 
 
+	sysInfo := sysinfo.New(false)
+
 	v := &types.Info{
 	v := &types.Info{
 		ID:                 daemon.ID,
 		ID:                 daemon.ID,
 		Containers:         len(daemon.List()),
 		Containers:         len(daemon.List()),
 		Images:             imgcount,
 		Images:             imgcount,
 		Driver:             daemon.GraphDriver().String(),
 		Driver:             daemon.GraphDriver().String(),
 		DriverStatus:       daemon.GraphDriver().Status(),
 		DriverStatus:       daemon.GraphDriver().Status(),
-		IPv4Forwarding:     !daemon.SystemConfig().IPv4ForwardingDisabled,
-		BridgeNfIptables:   !daemon.SystemConfig().BridgeNfCallIptablesDisabled,
-		BridgeNfIp6tables:  !daemon.SystemConfig().BridgeNfCallIP6tablesDisabled,
+		IPv4Forwarding:     !sysInfo.IPv4ForwardingDisabled,
+		BridgeNfIptables:   !sysInfo.BridgeNfCallIptablesDisabled,
+		BridgeNfIp6tables:  !sysInfo.BridgeNfCallIP6tablesDisabled,
 		Debug:              os.Getenv("DEBUG") != "",
 		Debug:              os.Getenv("DEBUG") != "",
 		NFd:                fileutils.GetTotalUsedFds(),
 		NFd:                fileutils.GetTotalUsedFds(),
 		NGoroutines:        runtime.NumGoroutine(),
 		NGoroutines:        runtime.NumGoroutine(),
@@ -90,11 +93,11 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
 	// sysinfo.cgroupCpuInfo will be nil otherwise and cause a SIGSEGV if
 	// sysinfo.cgroupCpuInfo will be nil otherwise and cause a SIGSEGV if
 	// an attempt is made to access through them.
 	// an attempt is made to access through them.
 	if runtime.GOOS != "windows" {
 	if runtime.GOOS != "windows" {
-		v.MemoryLimit = daemon.SystemConfig().MemoryLimit
-		v.SwapLimit = daemon.SystemConfig().SwapLimit
-		v.OomKillDisable = daemon.SystemConfig().OomKillDisable
-		v.CpuCfsPeriod = daemon.SystemConfig().CPUCfsPeriod
-		v.CpuCfsQuota = daemon.SystemConfig().CPUCfsQuota
+		v.MemoryLimit = sysInfo.MemoryLimit
+		v.SwapLimit = sysInfo.SwapLimit
+		v.OomKillDisable = sysInfo.OomKillDisable
+		v.CpuCfsPeriod = sysInfo.CPUCfsPeriod
+		v.CpuCfsQuota = sysInfo.CPUCfsQuota
 	}
 	}
 
 
 	if httpProxy := os.Getenv("http_proxy"); httpProxy != "" {
 	if httpProxy := os.Getenv("http_proxy"); httpProxy != "" {

+ 6 - 4
daemon/start.go

@@ -21,10 +21,6 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *runconfig.HostConf
 		return fmt.Errorf("Container already started")
 		return fmt.Errorf("Container already started")
 	}
 	}
 
 
-	if _, err = daemon.verifyContainerSettings(hostConfig, nil); err != nil {
-		return err
-	}
-
 	// Windows does not have the backwards compatibilty issue here.
 	// Windows does not have the backwards compatibilty issue here.
 	if runtime.GOOS != "windows" {
 	if runtime.GOOS != "windows" {
 		// This is kept for backward compatibility - hostconfig should be passed when
 		// This is kept for backward compatibility - hostconfig should be passed when
@@ -40,6 +36,12 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *runconfig.HostConf
 		}
 		}
 	}
 	}
 
 
+	// check if hostConfig is in line with the current system settings.
+	// It may happen cgroups are umounted or the like.
+	if _, err = daemon.verifyContainerSettings(container.hostConfig, nil); err != nil {
+		return err
+	}
+
 	if err := container.Start(); err != nil {
 	if err := container.Start(); err != nil {
 		return fmt.Errorf("Cannot start container %s: %s", name, err)
 		return fmt.Errorf("Cannot start container %s: %s", name, err)
 	}
 	}

+ 3 - 1
pkg/sysinfo/sysinfo_linux.go

@@ -10,7 +10,9 @@ import (
 	"github.com/opencontainers/runc/libcontainer/cgroups"
 	"github.com/opencontainers/runc/libcontainer/cgroups"
 )
 )
 
 
-// New returns a new SysInfo, using the filesystem to detect which features the kernel supports.
+// 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 {
 func New(quiet bool) *SysInfo {
 	sysInfo := &SysInfo{}
 	sysInfo := &SysInfo{}
 	sysInfo.cgroupMemInfo = checkCgroupMem(quiet)
 	sysInfo.cgroupMemInfo = checkCgroupMem(quiet)

+ 4 - 4
runconfig/parse.go

@@ -188,16 +188,16 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
 		flMemory = parsedMemory
 		flMemory = parsedMemory
 	}
 	}
 
 
-	var MemorySwap int64
+	var memorySwap int64
 	if *flMemorySwap != "" {
 	if *flMemorySwap != "" {
 		if *flMemorySwap == "-1" {
 		if *flMemorySwap == "-1" {
-			MemorySwap = -1
+			memorySwap = -1
 		} else {
 		} else {
 			parsedMemorySwap, err := units.RAMInBytes(*flMemorySwap)
 			parsedMemorySwap, err := units.RAMInBytes(*flMemorySwap)
 			if err != nil {
 			if err != nil {
 				return nil, nil, cmd, err
 				return nil, nil, cmd, err
 			}
 			}
-			MemorySwap = parsedMemorySwap
+			memorySwap = parsedMemorySwap
 		}
 		}
 	}
 	}
 
 
@@ -354,7 +354,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe
 		ContainerIDFile:  *flContainerIDFile,
 		ContainerIDFile:  *flContainerIDFile,
 		LxcConf:          lxcConf,
 		LxcConf:          lxcConf,
 		Memory:           flMemory,
 		Memory:           flMemory,
-		MemorySwap:       MemorySwap,
+		MemorySwap:       memorySwap,
 		CPUShares:        *flCPUShares,
 		CPUShares:        *flCPUShares,
 		CPUPeriod:        *flCPUPeriod,
 		CPUPeriod:        *flCPUPeriod,
 		CpusetCpus:       *flCpusetCpus,
 		CpusetCpus:       *flCpusetCpus,