diff --git a/container/docker/factory.go b/container/docker/factory.go index ed5ff14c..35bd15ac 100644 --- a/container/docker/factory.go +++ b/container/docker/factory.go @@ -163,6 +163,7 @@ var ( version_re = regexp.MustCompile(version_regexp_string) ) +// TODO: switch to a semantic versioning library. func parseDockerVersion(full_version_string string) ([]int, error) { matches := version_re.FindAllStringSubmatch(full_version_string, -1) if len(matches) != 1 { @@ -186,38 +187,14 @@ func Register(factory info.MachineInfoFactory, fsInfo fs.FsInfo, ignoreMetrics c if err != nil { return fmt.Errorf("unable to communicate with docker daemon: %v", err) } - var dockerVersion []int - if version, err := client.Version(); err != nil { - return fmt.Errorf("unable to communicate with docker daemon: %v", err) - } else { - expected_version := []int{1, 0, 0} - version_string := version.Get("Version") - dockerVersion, err = parseDockerVersion(version_string) - if err != nil { - return fmt.Errorf("couldn't parse docker version: %v", err) - } - for index, number := range dockerVersion { - if number > expected_version[index] { - break - } else if number < expected_version[index] { - return fmt.Errorf("cAdvisor requires docker version %v or above but we have found version %v reported as \"%v\"", expected_version, dockerVersion, version_string) - } - } - } - dockerInfo, err := client.Info() + dockerInfo, err := ValidateInfo() if err != nil { - return fmt.Errorf("failed to detect Docker info: %v", err) + return fmt.Errorf("failed to validate Docker info: %v", err) } - // Check that the libcontainer execdriver is used. - if !strings.HasPrefix(dockerInfo.ExecutionDriver, "native") { - return fmt.Errorf("docker found, but not using native exec driver") - } - - if dockerInfo.Driver == "" { - return fmt.Errorf("failed to find docker storage driver") - } + // Version already validated above, assume no error here. + dockerVersion, _ := parseDockerVersion(dockerInfo.ServerVersion) storageDir := dockerInfo.DockerRootDir if storageDir == "" { diff --git a/container/docker/handler.go b/container/docker/handler.go index 10a09ba5..04a4a8dd 100644 --- a/container/docker/handler.go +++ b/container/docker/handler.go @@ -425,3 +425,47 @@ func DockerImages() ([]docker.APIImages, error) { } return images, nil } + +// Checks whether the dockerInfo reflects a valid docker setup, and returns it if it does, or an +// error otherwise. +func ValidateInfo() (*docker.DockerInfo, error) { + client, err := Client() + if err != nil { + return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err) + } + + dockerInfo, err := client.Info() + if err != nil { + return nil, fmt.Errorf("failed to detect Docker info: %v", err) + } + + // Fall back to version API if ServerVersion is not set in info. + if dockerInfo.ServerVersion == "" { + version, err := client.Version() + if err != nil { + return nil, fmt.Errorf("unable to get docker version: %v", err) + } + dockerInfo.ServerVersion = version.Get("Version") + } + version, err := parseDockerVersion(dockerInfo.ServerVersion) + if err != nil { + return nil, err + } + + if version[0] < 1 { + return nil, fmt.Errorf("cAdvisor requires docker version %v or above but we have found version %v reported as %q", []int{1, 0, 0}, version, dockerInfo.ServerVersion) + } + + // Check that the libcontainer execdriver is used if the version is < 1.11 + // (execution drivers are no longer supported as of 1.11). + if version[0] <= 1 && version[1] <= 10 && + !strings.HasPrefix(dockerInfo.ExecutionDriver, "native") { + return nil, fmt.Errorf("docker found, but not using native exec driver") + } + + if dockerInfo.Driver == "" { + return nil, fmt.Errorf("failed to find docker storage driver") + } + + return dockerInfo, nil +} diff --git a/manager/manager.go b/manager/manager.go index 076bb649..693bba2f 100644 --- a/manager/manager.go +++ b/manager/manager.go @@ -233,7 +233,6 @@ func (self *manager) Start() error { glog.Errorf("Registration of the raw container factory failed: %v", err) } - // FIXME - delete? self.DockerInfo() self.DockerImages() diff --git a/validate/validate.go b/validate/validate.go index 0fd519c0..385a798f 100644 --- a/validate/validate.go +++ b/validate/validate.go @@ -185,24 +185,19 @@ func validateCgroups() (string, string) { } func validateDockerInfo() (string, string) { - info, err := docker.DockerInfo() + info, err := docker.ValidateInfo() if err != nil { - return Unknown, "Docker remote API not reachable\n\t" + return Unsupported, fmt.Sprintf("Docker setup is invalid: %v", err) } desc := fmt.Sprintf("Docker exec driver is %s. Storage driver is %s.\n", info.ExecutionDriver, info.Driver) - if strings.Contains(info.ExecutionDriver, "native") { - stateFile := docker.DockerStateDir() - if !utils.FileExists(stateFile) { - desc += fmt.Sprintf("\tDocker container state directory %q is not accessible.\n", stateFile) - return Unsupported, desc - } - desc += fmt.Sprintf("\tDocker container state directory is at %q and is accessible.\n", stateFile) - return Recommended, desc - } else if strings.Contains(info.ExecutionDriver, "lxc") { - return Supported, desc + stateFile := docker.DockerStateDir() + if !utils.FileExists(stateFile) { + desc += fmt.Sprintf("\tDocker container state directory %q is not accessible.\n", stateFile) + return Unsupported, desc } - return Unknown, desc + desc += fmt.Sprintf("\tDocker container state directory is at %q and is accessible.\n", stateFile) + return Recommended, desc } func validateCgroupMounts() (string, string) {