Fix usage of the latest go-dockerclient
This commit is contained in:
parent
d2bb061da0
commit
d9c864324b
@ -27,7 +27,7 @@ import (
|
||||
"github.com/google/cadvisor/fs"
|
||||
info "github.com/google/cadvisor/info/v1"
|
||||
|
||||
"github.com/fsouza/go-dockerclient"
|
||||
docker "github.com/fsouza/go-dockerclient"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
@ -205,23 +205,21 @@ func Register(factory info.MachineInfoFactory, fsInfo fs.FsInfo, ignoreMetrics c
|
||||
}
|
||||
}
|
||||
|
||||
information, err := client.Info()
|
||||
dockerInfo, err := client.Info()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to detect Docker info: %v", err)
|
||||
}
|
||||
|
||||
// Check that the libcontainer execdriver is used.
|
||||
execDriver := information.Get("ExecutionDriver")
|
||||
if !strings.HasPrefix(execDriver, "native") {
|
||||
if !strings.HasPrefix(dockerInfo.ExecutionDriver, "native") {
|
||||
return fmt.Errorf("docker found, but not using native exec driver")
|
||||
}
|
||||
|
||||
sd := information.Get("Driver")
|
||||
if sd == "" {
|
||||
if dockerInfo.Driver == "" {
|
||||
return fmt.Errorf("failed to find docker storage driver")
|
||||
}
|
||||
|
||||
storageDir := information.Get("DockerRootDir")
|
||||
storageDir := dockerInfo.DockerRootDir
|
||||
if storageDir == "" {
|
||||
storageDir = *dockerRootDir
|
||||
}
|
||||
@ -237,7 +235,7 @@ func Register(factory info.MachineInfoFactory, fsInfo fs.FsInfo, ignoreMetrics c
|
||||
dockerVersion: dockerVersion,
|
||||
fsInfo: fsInfo,
|
||||
machineInfoFactory: factory,
|
||||
storageDriver: storageDriver(sd),
|
||||
storageDriver: storageDriver(dockerInfo.Driver),
|
||||
storageDir: storageDir,
|
||||
ignoreMetrics: ignoreMetrics,
|
||||
}
|
||||
|
@ -402,16 +402,16 @@ func (self *dockerContainerHandler) Exists() bool {
|
||||
return containerlibcontainer.Exists(*dockerRootDir, *dockerRunDir, self.id)
|
||||
}
|
||||
|
||||
func DockerInfo() (map[string]string, error) {
|
||||
func DockerInfo() (docker.DockerInfo, error) {
|
||||
client, err := Client()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to communicate with docker daemon: %v", err)
|
||||
return docker.DockerInfo{}, fmt.Errorf("unable to communicate with docker daemon: %v", err)
|
||||
}
|
||||
info, err := client.Info()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return docker.DockerInfo{}, err
|
||||
}
|
||||
return info.Map(), nil
|
||||
return *info, nil
|
||||
}
|
||||
|
||||
func DockerImages() ([]docker.APIImages, error) {
|
||||
|
44
fs/fs.go
44
fs/fs.go
@ -19,7 +19,6 @@ package fs
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@ -63,9 +62,14 @@ type RealFsInfo struct {
|
||||
|
||||
type Context struct {
|
||||
// docker root directory.
|
||||
DockerRoot string
|
||||
DockerInfo map[string]string
|
||||
RktPath string
|
||||
Docker DockerContext
|
||||
RktPath string
|
||||
}
|
||||
|
||||
type DockerContext struct {
|
||||
Root string
|
||||
Driver string
|
||||
DriverStatus map[string]string
|
||||
}
|
||||
|
||||
func NewFsInfo(context Context) (FsInfo, error) {
|
||||
@ -117,22 +121,17 @@ func NewFsInfo(context Context) (FsInfo, error) {
|
||||
// docker is using devicemapper for its storage driver. If a loopback device is being used, don't
|
||||
// return any information or error, as we want to report based on the actual partition where the
|
||||
// loopback file resides, inside of the loopback file itself.
|
||||
func (self *RealFsInfo) getDockerDeviceMapperInfo(dockerInfo map[string]string) (string, *partition, error) {
|
||||
if storageDriver, ok := dockerInfo["Driver"]; ok && storageDriver != DeviceMapper.String() {
|
||||
func (self *RealFsInfo) getDockerDeviceMapperInfo(context DockerContext) (string, *partition, error) {
|
||||
if context.Driver != DeviceMapper.String() {
|
||||
return "", nil, nil
|
||||
}
|
||||
|
||||
var driverStatus [][]string
|
||||
if err := json.Unmarshal([]byte(dockerInfo["DriverStatus"]), &driverStatus); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
dataLoopFile := dockerStatusValue(driverStatus, "Data loop file")
|
||||
dataLoopFile := context.DriverStatus["Data loop file"]
|
||||
if len(dataLoopFile) > 0 {
|
||||
return "", nil, nil
|
||||
}
|
||||
|
||||
dev, major, minor, blockSize, err := dockerDMDevice(driverStatus, self.dmsetup)
|
||||
dev, major, minor, blockSize, err := dockerDMDevice(context.DriverStatus, self.dmsetup)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
@ -163,7 +162,7 @@ func (self *RealFsInfo) addSystemRootLabel(mounts []*mount.Info) {
|
||||
|
||||
// addDockerImagesLabel attempts to determine which device contains the mount for docker images.
|
||||
func (self *RealFsInfo) addDockerImagesLabel(context Context, mounts []*mount.Info) {
|
||||
dockerDev, dockerPartition, err := self.getDockerDeviceMapperInfo(context.DockerInfo)
|
||||
dockerDev, dockerPartition, err := self.getDockerDeviceMapperInfo(context.Docker)
|
||||
if err != nil {
|
||||
glog.Warningf("Could not get Docker devicemapper device: %v", err)
|
||||
}
|
||||
@ -198,7 +197,7 @@ func getDockerImagePaths(context Context) map[string]struct{} {
|
||||
}
|
||||
|
||||
// TODO(rjnagal): Detect docker root and graphdriver directories from docker info.
|
||||
dockerRoot := context.DockerRoot
|
||||
dockerRoot := context.Docker.Root
|
||||
for _, dir := range []string{"devicemapper", "btrfs", "aufs", "overlay", "zfs"} {
|
||||
dockerImagePaths[path.Join(dockerRoot, dir)] = struct{}{}
|
||||
}
|
||||
@ -435,15 +434,6 @@ func getVfsStats(path string) (total uint64, free uint64, avail uint64, inodes u
|
||||
return total, free, avail, inodes, inodesFree, nil
|
||||
}
|
||||
|
||||
func dockerStatusValue(status [][]string, target string) string {
|
||||
for _, v := range status {
|
||||
if len(v) == 2 && strings.ToLower(v[0]) == strings.ToLower(target) {
|
||||
return v[1]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// dmsetupClient knows to to interact with dmsetup to retrieve information about devicemapper.
|
||||
type dmsetupClient interface {
|
||||
table(poolName string) ([]byte, error)
|
||||
@ -461,9 +451,9 @@ func (*defaultDmsetupClient) table(poolName string) ([]byte, error) {
|
||||
|
||||
// Devicemapper thin provisioning is detailed at
|
||||
// https://www.kernel.org/doc/Documentation/device-mapper/thin-provisioning.txt
|
||||
func dockerDMDevice(driverStatus [][]string, dmsetup dmsetupClient) (string, uint, uint, uint, error) {
|
||||
poolName := dockerStatusValue(driverStatus, "Pool Name")
|
||||
if len(poolName) == 0 {
|
||||
func dockerDMDevice(driverStatus map[string]string, dmsetup dmsetupClient) (string, uint, uint, uint, error) {
|
||||
poolName, ok := driverStatus["Pool Name"]
|
||||
if !ok || len(poolName) == 0 {
|
||||
return "", 0, 0, 0, fmt.Errorf("Could not get dm pool name")
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ func TestGetDockerDeviceMapperInfo(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
driver string
|
||||
driverStatus string
|
||||
driverStatus map[string]string
|
||||
dmsetupTable string
|
||||
dmsetupTableError error
|
||||
expectedDevice string
|
||||
@ -216,9 +216,9 @@ func TestGetDockerDeviceMapperInfo(t *testing.T) {
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "error unmarshaling driver status",
|
||||
name: "nil driver status",
|
||||
driver: "devicemapper",
|
||||
driverStatus: "{[[[asdf",
|
||||
driverStatus: nil,
|
||||
expectedDevice: "",
|
||||
expectedPartition: nil,
|
||||
expectedError: true,
|
||||
@ -226,7 +226,7 @@ func TestGetDockerDeviceMapperInfo(t *testing.T) {
|
||||
{
|
||||
name: "loopback",
|
||||
driver: "devicemapper",
|
||||
driverStatus: `[["Data loop file","/var/lib/docker/devicemapper/devicemapper/data"]]`,
|
||||
driverStatus: map[string]string{"Data loop file": "/var/lib/docker/devicemapper/devicemapper/data"},
|
||||
expectedDevice: "",
|
||||
expectedPartition: nil,
|
||||
expectedError: false,
|
||||
@ -234,7 +234,7 @@ func TestGetDockerDeviceMapperInfo(t *testing.T) {
|
||||
{
|
||||
name: "missing pool name",
|
||||
driver: "devicemapper",
|
||||
driverStatus: `[[]]`,
|
||||
driverStatus: map[string]string{},
|
||||
expectedDevice: "",
|
||||
expectedPartition: nil,
|
||||
expectedError: true,
|
||||
@ -242,7 +242,7 @@ func TestGetDockerDeviceMapperInfo(t *testing.T) {
|
||||
{
|
||||
name: "error invoking dmsetup",
|
||||
driver: "devicemapper",
|
||||
driverStatus: `[["Pool Name", "vg_vagrant-docker--pool"]]`,
|
||||
driverStatus: map[string]string{"Pool Name": "vg_vagrant-docker--pool"},
|
||||
dmsetupTableError: errors.New("foo"),
|
||||
expectedDevice: "",
|
||||
expectedPartition: nil,
|
||||
@ -251,7 +251,7 @@ func TestGetDockerDeviceMapperInfo(t *testing.T) {
|
||||
{
|
||||
name: "unable to parse dmsetup table",
|
||||
driver: "devicemapper",
|
||||
driverStatus: `[["Pool Name", "vg_vagrant-docker--pool"]]`,
|
||||
driverStatus: map[string]string{"Pool Name": "vg_vagrant-docker--pool"},
|
||||
dmsetupTable: "no data here!",
|
||||
expectedDevice: "",
|
||||
expectedPartition: nil,
|
||||
@ -260,7 +260,7 @@ func TestGetDockerDeviceMapperInfo(t *testing.T) {
|
||||
{
|
||||
name: "happy path",
|
||||
driver: "devicemapper",
|
||||
driverStatus: `[["Pool Name", "vg_vagrant-docker--pool"]]`,
|
||||
driverStatus: map[string]string{"Pool Name": "vg_vagrant-docker--pool"},
|
||||
dmsetupTable: "0 53870592 thin-pool 253:2 253:3 1024 0 1 skip_block_zeroing",
|
||||
expectedDevice: "vg_vagrant-docker--pool",
|
||||
expectedPartition: &partition{
|
||||
@ -280,12 +280,12 @@ func TestGetDockerDeviceMapperInfo(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
dockerInfo := map[string]string{
|
||||
"Driver": tt.driver,
|
||||
"DriverStatus": tt.driverStatus,
|
||||
dockerCtx := DockerContext{
|
||||
Driver: tt.driver,
|
||||
DriverStatus: tt.driverStatus,
|
||||
}
|
||||
|
||||
device, partition, err := fsInfo.getDockerDeviceMapperInfo(dockerInfo)
|
||||
device, partition, err := fsInfo.getDockerDeviceMapperInfo(dockerCtx)
|
||||
|
||||
if tt.expectedError && err == nil {
|
||||
t.Errorf("%s: expected error but got nil", tt.name)
|
||||
@ -310,7 +310,7 @@ func TestAddDockerImagesLabel(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
driver string
|
||||
driverStatus string
|
||||
driverStatus map[string]string
|
||||
dmsetupTable string
|
||||
getDockerDeviceMapperInfoError error
|
||||
mounts []*mount.Info
|
||||
@ -320,7 +320,7 @@ func TestAddDockerImagesLabel(t *testing.T) {
|
||||
{
|
||||
name: "devicemapper, not loopback",
|
||||
driver: "devicemapper",
|
||||
driverStatus: `[["Pool Name", "vg_vagrant-docker--pool"]]`,
|
||||
driverStatus: map[string]string{"Pool Name": "vg_vagrant-docker--pool"},
|
||||
dmsetupTable: "0 53870592 thin-pool 253:2 253:3 1024 0 1 skip_block_zeroing",
|
||||
mounts: []*mount.Info{
|
||||
{
|
||||
@ -340,7 +340,7 @@ func TestAddDockerImagesLabel(t *testing.T) {
|
||||
{
|
||||
name: "devicemapper, loopback on non-root partition",
|
||||
driver: "devicemapper",
|
||||
driverStatus: `[["Data loop file","/var/lib/docker/devicemapper/devicemapper/data"]]`,
|
||||
driverStatus: map[string]string{"Data loop file": "/var/lib/docker/devicemapper/devicemapper/data"},
|
||||
mounts: []*mount.Info{
|
||||
{
|
||||
Source: "/dev/mapper/vg_vagrant-lv_root",
|
||||
@ -403,10 +403,10 @@ func TestAddDockerImagesLabel(t *testing.T) {
|
||||
}
|
||||
|
||||
context := Context{
|
||||
DockerRoot: "/var/lib/docker",
|
||||
DockerInfo: map[string]string{
|
||||
"Driver": tt.driver,
|
||||
"DriverStatus": tt.driverStatus,
|
||||
Docker: DockerContext{
|
||||
Root: "/var/lib/docker",
|
||||
Driver: tt.driver,
|
||||
DriverStatus: tt.driverStatus,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
package manager
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
@ -61,7 +60,7 @@ type Manager interface {
|
||||
// Stops the manager.
|
||||
Stop() error
|
||||
|
||||
// Get information about a container.
|
||||
// information about a container.
|
||||
GetContainerInfo(containerName string, query *info.ContainerInfoRequest) (*info.ContainerInfo, error)
|
||||
|
||||
// Get V2 information about a container.
|
||||
@ -132,7 +131,7 @@ func New(memoryCache *memory.InMemoryCache, sysfs sysfs.SysFs, maxHousekeepingIn
|
||||
}
|
||||
glog.Infof("cAdvisor running in container: %q", selfContainer)
|
||||
|
||||
dockerInfo, err := docker.DockerInfo()
|
||||
dockerInfo, err := dockerInfo()
|
||||
if err != nil {
|
||||
glog.Warningf("Unable to connect to Docker: %v", err)
|
||||
}
|
||||
@ -141,7 +140,14 @@ func New(memoryCache *memory.InMemoryCache, sysfs sysfs.SysFs, maxHousekeepingIn
|
||||
glog.Warningf("unable to connect to Rkt api service: %v", err)
|
||||
}
|
||||
|
||||
context := fs.Context{DockerRoot: docker.RootDir(), DockerInfo: dockerInfo, RktPath: rktPath}
|
||||
context := fs.Context{
|
||||
Docker: fs.DockerContext{
|
||||
Root: docker.RootDir(),
|
||||
Driver: dockerInfo.Driver,
|
||||
DriverStatus: dockerInfo.DriverStatus,
|
||||
},
|
||||
RktPath: rktPath,
|
||||
}
|
||||
fsInfo, err := fs.NewFsInfo(context)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -227,6 +233,7 @@ func (self *manager) Start() error {
|
||||
glog.Errorf("Registration of the raw container factory failed: %v", err)
|
||||
}
|
||||
|
||||
// FIXME - delete?
|
||||
self.DockerInfo()
|
||||
self.DockerImages()
|
||||
|
||||
@ -1159,58 +1166,31 @@ func (m *manager) DockerImages() ([]DockerImage, error) {
|
||||
}
|
||||
|
||||
func (m *manager) DockerInfo() (DockerStatus, error) {
|
||||
info, err := docker.DockerInfo()
|
||||
return dockerInfo()
|
||||
}
|
||||
|
||||
func dockerInfo() (DockerStatus, error) {
|
||||
dockerInfo, err := docker.DockerInfo()
|
||||
if err != nil {
|
||||
return DockerStatus{}, err
|
||||
}
|
||||
versionInfo, err := m.GetVersionInfo()
|
||||
versionInfo, err := getVersionInfo()
|
||||
if err != nil {
|
||||
return DockerStatus{}, err
|
||||
}
|
||||
out := DockerStatus{}
|
||||
out.Version = versionInfo.DockerVersion
|
||||
if val, ok := info["KernelVersion"]; ok {
|
||||
out.KernelVersion = val
|
||||
}
|
||||
if val, ok := info["OperatingSystem"]; ok {
|
||||
out.OS = val
|
||||
}
|
||||
if val, ok := info["Name"]; ok {
|
||||
out.Hostname = val
|
||||
}
|
||||
if val, ok := info["DockerRootDir"]; ok {
|
||||
out.RootDir = val
|
||||
}
|
||||
if val, ok := info["Driver"]; ok {
|
||||
out.Driver = val
|
||||
}
|
||||
if val, ok := info["ExecutionDriver"]; ok {
|
||||
out.ExecDriver = val
|
||||
}
|
||||
if val, ok := info["Images"]; ok {
|
||||
n, err := strconv.Atoi(val)
|
||||
if err == nil {
|
||||
out.NumImages = n
|
||||
}
|
||||
}
|
||||
if val, ok := info["Containers"]; ok {
|
||||
n, err := strconv.Atoi(val)
|
||||
if err == nil {
|
||||
out.NumContainers = n
|
||||
}
|
||||
}
|
||||
if val, ok := info["DriverStatus"]; ok {
|
||||
var driverStatus [][]string
|
||||
err := json.Unmarshal([]byte(val), &driverStatus)
|
||||
if err != nil {
|
||||
return DockerStatus{}, err
|
||||
}
|
||||
out.DriverStatus = make(map[string]string)
|
||||
for _, v := range driverStatus {
|
||||
if len(v) == 2 {
|
||||
out.DriverStatus[v[0]] = v[1]
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
|
@ -185,28 +185,24 @@ func validateCgroups() (string, string) {
|
||||
}
|
||||
|
||||
func validateDockerInfo() (string, string) {
|
||||
client, err := docker.Client()
|
||||
if err == nil {
|
||||
info, err := client.Info()
|
||||
if err == nil {
|
||||
execDriver := info.Get("ExecutionDriver")
|
||||
storageDriver := info.Get("Driver")
|
||||
desc := fmt.Sprintf("Docker exec driver is %s. Storage driver is %s.\n", execDriver, storageDriver)
|
||||
if strings.Contains(execDriver, "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(execDriver, "lxc") {
|
||||
return Supported, desc
|
||||
}
|
||||
return Unknown, desc
|
||||
}
|
||||
info, err := docker.DockerInfo()
|
||||
if err != nil {
|
||||
return Unknown, "Docker remote API not reachable\n\t"
|
||||
}
|
||||
return Unknown, "Docker remote API not reachable\n\t"
|
||||
|
||||
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
|
||||
}
|
||||
return Unknown, desc
|
||||
}
|
||||
|
||||
func validateCgroupMounts() (string, string) {
|
||||
|
Loading…
Reference in New Issue
Block a user