Skip to content

Commit

Permalink
Merge branch 'master' into overlay2
Browse files Browse the repository at this point in the history
  • Loading branch information
dashpole authored May 31, 2017
2 parents e0c8ec5 + 2835c35 commit 96b603e
Show file tree
Hide file tree
Showing 82 changed files with 4,623 additions and 1,505 deletions.
29 changes: 21 additions & 8 deletions Godeps/Godeps.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 19 additions & 5 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,35 @@ import (
"github.com/google/cadvisor/info/v1"

"github.com/golang/glog"
"time"
)

// Client represents the base URL for a cAdvisor client.
type Client struct {
baseUrl string
baseUrl string
httpClient *http.Client
}

// NewClient returns a new v1.3 client with the specified base URL.
func NewClient(url string) (*Client, error) {
return newClient(url, http.DefaultClient)
}

// NewClientWithTimeout returns a new v1.3 client with the specified base URL and http client timeout.
func NewClientWithTimeout(url string, timeout time.Duration) (*Client, error) {
return newClient(url, &http.Client{
Timeout: timeout,
})
}

func newClient(url string, client *http.Client) (*Client, error) {
if !strings.HasSuffix(url, "/") {
url += "/"
}

return &Client{
baseUrl: fmt.Sprintf("%sapi/v1.3/", url),
baseUrl: fmt.Sprintf("%sapi/v1.3/", url),
httpClient: client,
}, nil
}

Expand Down Expand Up @@ -168,9 +182,9 @@ func (self *Client) httpGetJsonData(data, postData interface{}, url, infoName st
if marshalErr != nil {
return fmt.Errorf("unable to marshal data: %v", marshalErr)
}
resp, err = http.Post(url, "application/json", bytes.NewBuffer(data))
resp, err = self.httpClient.Post(url, "application/json", bytes.NewBuffer(data))
} else {
resp, err = http.Get(url)
resp, err = self.httpClient.Get(url)
}
if err != nil {
return fmt.Errorf("unable to get %q from %q: %v", infoName, url, err)
Expand Down Expand Up @@ -199,7 +213,7 @@ func (self *Client) getEventStreamingData(url string, einfo chan *v1.Event) erro
if err != nil {
return err
}
resp, err := http.DefaultClient.Do(req)
resp, err := self.httpClient.Do(req)
if err != nil {
return err
}
Expand Down
68 changes: 68 additions & 0 deletions container/common/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,71 @@ func ListContainers(name string, cgroupPaths map[string]string, listType contain

return ret, nil
}

// AssignDeviceNamesToDiskStats assigns the Device field on the provided DiskIoStats by looking up
// the device major and minor identifiers in the provided device namer.
func AssignDeviceNamesToDiskStats(namer DeviceNamer, stats *info.DiskIoStats) {
assignDeviceNamesToPerDiskStats(
namer,
stats.IoMerged,
stats.IoQueued,
stats.IoServiceBytes,
stats.IoServiceTime,
stats.IoServiced,
stats.IoTime,
stats.IoWaitTime,
stats.Sectors,
)
}

// assignDeviceNamesToPerDiskStats looks up device names for the provided stats, caching names
// if necessary.
func assignDeviceNamesToPerDiskStats(namer DeviceNamer, diskStats ...[]info.PerDiskStats) {
devices := make(deviceIdentifierMap)
for _, stats := range diskStats {
for i, stat := range stats {
stats[i].Device = devices.Find(stat.Major, stat.Minor, namer)
}
}
}

// DeviceNamer returns string names for devices by their major and minor id.
type DeviceNamer interface {
// DeviceName returns the name of the device by its major and minor ids, or false if no
// such device is recognized.
DeviceName(major, minor uint64) (string, bool)
}

type MachineInfoNamer info.MachineInfo

func (n *MachineInfoNamer) DeviceName(major, minor uint64) (string, bool) {
for _, info := range n.DiskMap {
if info.Major == major && info.Minor == minor {
return "/dev/" + info.Name, true
}
}
for _, info := range n.Filesystems {
if info.DeviceMajor == major && info.DeviceMinor == minor {
return info.Device, true
}
}
return "", false
}

type deviceIdentifier struct {
major uint64
minor uint64
}

type deviceIdentifierMap map[deviceIdentifier]string

// Find locates the device name by device identifier out of from, caching the result as necessary.
func (m deviceIdentifierMap) Find(major, minor uint64, namer DeviceNamer) string {
d := deviceIdentifier{major, minor}
if s, ok := m[d]; ok {
return s
}
s, _ := namer.DeviceName(major, minor)
m[d] = s
return s
}
5 changes: 4 additions & 1 deletion container/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ func Status() (v1.DockerStatus, error) {
if err != nil {
return v1.DockerStatus{}, err
}
return StatusFromDockerInfo(dockerInfo), nil
}

func StatusFromDockerInfo(dockerInfo dockertypes.Info) v1.DockerStatus {
out := v1.DockerStatus{}
out.Version = VersionString()
out.APIVersion = APIVersionString()
Expand All @@ -53,7 +56,7 @@ func Status() (v1.DockerStatus, error) {
for _, v := range dockerInfo.DriverStatus {
out.DriverStatus[v[0]] = v[1]
}
return out, nil
return out
}

func Images() ([]v1.DockerImage, error) {
Expand Down
11 changes: 10 additions & 1 deletion container/docker/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ type dockerFactory struct {

ignoreMetrics container.MetricSet

thinPoolName string
thinPoolWatcher *devicemapper.ThinPoolWatcher

zfsWatcher *zfs.ZfsWatcher
Expand Down Expand Up @@ -137,6 +138,7 @@ func (self *dockerFactory) NewContainerHandler(name string, inHostNamespace bool
metadataEnvs,
self.dockerVersion,
self.ignoreMetrics,
self.thinPoolName,
self.thinPoolWatcher,
self.zfsWatcher,
)
Expand Down Expand Up @@ -324,12 +326,18 @@ func Register(factory info.MachineInfoFactory, fsInfo fs.FsInfo, ignoreMetrics c
return fmt.Errorf("failed to get cgroup subsystems: %v", err)
}

var thinPoolWatcher *devicemapper.ThinPoolWatcher
var (
thinPoolWatcher *devicemapper.ThinPoolWatcher
thinPoolName string
)
if storageDriver(dockerInfo.Driver) == devicemapperStorageDriver {
thinPoolWatcher, err = startThinPoolWatcher(dockerInfo)
if err != nil {
glog.Errorf("devicemapper filesystem stats will not be reported: %v", err)
}

status := StatusFromDockerInfo(*dockerInfo)
thinPoolName = status.DriverStatus[dockerutil.DriverStatusPoolName]
}

var zfsWatcher *zfs.ZfsWatcher
Expand All @@ -351,6 +359,7 @@ func Register(factory info.MachineInfoFactory, fsInfo fs.FsInfo, ignoreMetrics c
storageDriver: storageDriver(dockerInfo.Driver),
storageDir: RootDir(),
ignoreMetrics: ignoreMetrics,
thinPoolName: thinPoolName,
thinPoolWatcher: thinPoolWatcher,
zfsWatcher: zfsWatcher,
}
Expand Down
37 changes: 22 additions & 15 deletions container/docker/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"fmt"
"io/ioutil"
"path"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -112,6 +113,9 @@ type dockerContainerHandler struct {

// zfs watcher
zfsWatcher *zfs.ZfsWatcher

// container restart count
restartCount int
}

var _ container.ContainerHandler = &dockerContainerHandler{}
Expand Down Expand Up @@ -146,6 +150,7 @@ func newDockerContainerHandler(
metadataEnvs []string,
dockerVersion []int,
ignoreMetrics container.MetricSet,
thinPoolName string,
thinPoolWatcher *devicemapper.ThinPoolWatcher,
zfsWatcher *zfs.ZfsWatcher,
) (container.ContainerHandler, error) {
Expand Down Expand Up @@ -180,10 +185,10 @@ func newDockerContainerHandler(
return nil, err
}

// Determine the rootfs storage dir OR the pool name to determine the device
// Determine the rootfs storage dir OR the pool name to determine the device.
// For devicemapper, we only need the thin pool name, and that is passed in to this call
var (
rootfsStorageDir string
poolName string
zfsFilesystem string
zfsParent string
)
Expand All @@ -199,13 +204,6 @@ func newDockerContainerHandler(
}
zfsParent = status.DriverStatus[dockerutil.DriverStatusParentDataset]
zfsFilesystem = path.Join(zfsParent, rwLayerID)
case devicemapperStorageDriver:
status, err := Status()
if err != nil {
return nil, fmt.Errorf("unable to determine docker status: %v", err)
}

poolName = status.DriverStatus[dockerutil.DriverStatusPoolName]
}

// TODO: extract object mother method
Expand All @@ -219,7 +217,7 @@ func newDockerContainerHandler(
storageDriver: storageDriver,
fsInfo: fsInfo,
rootFs: rootFs,
poolName: poolName,
poolName: thinPoolName,
zfsFilesystem: zfsFilesystem,
rootfsStorageDir: rootfsStorageDir,
envs: make(map[string]string),
Expand Down Expand Up @@ -248,6 +246,7 @@ func newDockerContainerHandler(
handler.image = ctnr.Config.Image
handler.networkMode = ctnr.HostConfig.NetworkMode
handler.deviceID = ctnr.GraphDriver.Data["DeviceId"]
handler.restartCount = ctnr.RestartCount

// Obtain the IP address for the contianer.
// If the NetworkMode starts with 'container:' then we need to use the IP address of the container specified.
Expand Down Expand Up @@ -383,13 +382,26 @@ func (self *dockerContainerHandler) GetSpec() (info.ContainerSpec, error) {
spec, err := common.GetSpec(self.cgroupPaths, self.machineInfoFactory, self.needNet(), hasFilesystem)

spec.Labels = self.labels
// Only adds restartcount label if it's greater than 0
if self.restartCount > 0 {
spec.Labels["restartcount"] = strconv.Itoa(self.restartCount)
}
spec.Envs = self.envs
spec.Image = self.image

return spec, err
}

func (self *dockerContainerHandler) getFsStats(stats *info.ContainerStats) error {
mi, err := self.machineInfoFactory.GetMachineInfo()
if err != nil {
return err
}

if !self.ignoreMetrics.Has(container.DiskIOMetrics) {
common.AssignDeviceNamesToDiskStats((*common.MachineInfoNamer)(mi), &stats.DiskIo)
}

if self.ignoreMetrics.Has(container.DiskUsageMetrics) {
return nil
}
Expand All @@ -411,11 +423,6 @@ func (self *dockerContainerHandler) getFsStats(stats *info.ContainerStats) error
return nil
}

mi, err := self.machineInfoFactory.GetMachineInfo()
if err != nil {
return err
}

var (
limit uint64
fsType string
Expand Down
Loading

0 comments on commit 96b603e

Please sign in to comment.