Refactor docker-specific functions from manager to docker
This commit is contained in:
parent
b983d32d96
commit
0c89fd1b71
162
container/docker/docker.go
Normal file
162
container/docker/docker.go
Normal file
@ -0,0 +1,162 @@
|
||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Provides global docker information.
|
||||
package docker
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
dockertypes "github.com/docker/engine-api/types"
|
||||
"github.com/google/cadvisor/utils/machine"
|
||||
)
|
||||
|
||||
func Status() (DockerStatus, error) {
|
||||
client, err := Client()
|
||||
if err != nil {
|
||||
return DockerStatus{}, fmt.Errorf("unable to communicate with docker daemon: %v", err)
|
||||
}
|
||||
dockerInfo, err := client.Info(context.Background())
|
||||
if err != nil {
|
||||
return DockerStatus{}, err
|
||||
}
|
||||
|
||||
out := DockerStatus{}
|
||||
out.Version = VersionString()
|
||||
out.KernelVersion = machine.KernelVersion()
|
||||
out.OS = dockerInfo.OperatingSystem
|
||||
out.Hostname = dockerInfo.Name
|
||||
out.RootDir = dockerInfo.DockerRootDir
|
||||
out.Driver = dockerInfo.Driver
|
||||
out.ExecDriver = dockerInfo.ExecutionDriver
|
||||
out.NumImages = dockerInfo.Images
|
||||
out.NumContainers = dockerInfo.Containers
|
||||
out.DriverStatus = make(map[string]string, len(dockerInfo.DriverStatus))
|
||||
for _, v := range dockerInfo.DriverStatus {
|
||||
out.DriverStatus[v[0]] = v[1]
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func Images() ([]DockerImage, error) {
|
||||
client, err := Client()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err)
|
||||
}
|
||||
images, err := client.ImageList(context.Background(), dockertypes.ImageListOptions{All: false})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := []DockerImage{}
|
||||
const unknownTag = "<none>:<none>"
|
||||
for _, image := range images {
|
||||
if len(image.RepoTags) == 1 && image.RepoTags[0] == unknownTag {
|
||||
// images with repo or tags are uninteresting.
|
||||
continue
|
||||
}
|
||||
di := DockerImage{
|
||||
ID: image.ID,
|
||||
RepoTags: image.RepoTags,
|
||||
Created: image.Created,
|
||||
VirtualSize: image.VirtualSize,
|
||||
Size: image.Size,
|
||||
}
|
||||
out = append(out, di)
|
||||
}
|
||||
return out, nil
|
||||
|
||||
}
|
||||
|
||||
// Checks whether the dockerInfo reflects a valid docker setup, and returns it if it does, or an
|
||||
// error otherwise.
|
||||
func ValidateInfo() (*dockertypes.Info, error) {
|
||||
client, err := Client()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err)
|
||||
}
|
||||
|
||||
dockerInfo, err := client.Info(context.Background())
|
||||
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.ServerVersion(context.Background())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to get docker version: %v", err)
|
||||
}
|
||||
dockerInfo.ServerVersion = version.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
|
||||
}
|
||||
|
||||
func Version() ([]int, error) {
|
||||
return parseDockerVersion(VersionString())
|
||||
}
|
||||
|
||||
func VersionString() string {
|
||||
docker_version := "Unknown"
|
||||
client, err := Client()
|
||||
if err == nil {
|
||||
version, err := client.ServerVersion(context.Background())
|
||||
if err == nil {
|
||||
docker_version = version.Version
|
||||
}
|
||||
}
|
||||
return docker_version
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return nil, fmt.Errorf("version string \"%v\" doesn't match expected regular expression: \"%v\"", full_version_string, version_regexp_string)
|
||||
}
|
||||
version_string_array := matches[0][1:]
|
||||
version_array := make([]int, 3)
|
||||
for index, version_string := range version_string_array {
|
||||
version, err := strconv.Atoi(version_string)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while parsing \"%v\" in \"%v\"", version_string, full_version_string)
|
||||
}
|
||||
version_array[index] = version
|
||||
}
|
||||
return version_array, nil
|
||||
}
|
@ -19,7 +19,6 @@ import (
|
||||
"fmt"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/google/cadvisor/container"
|
||||
@ -164,24 +163,6 @@ 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 {
|
||||
return nil, fmt.Errorf("version string \"%v\" doesn't match expected regular expression: \"%v\"", full_version_string, version_regexp_string)
|
||||
}
|
||||
version_string_array := matches[0][1:]
|
||||
version_array := make([]int, 3)
|
||||
for index, version_string := range version_string_array {
|
||||
version, err := strconv.Atoi(version_string)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while parsing \"%v\" in \"%v\"", version_string, full_version_string)
|
||||
}
|
||||
version_array[index] = version
|
||||
}
|
||||
return version_array, nil
|
||||
}
|
||||
|
||||
// Register root container before running this function!
|
||||
func Register(factory info.MachineInfoFactory, fsInfo fs.FsInfo, ignoreMetrics container.MetricSet) error {
|
||||
client, err := Client()
|
||||
|
@ -29,7 +29,6 @@ import (
|
||||
info "github.com/google/cadvisor/info/v1"
|
||||
|
||||
docker "github.com/docker/engine-api/client"
|
||||
dockertypes "github.com/docker/engine-api/types"
|
||||
dockercontainer "github.com/docker/engine-api/types/container"
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||
cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
|
||||
@ -349,63 +348,3 @@ func (self *dockerContainerHandler) StopWatchingSubcontainers() error {
|
||||
func (self *dockerContainerHandler) Exists() bool {
|
||||
return common.CgroupExists(self.cgroupPaths)
|
||||
}
|
||||
|
||||
func DockerInfo() (dockertypes.Info, error) {
|
||||
client, err := Client()
|
||||
if err != nil {
|
||||
return dockertypes.Info{}, fmt.Errorf("unable to communicate with docker daemon: %v", err)
|
||||
}
|
||||
return client.Info(context.Background())
|
||||
}
|
||||
|
||||
func DockerImages() ([]dockertypes.Image, error) {
|
||||
client, err := Client()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err)
|
||||
}
|
||||
return client.ImageList(context.Background(), dockertypes.ImageListOptions{All: false})
|
||||
}
|
||||
|
||||
// Checks whether the dockerInfo reflects a valid docker setup, and returns it if it does, or an
|
||||
// error otherwise.
|
||||
func ValidateInfo() (*dockertypes.Info, error) {
|
||||
client, err := Client()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err)
|
||||
}
|
||||
|
||||
dockerInfo, err := client.Info(context.Background())
|
||||
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.ServerVersion(context.Background())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to get docker version: %v", err)
|
||||
}
|
||||
dockerInfo.ServerVersion = version.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
|
||||
}
|
||||
|
37
container/docker/types.go
Normal file
37
container/docker/types.go
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Types used for docker containers.
|
||||
package docker
|
||||
|
||||
type DockerStatus struct {
|
||||
Version string `json:"version"`
|
||||
KernelVersion string `json:"kernel_version"`
|
||||
OS string `json:"os"`
|
||||
Hostname string `json:"hostname"`
|
||||
RootDir string `json:"root_dir"`
|
||||
Driver string `json:"driver"`
|
||||
DriverStatus map[string]string `json:"driver_status"`
|
||||
ExecDriver string `json:"exec_driver"`
|
||||
NumImages int `json:"num_images"`
|
||||
NumContainers int `json:"num_containers"`
|
||||
}
|
||||
|
||||
type DockerImage struct {
|
||||
ID string `json:"id"`
|
||||
RepoTags []string `json:"repo_tags"` // repository name and tags.
|
||||
Created int64 `json:"created"` // unix time since creation.
|
||||
VirtualSize int64 `json:"virtual_size"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
@ -112,10 +112,10 @@ type Manager interface {
|
||||
CloseEventChannel(watch_id int)
|
||||
|
||||
// Get status information about docker.
|
||||
DockerInfo() (DockerStatus, error)
|
||||
DockerInfo() (docker.DockerStatus, error)
|
||||
|
||||
// Get details about interesting docker images.
|
||||
DockerImages() ([]DockerImage, error)
|
||||
DockerImages() ([]docker.DockerImage, error)
|
||||
|
||||
// Returns debugging information. Map of lines per category.
|
||||
DebugInfo() map[string][]string
|
||||
@ -134,7 +134,7 @@ func New(memoryCache *memory.InMemoryCache, sysfs sysfs.SysFs, maxHousekeepingIn
|
||||
}
|
||||
glog.Infof("cAdvisor running in container: %q", selfContainer)
|
||||
|
||||
dockerInfo, err := dockerInfo()
|
||||
dockerStatus, err := docker.Status()
|
||||
if err != nil {
|
||||
glog.Warningf("Unable to connect to Docker: %v", err)
|
||||
}
|
||||
@ -146,8 +146,8 @@ func New(memoryCache *memory.InMemoryCache, sysfs sysfs.SysFs, maxHousekeepingIn
|
||||
context := fs.Context{
|
||||
Docker: fs.DockerContext{
|
||||
Root: docker.RootDir(),
|
||||
Driver: dockerInfo.Driver,
|
||||
DriverStatus: dockerInfo.DriverStatus,
|
||||
Driver: dockerStatus.Driver,
|
||||
DriverStatus: dockerStatus.DriverStatus,
|
||||
},
|
||||
RktPath: rktPath,
|
||||
}
|
||||
@ -241,9 +241,6 @@ func (self *manager) Start() error {
|
||||
glog.Errorf("Registration of the raw container factory failed: %v", err)
|
||||
}
|
||||
|
||||
self.DockerInfo()
|
||||
self.DockerImages()
|
||||
|
||||
if *enableLoadReader {
|
||||
// Create cpu load reader.
|
||||
cpuLoadReader, err := cpuload.New()
|
||||
@ -1127,79 +1124,12 @@ func parseEventsStoragePolicy() events.StoragePolicy {
|
||||
return policy
|
||||
}
|
||||
|
||||
type DockerStatus struct {
|
||||
Version string `json:"version"`
|
||||
KernelVersion string `json:"kernel_version"`
|
||||
OS string `json:"os"`
|
||||
Hostname string `json:"hostname"`
|
||||
RootDir string `json:"root_dir"`
|
||||
Driver string `json:"driver"`
|
||||
DriverStatus map[string]string `json:"driver_status"`
|
||||
ExecDriver string `json:"exec_driver"`
|
||||
NumImages int `json:"num_images"`
|
||||
NumContainers int `json:"num_containers"`
|
||||
func (m *manager) DockerImages() ([]docker.DockerImage, error) {
|
||||
return docker.Images()
|
||||
}
|
||||
|
||||
type DockerImage struct {
|
||||
ID string `json:"id"`
|
||||
RepoTags []string `json:"repo_tags"` // repository name and tags.
|
||||
Created int64 `json:"created"` // unix time since creation.
|
||||
VirtualSize int64 `json:"virtual_size"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
||||
|
||||
func (m *manager) DockerImages() ([]DockerImage, error) {
|
||||
images, err := docker.DockerImages()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := []DockerImage{}
|
||||
const unknownTag = "<none>:<none>"
|
||||
for _, image := range images {
|
||||
if len(image.RepoTags) == 1 && image.RepoTags[0] == unknownTag {
|
||||
// images with repo or tags are uninteresting.
|
||||
continue
|
||||
}
|
||||
di := DockerImage{
|
||||
ID: image.ID,
|
||||
RepoTags: image.RepoTags,
|
||||
Created: image.Created,
|
||||
VirtualSize: image.VirtualSize,
|
||||
Size: image.Size,
|
||||
}
|
||||
out = append(out, di)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (m *manager) DockerInfo() (DockerStatus, error) {
|
||||
return dockerInfo()
|
||||
}
|
||||
|
||||
func dockerInfo() (DockerStatus, error) {
|
||||
dockerInfo, err := docker.DockerInfo()
|
||||
if err != nil {
|
||||
return DockerStatus{}, err
|
||||
}
|
||||
versionInfo, err := getVersionInfo()
|
||||
if err != nil {
|
||||
return DockerStatus{}, err
|
||||
}
|
||||
out := DockerStatus{}
|
||||
out.Version = versionInfo.DockerVersion
|
||||
out.KernelVersion = dockerInfo.KernelVersion
|
||||
out.OS = dockerInfo.OperatingSystem
|
||||
out.Hostname = dockerInfo.Name
|
||||
out.RootDir = dockerInfo.DockerRootDir
|
||||
out.Driver = dockerInfo.Driver
|
||||
out.ExecDriver = dockerInfo.ExecutionDriver
|
||||
out.NumImages = dockerInfo.Images
|
||||
out.NumContainers = dockerInfo.Containers
|
||||
out.DriverStatus = make(map[string]string, len(dockerInfo.DriverStatus))
|
||||
for _, v := range dockerInfo.DriverStatus {
|
||||
out.DriverStatus[v[0]] = v[1]
|
||||
}
|
||||
return out, nil
|
||||
func (m *manager) DockerInfo() (docker.DockerStatus, error) {
|
||||
return docker.Status()
|
||||
}
|
||||
|
||||
func (m *manager) DebugInfo() map[string][]string {
|
||||
@ -1241,7 +1171,7 @@ func getVersionInfo() (*info.VersionInfo, error) {
|
||||
|
||||
kernel_version := machine.KernelVersion()
|
||||
container_os := machine.ContainerOsVersion()
|
||||
docker_version := machine.DockerVersion()
|
||||
docker_version := docker.VersionString()
|
||||
|
||||
return &info.VersionInfo{
|
||||
KernelVersion: kernel_version,
|
||||
|
@ -31,7 +31,7 @@ import (
|
||||
|
||||
const DockerPage = "/docker/"
|
||||
|
||||
func toStatusKV(status manager.DockerStatus) ([]keyVal, []keyVal) {
|
||||
func toStatusKV(status docker.DockerStatus) ([]keyVal, []keyVal) {
|
||||
ds := []keyVal{
|
||||
{Key: "Driver", Value: status.Driver},
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/google/cadvisor/container/docker"
|
||||
httpmux "github.com/google/cadvisor/http/mux"
|
||||
info "github.com/google/cadvisor/info/v1"
|
||||
"github.com/google/cadvisor/manager"
|
||||
@ -62,7 +63,7 @@ type pageData struct {
|
||||
Root string
|
||||
DockerStatus []keyVal
|
||||
DockerDriverStatus []keyVal
|
||||
DockerImages []manager.DockerImage
|
||||
DockerImages []docker.DockerImage
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/google/cadvisor/container/docker"
|
||||
"github.com/google/cadvisor/fs"
|
||||
info "github.com/google/cadvisor/info/v1"
|
||||
"github.com/google/cadvisor/utils/cloudinfo"
|
||||
@ -30,7 +29,6 @@ import (
|
||||
"github.com/google/cadvisor/utils/sysinfo"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
var machineIdFilePath = flag.String("machine_id_file", "/etc/machine-id,/var/lib/dbus/machine-id", "Comma-separated list of files to check for machine-id. Use the first one that exists.")
|
||||
@ -136,18 +134,6 @@ func ContainerOsVersion() string {
|
||||
return container_os
|
||||
}
|
||||
|
||||
func DockerVersion() string {
|
||||
docker_version := "Unknown"
|
||||
client, err := docker.Client()
|
||||
if err == nil {
|
||||
version, err := client.ServerVersion(context.Background())
|
||||
if err == nil {
|
||||
docker_version = version.Version
|
||||
}
|
||||
}
|
||||
return docker_version
|
||||
}
|
||||
|
||||
func KernelVersion() string {
|
||||
uname := &syscall.Utsname{}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user