123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- // 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"
- "regexp"
- "strconv"
- dockertypes "github.com/docker/docker/api/types"
- "golang.org/x/net/context"
- "time"
- "github.com/google/cadvisor/info/v1"
- "github.com/google/cadvisor/machine"
- )
- var dockerTimeout = 10 * time.Second
- func defaultContext() context.Context {
- ctx, _ := context.WithTimeout(context.Background(), dockerTimeout)
- return ctx
- }
- func SetTimeout(timeout time.Duration) {
- dockerTimeout = timeout
- }
- func Status() (v1.DockerStatus, error) {
- return StatusWithContext(defaultContext())
- }
- func StatusWithContext(ctx context.Context) (v1.DockerStatus, error) {
- client, err := Client()
- if err != nil {
- return v1.DockerStatus{}, fmt.Errorf("unable to communicate with docker daemon: %v", err)
- }
- dockerInfo, err := client.Info(ctx)
- if err != nil {
- return v1.DockerStatus{}, err
- }
- return StatusFromDockerInfo(dockerInfo)
- }
- func StatusFromDockerInfo(dockerInfo dockertypes.Info) (v1.DockerStatus, error) {
- out := v1.DockerStatus{}
- out.KernelVersion = machine.KernelVersion()
- out.OS = dockerInfo.OperatingSystem
- out.Hostname = dockerInfo.Name
- out.RootDir = dockerInfo.DockerRootDir
- out.Driver = dockerInfo.Driver
- 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]
- }
- var err error
- ver, err := VersionString()
- if err != nil {
- return out, err
- }
- out.Version = ver
- ver, err = APIVersionString()
- if err != nil {
- return out, err
- }
- out.APIVersion = ver
- return out, nil
- }
- func Images() ([]v1.DockerImage, error) {
- client, err := Client()
- if err != nil {
- return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err)
- }
- images, err := client.ImageList(defaultContext(), dockertypes.ImageListOptions{All: false})
- if err != nil {
- return nil, err
- }
- out := []v1.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 := v1.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(defaultContext())
- 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(defaultContext())
- if err != nil {
- return nil, fmt.Errorf("unable to get docker version: %v", err)
- }
- dockerInfo.ServerVersion = version.Version
- }
- version, err := parseVersion(dockerInfo.ServerVersion, version_re, 3)
- 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)
- }
- if dockerInfo.Driver == "" {
- return nil, fmt.Errorf("failed to find docker storage driver")
- }
- return &dockerInfo, nil
- }
- func Version() ([]int, error) {
- ver, err := VersionString()
- if err != nil {
- return nil, err
- }
- return parseVersion(ver, version_re, 3)
- }
- func APIVersion() ([]int, error) {
- ver, err := APIVersionString()
- if err != nil {
- return nil, err
- }
- return parseVersion(ver, apiversion_re, 2)
- }
- func VersionString() (string, error) {
- docker_version := "Unknown"
- client, err := Client()
- if err == nil {
- version, err := client.ServerVersion(defaultContext())
- if err == nil {
- docker_version = version.Version
- }
- }
- return docker_version, err
- }
- func APIVersionString() (string, error) {
- docker_api_version := "Unknown"
- client, err := Client()
- if err == nil {
- version, err := client.ServerVersion(defaultContext())
- if err == nil {
- docker_api_version = version.APIVersion
- }
- }
- return docker_api_version, err
- }
- func parseVersion(version_string string, regex *regexp.Regexp, length int) ([]int, error) {
- matches := regex.FindAllStringSubmatch(version_string, -1)
- if len(matches) != 1 {
- return nil, fmt.Errorf("version string \"%v\" doesn't match expected regular expression: \"%v\"", version_string, regex.String())
- }
- version_string_array := matches[0][1:]
- version_array := make([]int, length)
- for index, version_str := range version_string_array {
- version, err := strconv.Atoi(version_str)
- if err != nil {
- return nil, fmt.Errorf("error while parsing \"%v\" in \"%v\"", version_str, version_string)
- }
- version_array[index] = version
- }
- return version_array, nil
- }
|