Merge pull request #24113 from timstclair/docker11-godeps
Automatic merge from submit-queue Update cAdvisor & go-dockerclient for docker v1.11 compatability
This commit is contained in:
74
Godeps/Godeps.json
generated
74
Godeps/Godeps.json
generated
@@ -511,7 +511,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/fsouza/go-dockerclient",
|
"ImportPath": "github.com/fsouza/go-dockerclient",
|
||||||
"Rev": "0099401a7342ad77e71ca9f9a57c5e72fb80f6b2"
|
"Rev": "bf97c77db7c945cbcdbf09d56c6f87a66f54537b"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/garyburd/redigo/internal",
|
"ImportPath": "github.com/garyburd/redigo/internal",
|
||||||
@@ -672,93 +672,93 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/api",
|
"ImportPath": "github.com/google/cadvisor/api",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/cache/memory",
|
"ImportPath": "github.com/google/cadvisor/cache/memory",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/collector",
|
"ImportPath": "github.com/google/cadvisor/collector",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/container",
|
"ImportPath": "github.com/google/cadvisor/container",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/events",
|
"ImportPath": "github.com/google/cadvisor/events",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/fs",
|
"ImportPath": "github.com/google/cadvisor/fs",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/healthz",
|
"ImportPath": "github.com/google/cadvisor/healthz",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/http",
|
"ImportPath": "github.com/google/cadvisor/http",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/info/v1",
|
"ImportPath": "github.com/google/cadvisor/info/v1",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/info/v2",
|
"ImportPath": "github.com/google/cadvisor/info/v2",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/manager",
|
"ImportPath": "github.com/google/cadvisor/manager",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/metrics",
|
"ImportPath": "github.com/google/cadvisor/metrics",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/pages",
|
"ImportPath": "github.com/google/cadvisor/pages",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/storage",
|
"ImportPath": "github.com/google/cadvisor/storage",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/summary",
|
"ImportPath": "github.com/google/cadvisor/summary",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/utils",
|
"ImportPath": "github.com/google/cadvisor/utils",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/validate",
|
"ImportPath": "github.com/google/cadvisor/validate",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/version",
|
"ImportPath": "github.com/google/cadvisor/version",
|
||||||
"Comment": "v0.22.2",
|
"Comment": "v0.23.0",
|
||||||
"Rev": "546a3771589bdb356777c646c6eca24914fdd48b"
|
"Rev": "750f18e5eac3f6193b354fc14c03d92d4318a0ec"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/gofuzz",
|
"ImportPath": "github.com/google/gofuzz",
|
||||||
|
2
Godeps/LICENSES
generated
2
Godeps/LICENSES
generated
@@ -18961,7 +18961,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
================================================================================
|
================================================================================
|
||||||
= Godeps/_workspace/src/github.com/fsouza/go-dockerclient licensed under: =
|
= Godeps/_workspace/src/github.com/fsouza/go-dockerclient licensed under: =
|
||||||
|
|
||||||
Copyright (c) 2015, go-dockerclient authors
|
Copyright (c) 2016, go-dockerclient authors
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
21
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/.travis.yml
generated
vendored
21
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/.travis.yml
generated
vendored
@@ -1,24 +1,27 @@
|
|||||||
language: go
|
language: go
|
||||||
sudo: required
|
sudo: required
|
||||||
go:
|
go:
|
||||||
- 1.3.3
|
|
||||||
- 1.4.2
|
- 1.4.2
|
||||||
- 1.5.3
|
- 1.5.3
|
||||||
- 1.6rc2
|
- 1.6
|
||||||
- tip
|
- tip
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
env:
|
env:
|
||||||
- GOARCH=amd64 DOCKER_VERSION=1.7.1
|
|
||||||
- GOARCH=386 DOCKER_VERSION=1.7.1
|
|
||||||
- GOARCH=amd64 DOCKER_VERSION=1.8.3
|
- GOARCH=amd64 DOCKER_VERSION=1.8.3
|
||||||
- GOARCH=386 DOCKER_VERSION=1.8.3
|
- GOARCH=386 DOCKER_VERSION=1.8.3
|
||||||
- GOARCH=amd64 DOCKER_VERSION=1.9.1
|
- GOARCH=amd64 DOCKER_VERSION=1.9.1
|
||||||
- GOARCH=386 DOCKER_VERSION=1.9.1
|
- GOARCH=386 DOCKER_VERSION=1.9.1
|
||||||
- GOARCH=amd64 DOCKER_VERSION=1.10.0
|
- GOARCH=amd64 DOCKER_VERSION=1.10.3
|
||||||
- GOARCH=386 DOCKER_VERSION=1.10.0
|
- GOARCH=386 DOCKER_VERSION=1.10.3
|
||||||
install:
|
install:
|
||||||
- make prepare_docker
|
- travis_retry travis-scripts/install.bash
|
||||||
script:
|
script:
|
||||||
- make test
|
- travis-scripts/run-tests.bash
|
||||||
- DOCKER_HOST=tcp://127.0.0.1:2375 make integration
|
|
||||||
services:
|
services:
|
||||||
- docker
|
- docker
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
allow_failures:
|
||||||
|
- go: tip
|
||||||
|
7
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/AUTHORS
generated
vendored
7
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/AUTHORS
generated
vendored
@@ -14,6 +14,7 @@ Ben Marini <ben@remind101.com>
|
|||||||
Ben McCann <benmccann.com>
|
Ben McCann <benmccann.com>
|
||||||
Ben Parees <bparees@redhat.com>
|
Ben Parees <bparees@redhat.com>
|
||||||
Benno van den Berg <bennovandenberg@gmail.com>
|
Benno van den Berg <bennovandenberg@gmail.com>
|
||||||
|
Bradley Cicenas <bradley.cicenas@gmail.com>
|
||||||
Brendan Fosberry <brendan@codeship.com>
|
Brendan Fosberry <brendan@codeship.com>
|
||||||
Brian Lalor <blalor@bravo5.org>
|
Brian Lalor <blalor@bravo5.org>
|
||||||
Brian P. Hamachek <brian@brianhama.com>
|
Brian P. Hamachek <brian@brianhama.com>
|
||||||
@@ -48,6 +49,8 @@ Fabio Rehm <fgrehm@gmail.com>
|
|||||||
Fatih Arslan <ftharsln@gmail.com>
|
Fatih Arslan <ftharsln@gmail.com>
|
||||||
Flavia Missi <flaviamissi@gmail.com>
|
Flavia Missi <flaviamissi@gmail.com>
|
||||||
Francisco Souza <f@souza.cc>
|
Francisco Souza <f@souza.cc>
|
||||||
|
Frank Groeneveld <frank@frankgroeneveld.nl>
|
||||||
|
George Moura <gwmoura@gmail.com>
|
||||||
Grégoire Delattre <gregoire.delattre@gmail.com>
|
Grégoire Delattre <gregoire.delattre@gmail.com>
|
||||||
Guillermo Álvarez Fernández <guillermo@cientifico.net>
|
Guillermo Álvarez Fernández <guillermo@cientifico.net>
|
||||||
Harry Zhang <harryzhang@zju.edu.cn>
|
Harry Zhang <harryzhang@zju.edu.cn>
|
||||||
@@ -84,7 +87,9 @@ Michael Schmatz <michaelschmatz@gmail.com>
|
|||||||
Michal Fojtik <mfojtik@redhat.com>
|
Michal Fojtik <mfojtik@redhat.com>
|
||||||
Mike Dillon <mike.dillon@synctree.com>
|
Mike Dillon <mike.dillon@synctree.com>
|
||||||
Mrunal Patel <mrunalp@gmail.com>
|
Mrunal Patel <mrunalp@gmail.com>
|
||||||
|
Nate Jones <nate@endot.org>
|
||||||
Nguyen Sy Thanh Son <sonnst@sigma-solutions.eu>
|
Nguyen Sy Thanh Son <sonnst@sigma-solutions.eu>
|
||||||
|
Nicholas Van Wiggeren <nvanwiggeren@digitalocean.com>
|
||||||
Nick Ethier <ncethier@gmail.com>
|
Nick Ethier <ncethier@gmail.com>
|
||||||
Omeid Matten <public@omeid.me>
|
Omeid Matten <public@omeid.me>
|
||||||
Orivej Desh <orivej@gmx.fr>
|
Orivej Desh <orivej@gmx.fr>
|
||||||
@@ -98,9 +103,11 @@ Philippe Lafoucrière <philippe.lafoucriere@tech-angels.com>
|
|||||||
Rafe Colton <rafael.colton@gmail.com>
|
Rafe Colton <rafael.colton@gmail.com>
|
||||||
Rob Miller <rob@kalistra.com>
|
Rob Miller <rob@kalistra.com>
|
||||||
Robert Williamson <williamson.robert@gmail.com>
|
Robert Williamson <williamson.robert@gmail.com>
|
||||||
|
Roman Khlystik <roman.khlystik@gmail.com>
|
||||||
Salvador Gironès <salvadorgirones@gmail.com>
|
Salvador Gironès <salvadorgirones@gmail.com>
|
||||||
Sam Rijs <srijs@airpost.net>
|
Sam Rijs <srijs@airpost.net>
|
||||||
Sami Wagiaalla <swagiaal@redhat.com>
|
Sami Wagiaalla <swagiaal@redhat.com>
|
||||||
|
Samuel Archambault <sarchambault@lapresse.ca>
|
||||||
Samuel Karp <skarp@amazon.com>
|
Samuel Karp <skarp@amazon.com>
|
||||||
Silas Sewell <silas@sewell.org>
|
Silas Sewell <silas@sewell.org>
|
||||||
Simon Eskildsen <sirup@sirupsen.com>
|
Simon Eskildsen <sirup@sirupsen.com>
|
||||||
|
2
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/LICENSE
generated
vendored
2
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/LICENSE
generated
vendored
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2015, go-dockerclient authors
|
Copyright (c) 2016, go-dockerclient authors
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
29
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/Makefile
generated
vendored
29
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/Makefile
generated
vendored
@@ -11,8 +11,7 @@
|
|||||||
cov \
|
cov \
|
||||||
clean
|
clean
|
||||||
|
|
||||||
SRCS = $(shell git ls-files '*.go' | grep -v '^external/')
|
PKGS = . ./testing
|
||||||
PKGS = ./. ./testing
|
|
||||||
|
|
||||||
all: test
|
all: test
|
||||||
|
|
||||||
@@ -22,32 +21,30 @@ vendor:
|
|||||||
|
|
||||||
lint:
|
lint:
|
||||||
@ go get -v github.com/golang/lint/golint
|
@ go get -v github.com/golang/lint/golint
|
||||||
$(foreach file,$(SRCS),golint $(file) || exit;)
|
@for file in $$(git ls-files '*.go' | grep -v 'external/'); do \
|
||||||
|
export output="$$(golint $${file} | grep -v 'type name will be used as docker.DockerInfo')"; \
|
||||||
|
[ -n "$${output}" ] && echo "$${output}" && export status=1; \
|
||||||
|
done; \
|
||||||
|
exit $${status:-0}
|
||||||
|
|
||||||
vet:
|
vet:
|
||||||
@-go get -v golang.org/x/tools/cmd/vet
|
|
||||||
$(foreach pkg,$(PKGS),go vet $(pkg);)
|
$(foreach pkg,$(PKGS),go vet $(pkg);)
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
gofmt -w $(SRCS)
|
gofmt -s -w $(PKGS)
|
||||||
|
|
||||||
fmtcheck:
|
fmtcheck:
|
||||||
$(foreach file,$(SRCS),gofmt -d $(file);)
|
@ export output=$$(gofmt -s -d $(PKGS)); \
|
||||||
|
[ -n "$${output}" ] && echo "$${output}" && export status=1; \
|
||||||
prepare_docker:
|
exit $${status:-0}
|
||||||
sudo stop docker
|
|
||||||
sudo rm -rf /var/lib/docker
|
|
||||||
sudo rm -f `which docker`
|
|
||||||
sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
|
|
||||||
echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" | sudo tee /etc/apt/sources.list.d/docker.list
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install docker-engine=$(DOCKER_VERSION)-0~$(shell lsb_release -cs) -y --force-yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"
|
|
||||||
|
|
||||||
pretest: lint vet fmtcheck
|
pretest: lint vet fmtcheck
|
||||||
|
|
||||||
test: pretest
|
gotest:
|
||||||
$(foreach pkg,$(PKGS),go test $(pkg) || exit;)
|
$(foreach pkg,$(PKGS),go test $(pkg) || exit;)
|
||||||
|
|
||||||
|
test: pretest gotest
|
||||||
|
|
||||||
integration:
|
integration:
|
||||||
go test -tags docker_integration -run TestIntegration -v
|
go test -tags docker_integration -run TestIntegration -v
|
||||||
|
|
||||||
|
2
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/README.markdown
generated
vendored
2
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/README.markdown
generated
vendored
@@ -4,7 +4,7 @@
|
|||||||
[](https://godoc.org/github.com/fsouza/go-dockerclient)
|
[](https://godoc.org/github.com/fsouza/go-dockerclient)
|
||||||
|
|
||||||
This package presents a client for the Docker remote API. It also provides
|
This package presents a client for the Docker remote API. It also provides
|
||||||
support for the extensions in the [Swarm API](https://docs.docker.com/swarm/api/swarm-api/).
|
support for the extensions in the [Swarm API](https://docs.docker.com/swarm/swarm-api/).
|
||||||
|
|
||||||
This package also provides support for docker's network API, which is a simple
|
This package also provides support for docker's network API, which is a simple
|
||||||
passthrough to the libnetwork remote API. Note that docker's network API is
|
passthrough to the libnetwork remote API. Note that docker's network API is
|
||||||
|
8
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/auth.go
generated
vendored
8
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/auth.go
generated
vendored
@@ -82,10 +82,12 @@ func parseDockerConfig(r io.Reader) (map[string]dockerConfig, error) {
|
|||||||
buf.ReadFrom(r)
|
buf.ReadFrom(r)
|
||||||
byteData := buf.Bytes()
|
byteData := buf.Bytes()
|
||||||
|
|
||||||
var confsWrapper map[string]map[string]dockerConfig
|
confsWrapper := struct {
|
||||||
|
Auths map[string]dockerConfig `json:"auths"`
|
||||||
|
}{}
|
||||||
if err := json.Unmarshal(byteData, &confsWrapper); err == nil {
|
if err := json.Unmarshal(byteData, &confsWrapper); err == nil {
|
||||||
if confs, ok := confsWrapper["auths"]; ok {
|
if len(confsWrapper.Auths) > 0 {
|
||||||
return confs, nil
|
return confsWrapper.Auths, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/client.go
generated
vendored
2
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/client.go
generated
vendored
@@ -555,6 +555,8 @@ type hijackOptions struct {
|
|||||||
data interface{}
|
data interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CloseWaiter is an interface with methods for closing the underlying resource
|
||||||
|
// and then waiting for it to finish processing.
|
||||||
type CloseWaiter interface {
|
type CloseWaiter interface {
|
||||||
io.Closer
|
io.Closer
|
||||||
Wait() error
|
Wait() error
|
||||||
|
114
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/container.go
generated
vendored
114
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/container.go
generated
vendored
@@ -14,6 +14,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fsouza/go-dockerclient/external/github.com/docker/go-units"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrContainerAlreadyExists is the error returned by CreateContainer when the
|
// ErrContainerAlreadyExists is the error returned by CreateContainer when the
|
||||||
@@ -53,6 +55,13 @@ type APIContainers struct {
|
|||||||
SizeRootFs int64 `json:"SizeRootFs,omitempty" yaml:"SizeRootFs,omitempty"`
|
SizeRootFs int64 `json:"SizeRootFs,omitempty" yaml:"SizeRootFs,omitempty"`
|
||||||
Names []string `json:"Names,omitempty" yaml:"Names,omitempty"`
|
Names []string `json:"Names,omitempty" yaml:"Names,omitempty"`
|
||||||
Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty"`
|
Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty"`
|
||||||
|
Networks NetworkList `json:"NetworkSettings,omitempty" yaml:"NetworkSettings,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkList encapsulates a map of networks, as returned by the Docker API in
|
||||||
|
// ListContainers.
|
||||||
|
type NetworkList struct {
|
||||||
|
Networks map[string]ContainerNetwork `json:"Networks" yaml:"Networks,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListContainers returns a slice of containers matching the given criteria.
|
// ListContainers returns a slice of containers matching the given criteria.
|
||||||
@@ -92,10 +101,13 @@ func (p Port) Proto() string {
|
|||||||
|
|
||||||
// State represents the state of a container.
|
// State represents the state of a container.
|
||||||
type State struct {
|
type State struct {
|
||||||
|
Status string `json:"Status,omitempty" yaml:"Status,omitempty"`
|
||||||
Running bool `json:"Running,omitempty" yaml:"Running,omitempty"`
|
Running bool `json:"Running,omitempty" yaml:"Running,omitempty"`
|
||||||
Paused bool `json:"Paused,omitempty" yaml:"Paused,omitempty"`
|
Paused bool `json:"Paused,omitempty" yaml:"Paused,omitempty"`
|
||||||
Restarting bool `json:"Restarting,omitempty" yaml:"Restarting,omitempty"`
|
Restarting bool `json:"Restarting,omitempty" yaml:"Restarting,omitempty"`
|
||||||
OOMKilled bool `json:"OOMKilled,omitempty" yaml:"OOMKilled,omitempty"`
|
OOMKilled bool `json:"OOMKilled,omitempty" yaml:"OOMKilled,omitempty"`
|
||||||
|
RemovalInProgress bool `json:"RemovalInProgress,omitempty" yaml:"RemovalInProgress,omitempty"`
|
||||||
|
Dead bool `json:"Dead,omitempty" yaml:"Dead,omitempty"`
|
||||||
Pid int `json:"Pid,omitempty" yaml:"Pid,omitempty"`
|
Pid int `json:"Pid,omitempty" yaml:"Pid,omitempty"`
|
||||||
ExitCode int `json:"ExitCode,omitempty" yaml:"ExitCode,omitempty"`
|
ExitCode int `json:"ExitCode,omitempty" yaml:"ExitCode,omitempty"`
|
||||||
Error string `json:"Error,omitempty" yaml:"Error,omitempty"`
|
Error string `json:"Error,omitempty" yaml:"Error,omitempty"`
|
||||||
@@ -103,15 +115,59 @@ type State struct {
|
|||||||
FinishedAt time.Time `json:"FinishedAt,omitempty" yaml:"FinishedAt,omitempty"`
|
FinishedAt time.Time `json:"FinishedAt,omitempty" yaml:"FinishedAt,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the string representation of a state.
|
// String returns a human-readable description of the state
|
||||||
func (s *State) String() string {
|
func (s *State) String() string {
|
||||||
|
if s.Running {
|
||||||
|
if s.Paused {
|
||||||
|
return fmt.Sprintf("Up %s (Paused)", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt)))
|
||||||
|
}
|
||||||
|
if s.Restarting {
|
||||||
|
return fmt.Sprintf("Restarting (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("Up %s", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.RemovalInProgress {
|
||||||
|
return "Removal In Progress"
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Dead {
|
||||||
|
return "Dead"
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.StartedAt.IsZero() {
|
||||||
|
return "Created"
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.FinishedAt.IsZero() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("Exited (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// StateString returns a single string to describe state
|
||||||
|
func (s *State) StateString() string {
|
||||||
if s.Running {
|
if s.Running {
|
||||||
if s.Paused {
|
if s.Paused {
|
||||||
return "paused"
|
return "paused"
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("Up %s", time.Now().UTC().Sub(s.StartedAt))
|
if s.Restarting {
|
||||||
|
return "restarting"
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("Exit %d", s.ExitCode)
|
return "running"
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Dead {
|
||||||
|
return "dead"
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.StartedAt.IsZero() {
|
||||||
|
return "created"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "exited"
|
||||||
}
|
}
|
||||||
|
|
||||||
// PortBinding represents the host/container port mapping as returned in the
|
// PortBinding represents the host/container port mapping as returned in the
|
||||||
@@ -135,6 +191,7 @@ type ContainerNetwork struct {
|
|||||||
IPAddress string `json:"IPAddress,omitempty" yaml:"IPAddress,omitempty"`
|
IPAddress string `json:"IPAddress,omitempty" yaml:"IPAddress,omitempty"`
|
||||||
Gateway string `json:"Gateway,omitempty" yaml:"Gateway,omitempty"`
|
Gateway string `json:"Gateway,omitempty" yaml:"Gateway,omitempty"`
|
||||||
EndpointID string `json:"EndpointID,omitempty" yaml:"EndpointID,omitempty"`
|
EndpointID string `json:"EndpointID,omitempty" yaml:"EndpointID,omitempty"`
|
||||||
|
NetworkID string `json:"NetworkID,omitempty" yaml:"NetworkID,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkSettings contains network-related information about a container
|
// NetworkSettings contains network-related information about a container
|
||||||
@@ -308,6 +365,34 @@ type Container struct {
|
|||||||
AppArmorProfile string `json:"AppArmorProfile,omitempty" yaml:"AppArmorProfile,omitempty"`
|
AppArmorProfile string `json:"AppArmorProfile,omitempty" yaml:"AppArmorProfile,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateContainerOptions specify parameters to the UpdateContainer function.
|
||||||
|
//
|
||||||
|
// See https://goo.gl/Y6fXUy for more details.
|
||||||
|
type UpdateContainerOptions struct {
|
||||||
|
BlkioWeight int `json:"BlkioWeight"`
|
||||||
|
CPUShares int `json:"CpuShares"`
|
||||||
|
CPUPeriod int `json:"CpuPeriod"`
|
||||||
|
CPUQuota int `json:"CpuQuota"`
|
||||||
|
CpusetCpus string `json:"CpusetCpus"`
|
||||||
|
CpusetMems string `json:"CpusetMems"`
|
||||||
|
Memory int `json:"Memory"`
|
||||||
|
MemorySwap int `json:"MemorySwap"`
|
||||||
|
MemoryReservation int `json:"MemoryReservation"`
|
||||||
|
KernelMemory int `json:"KernelMemory"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateContainer updates the container at ID with the options
|
||||||
|
//
|
||||||
|
// See https://goo.gl/Y6fXUy for more details.
|
||||||
|
func (c *Client) UpdateContainer(id string, opts UpdateContainerOptions) error {
|
||||||
|
resp, err := c.do("POST", fmt.Sprintf("/containers/"+id+"/update"), doOptions{data: opts, forceJSON: true})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// RenameContainerOptions specify parameters to the RenameContainer function.
|
// RenameContainerOptions specify parameters to the RenameContainer function.
|
||||||
//
|
//
|
||||||
// See https://goo.gl/laSOIy for more details.
|
// See https://goo.gl/laSOIy for more details.
|
||||||
@@ -469,6 +554,24 @@ type Device struct {
|
|||||||
CgroupPermissions string `json:"CgroupPermissions,omitempty" yaml:"CgroupPermissions,omitempty"`
|
CgroupPermissions string `json:"CgroupPermissions,omitempty" yaml:"CgroupPermissions,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BlockWeight represents a relative device weight for an individual device inside
|
||||||
|
// of a container
|
||||||
|
//
|
||||||
|
// See https://goo.gl/FSdP0H for more details.
|
||||||
|
type BlockWeight struct {
|
||||||
|
Path string `json:"Path,omitempty"`
|
||||||
|
Weight string `json:"Weight,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockLimit represents a read/write limit in IOPS or Bandwidth for a device
|
||||||
|
// inside of a container
|
||||||
|
//
|
||||||
|
// See https://goo.gl/FSdP0H for more details.
|
||||||
|
type BlockLimit struct {
|
||||||
|
Path string `json:"Path,omitempty"`
|
||||||
|
Rate string `json:"Rate,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// HostConfig contains the container options related to starting a container on
|
// HostConfig contains the container options related to starting a container on
|
||||||
// a given host
|
// a given host
|
||||||
type HostConfig struct {
|
type HostConfig struct {
|
||||||
@@ -508,6 +611,11 @@ type HostConfig struct {
|
|||||||
CPUQuota int64 `json:"CpuQuota,omitempty" yaml:"CpuQuota,omitempty"`
|
CPUQuota int64 `json:"CpuQuota,omitempty" yaml:"CpuQuota,omitempty"`
|
||||||
CPUPeriod int64 `json:"CpuPeriod,omitempty" yaml:"CpuPeriod,omitempty"`
|
CPUPeriod int64 `json:"CpuPeriod,omitempty" yaml:"CpuPeriod,omitempty"`
|
||||||
BlkioWeight int64 `json:"BlkioWeight,omitempty" yaml:"BlkioWeight"`
|
BlkioWeight int64 `json:"BlkioWeight,omitempty" yaml:"BlkioWeight"`
|
||||||
|
BlkioWeightDevice []BlockWeight `json:"BlkioWeightDevice,omitempty" yaml:"BlkioWeightDevice"`
|
||||||
|
BlkioDeviceReadBps []BlockLimit `json:"BlkioDeviceReadBps,omitempty" yaml:"BlkioDeviceReadBps"`
|
||||||
|
BlkioDeviceReadIOps []BlockLimit `json:"BlkioDeviceReadIOps,omitempty" yaml:"BlkioDeviceReadIOps"`
|
||||||
|
BlkioDeviceWriteBps []BlockLimit `json:"BlkioDeviceWriteBps,omitempty" yaml:"BlkioDeviceWriteBps"`
|
||||||
|
BlkioDeviceWriteIOps []BlockLimit `json:"BlkioDeviceWriteIOps,omitempty" yaml:"BlkioDeviceWriteIOps"`
|
||||||
Ulimits []ULimit `json:"Ulimits,omitempty" yaml:"Ulimits,omitempty"`
|
Ulimits []ULimit `json:"Ulimits,omitempty" yaml:"Ulimits,omitempty"`
|
||||||
VolumeDriver string `json:"VolumeDriver,omitempty" yaml:"VolumeDriver,omitempty"`
|
VolumeDriver string `json:"VolumeDriver,omitempty" yaml:"VolumeDriver,omitempty"`
|
||||||
OomScoreAdj int `json:"OomScoreAdj,omitempty" yaml:"OomScoreAdj,omitempty"`
|
OomScoreAdj int `json:"OomScoreAdj,omitempty" yaml:"OomScoreAdj,omitempty"`
|
||||||
|
76
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/event.go
generated
vendored
76
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/event.go
generated
vendored
@@ -18,12 +18,38 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// APIEvents represents an event returned by the API.
|
// APIEvents represents events coming from the Docker API
|
||||||
|
// The fields in the Docker API changed in API version 1.22, and
|
||||||
|
// events for more than images and containers are now fired off.
|
||||||
|
// To maintain forward and backward compatibility, go-dockerclient
|
||||||
|
// replicates the event in both the new and old format as faithfully as possible.
|
||||||
|
//
|
||||||
|
// For events that only exist in 1.22 in later, `Status` is filled in as
|
||||||
|
// `"Type:Action"` instead of just `Action` to allow for older clients to
|
||||||
|
// differentiate and not break if they rely on the pre-1.22 Status types.
|
||||||
|
//
|
||||||
|
// The transformEvent method can be consulted for more information about how
|
||||||
|
// events are translated from new/old API formats
|
||||||
type APIEvents struct {
|
type APIEvents struct {
|
||||||
Status string `json:"Status,omitempty" yaml:"Status,omitempty"`
|
// New API Fields in 1.22
|
||||||
ID string `json:"ID,omitempty" yaml:"ID,omitempty"`
|
Action string `json:"action,omitempty"`
|
||||||
From string `json:"From,omitempty" yaml:"From,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
Time int64 `json:"Time,omitempty" yaml:"Time,omitempty"`
|
Actor APIActor `json:"actor,omitempty"`
|
||||||
|
|
||||||
|
// Old API fields for < 1.22
|
||||||
|
Status string `json:"status,omitempty"`
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
From string `json:"from,omitempty"`
|
||||||
|
|
||||||
|
// Fields in both
|
||||||
|
Time int64 `json:"time,omitempty"`
|
||||||
|
TimeNano int64 `json:"timeNano,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIActor represents an actor that accomplishes something for an event
|
||||||
|
type APIActor struct {
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
Attributes map[string]string `json:"attributes,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type eventMonitoringState struct {
|
type eventMonitoringState struct {
|
||||||
@@ -52,6 +78,7 @@ var (
|
|||||||
|
|
||||||
// EOFEvent is sent when the event listener receives an EOF error.
|
// EOFEvent is sent when the event listener receives an EOF error.
|
||||||
EOFEvent = &APIEvents{
|
EOFEvent = &APIEvents{
|
||||||
|
Type: "EOF",
|
||||||
Status: "EOF",
|
Status: "EOF",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -297,8 +324,47 @@ func (c *Client) eventHijack(startTime int64, eventChan chan *APIEvents, errChan
|
|||||||
if !c.eventMonitor.isEnabled() {
|
if !c.eventMonitor.isEnabled() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
transformEvent(&event)
|
||||||
eventChan <- &event
|
eventChan <- &event
|
||||||
}
|
}
|
||||||
}(res, conn)
|
}(res, conn)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// transformEvent takes an event and determines what version it is from
|
||||||
|
// then populates both versions of the event
|
||||||
|
func transformEvent(event *APIEvents) {
|
||||||
|
// if event version is <= 1.21 there will be no Action and no Type
|
||||||
|
if event.Action == "" && event.Type == "" {
|
||||||
|
event.Action = event.Status
|
||||||
|
event.Actor.ID = event.ID
|
||||||
|
event.Actor.Attributes = map[string]string{}
|
||||||
|
switch event.Status {
|
||||||
|
case "delete", "import", "pull", "push", "tag", "untag":
|
||||||
|
event.Type = "image"
|
||||||
|
default:
|
||||||
|
event.Type = "container"
|
||||||
|
if event.From != "" {
|
||||||
|
event.Actor.Attributes["image"] = event.From
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if event.Status == "" {
|
||||||
|
if event.Type == "image" || event.Type == "container" {
|
||||||
|
event.Status = event.Action
|
||||||
|
} else {
|
||||||
|
// Because just the Status has been overloaded with different Types
|
||||||
|
// if an event is not for an image or a container, we prepend the type
|
||||||
|
// to avoid problems for people relying on actions being only for
|
||||||
|
// images and containers
|
||||||
|
event.Status = event.Type + ":" + event.Action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if event.ID == "" {
|
||||||
|
event.ID = event.Actor.ID
|
||||||
|
}
|
||||||
|
if event.From == "" {
|
||||||
|
event.From = event.Actor.Attributes["image"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
14
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/system/chtimes_unix.go
generated
vendored
Normal file
14
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/system/chtimes_unix.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//setCTime will set the create time on a file. On Unix, the create
|
||||||
|
//time is updated as a side effect of setting the modified time, so
|
||||||
|
//no action is required.
|
||||||
|
func setCTime(path string, ctime time.Time) error {
|
||||||
|
return nil
|
||||||
|
}
|
27
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/system/chtimes_windows.go
generated
vendored
Normal file
27
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/system/chtimes_windows.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//setCTime will set the create time on a file. On Windows, this requires
|
||||||
|
//calling SetFileTime and explicitly including the create time.
|
||||||
|
func setCTime(path string, ctime time.Time) error {
|
||||||
|
ctimespec := syscall.NsecToTimespec(ctime.UnixNano())
|
||||||
|
pathp, e := syscall.UTF16PtrFromString(path)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
h, e := syscall.CreateFile(pathp,
|
||||||
|
syscall.FILE_WRITE_ATTRIBUTES, syscall.FILE_SHARE_WRITE, nil,
|
||||||
|
syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
defer syscall.Close(h)
|
||||||
|
c := syscall.NsecToFiletime(syscall.TimespecToNsec(ctimespec))
|
||||||
|
return syscall.SetFileTime(h, &c, nil, nil)
|
||||||
|
}
|
15
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/system/stat_openbsd.go
generated
vendored
Normal file
15
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/system/stat_openbsd.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// fromStatT creates a system.StatT type from a syscall.Stat_t type
|
||||||
|
func fromStatT(s *syscall.Stat_t) (*StatT, error) {
|
||||||
|
return &StatT{size: s.Size,
|
||||||
|
mode: uint32(s.Mode),
|
||||||
|
uid: s.Uid,
|
||||||
|
gid: s.Gid,
|
||||||
|
rdev: uint64(s.Rdev),
|
||||||
|
mtim: s.Mtim}, nil
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
// +build !linux,!windows,!freebsd,!solaris
|
// +build !linux,!windows,!freebsd,!solaris,!openbsd
|
||||||
|
|
||||||
package system
|
package system
|
||||||
|
|
||||||
|
@@ -210,13 +210,13 @@ type CancelFunc func()
|
|||||||
// call cancel as soon as the operations running in this Context complete.
|
// call cancel as soon as the operations running in this Context complete.
|
||||||
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
|
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
|
||||||
c := newCancelCtx(parent)
|
c := newCancelCtx(parent)
|
||||||
propagateCancel(parent, &c)
|
propagateCancel(parent, c)
|
||||||
return &c, func() { c.cancel(true, Canceled) }
|
return c, func() { c.cancel(true, Canceled) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// newCancelCtx returns an initialized cancelCtx.
|
// newCancelCtx returns an initialized cancelCtx.
|
||||||
func newCancelCtx(parent Context) cancelCtx {
|
func newCancelCtx(parent Context) *cancelCtx {
|
||||||
return cancelCtx{
|
return &cancelCtx{
|
||||||
Context: parent,
|
Context: parent,
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
}
|
}
|
||||||
@@ -259,7 +259,7 @@ func parentCancelCtx(parent Context) (*cancelCtx, bool) {
|
|||||||
case *cancelCtx:
|
case *cancelCtx:
|
||||||
return c, true
|
return c, true
|
||||||
case *timerCtx:
|
case *timerCtx:
|
||||||
return &c.cancelCtx, true
|
return c.cancelCtx, true
|
||||||
case *valueCtx:
|
case *valueCtx:
|
||||||
parent = c.Context
|
parent = c.Context
|
||||||
default:
|
default:
|
||||||
@@ -377,7 +377,7 @@ func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
|
|||||||
// implement Done and Err. It implements cancel by stopping its timer then
|
// implement Done and Err. It implements cancel by stopping its timer then
|
||||||
// delegating to cancelCtx.cancel.
|
// delegating to cancelCtx.cancel.
|
||||||
type timerCtx struct {
|
type timerCtx struct {
|
||||||
cancelCtx
|
*cancelCtx
|
||||||
timer *time.Timer // Under cancelCtx.mu.
|
timer *time.Timer // Under cancelCtx.mu.
|
||||||
|
|
||||||
deadline time.Time
|
deadline time.Time
|
||||||
|
24
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/image.go
generated
vendored
24
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/image.go
generated
vendored
@@ -32,6 +32,7 @@ type APIImages struct {
|
|||||||
// Image is the type representing a docker image and its various properties
|
// Image is the type representing a docker image and its various properties
|
||||||
type Image struct {
|
type Image struct {
|
||||||
ID string `json:"Id" yaml:"Id"`
|
ID string `json:"Id" yaml:"Id"`
|
||||||
|
RepoTags []string `json:"RepoTags,omitempty" yaml:"RepoTags,omitempty"`
|
||||||
Parent string `json:"Parent,omitempty" yaml:"Parent,omitempty"`
|
Parent string `json:"Parent,omitempty" yaml:"Parent,omitempty"`
|
||||||
Comment string `json:"Comment,omitempty" yaml:"Comment,omitempty"`
|
Comment string `json:"Comment,omitempty" yaml:"Comment,omitempty"`
|
||||||
Created time.Time `json:"Created,omitempty" yaml:"Created,omitempty"`
|
Created time.Time `json:"Created,omitempty" yaml:"Created,omitempty"`
|
||||||
@@ -421,6 +422,17 @@ type BuildImageOptions struct {
|
|||||||
AuthConfigs AuthConfigurations `qs:"-"` // for newer docker X-Registry-Config header
|
AuthConfigs AuthConfigurations `qs:"-"` // for newer docker X-Registry-Config header
|
||||||
ContextDir string `qs:"-"`
|
ContextDir string `qs:"-"`
|
||||||
Ulimits []ULimit `qs:"-"`
|
Ulimits []ULimit `qs:"-"`
|
||||||
|
BuildArgs []BuildArg `qs:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildArg represents arguments that can be passed to the image when building
|
||||||
|
// it from a Dockerfile.
|
||||||
|
//
|
||||||
|
// For more details about the Docker building process, see
|
||||||
|
// http://goo.gl/tlPXPu.
|
||||||
|
type BuildArg struct {
|
||||||
|
Name string `json:"Name,omitempty" yaml:"Name,omitempty"`
|
||||||
|
Value string `json:"Value,omitempty" yaml:"Value,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildImage builds an image from a tarball's url or a Dockerfile in the input
|
// BuildImage builds an image from a tarball's url or a Dockerfile in the input
|
||||||
@@ -463,6 +475,18 @@ func (c *Client) BuildImage(opts BuildImageOptions) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(opts.BuildArgs) > 0 {
|
||||||
|
v := make(map[string]string)
|
||||||
|
for _, arg := range opts.BuildArgs {
|
||||||
|
v[arg.Name] = arg.Value
|
||||||
|
}
|
||||||
|
if b, err := json.Marshal(v); err == nil {
|
||||||
|
item := url.Values(map[string][]string{})
|
||||||
|
item.Add("buildargs", string(b))
|
||||||
|
qs = fmt.Sprintf("%s&%s", qs, item.Encode())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return c.stream("POST", fmt.Sprintf("/build?%s", qs), streamOptions{
|
return c.stream("POST", fmt.Sprintf("/build?%s", qs), streamOptions{
|
||||||
setRawTerminal: true,
|
setRawTerminal: true,
|
||||||
rawJSONStream: opts.RawJSONStream,
|
rawJSONStream: opts.RawJSONStream,
|
||||||
|
75
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/misc.go
generated
vendored
75
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/misc.go
generated
vendored
@@ -4,7 +4,10 @@
|
|||||||
|
|
||||||
package docker
|
package docker
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
// Version returns version information about the docker server.
|
// Version returns version information about the docker server.
|
||||||
//
|
//
|
||||||
@@ -22,17 +25,81 @@ func (c *Client) Version() (*Env, error) {
|
|||||||
return &env, nil
|
return &env, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DockerInfo contains information about the Docker server
|
||||||
|
//
|
||||||
|
// See https://goo.gl/bHUoz9 for more details.
|
||||||
|
type DockerInfo struct {
|
||||||
|
ID string
|
||||||
|
Containers int
|
||||||
|
ContainersRunning int
|
||||||
|
ContainersPaused int
|
||||||
|
ContainersStopped int
|
||||||
|
Images int
|
||||||
|
Driver string
|
||||||
|
DriverStatus [][2]string
|
||||||
|
SystemStatus [][2]string
|
||||||
|
Plugins PluginsInfo
|
||||||
|
MemoryLimit bool
|
||||||
|
SwapLimit bool
|
||||||
|
KernelMemory bool
|
||||||
|
CPUCfsPeriod bool `json:"CpuCfsPeriod"`
|
||||||
|
CPUCfsQuota bool `json:"CpuCfsQuota"`
|
||||||
|
CPUShares bool
|
||||||
|
CPUSet bool
|
||||||
|
IPv4Forwarding bool
|
||||||
|
BridgeNfIptables bool
|
||||||
|
BridgeNfIP6tables bool `json:"BridgeNfIp6tables"`
|
||||||
|
Debug bool
|
||||||
|
NFd int
|
||||||
|
OomKillDisable bool
|
||||||
|
NGoroutines int
|
||||||
|
SystemTime string
|
||||||
|
ExecutionDriver string
|
||||||
|
LoggingDriver string
|
||||||
|
CgroupDriver string
|
||||||
|
NEventsListener int
|
||||||
|
KernelVersion string
|
||||||
|
OperatingSystem string
|
||||||
|
OSType string
|
||||||
|
Architecture string
|
||||||
|
IndexServerAddress string
|
||||||
|
NCPU int
|
||||||
|
MemTotal int64
|
||||||
|
DockerRootDir string
|
||||||
|
HTTPProxy string `json:"HttpProxy"`
|
||||||
|
HTTPSProxy string `json:"HttpsProxy"`
|
||||||
|
NoProxy string
|
||||||
|
Name string
|
||||||
|
Labels []string
|
||||||
|
ExperimentalBuild bool
|
||||||
|
ServerVersion string
|
||||||
|
ClusterStore string
|
||||||
|
ClusterAdvertise string
|
||||||
|
}
|
||||||
|
|
||||||
|
// PluginsInfo is a struct with the plugins registered with the docker daemon
|
||||||
|
//
|
||||||
|
// for more information, see: https://goo.gl/bHUoz9
|
||||||
|
type PluginsInfo struct {
|
||||||
|
// List of Volume plugins registered
|
||||||
|
Volume []string
|
||||||
|
// List of Network plugins registered
|
||||||
|
Network []string
|
||||||
|
// List of Authorization plugins registered
|
||||||
|
Authorization []string
|
||||||
|
}
|
||||||
|
|
||||||
// Info returns system-wide information about the Docker server.
|
// Info returns system-wide information about the Docker server.
|
||||||
//
|
//
|
||||||
// See https://goo.gl/ElTHi2 for more details.
|
// See https://goo.gl/ElTHi2 for more details.
|
||||||
func (c *Client) Info() (*Env, error) {
|
func (c *Client) Info() (*DockerInfo, error) {
|
||||||
resp, err := c.do("GET", "/info", doOptions{})
|
resp, err := c.do("GET", "/info", doOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
var info Env
|
var info DockerInfo
|
||||||
if err := info.Decode(resp.Body); err != nil {
|
if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &info, nil
|
return &info, nil
|
||||||
|
65
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/network.go
generated
vendored
65
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/network.go
generated
vendored
@@ -5,6 +5,7 @@
|
|||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -26,6 +27,7 @@ type Network struct {
|
|||||||
IPAM IPAMOptions
|
IPAM IPAMOptions
|
||||||
Containers map[string]Endpoint
|
Containers map[string]Endpoint
|
||||||
Options map[string]string
|
Options map[string]string
|
||||||
|
Internal bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Endpoint contains network resources allocated and used for a container in a network
|
// Endpoint contains network resources allocated and used for a container in a network
|
||||||
@@ -55,6 +57,31 @@ func (c *Client) ListNetworks() ([]Network, error) {
|
|||||||
return networks, nil
|
return networks, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NetworkFilterOpts is an aggregation of key=value that Docker
|
||||||
|
// uses to filter networks
|
||||||
|
type NetworkFilterOpts map[string]map[string]bool
|
||||||
|
|
||||||
|
// FilteredListNetworks returns all networks with the filters applied
|
||||||
|
//
|
||||||
|
// See goo.gl/zd2mx4 for more details.
|
||||||
|
func (c *Client) FilteredListNetworks(opts NetworkFilterOpts) ([]Network, error) {
|
||||||
|
params := bytes.NewBuffer(nil)
|
||||||
|
if err := json.NewEncoder(params).Encode(&opts); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
path := "/networks?filters=" + params.String()
|
||||||
|
resp, err := c.do("GET", path, doOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
var networks []Network
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&networks); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return networks, nil
|
||||||
|
}
|
||||||
|
|
||||||
// NetworkInfo returns information about a network by its ID.
|
// NetworkInfo returns information about a network by its ID.
|
||||||
//
|
//
|
||||||
// See https://goo.gl/6GugX3 for more details.
|
// See https://goo.gl/6GugX3 for more details.
|
||||||
@@ -158,14 +185,40 @@ func (c *Client) RemoveNetwork(id string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkConnectionOptions specify parameters to the ConnectNetwork and DisconnectNetwork function.
|
// NetworkConnectionOptions specify parameters to the ConnectNetwork and
|
||||||
|
// DisconnectNetwork function.
|
||||||
//
|
//
|
||||||
// See https://goo.gl/6GugX3 for more details.
|
// See https://goo.gl/RV7BJU for more details.
|
||||||
type NetworkConnectionOptions struct {
|
type NetworkConnectionOptions struct {
|
||||||
Container string
|
Container string
|
||||||
|
|
||||||
|
// EndpointConfig is only applicable to the ConnectNetwork call
|
||||||
|
EndpointConfig *EndpointConfig `json:"EndpointConfig,omitempty"`
|
||||||
|
|
||||||
|
// Force is only applicable to the DisconnectNetwork call
|
||||||
|
Force bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConnectNetwork adds a container to a network or returns an error in case of failure.
|
// EndpointConfig stores network endpoint details
|
||||||
|
//
|
||||||
|
// See https://goo.gl/RV7BJU for more details.
|
||||||
|
type EndpointConfig struct {
|
||||||
|
IPAMConfig *EndpointIPAMConfig
|
||||||
|
Links []string
|
||||||
|
Aliases []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// EndpointIPAMConfig represents IPAM configurations for an
|
||||||
|
// endpoint
|
||||||
|
//
|
||||||
|
// See https://goo.gl/RV7BJU for more details.
|
||||||
|
type EndpointIPAMConfig struct {
|
||||||
|
IPv4Address string `json:",omitempty"`
|
||||||
|
IPv6Address string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConnectNetwork adds a container to a network or returns an error in case of
|
||||||
|
// failure.
|
||||||
//
|
//
|
||||||
// See https://goo.gl/6GugX3 for more details.
|
// See https://goo.gl/6GugX3 for more details.
|
||||||
func (c *Client) ConnectNetwork(id string, opts NetworkConnectionOptions) error {
|
func (c *Client) ConnectNetwork(id string, opts NetworkConnectionOptions) error {
|
||||||
@@ -180,7 +233,8 @@ func (c *Client) ConnectNetwork(id string, opts NetworkConnectionOptions) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisconnectNetwork removes a container from a network or returns an error in case of failure.
|
// DisconnectNetwork removes a container from a network or returns an error in
|
||||||
|
// case of failure.
|
||||||
//
|
//
|
||||||
// See https://goo.gl/6GugX3 for more details.
|
// See https://goo.gl/6GugX3 for more details.
|
||||||
func (c *Client) DisconnectNetwork(id string, opts NetworkConnectionOptions) error {
|
func (c *Client) DisconnectNetwork(id string, opts NetworkConnectionOptions) error {
|
||||||
@@ -204,7 +258,8 @@ func (err *NoSuchNetwork) Error() string {
|
|||||||
return fmt.Sprintf("No such network: %s", err.ID)
|
return fmt.Sprintf("No such network: %s", err.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoSuchNetwork is the error returned when a given network or container does not exist.
|
// NoSuchNetworkOrContainer is the error returned when a given network or
|
||||||
|
// container does not exist.
|
||||||
type NoSuchNetworkOrContainer struct {
|
type NoSuchNetworkOrContainer struct {
|
||||||
NetworkID string
|
NetworkID string
|
||||||
ContainerID string
|
ContainerID string
|
||||||
|
88
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/server.go
generated
vendored
88
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/server.go
generated
vendored
@@ -144,6 +144,7 @@ func (s *DockerServer) buildMuxer() {
|
|||||||
s.mux.Path("/volumes/create").Methods("POST").HandlerFunc(s.handlerWrapper(s.createVolume))
|
s.mux.Path("/volumes/create").Methods("POST").HandlerFunc(s.handlerWrapper(s.createVolume))
|
||||||
s.mux.Path("/volumes/{name:.*}").Methods("GET").HandlerFunc(s.handlerWrapper(s.inspectVolume))
|
s.mux.Path("/volumes/{name:.*}").Methods("GET").HandlerFunc(s.handlerWrapper(s.inspectVolume))
|
||||||
s.mux.Path("/volumes/{name:.*}").Methods("DELETE").HandlerFunc(s.handlerWrapper(s.removeVolume))
|
s.mux.Path("/volumes/{name:.*}").Methods("DELETE").HandlerFunc(s.handlerWrapper(s.removeVolume))
|
||||||
|
s.mux.Path("/info").Methods("GET").HandlerFunc(s.handlerWrapper(s.infoDocker))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetHook changes the hook function used by the server.
|
// SetHook changes the hook function used by the server.
|
||||||
@@ -743,10 +744,9 @@ func (s *DockerServer) commitContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Error(w, err.Error(), http.StatusNotFound)
|
http.Error(w, err.Error(), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var config *docker.Config
|
config := new(docker.Config)
|
||||||
runConfig := r.URL.Query().Get("run")
|
runConfig := r.URL.Query().Get("run")
|
||||||
if runConfig != "" {
|
if runConfig != "" {
|
||||||
config = new(docker.Config)
|
|
||||||
err = json.Unmarshal([]byte(runConfig), config)
|
err = json.Unmarshal([]byte(runConfig), config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
@@ -829,6 +829,7 @@ func (s *DockerServer) pullImage(w http.ResponseWriter, r *http.Request) {
|
|||||||
tag := r.URL.Query().Get("tag")
|
tag := r.URL.Query().Get("tag")
|
||||||
image := docker.Image{
|
image := docker.Image{
|
||||||
ID: s.generateID(),
|
ID: s.generateID(),
|
||||||
|
Config: &docker.Config{},
|
||||||
}
|
}
|
||||||
s.iMut.Lock()
|
s.iMut.Lock()
|
||||||
s.images = append(s.images, image)
|
s.images = append(s.images, image)
|
||||||
@@ -1244,3 +1245,86 @@ func (s *DockerServer) removeVolume(w http.ResponseWriter, r *http.Request) {
|
|||||||
s.volStore[vol.volume.Name] = nil
|
s.volStore[vol.volume.Name] = nil
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DockerServer) infoDocker(w http.ResponseWriter, r *http.Request) {
|
||||||
|
s.cMut.RLock()
|
||||||
|
defer s.cMut.RUnlock()
|
||||||
|
s.iMut.RLock()
|
||||||
|
defer s.iMut.RUnlock()
|
||||||
|
var running, stopped, paused int
|
||||||
|
for _, c := range s.containers {
|
||||||
|
if c.State.Running {
|
||||||
|
running++
|
||||||
|
} else {
|
||||||
|
stopped++
|
||||||
|
}
|
||||||
|
if c.State.Paused {
|
||||||
|
paused++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
envs := map[string]interface{}{
|
||||||
|
"ID": "AAAA:XXXX:0000:BBBB:AAAA:XXXX:0000:BBBB:AAAA:XXXX:0000:BBBB",
|
||||||
|
"Containers": len(s.containers),
|
||||||
|
"ContainersRunning": running,
|
||||||
|
"ContainersPaused": paused,
|
||||||
|
"ContainersStopped": stopped,
|
||||||
|
"Images": len(s.images),
|
||||||
|
"Driver": "aufs",
|
||||||
|
"DriverStatus": [][]string{},
|
||||||
|
"SystemStatus": nil,
|
||||||
|
"Plugins": map[string]interface{}{
|
||||||
|
"Volume": []string{
|
||||||
|
"local",
|
||||||
|
},
|
||||||
|
"Network": []string{
|
||||||
|
"bridge",
|
||||||
|
"null",
|
||||||
|
"host",
|
||||||
|
},
|
||||||
|
"Authorization": nil,
|
||||||
|
},
|
||||||
|
"MemoryLimit": true,
|
||||||
|
"SwapLimit": false,
|
||||||
|
"CpuCfsPeriod": true,
|
||||||
|
"CpuCfsQuota": true,
|
||||||
|
"CPUShares": true,
|
||||||
|
"CPUSet": true,
|
||||||
|
"IPv4Forwarding": true,
|
||||||
|
"BridgeNfIptables": true,
|
||||||
|
"BridgeNfIp6tables": true,
|
||||||
|
"Debug": false,
|
||||||
|
"NFd": 79,
|
||||||
|
"OomKillDisable": true,
|
||||||
|
"NGoroutines": 101,
|
||||||
|
"SystemTime": "2016-02-25T18:13:10.25870078Z",
|
||||||
|
"ExecutionDriver": "native-0.2",
|
||||||
|
"LoggingDriver": "json-file",
|
||||||
|
"NEventsListener": 0,
|
||||||
|
"KernelVersion": "3.13.0-77-generic",
|
||||||
|
"OperatingSystem": "Ubuntu 14.04.3 LTS",
|
||||||
|
"OSType": "linux",
|
||||||
|
"Architecture": "x86_64",
|
||||||
|
"IndexServerAddress": "https://index.docker.io/v1/",
|
||||||
|
"RegistryConfig": map[string]interface{}{
|
||||||
|
"InsecureRegistryCIDRs": []string{},
|
||||||
|
"IndexConfigs": map[string]interface{}{},
|
||||||
|
"Mirrors": nil,
|
||||||
|
},
|
||||||
|
"InitSha1": "e2042dbb0fcf49bb9da199186d9a5063cda92a01",
|
||||||
|
"InitPath": "/usr/lib/docker/dockerinit",
|
||||||
|
"NCPU": 1,
|
||||||
|
"MemTotal": 2099204096,
|
||||||
|
"DockerRootDir": "/var/lib/docker",
|
||||||
|
"HttpProxy": "",
|
||||||
|
"HttpsProxy": "",
|
||||||
|
"NoProxy": "",
|
||||||
|
"Name": "vagrant-ubuntu-trusty-64",
|
||||||
|
"Labels": nil,
|
||||||
|
"ExperimentalBuild": false,
|
||||||
|
"ServerVersion": "1.10.1",
|
||||||
|
"ClusterStore": "",
|
||||||
|
"ClusterAdvertise": "",
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(envs)
|
||||||
|
}
|
||||||
|
17
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/travis-scripts/install.bash
generated
vendored
Normal file
17
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/travis-scripts/install.bash
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/bash -x
|
||||||
|
|
||||||
|
# Copyright 2016 go-dockerclient authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style
|
||||||
|
# license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
if [[ $TRAVIS_OS_NAME == "linux" ]]; then
|
||||||
|
sudo stop docker || true
|
||||||
|
sudo rm -rf /var/lib/docker
|
||||||
|
sudo rm -f `which docker`
|
||||||
|
|
||||||
|
set -e
|
||||||
|
sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
|
||||||
|
echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" | sudo tee /etc/apt/sources.list.d/docker.list
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install docker-engine=${DOCKER_VERSION}-0~$(lsb_release -cs) -y --force-yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"
|
||||||
|
fi
|
15
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/travis-scripts/run-tests.bash
generated
vendored
Normal file
15
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/travis-scripts/run-tests.bash
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash -ex
|
||||||
|
|
||||||
|
# Copyright 2016 go-dockerclient authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style
|
||||||
|
# license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
if ! [[ $TRAVIS_GO_VERSION =~ ^1\.[34] ]]; then
|
||||||
|
make lint vet
|
||||||
|
fi
|
||||||
|
|
||||||
|
make fmtcheck gotest
|
||||||
|
|
||||||
|
if [[ $TRAVIS_OS_NAME == "linux" ]]; then
|
||||||
|
DOCKER_HOST=tcp://127.0.0.1:2375 make integration
|
||||||
|
fi
|
@@ -16,7 +16,7 @@
|
|||||||
// an array of ContainerHint structs, each with a container's id and networkInterface
|
// an array of ContainerHint structs, each with a container's id and networkInterface
|
||||||
// This allows collecting stats about network interfaces configured outside docker
|
// This allows collecting stats about network interfaces configured outside docker
|
||||||
// and lxc
|
// and lxc
|
||||||
package raw
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -25,7 +25,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
var argContainerHints = flag.String("container_hints", "/etc/cadvisor/container_hints.json", "location of the container hints file")
|
var ArgContainerHints = flag.String("container_hints", "/etc/cadvisor/container_hints.json", "location of the container hints file")
|
||||||
|
|
||||||
type containerHints struct {
|
type containerHints struct {
|
||||||
AllHosts []containerHint `json:"all_hosts,omitempty"`
|
AllHosts []containerHint `json:"all_hosts,omitempty"`
|
||||||
@@ -34,10 +34,10 @@ type containerHints struct {
|
|||||||
type containerHint struct {
|
type containerHint struct {
|
||||||
FullName string `json:"full_path,omitempty"`
|
FullName string `json:"full_path,omitempty"`
|
||||||
NetworkInterface *networkInterface `json:"network_interface,omitempty"`
|
NetworkInterface *networkInterface `json:"network_interface,omitempty"`
|
||||||
Mounts []mount `json:"mounts,omitempty"`
|
Mounts []Mount `json:"mounts,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type mount struct {
|
type Mount struct {
|
||||||
HostDir string `json:"host_dir,omitempty"`
|
HostDir string `json:"host_dir,omitempty"`
|
||||||
ContainerDir string `json:"container_dir,omitempty"`
|
ContainerDir string `json:"container_dir,omitempty"`
|
||||||
}
|
}
|
||||||
@@ -47,7 +47,7 @@ type networkInterface struct {
|
|||||||
VethChild string `json:"veth_child,omitempty"`
|
VethChild string `json:"veth_child,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func getContainerHintsFromFile(containerHintsFile string) (containerHints, error) {
|
func GetContainerHintsFromFile(containerHintsFile string) (containerHints, error) {
|
||||||
dat, err := ioutil.ReadFile(containerHintsFile)
|
dat, err := ioutil.ReadFile(containerHintsFile)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return containerHints{}, nil
|
return containerHints{}, nil
|
@@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
// Handler for Docker containers.
|
// Handler for Docker containers.
|
||||||
package docker
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
@@ -24,10 +24,10 @@ import (
|
|||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
type fsHandler interface {
|
type FsHandler interface {
|
||||||
start()
|
Start()
|
||||||
usage() (uint64, uint64)
|
Usage() (baseUsageBytes uint64, totalUsageBytes uint64)
|
||||||
stop()
|
Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
type realFsHandler struct {
|
type realFsHandler struct {
|
||||||
@@ -50,9 +50,9 @@ const (
|
|||||||
maxDuBackoffFactor = 20
|
maxDuBackoffFactor = 20
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ fsHandler = &realFsHandler{}
|
var _ FsHandler = &realFsHandler{}
|
||||||
|
|
||||||
func newFsHandler(period time.Duration, rootfs, extraDir string, fsInfo fs.FsInfo) fsHandler {
|
func NewFsHandler(period time.Duration, rootfs, extraDir string, fsInfo fs.FsInfo) FsHandler {
|
||||||
return &realFsHandler{
|
return &realFsHandler{
|
||||||
lastUpdate: time.Time{},
|
lastUpdate: time.Time{},
|
||||||
usageBytes: 0,
|
usageBytes: 0,
|
||||||
@@ -119,15 +119,15 @@ func (fh *realFsHandler) trackUsage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fh *realFsHandler) start() {
|
func (fh *realFsHandler) Start() {
|
||||||
go fh.trackUsage()
|
go fh.trackUsage()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fh *realFsHandler) stop() {
|
func (fh *realFsHandler) Stop() {
|
||||||
close(fh.stopChan)
|
close(fh.stopChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fh *realFsHandler) usage() (baseUsageBytes, totalUsageBytes uint64) {
|
func (fh *realFsHandler) Usage() (baseUsageBytes, totalUsageBytes uint64) {
|
||||||
fh.RLock()
|
fh.RLock()
|
||||||
defer fh.RUnlock()
|
defer fh.RUnlock()
|
||||||
return fh.baseUsageBytes, fh.usageBytes
|
return fh.baseUsageBytes, fh.usageBytes
|
203
Godeps/_workspace/src/github.com/google/cadvisor/container/common/helpers.go
generated
vendored
Normal file
203
Godeps/_workspace/src/github.com/google/cadvisor/container/common/helpers.go
generated
vendored
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
info "github.com/google/cadvisor/info/v1"
|
||||||
|
"github.com/google/cadvisor/utils"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DebugInfo(watches map[string][]string) map[string][]string {
|
||||||
|
out := make(map[string][]string)
|
||||||
|
|
||||||
|
lines := make([]string, 0, len(watches))
|
||||||
|
for containerName, cgroupWatches := range watches {
|
||||||
|
lines = append(lines, fmt.Sprintf("%s:", containerName))
|
||||||
|
for _, cg := range cgroupWatches {
|
||||||
|
lines = append(lines, fmt.Sprintf("\t%s", cg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out["Inotify watches"] = lines
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSpec(cgroupPaths map[string]string, machineInfoFactory info.MachineInfoFactory, hasNetwork, hasFilesystem bool) (info.ContainerSpec, error) {
|
||||||
|
var spec info.ContainerSpec
|
||||||
|
|
||||||
|
// Assume unified hierarchy containers.
|
||||||
|
// Get the lowest creation time from all hierarchies as the container creation time.
|
||||||
|
now := time.Now()
|
||||||
|
lowestTime := now
|
||||||
|
for _, cgroupPath := range cgroupPaths {
|
||||||
|
// The modified time of the cgroup directory changes whenever a subcontainer is created.
|
||||||
|
// eg. /docker will have creation time matching the creation of latest docker container.
|
||||||
|
// Use clone_children as a workaround as it isn't usually modified. It is only likely changed
|
||||||
|
// immediately after creating a container.
|
||||||
|
cgroupPath = path.Join(cgroupPath, "cgroup.clone_children")
|
||||||
|
fi, err := os.Stat(cgroupPath)
|
||||||
|
if err == nil && fi.ModTime().Before(lowestTime) {
|
||||||
|
lowestTime = fi.ModTime()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if lowestTime != now {
|
||||||
|
spec.CreationTime = lowestTime
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get machine info.
|
||||||
|
mi, err := machineInfoFactory.GetMachineInfo()
|
||||||
|
if err != nil {
|
||||||
|
return spec, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// CPU.
|
||||||
|
cpuRoot, ok := cgroupPaths["cpu"]
|
||||||
|
if ok {
|
||||||
|
if utils.FileExists(cpuRoot) {
|
||||||
|
spec.HasCpu = true
|
||||||
|
spec.Cpu.Limit = readUInt64(cpuRoot, "cpu.shares")
|
||||||
|
spec.Cpu.Period = readUInt64(cpuRoot, "cpu.cfs_period_us")
|
||||||
|
quota := readString(cpuRoot, "cpu.cfs_quota_us")
|
||||||
|
|
||||||
|
if quota != "" && quota != "-1" {
|
||||||
|
val, err := strconv.ParseUint(quota, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("GetSpec: Failed to parse CPUQuota from %q: %s", path.Join(cpuRoot, "cpu.cfs_quota_us"), err)
|
||||||
|
}
|
||||||
|
spec.Cpu.Quota = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cpu Mask.
|
||||||
|
// This will fail for non-unified hierarchies. We'll return the whole machine mask in that case.
|
||||||
|
cpusetRoot, ok := cgroupPaths["cpuset"]
|
||||||
|
if ok {
|
||||||
|
if utils.FileExists(cpusetRoot) {
|
||||||
|
spec.HasCpu = true
|
||||||
|
mask := readString(cpusetRoot, "cpuset.cpus")
|
||||||
|
spec.Cpu.Mask = utils.FixCpuMask(mask, mi.NumCores)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Memory
|
||||||
|
memoryRoot, ok := cgroupPaths["memory"]
|
||||||
|
if ok {
|
||||||
|
if utils.FileExists(memoryRoot) {
|
||||||
|
spec.HasMemory = true
|
||||||
|
spec.Memory.Limit = readUInt64(memoryRoot, "memory.limit_in_bytes")
|
||||||
|
spec.Memory.SwapLimit = readUInt64(memoryRoot, "memory.memsw.limit_in_bytes")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spec.HasNetwork = hasNetwork
|
||||||
|
spec.HasFilesystem = hasFilesystem
|
||||||
|
|
||||||
|
if blkioRoot, ok := cgroupPaths["blkio"]; ok && utils.FileExists(blkioRoot) {
|
||||||
|
spec.HasDiskIo = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readString(dirpath string, file string) string {
|
||||||
|
cgroupFile := path.Join(dirpath, file)
|
||||||
|
|
||||||
|
// Ignore non-existent files
|
||||||
|
if !utils.FileExists(cgroupFile) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read
|
||||||
|
out, err := ioutil.ReadFile(cgroupFile)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("readString: Failed to read %q: %s", cgroupFile, err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(string(out))
|
||||||
|
}
|
||||||
|
|
||||||
|
func readUInt64(dirpath string, file string) uint64 {
|
||||||
|
out := readString(dirpath, file)
|
||||||
|
if out == "" {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
val, err := strconv.ParseUint(out, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("readUInt64: Failed to parse int %q from file %q: %s", out, path.Join(dirpath, file), err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lists all directories under "path" and outputs the results as children of "parent".
|
||||||
|
func ListDirectories(dirpath string, parent string, recursive bool, output map[string]struct{}) error {
|
||||||
|
// Ignore if this hierarchy does not exist.
|
||||||
|
if !utils.FileExists(dirpath) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
entries, err := ioutil.ReadDir(dirpath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, entry := range entries {
|
||||||
|
// We only grab directories.
|
||||||
|
if entry.IsDir() {
|
||||||
|
name := path.Join(parent, entry.Name())
|
||||||
|
output[name] = struct{}{}
|
||||||
|
|
||||||
|
// List subcontainers if asked to.
|
||||||
|
if recursive {
|
||||||
|
err := ListDirectories(path.Join(dirpath, entry.Name()), name, true, output)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeCgroupPaths(mountPoints map[string]string, name string) map[string]string {
|
||||||
|
cgroupPaths := make(map[string]string, len(mountPoints))
|
||||||
|
for key, val := range mountPoints {
|
||||||
|
cgroupPaths[key] = path.Join(val, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cgroupPaths
|
||||||
|
}
|
||||||
|
|
||||||
|
func CgroupExists(cgroupPaths map[string]string) bool {
|
||||||
|
// If any cgroup exists, the container is still alive.
|
||||||
|
for _, cgroupPath := range cgroupPaths {
|
||||||
|
if utils.FileExists(cgroupPath) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
@@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package raw
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
43
Godeps/_workspace/src/github.com/google/cadvisor/container/docker/factory.go
generated
vendored
43
Godeps/_workspace/src/github.com/google/cadvisor/container/docker/factory.go
generated
vendored
@@ -27,7 +27,7 @@ import (
|
|||||||
"github.com/google/cadvisor/fs"
|
"github.com/google/cadvisor/fs"
|
||||||
info "github.com/google/cadvisor/info/v1"
|
info "github.com/google/cadvisor/info/v1"
|
||||||
|
|
||||||
"github.com/fsouza/go-dockerclient"
|
docker "github.com/fsouza/go-dockerclient"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -163,6 +163,7 @@ var (
|
|||||||
version_re = regexp.MustCompile(version_regexp_string)
|
version_re = regexp.MustCompile(version_regexp_string)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: switch to a semantic versioning library.
|
||||||
func parseDockerVersion(full_version_string string) ([]int, error) {
|
func parseDockerVersion(full_version_string string) ([]int, error) {
|
||||||
matches := version_re.FindAllStringSubmatch(full_version_string, -1)
|
matches := version_re.FindAllStringSubmatch(full_version_string, -1)
|
||||||
if len(matches) != 1 {
|
if len(matches) != 1 {
|
||||||
@@ -186,42 +187,16 @@ func Register(factory info.MachineInfoFactory, fsInfo fs.FsInfo, ignoreMetrics c
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to communicate with docker daemon: %v", err)
|
return fmt.Errorf("unable to communicate with docker daemon: %v", err)
|
||||||
}
|
}
|
||||||
var dockerVersion []int
|
|
||||||
if version, err := client.Version(); err != nil {
|
dockerInfo, err := ValidateInfo()
|
||||||
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("couldn't parse docker version: %v", err)
|
return fmt.Errorf("failed to validate Docker info: %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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
information, err := client.Info()
|
// Version already validated above, assume no error here.
|
||||||
if err != nil {
|
dockerVersion, _ := parseDockerVersion(dockerInfo.ServerVersion)
|
||||||
return fmt.Errorf("failed to detect Docker info: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the libcontainer execdriver is used.
|
storageDir := dockerInfo.DockerRootDir
|
||||||
execDriver := information.Get("ExecutionDriver")
|
|
||||||
if !strings.HasPrefix(execDriver, "native") {
|
|
||||||
return fmt.Errorf("docker found, but not using native exec driver")
|
|
||||||
}
|
|
||||||
|
|
||||||
sd := information.Get("Driver")
|
|
||||||
if sd == "" {
|
|
||||||
return fmt.Errorf("failed to find docker storage driver")
|
|
||||||
}
|
|
||||||
|
|
||||||
storageDir := information.Get("DockerRootDir")
|
|
||||||
if storageDir == "" {
|
if storageDir == "" {
|
||||||
storageDir = *dockerRootDir
|
storageDir = *dockerRootDir
|
||||||
}
|
}
|
||||||
@@ -237,7 +212,7 @@ func Register(factory info.MachineInfoFactory, fsInfo fs.FsInfo, ignoreMetrics c
|
|||||||
dockerVersion: dockerVersion,
|
dockerVersion: dockerVersion,
|
||||||
fsInfo: fsInfo,
|
fsInfo: fsInfo,
|
||||||
machineInfoFactory: factory,
|
machineInfoFactory: factory,
|
||||||
storageDriver: storageDriver(sd),
|
storageDriver: storageDriver(dockerInfo.Driver),
|
||||||
storageDir: storageDir,
|
storageDir: storageDir,
|
||||||
ignoreMetrics: ignoreMetrics,
|
ignoreMetrics: ignoreMetrics,
|
||||||
}
|
}
|
||||||
|
134
Godeps/_workspace/src/github.com/google/cadvisor/container/docker/handler.go
generated
vendored
134
Godeps/_workspace/src/github.com/google/cadvisor/container/docker/handler.go
generated
vendored
@@ -18,16 +18,15 @@ package docker
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math"
|
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/cadvisor/container"
|
"github.com/google/cadvisor/container"
|
||||||
|
"github.com/google/cadvisor/container/common"
|
||||||
containerlibcontainer "github.com/google/cadvisor/container/libcontainer"
|
containerlibcontainer "github.com/google/cadvisor/container/libcontainer"
|
||||||
"github.com/google/cadvisor/fs"
|
"github.com/google/cadvisor/fs"
|
||||||
info "github.com/google/cadvisor/info/v1"
|
info "github.com/google/cadvisor/info/v1"
|
||||||
"github.com/google/cadvisor/utils"
|
|
||||||
|
|
||||||
docker "github.com/fsouza/go-dockerclient"
|
docker "github.com/fsouza/go-dockerclient"
|
||||||
"github.com/opencontainers/runc/libcontainer/cgroups"
|
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||||
@@ -80,7 +79,7 @@ type dockerContainerHandler struct {
|
|||||||
networkMode string
|
networkMode string
|
||||||
|
|
||||||
// Filesystem handler.
|
// Filesystem handler.
|
||||||
fsHandler fsHandler
|
fsHandler common.FsHandler
|
||||||
|
|
||||||
ignoreMetrics container.MetricSet
|
ignoreMetrics container.MetricSet
|
||||||
}
|
}
|
||||||
@@ -169,7 +168,7 @@ func newDockerContainerHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !ignoreMetrics.Has(container.DiskUsageMetrics) {
|
if !ignoreMetrics.Has(container.DiskUsageMetrics) {
|
||||||
handler.fsHandler = newFsHandler(time.Minute, rootfsStorageDir, otherStorageDir, fsInfo)
|
handler.fsHandler = common.NewFsHandler(time.Minute, rootfsStorageDir, otherStorageDir, fsInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We assume that if Inspect fails then the container is not known to docker.
|
// We assume that if Inspect fails then the container is not known to docker.
|
||||||
@@ -200,15 +199,14 @@ func newDockerContainerHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *dockerContainerHandler) Start() {
|
func (self *dockerContainerHandler) Start() {
|
||||||
// Start the filesystem handler.
|
|
||||||
if self.fsHandler != nil {
|
if self.fsHandler != nil {
|
||||||
self.fsHandler.start()
|
self.fsHandler.Start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *dockerContainerHandler) Cleanup() {
|
func (self *dockerContainerHandler) Cleanup() {
|
||||||
if self.fsHandler != nil {
|
if self.fsHandler != nil {
|
||||||
self.fsHandler.stop()
|
self.fsHandler.Stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,50 +220,6 @@ func (self *dockerContainerHandler) ContainerReference() (info.ContainerReferenc
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *dockerContainerHandler) readLibcontainerConfig() (*libcontainerconfigs.Config, error) {
|
|
||||||
config, err := containerlibcontainer.ReadConfig(*dockerRootDir, *dockerRunDir, self.id)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to read libcontainer config: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace cgroup parent and name with our own since we may be running in a different context.
|
|
||||||
if config.Cgroups == nil {
|
|
||||||
config.Cgroups = new(libcontainerconfigs.Cgroup)
|
|
||||||
}
|
|
||||||
config.Cgroups.Name = self.name
|
|
||||||
config.Cgroups.Parent = "/"
|
|
||||||
|
|
||||||
return config, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func libcontainerConfigToContainerSpec(config *libcontainerconfigs.Config, mi *info.MachineInfo) info.ContainerSpec {
|
|
||||||
var spec info.ContainerSpec
|
|
||||||
spec.HasMemory = true
|
|
||||||
spec.Memory.Limit = math.MaxUint64
|
|
||||||
spec.Memory.SwapLimit = math.MaxUint64
|
|
||||||
|
|
||||||
if config.Cgroups.Resources != nil {
|
|
||||||
if config.Cgroups.Resources.Memory > 0 {
|
|
||||||
spec.Memory.Limit = uint64(config.Cgroups.Resources.Memory)
|
|
||||||
}
|
|
||||||
if config.Cgroups.Resources.MemorySwap > 0 {
|
|
||||||
spec.Memory.SwapLimit = uint64(config.Cgroups.Resources.MemorySwap)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get CPU info
|
|
||||||
spec.HasCpu = true
|
|
||||||
spec.Cpu.Limit = 1024
|
|
||||||
if config.Cgroups.Resources.CpuShares != 0 {
|
|
||||||
spec.Cpu.Limit = uint64(config.Cgroups.Resources.CpuShares)
|
|
||||||
}
|
|
||||||
spec.Cpu.Mask = utils.FixCpuMask(config.Cgroups.Resources.CpusetCpus, mi.NumCores)
|
|
||||||
}
|
|
||||||
|
|
||||||
spec.HasDiskIo = true
|
|
||||||
|
|
||||||
return spec
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *dockerContainerHandler) needNet() bool {
|
func (self *dockerContainerHandler) needNet() bool {
|
||||||
if !self.ignoreMetrics.Has(container.NetworkUsageMetrics) {
|
if !self.ignoreMetrics.Has(container.NetworkUsageMetrics) {
|
||||||
return !strings.HasPrefix(self.networkMode, "container:")
|
return !strings.HasPrefix(self.networkMode, "container:")
|
||||||
@@ -274,29 +228,12 @@ func (self *dockerContainerHandler) needNet() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *dockerContainerHandler) GetSpec() (info.ContainerSpec, error) {
|
func (self *dockerContainerHandler) GetSpec() (info.ContainerSpec, error) {
|
||||||
mi, err := self.machineInfoFactory.GetMachineInfo()
|
hasFilesystem := !self.ignoreMetrics.Has(container.DiskUsageMetrics)
|
||||||
if err != nil {
|
spec, err := common.GetSpec(self.cgroupPaths, self.machineInfoFactory, self.needNet(), hasFilesystem)
|
||||||
return info.ContainerSpec{}, err
|
|
||||||
}
|
|
||||||
libcontainerConfig, err := self.readLibcontainerConfig()
|
|
||||||
if err != nil {
|
|
||||||
return info.ContainerSpec{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
spec := libcontainerConfigToContainerSpec(libcontainerConfig, mi)
|
|
||||||
spec.CreationTime = self.creationTime
|
|
||||||
|
|
||||||
if !self.ignoreMetrics.Has(container.DiskUsageMetrics) {
|
|
||||||
switch self.storageDriver {
|
|
||||||
case aufsStorageDriver, overlayStorageDriver, zfsStorageDriver:
|
|
||||||
spec.HasFilesystem = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spec.Labels = self.labels
|
spec.Labels = self.labels
|
||||||
spec.Envs = self.envs
|
spec.Envs = self.envs
|
||||||
spec.Image = self.image
|
spec.Image = self.image
|
||||||
spec.HasNetwork = self.needNet()
|
|
||||||
|
|
||||||
return spec, err
|
return spec, err
|
||||||
}
|
}
|
||||||
@@ -320,6 +257,7 @@ func (self *dockerContainerHandler) getFsStats(stats *info.ContainerStats) error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
limit uint64
|
limit uint64
|
||||||
fsType string
|
fsType string
|
||||||
@@ -336,7 +274,7 @@ func (self *dockerContainerHandler) getFsStats(stats *info.ContainerStats) error
|
|||||||
|
|
||||||
fsStat := info.FsStats{Device: deviceInfo.Device, Type: fsType, Limit: limit}
|
fsStat := info.FsStats{Device: deviceInfo.Device, Type: fsType, Limit: limit}
|
||||||
|
|
||||||
fsStat.BaseUsage, fsStat.Usage = self.fsHandler.usage()
|
fsStat.BaseUsage, fsStat.Usage = self.fsHandler.Usage()
|
||||||
stats.Filesystem = append(stats.Filesystem, fsStat)
|
stats.Filesystem = append(stats.Filesystem, fsStat)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -401,19 +339,19 @@ func (self *dockerContainerHandler) StopWatchingSubcontainers() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *dockerContainerHandler) Exists() bool {
|
func (self *dockerContainerHandler) Exists() bool {
|
||||||
return containerlibcontainer.Exists(*dockerRootDir, *dockerRunDir, self.id)
|
return common.CgroupExists(self.cgroupPaths)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DockerInfo() (map[string]string, error) {
|
func DockerInfo() (docker.DockerInfo, error) {
|
||||||
client, err := Client()
|
client, err := Client()
|
||||||
if err != nil {
|
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()
|
info, err := client.Info()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return docker.DockerInfo{}, err
|
||||||
}
|
}
|
||||||
return info.Map(), nil
|
return *info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DockerImages() ([]docker.APIImages, error) {
|
func DockerImages() ([]docker.APIImages, error) {
|
||||||
@@ -427,3 +365,47 @@ func DockerImages() ([]docker.APIImages, error) {
|
|||||||
}
|
}
|
||||||
return images, nil
|
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
|
||||||
|
}
|
||||||
|
367
Godeps/_workspace/src/github.com/google/cadvisor/container/libcontainer/compatibility.go
generated
vendored
367
Godeps/_workspace/src/github.com/google/cadvisor/container/libcontainer/compatibility.go
generated
vendored
@@ -1,367 +0,0 @@
|
|||||||
// Copyright 2015 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.
|
|
||||||
|
|
||||||
package libcontainer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"io/ioutil"
|
|
||||||
"path"
|
|
||||||
|
|
||||||
"github.com/google/cadvisor/utils"
|
|
||||||
|
|
||||||
"github.com/opencontainers/runc/libcontainer"
|
|
||||||
"github.com/opencontainers/runc/libcontainer/configs"
|
|
||||||
)
|
|
||||||
|
|
||||||
// State represents a running container's state
|
|
||||||
type preAPIState struct {
|
|
||||||
// InitPid is the init process id in the parent namespace
|
|
||||||
InitPid int `json:"init_pid,omitempty"`
|
|
||||||
|
|
||||||
// InitStartTime is the init process start time
|
|
||||||
InitStartTime string `json:"init_start_time,omitempty"`
|
|
||||||
|
|
||||||
// Network runtime state.
|
|
||||||
NetworkState preAPINetworkState `json:"network_state,omitempty"`
|
|
||||||
|
|
||||||
// Path to all the cgroups setup for a container. Key is cgroup subsystem name.
|
|
||||||
CgroupPaths map[string]string `json:"cgroup_paths,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Struct describing the network specific runtime state that will be maintained by libcontainer for all running containers
|
|
||||||
// Do not depend on it outside of libcontainer.
|
|
||||||
type preAPINetworkState struct {
|
|
||||||
// The name of the veth interface on the Host.
|
|
||||||
VethHost string `json:"veth_host,omitempty"`
|
|
||||||
// The name of the veth interface created inside the container for the child.
|
|
||||||
VethChild string `json:"veth_child,omitempty"`
|
|
||||||
// Net namespace path.
|
|
||||||
NsPath string `json:"ns_path,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type preAPIConfig struct {
|
|
||||||
// Pathname to container's root filesystem
|
|
||||||
RootFs string `json:"root_fs,omitempty"`
|
|
||||||
|
|
||||||
// Hostname optionally sets the container's hostname if provided
|
|
||||||
Hostname string `json:"hostname,omitempty"`
|
|
||||||
|
|
||||||
// User will set the uid and gid of the executing process running inside the container
|
|
||||||
User string `json:"user,omitempty"`
|
|
||||||
|
|
||||||
// WorkingDir will change the processes current working directory inside the container's rootfs
|
|
||||||
WorkingDir string `json:"working_dir,omitempty"`
|
|
||||||
|
|
||||||
// Env will populate the processes environment with the provided values
|
|
||||||
// Any values from the parent processes will be cleared before the values
|
|
||||||
// provided in Env are provided to the process
|
|
||||||
Env []string `json:"environment,omitempty"`
|
|
||||||
|
|
||||||
// Tty when true will allocate a pty slave on the host for access by the container's process
|
|
||||||
// and ensure that it is mounted inside the container's rootfs
|
|
||||||
Tty bool `json:"tty,omitempty"`
|
|
||||||
|
|
||||||
// Namespaces specifies the container's namespaces that it should setup when cloning the init process
|
|
||||||
// If a namespace is not provided that namespace is shared from the container's parent process
|
|
||||||
Namespaces []configs.Namespace `json:"namespaces,omitempty"`
|
|
||||||
|
|
||||||
// Capabilities specify the capabilities to keep when executing the process inside the container
|
|
||||||
// All capbilities not specified will be dropped from the processes capability mask
|
|
||||||
Capabilities []string `json:"capabilities,omitempty"`
|
|
||||||
|
|
||||||
// Networks specifies the container's network setup to be created
|
|
||||||
Networks []preAPINetwork `json:"networks,omitempty"`
|
|
||||||
|
|
||||||
// Routes can be specified to create entries in the route table as the container is started
|
|
||||||
Routes []*configs.Route `json:"routes,omitempty"`
|
|
||||||
|
|
||||||
// Cgroups specifies specific cgroup settings for the various subsystems that the container is
|
|
||||||
// placed into to limit the resources the container has available
|
|
||||||
Cgroups *configs.Cgroup `json:"cgroups,omitempty"`
|
|
||||||
|
|
||||||
// AppArmorProfile specifies the profile to apply to the process running in the container and is
|
|
||||||
// change at the time the process is execed
|
|
||||||
AppArmorProfile string `json:"apparmor_profile,omitempty"`
|
|
||||||
|
|
||||||
// ProcessLabel specifies the label to apply to the process running in the container. It is
|
|
||||||
// commonly used by selinux
|
|
||||||
ProcessLabel string `json:"process_label,omitempty"`
|
|
||||||
|
|
||||||
// RestrictSys will remount /proc/sys, /sys, and mask over sysrq-trigger as well as /proc/irq and
|
|
||||||
// /proc/bus
|
|
||||||
RestrictSys bool `json:"restrict_sys,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Network defines configuration for a container's networking stack
|
|
||||||
//
|
|
||||||
// The network configuration can be omited from a container causing the
|
|
||||||
// container to be setup with the host's networking stack
|
|
||||||
type preAPINetwork struct {
|
|
||||||
// Type sets the networks type, commonly veth and loopback
|
|
||||||
Type string `json:"type,omitempty"`
|
|
||||||
|
|
||||||
// The bridge to use.
|
|
||||||
Bridge string `json:"bridge,omitempty"`
|
|
||||||
|
|
||||||
// Prefix for the veth interfaces.
|
|
||||||
VethPrefix string `json:"veth_prefix,omitempty"`
|
|
||||||
|
|
||||||
// MacAddress contains the MAC address to set on the network interface
|
|
||||||
MacAddress string `json:"mac_address,omitempty"`
|
|
||||||
|
|
||||||
// Address contains the IPv4 and mask to set on the network interface
|
|
||||||
Address string `json:"address,omitempty"`
|
|
||||||
|
|
||||||
// IPv6Address contains the IPv6 and mask to set on the network interface
|
|
||||||
IPv6Address string `json:"ipv6_address,omitempty"`
|
|
||||||
|
|
||||||
// Gateway sets the gateway address that is used as the default for the interface
|
|
||||||
Gateway string `json:"gateway,omitempty"`
|
|
||||||
|
|
||||||
// IPv6Gateway sets the ipv6 gateway address that is used as the default for the interface
|
|
||||||
IPv6Gateway string `json:"ipv6_gateway,omitempty"`
|
|
||||||
|
|
||||||
// Mtu sets the mtu value for the interface and will be mirrored on both the host and
|
|
||||||
// container's interfaces if a pair is created, specifically in the case of type veth
|
|
||||||
// Note: This does not apply to loopback interfaces.
|
|
||||||
Mtu int `json:"mtu,omitempty"`
|
|
||||||
|
|
||||||
// TxQueueLen sets the tx_queuelen value for the interface and will be mirrored on both the host and
|
|
||||||
// container's interfaces if a pair is created, specifically in the case of type veth
|
|
||||||
// Note: This does not apply to loopback interfaces.
|
|
||||||
TxQueueLen int `json:"txqueuelen,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type v1Cgroup struct {
|
|
||||||
configs.Cgroup
|
|
||||||
|
|
||||||
// Weight per cgroup per device, can override BlkioWeight.
|
|
||||||
BlkioWeightDevice string `json:"blkio_weight_device"`
|
|
||||||
// IO read rate limit per cgroup per device, bytes per second.
|
|
||||||
BlkioThrottleReadBpsDevice string `json:"blkio_throttle_read_bps_device"`
|
|
||||||
|
|
||||||
// IO write rate limit per cgroup per divice, bytes per second.
|
|
||||||
BlkioThrottleWriteBpsDevice string `json:"blkio_throttle_write_bps_device"`
|
|
||||||
|
|
||||||
// IO read rate limit per cgroup per device, IO per second.
|
|
||||||
BlkioThrottleReadIOPSDevice string `json:"blkio_throttle_read_iops_device"`
|
|
||||||
|
|
||||||
// IO write rate limit per cgroup per device, IO per second.
|
|
||||||
BlkioThrottleWriteIOPSDevice string `json:"blkio_throttle_write_iops_device"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type v1Config struct {
|
|
||||||
configs.Config
|
|
||||||
|
|
||||||
// Cgroups specifies specific cgroup settings for the various subsystems that the container is
|
|
||||||
// placed into to limit the resources the container has available
|
|
||||||
Cgroup *v1Cgroup `json:"cgroups"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// State represents a running container's state
|
|
||||||
type v1State struct {
|
|
||||||
libcontainer.State
|
|
||||||
|
|
||||||
// Config is the container's configuration.
|
|
||||||
Config v1Config `json:"config"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Relative path to the libcontainer execdriver directory.
|
|
||||||
const libcontainerExecDriverPath = "execdriver/native"
|
|
||||||
|
|
||||||
// TODO(vmarmol): Deprecate over time as old Dockers are phased out.
|
|
||||||
func ReadConfig(dockerRoot, dockerRun, containerID string) (*configs.Config, error) {
|
|
||||||
// Try using the new config if it is available.
|
|
||||||
configPath := configPath(dockerRun, containerID)
|
|
||||||
if utils.FileExists(configPath) {
|
|
||||||
out, err := ioutil.ReadFile(configPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var state libcontainer.State
|
|
||||||
if err = json.Unmarshal(out, &state); err != nil {
|
|
||||||
if _, ok := err.(*json.UnmarshalTypeError); ok {
|
|
||||||
// Since some fields changes in Cgroup struct, it will be failed while unmarshalling to libcontainer.State struct.
|
|
||||||
// This failure is caused by a change of runc(https://github.com/opencontainers/runc/commit/c6e406af243fab0c9636539c1cb5f4d60fe0787f).
|
|
||||||
// If we encountered the UnmarshalTypeError, try to unmarshal it again to v1State struct and convert it.
|
|
||||||
var state v1State
|
|
||||||
err2 := json.Unmarshal(out, &state)
|
|
||||||
if err2 != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return convertOldConfigToNew(state.Config), nil
|
|
||||||
} else {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &state.Config, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to reading the old config which is comprised of the state and config files.
|
|
||||||
oldConfigPath := oldConfigPath(dockerRoot, containerID)
|
|
||||||
out, err := ioutil.ReadFile(oldConfigPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try reading the preAPIConfig.
|
|
||||||
var config preAPIConfig
|
|
||||||
err = json.Unmarshal(out, &config)
|
|
||||||
if err != nil {
|
|
||||||
// Try to parse the old pre-API config. The main difference is that namespaces used to be a map, now it is a slice of structs.
|
|
||||||
// The JSON marshaler will use the non-nested field before the nested one.
|
|
||||||
type oldLibcontainerConfig struct {
|
|
||||||
preAPIConfig
|
|
||||||
OldNamespaces map[string]bool `json:"namespaces,omitempty"`
|
|
||||||
}
|
|
||||||
var oldConfig oldLibcontainerConfig
|
|
||||||
err2 := json.Unmarshal(out, &oldConfig)
|
|
||||||
if err2 != nil {
|
|
||||||
// Use original error.
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Translate the old pre-API config into the new config.
|
|
||||||
config = oldConfig.preAPIConfig
|
|
||||||
for ns := range oldConfig.OldNamespaces {
|
|
||||||
config.Namespaces = append(config.Namespaces, configs.Namespace{
|
|
||||||
Type: configs.NamespaceType(ns),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the old state file as well.
|
|
||||||
state, err := readState(dockerRoot, containerID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert preAPIConfig + old state file to Config.
|
|
||||||
// This only converts some of the fields, the ones we use.
|
|
||||||
// You may need to add fields if the one you're interested in is not available.
|
|
||||||
var result configs.Config
|
|
||||||
result.Cgroups = new(configs.Cgroup)
|
|
||||||
result.Rootfs = config.RootFs
|
|
||||||
result.Hostname = config.Hostname
|
|
||||||
result.Namespaces = config.Namespaces
|
|
||||||
result.Capabilities = config.Capabilities
|
|
||||||
for _, net := range config.Networks {
|
|
||||||
n := &configs.Network{
|
|
||||||
Name: state.NetworkState.VethChild,
|
|
||||||
Bridge: net.Bridge,
|
|
||||||
MacAddress: net.MacAddress,
|
|
||||||
Address: net.Address,
|
|
||||||
Gateway: net.Gateway,
|
|
||||||
IPv6Address: net.IPv6Address,
|
|
||||||
IPv6Gateway: net.IPv6Gateway,
|
|
||||||
HostInterfaceName: state.NetworkState.VethHost,
|
|
||||||
}
|
|
||||||
result.Networks = append(result.Networks, n)
|
|
||||||
}
|
|
||||||
result.Routes = config.Routes
|
|
||||||
if config.Cgroups != nil {
|
|
||||||
result.Cgroups = config.Cgroups
|
|
||||||
}
|
|
||||||
|
|
||||||
return &result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertOldConfigToNew(config v1Config) *configs.Config {
|
|
||||||
var (
|
|
||||||
result configs.Config
|
|
||||||
old *v1Cgroup = config.Cgroup
|
|
||||||
)
|
|
||||||
result.Rootfs = config.Config.Rootfs
|
|
||||||
result.Hostname = config.Config.Hostname
|
|
||||||
result.Namespaces = config.Config.Namespaces
|
|
||||||
result.Capabilities = config.Config.Capabilities
|
|
||||||
result.Networks = config.Config.Networks
|
|
||||||
result.Routes = config.Config.Routes
|
|
||||||
|
|
||||||
var newCgroup = &configs.Cgroup{
|
|
||||||
Name: old.Name,
|
|
||||||
Parent: old.Parent,
|
|
||||||
Resources: &configs.Resources{
|
|
||||||
AllowAllDevices: old.Resources.AllowAllDevices,
|
|
||||||
AllowedDevices: old.Resources.AllowedDevices,
|
|
||||||
DeniedDevices: old.Resources.DeniedDevices,
|
|
||||||
Memory: old.Resources.Memory,
|
|
||||||
MemoryReservation: old.Resources.MemoryReservation,
|
|
||||||
MemorySwap: old.Resources.MemorySwap,
|
|
||||||
KernelMemory: old.Resources.KernelMemory,
|
|
||||||
CpuShares: old.Resources.CpuShares,
|
|
||||||
CpuQuota: old.Resources.CpuQuota,
|
|
||||||
CpuPeriod: old.Resources.CpuPeriod,
|
|
||||||
CpuRtRuntime: old.Resources.CpuRtRuntime,
|
|
||||||
CpuRtPeriod: old.Resources.CpuRtPeriod,
|
|
||||||
CpusetCpus: old.Resources.CpusetCpus,
|
|
||||||
CpusetMems: old.Resources.CpusetMems,
|
|
||||||
BlkioWeight: old.Resources.BlkioWeight,
|
|
||||||
BlkioLeafWeight: old.Resources.BlkioLeafWeight,
|
|
||||||
Freezer: old.Resources.Freezer,
|
|
||||||
HugetlbLimit: old.Resources.HugetlbLimit,
|
|
||||||
OomKillDisable: old.Resources.OomKillDisable,
|
|
||||||
MemorySwappiness: old.Resources.MemorySwappiness,
|
|
||||||
NetPrioIfpriomap: old.Resources.NetPrioIfpriomap,
|
|
||||||
NetClsClassid: old.Resources.NetClsClassid,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Cgroups = newCgroup
|
|
||||||
|
|
||||||
return &result
|
|
||||||
}
|
|
||||||
|
|
||||||
func readState(dockerRoot, containerID string) (preAPIState, error) {
|
|
||||||
// pre-API libcontainer changed how its state was stored, try the old way of a "pid" file
|
|
||||||
statePath := path.Join(dockerRoot, libcontainerExecDriverPath, containerID, "state.json")
|
|
||||||
if !utils.FileExists(statePath) {
|
|
||||||
pidPath := path.Join(dockerRoot, libcontainerExecDriverPath, containerID, "pid")
|
|
||||||
if utils.FileExists(pidPath) {
|
|
||||||
// We don't need the old state, return an empty state and we'll gracefully degrade.
|
|
||||||
return preAPIState{}, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out, err := ioutil.ReadFile(statePath)
|
|
||||||
if err != nil {
|
|
||||||
return preAPIState{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the state.
|
|
||||||
var state preAPIState
|
|
||||||
err = json.Unmarshal(out, &state)
|
|
||||||
if err != nil {
|
|
||||||
return preAPIState{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return state, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the path to the libcontainer configuration.
|
|
||||||
func configPath(dockerRun, containerID string) string {
|
|
||||||
return path.Join(dockerRun, libcontainerExecDriverPath, containerID, "state.json")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the path to the old libcontainer configuration.
|
|
||||||
func oldConfigPath(dockerRoot, containerID string) string {
|
|
||||||
return path.Join(dockerRoot, libcontainerExecDriverPath, containerID, "container.json")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets whether the specified container exists.
|
|
||||||
func Exists(dockerRoot, dockerRun, containerID string) bool {
|
|
||||||
// New or old config must exist for the container to be considered alive.
|
|
||||||
return utils.FileExists(configPath(dockerRun, containerID)) || utils.FileExists(oldConfigPath(dockerRoot, containerID))
|
|
||||||
}
|
|
20
Godeps/_workspace/src/github.com/google/cadvisor/container/raw/factory.go
generated
vendored
20
Godeps/_workspace/src/github.com/google/cadvisor/container/raw/factory.go
generated
vendored
@@ -19,6 +19,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/google/cadvisor/container"
|
"github.com/google/cadvisor/container"
|
||||||
|
"github.com/google/cadvisor/container/common"
|
||||||
"github.com/google/cadvisor/container/libcontainer"
|
"github.com/google/cadvisor/container/libcontainer"
|
||||||
"github.com/google/cadvisor/fs"
|
"github.com/google/cadvisor/fs"
|
||||||
info "github.com/google/cadvisor/info/v1"
|
info "github.com/google/cadvisor/info/v1"
|
||||||
@@ -39,7 +40,7 @@ type rawFactory struct {
|
|||||||
fsInfo fs.FsInfo
|
fsInfo fs.FsInfo
|
||||||
|
|
||||||
// Watcher for inotify events.
|
// Watcher for inotify events.
|
||||||
watcher *InotifyWatcher
|
watcher *common.InotifyWatcher
|
||||||
|
|
||||||
// List of metrics to be ignored.
|
// List of metrics to be ignored.
|
||||||
ignoreMetrics map[container.MetricKind]struct{}
|
ignoreMetrics map[container.MetricKind]struct{}
|
||||||
@@ -64,20 +65,7 @@ func (self *rawFactory) CanHandleAndAccept(name string) (bool, bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *rawFactory) DebugInfo() map[string][]string {
|
func (self *rawFactory) DebugInfo() map[string][]string {
|
||||||
out := make(map[string][]string)
|
return common.DebugInfo(self.watcher.GetWatches())
|
||||||
|
|
||||||
// Get information about inotify watches.
|
|
||||||
watches := self.watcher.GetWatches()
|
|
||||||
lines := make([]string, 0, len(watches))
|
|
||||||
for containerName, cgroupWatches := range watches {
|
|
||||||
lines = append(lines, fmt.Sprintf("%s:", containerName))
|
|
||||||
for _, cg := range cgroupWatches {
|
|
||||||
lines = append(lines, fmt.Sprintf("\t%s", cg))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out["Inotify watches"] = lines
|
|
||||||
|
|
||||||
return out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Register(machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo, ignoreMetrics map[container.MetricKind]struct{}) error {
|
func Register(machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo, ignoreMetrics map[container.MetricKind]struct{}) error {
|
||||||
@@ -89,7 +77,7 @@ func Register(machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo, igno
|
|||||||
return fmt.Errorf("failed to find supported cgroup mounts for the raw factory")
|
return fmt.Errorf("failed to find supported cgroup mounts for the raw factory")
|
||||||
}
|
}
|
||||||
|
|
||||||
watcher, err := NewInotifyWatcher()
|
watcher, err := common.NewInotifyWatcher()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
180
Godeps/_workspace/src/github.com/google/cadvisor/container/raw/handler.go
generated
vendored
180
Godeps/_workspace/src/github.com/google/cadvisor/container/raw/handler.go
generated
vendored
@@ -18,17 +18,14 @@ package raw
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/cadvisor/container"
|
"github.com/google/cadvisor/container"
|
||||||
|
"github.com/google/cadvisor/container/common"
|
||||||
"github.com/google/cadvisor/container/libcontainer"
|
"github.com/google/cadvisor/container/libcontainer"
|
||||||
"github.com/google/cadvisor/fs"
|
"github.com/google/cadvisor/fs"
|
||||||
info "github.com/google/cadvisor/info/v1"
|
info "github.com/google/cadvisor/info/v1"
|
||||||
"github.com/google/cadvisor/utils"
|
|
||||||
"github.com/google/cadvisor/utils/machine"
|
"github.com/google/cadvisor/utils/machine"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
@@ -45,7 +42,7 @@ type rawContainerHandler struct {
|
|||||||
machineInfoFactory info.MachineInfoFactory
|
machineInfoFactory info.MachineInfoFactory
|
||||||
|
|
||||||
// Inotify event watcher.
|
// Inotify event watcher.
|
||||||
watcher *InotifyWatcher
|
watcher *common.InotifyWatcher
|
||||||
|
|
||||||
// Signal for watcher thread to stop.
|
// Signal for watcher thread to stop.
|
||||||
stopWatcher chan error
|
stopWatcher chan error
|
||||||
@@ -58,7 +55,7 @@ type rawContainerHandler struct {
|
|||||||
cgroupManager cgroups.Manager
|
cgroupManager cgroups.Manager
|
||||||
|
|
||||||
fsInfo fs.FsInfo
|
fsInfo fs.FsInfo
|
||||||
externalMounts []mount
|
externalMounts []common.Mount
|
||||||
|
|
||||||
rootFs string
|
rootFs string
|
||||||
|
|
||||||
@@ -72,14 +69,10 @@ func isRootCgroup(name string) bool {
|
|||||||
return name == "/"
|
return name == "/"
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRawContainerHandler(name string, cgroupSubsystems *libcontainer.CgroupSubsystems, machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo, watcher *InotifyWatcher, rootFs string, ignoreMetrics container.MetricSet) (container.ContainerHandler, error) {
|
func newRawContainerHandler(name string, cgroupSubsystems *libcontainer.CgroupSubsystems, machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo, watcher *common.InotifyWatcher, rootFs string, ignoreMetrics container.MetricSet) (container.ContainerHandler, error) {
|
||||||
// Create the cgroup paths.
|
cgroupPaths := common.MakeCgroupPaths(cgroupSubsystems.MountPoints, name)
|
||||||
cgroupPaths := make(map[string]string, len(cgroupSubsystems.MountPoints))
|
|
||||||
for key, val := range cgroupSubsystems.MountPoints {
|
|
||||||
cgroupPaths[key] = path.Join(val, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
cHints, err := getContainerHintsFromFile(*argContainerHints)
|
cHints, err := common.GetContainerHintsFromFile(*common.ArgContainerHints)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -92,7 +85,7 @@ func newRawContainerHandler(name string, cgroupSubsystems *libcontainer.CgroupSu
|
|||||||
Paths: cgroupPaths,
|
Paths: cgroupPaths,
|
||||||
}
|
}
|
||||||
|
|
||||||
var externalMounts []mount
|
var externalMounts []common.Mount
|
||||||
for _, container := range cHints.AllHosts {
|
for _, container := range cHints.AllHosts {
|
||||||
if name == container.FullName {
|
if name == container.FullName {
|
||||||
externalMounts = container.Mounts
|
externalMounts = container.Mounts
|
||||||
@@ -128,38 +121,6 @@ func (self *rawContainerHandler) ContainerReference() (info.ContainerReference,
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readString(dirpath string, file string) string {
|
|
||||||
cgroupFile := path.Join(dirpath, file)
|
|
||||||
|
|
||||||
// Ignore non-existent files
|
|
||||||
if !utils.FileExists(cgroupFile) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read
|
|
||||||
out, err := ioutil.ReadFile(cgroupFile)
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("raw driver: Failed to read %q: %s", cgroupFile, err)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return strings.TrimSpace(string(out))
|
|
||||||
}
|
|
||||||
|
|
||||||
func readUInt64(dirpath string, file string) uint64 {
|
|
||||||
out := readString(dirpath, file)
|
|
||||||
if out == "" {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
val, err := strconv.ParseUint(out, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
glog.Errorf("raw driver: Failed to parse int %q from file %q: %s", out, path.Join(dirpath, file), err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *rawContainerHandler) GetRootNetworkDevices() ([]info.NetInfo, error) {
|
func (self *rawContainerHandler) GetRootNetworkDevices() ([]info.NetInfo, error) {
|
||||||
nd := []info.NetInfo{}
|
nd := []info.NetInfo{}
|
||||||
if isRootCgroup(self.name) {
|
if isRootCgroup(self.name) {
|
||||||
@@ -179,66 +140,21 @@ func (self *rawContainerHandler) Start() {}
|
|||||||
func (self *rawContainerHandler) Cleanup() {}
|
func (self *rawContainerHandler) Cleanup() {}
|
||||||
|
|
||||||
func (self *rawContainerHandler) GetSpec() (info.ContainerSpec, error) {
|
func (self *rawContainerHandler) GetSpec() (info.ContainerSpec, error) {
|
||||||
var spec info.ContainerSpec
|
const hasNetwork = false
|
||||||
|
hasFilesystem := isRootCgroup(self.name) || len(self.externalMounts) > 0
|
||||||
// The raw driver assumes unified hierarchy containers.
|
spec, err := common.GetSpec(self.cgroupPaths, self.machineInfoFactory, hasNetwork, hasFilesystem)
|
||||||
|
|
||||||
// Get the lowest creation time from all hierarchies as the container creation time.
|
|
||||||
now := time.Now()
|
|
||||||
lowestTime := now
|
|
||||||
for _, cgroupPath := range self.cgroupPaths {
|
|
||||||
// The modified time of the cgroup directory changes whenever a subcontainer is created.
|
|
||||||
// eg. /docker will have creation time matching the creation of latest docker container.
|
|
||||||
// Use clone_children as a workaround as it isn't usually modified. It is only likely changed
|
|
||||||
// immediately after creating a container.
|
|
||||||
cgroupPath = path.Join(cgroupPath, "cgroup.clone_children")
|
|
||||||
fi, err := os.Stat(cgroupPath)
|
|
||||||
if err == nil && fi.ModTime().Before(lowestTime) {
|
|
||||||
lowestTime = fi.ModTime()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if lowestTime != now {
|
|
||||||
spec.CreationTime = lowestTime
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get machine info.
|
|
||||||
mi, err := self.machineInfoFactory.GetMachineInfo()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return spec, err
|
return spec, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// CPU.
|
if isRootCgroup(self.name) {
|
||||||
cpuRoot, ok := self.cgroupPaths["cpu"]
|
// Check physical network devices for root container.
|
||||||
if ok {
|
nd, err := self.GetRootNetworkDevices()
|
||||||
if utils.FileExists(cpuRoot) {
|
|
||||||
spec.HasCpu = true
|
|
||||||
spec.Cpu.Limit = readUInt64(cpuRoot, "cpu.shares")
|
|
||||||
spec.Cpu.Period = readUInt64(cpuRoot, "cpu.cfs_period_us")
|
|
||||||
quota := readString(cpuRoot, "cpu.cfs_quota_us")
|
|
||||||
|
|
||||||
if quota != "" && quota != "-1" {
|
|
||||||
val, err := strconv.ParseUint(quota, 10, 64)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("raw driver: Failed to parse CPUQuota from %q: %s", path.Join(cpuRoot, "cpu.cfs_quota_us"), err)
|
return spec, err
|
||||||
}
|
|
||||||
spec.Cpu.Quota = val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
spec.HasNetwork = spec.HasNetwork || len(nd) != 0
|
||||||
|
|
||||||
// Cpu Mask.
|
|
||||||
// This will fail for non-unified hierarchies. We'll return the whole machine mask in that case.
|
|
||||||
cpusetRoot, ok := self.cgroupPaths["cpuset"]
|
|
||||||
if ok {
|
|
||||||
if utils.FileExists(cpusetRoot) {
|
|
||||||
spec.HasCpu = true
|
|
||||||
mask := readString(cpusetRoot, "cpuset.cpus")
|
|
||||||
spec.Cpu.Mask = utils.FixCpuMask(mask, mi.NumCores)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Memory
|
|
||||||
if self.name == "/" {
|
|
||||||
// Get memory and swap limits of the running machine
|
// Get memory and swap limits of the running machine
|
||||||
memLimit, err := machine.GetMachineMemoryCapacity()
|
memLimit, err := machine.GetMachineMemoryCapacity()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -256,35 +172,8 @@ func (self *rawContainerHandler) GetSpec() (info.ContainerSpec, error) {
|
|||||||
} else {
|
} else {
|
||||||
spec.Memory.SwapLimit = uint64(swapLimit)
|
spec.Memory.SwapLimit = uint64(swapLimit)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
memoryRoot, ok := self.cgroupPaths["memory"]
|
|
||||||
if ok {
|
|
||||||
if utils.FileExists(memoryRoot) {
|
|
||||||
spec.HasMemory = true
|
|
||||||
spec.Memory.Limit = readUInt64(memoryRoot, "memory.limit_in_bytes")
|
|
||||||
spec.Memory.SwapLimit = readUInt64(memoryRoot, "memory.memsw.limit_in_bytes")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fs.
|
|
||||||
if self.name == "/" || self.externalMounts != nil {
|
|
||||||
spec.HasFilesystem = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// DiskIo.
|
|
||||||
if blkioRoot, ok := self.cgroupPaths["blkio"]; ok && utils.FileExists(blkioRoot) {
|
|
||||||
spec.HasDiskIo = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check physical network devices for root container.
|
|
||||||
nd, err := self.GetRootNetworkDevices()
|
|
||||||
if err != nil {
|
|
||||||
return spec, err
|
|
||||||
}
|
|
||||||
if len(nd) != 0 {
|
|
||||||
spec.HasNetwork = true
|
|
||||||
}
|
|
||||||
return spec, nil
|
return spec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,39 +268,10 @@ func (self *rawContainerHandler) GetContainerLabels() map[string]string {
|
|||||||
return map[string]string{}
|
return map[string]string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lists all directories under "path" and outputs the results as children of "parent".
|
|
||||||
func listDirectories(dirpath string, parent string, recursive bool, output map[string]struct{}) error {
|
|
||||||
// Ignore if this hierarchy does not exist.
|
|
||||||
if !utils.FileExists(dirpath) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
entries, err := ioutil.ReadDir(dirpath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, entry := range entries {
|
|
||||||
// We only grab directories.
|
|
||||||
if entry.IsDir() {
|
|
||||||
name := path.Join(parent, entry.Name())
|
|
||||||
output[name] = struct{}{}
|
|
||||||
|
|
||||||
// List subcontainers if asked to.
|
|
||||||
if recursive {
|
|
||||||
err := listDirectories(path.Join(dirpath, entry.Name()), name, true, output)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *rawContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) {
|
func (self *rawContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) {
|
||||||
containers := make(map[string]struct{})
|
containers := make(map[string]struct{})
|
||||||
for _, cgroupPath := range self.cgroupPaths {
|
for _, cgroupPath := range self.cgroupPaths {
|
||||||
err := listDirectories(cgroupPath, self.name, listType == container.ListRecursive, containers)
|
err := common.ListDirectories(cgroupPath, self.name, listType == container.ListRecursive, containers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -583,11 +443,5 @@ func (self *rawContainerHandler) StopWatchingSubcontainers() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *rawContainerHandler) Exists() bool {
|
func (self *rawContainerHandler) Exists() bool {
|
||||||
// If any cgroup exists, the container is still alive.
|
return common.CgroupExists(self.cgroupPaths)
|
||||||
for _, cgroupPath := range self.cgroupPaths {
|
|
||||||
if utils.FileExists(cgroupPath) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
76
Godeps/_workspace/src/github.com/google/cadvisor/container/rkt/client.go
generated
vendored
Normal file
76
Godeps/_workspace/src/github.com/google/cadvisor/container/rkt/client.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
package rkt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
rktapi "github.com/coreos/rkt/api/v1alpha"
|
||||||
|
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultRktAPIServiceAddr = "localhost:15441"
|
||||||
|
timeout = 2 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
rktClient rktapi.PublicAPIClient
|
||||||
|
rktClientErr error
|
||||||
|
once sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
func Client() (rktapi.PublicAPIClient, error) {
|
||||||
|
once.Do(func() {
|
||||||
|
conn, err := net.DialTimeout("tcp", defaultRktAPIServiceAddr, timeout)
|
||||||
|
if err != nil {
|
||||||
|
rktClient = nil
|
||||||
|
rktClientErr = fmt.Errorf("rkt: cannot tcp Dial rkt api service: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.Close()
|
||||||
|
|
||||||
|
apisvcConn, err := grpc.Dial(defaultRktAPIServiceAddr, grpc.WithInsecure(), grpc.WithTimeout(timeout))
|
||||||
|
if err != nil {
|
||||||
|
rktClient = nil
|
||||||
|
rktClientErr = fmt.Errorf("rkt: cannot grpc Dial rkt api service: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rktClient = rktapi.NewPublicAPIClient(apisvcConn)
|
||||||
|
})
|
||||||
|
|
||||||
|
return rktClient, rktClientErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func RktPath() (string, error) {
|
||||||
|
client, err := Client()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.GetInfo(context.Background(), &rktapi.GetInfoRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("couldn't GetInfo from rkt api service: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp.Info.GlobalFlags.Dir, nil
|
||||||
|
}
|
104
Godeps/_workspace/src/github.com/google/cadvisor/container/rkt/factory.go
generated
vendored
Normal file
104
Godeps/_workspace/src/github.com/google/cadvisor/container/rkt/factory.go
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
package rkt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/cadvisor/container"
|
||||||
|
"github.com/google/cadvisor/container/libcontainer"
|
||||||
|
"github.com/google/cadvisor/fs"
|
||||||
|
info "github.com/google/cadvisor/info/v1"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
)
|
||||||
|
|
||||||
|
const RktNamespace = "rkt"
|
||||||
|
|
||||||
|
type rktFactory struct {
|
||||||
|
machineInfoFactory info.MachineInfoFactory
|
||||||
|
|
||||||
|
cgroupSubsystems *libcontainer.CgroupSubsystems
|
||||||
|
|
||||||
|
fsInfo fs.FsInfo
|
||||||
|
|
||||||
|
ignoreMetrics container.MetricSet
|
||||||
|
|
||||||
|
rktPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *rktFactory) String() string {
|
||||||
|
return "rkt"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *rktFactory) NewContainerHandler(name string, inHostNamespace bool) (container.ContainerHandler, error) {
|
||||||
|
client, err := Client()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rootFs := "/"
|
||||||
|
if !inHostNamespace {
|
||||||
|
rootFs = "/rootfs"
|
||||||
|
}
|
||||||
|
return newRktContainerHandler(name, client, self.rktPath, self.cgroupSubsystems, self.machineInfoFactory, self.fsInfo, rootFs, self.ignoreMetrics)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *rktFactory) CanHandleAndAccept(name string) (bool, bool, error) {
|
||||||
|
// will ignore all cgroup names that don't either correspond to the machine.slice that is the pod or the containers that belong to the pod
|
||||||
|
// only works for machined rkt pods at the moment
|
||||||
|
|
||||||
|
if strings.HasPrefix(name, "/machine.slice/machine-rkt\\x2d") {
|
||||||
|
accept, err := verifyName(name)
|
||||||
|
return true, accept, err
|
||||||
|
}
|
||||||
|
return false, false, fmt.Errorf("%s not handled by rkt handler", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *rktFactory) DebugInfo() map[string][]string {
|
||||||
|
return map[string][]string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Register(machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo, ignoreMetrics container.MetricSet) error {
|
||||||
|
_, err := Client()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to communicate with Rkt api service: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rktPath, err := RktPath()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to get the RktPath variable %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cgroupSubsystems, err := libcontainer.GetCgroupSubsystems()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get cgroup subsystems: %v", err)
|
||||||
|
}
|
||||||
|
if len(cgroupSubsystems.Mounts) == 0 {
|
||||||
|
return fmt.Errorf("failed to find supported cgroup mounts for the raw factory")
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.Infof("Registering Rkt factory")
|
||||||
|
factory := &rktFactory{
|
||||||
|
machineInfoFactory: machineInfoFactory,
|
||||||
|
fsInfo: fsInfo,
|
||||||
|
cgroupSubsystems: &cgroupSubsystems,
|
||||||
|
ignoreMetrics: ignoreMetrics,
|
||||||
|
rktPath: rktPath,
|
||||||
|
}
|
||||||
|
container.RegisterContainerHandlerFactory(factory)
|
||||||
|
return nil
|
||||||
|
}
|
327
Godeps/_workspace/src/github.com/google/cadvisor/container/rkt/handler.go
generated
vendored
Normal file
327
Godeps/_workspace/src/github.com/google/cadvisor/container/rkt/handler.go
generated
vendored
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// Handler for "rkt" containers.
|
||||||
|
package rkt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
rktapi "github.com/coreos/rkt/api/v1alpha"
|
||||||
|
"github.com/google/cadvisor/container"
|
||||||
|
"github.com/google/cadvisor/container/common"
|
||||||
|
"github.com/google/cadvisor/container/libcontainer"
|
||||||
|
"github.com/google/cadvisor/fs"
|
||||||
|
info "github.com/google/cadvisor/info/v1"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||||
|
cgroupfs "github.com/opencontainers/runc/libcontainer/cgroups/fs"
|
||||||
|
"github.com/opencontainers/runc/libcontainer/configs"
|
||||||
|
)
|
||||||
|
|
||||||
|
type rktContainerHandler struct {
|
||||||
|
rktClient rktapi.PublicAPIClient
|
||||||
|
// Name of the container for this handler.
|
||||||
|
name string
|
||||||
|
cgroupSubsystems *libcontainer.CgroupSubsystems
|
||||||
|
machineInfoFactory info.MachineInfoFactory
|
||||||
|
|
||||||
|
// Absolute path to the cgroup hierarchies of this container.
|
||||||
|
// (e.g.: "cpu" -> "/sys/fs/cgroup/cpu/test")
|
||||||
|
cgroupPaths map[string]string
|
||||||
|
|
||||||
|
// Manager of this container's cgroups.
|
||||||
|
cgroupManager cgroups.Manager
|
||||||
|
|
||||||
|
// Whether this container has network isolation enabled.
|
||||||
|
hasNetwork bool
|
||||||
|
|
||||||
|
fsInfo fs.FsInfo
|
||||||
|
|
||||||
|
rootFs string
|
||||||
|
|
||||||
|
isPod bool
|
||||||
|
|
||||||
|
aliases []string
|
||||||
|
|
||||||
|
pid int
|
||||||
|
|
||||||
|
rootfsStorageDir string
|
||||||
|
|
||||||
|
labels map[string]string
|
||||||
|
|
||||||
|
// Filesystem handler.
|
||||||
|
fsHandler common.FsHandler
|
||||||
|
|
||||||
|
ignoreMetrics container.MetricSet
|
||||||
|
|
||||||
|
apiPod *rktapi.Pod
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRktContainerHandler(name string, rktClient rktapi.PublicAPIClient, rktPath string, cgroupSubsystems *libcontainer.CgroupSubsystems, machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo, rootFs string, ignoreMetrics container.MetricSet) (container.ContainerHandler, error) {
|
||||||
|
aliases := make([]string, 1)
|
||||||
|
isPod := false
|
||||||
|
|
||||||
|
apiPod := &rktapi.Pod{}
|
||||||
|
|
||||||
|
parsed, err := parseName(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("this should be impossible!, new handler failing, but factory allowed, name = %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
//rktnetes uses containerID: rkt://fff40827-b994-4e3a-8f88-6427c2c8a5ac:nginx
|
||||||
|
if parsed.Container == "" {
|
||||||
|
isPod = true
|
||||||
|
aliases = append(aliases, "rkt://"+parsed.Pod)
|
||||||
|
} else {
|
||||||
|
aliases = append(aliases, "rkt://"+parsed.Pod+":"+parsed.Container)
|
||||||
|
}
|
||||||
|
|
||||||
|
pid := os.Getpid()
|
||||||
|
labels := make(map[string]string)
|
||||||
|
resp, err := rktClient.InspectPod(context.Background(), &rktapi.InspectPodRequest{
|
||||||
|
Id: parsed.Pod,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
var annotations []*rktapi.KeyValue
|
||||||
|
if parsed.Container == "" {
|
||||||
|
pid = int(resp.Pod.Pid)
|
||||||
|
apiPod = resp.Pod
|
||||||
|
annotations = resp.Pod.Annotations
|
||||||
|
} else {
|
||||||
|
var ok bool
|
||||||
|
if annotations, ok = findAnnotations(resp.Pod.Apps, parsed.Container); !ok {
|
||||||
|
glog.Warningf("couldn't find application in Pod matching %v", parsed.Container)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
labels = createLabels(annotations)
|
||||||
|
}
|
||||||
|
|
||||||
|
cgroupPaths := common.MakeCgroupPaths(cgroupSubsystems.MountPoints, name)
|
||||||
|
|
||||||
|
// Generate the equivalent cgroup manager for this container.
|
||||||
|
cgroupManager := &cgroupfs.Manager{
|
||||||
|
Cgroups: &configs.Cgroup{
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
Paths: cgroupPaths,
|
||||||
|
}
|
||||||
|
|
||||||
|
hasNetwork := false
|
||||||
|
if isPod {
|
||||||
|
hasNetwork = true
|
||||||
|
}
|
||||||
|
|
||||||
|
rootfsStorageDir := getRootFs(rktPath, parsed)
|
||||||
|
|
||||||
|
handler := &rktContainerHandler{
|
||||||
|
name: name,
|
||||||
|
rktClient: rktClient,
|
||||||
|
cgroupSubsystems: cgroupSubsystems,
|
||||||
|
machineInfoFactory: machineInfoFactory,
|
||||||
|
cgroupPaths: cgroupPaths,
|
||||||
|
cgroupManager: cgroupManager,
|
||||||
|
fsInfo: fsInfo,
|
||||||
|
hasNetwork: hasNetwork,
|
||||||
|
rootFs: rootFs,
|
||||||
|
isPod: isPod,
|
||||||
|
aliases: aliases,
|
||||||
|
pid: pid,
|
||||||
|
labels: labels,
|
||||||
|
rootfsStorageDir: rootfsStorageDir,
|
||||||
|
ignoreMetrics: ignoreMetrics,
|
||||||
|
apiPod: apiPod,
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ignoreMetrics.Has(container.DiskUsageMetrics) {
|
||||||
|
handler.fsHandler = common.NewFsHandler(time.Minute, rootfsStorageDir, "", fsInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func findAnnotations(apps []*rktapi.App, container string) ([]*rktapi.KeyValue, bool) {
|
||||||
|
for _, app := range apps {
|
||||||
|
if app.Name == container {
|
||||||
|
return app.Annotations, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func createLabels(annotations []*rktapi.KeyValue) map[string]string {
|
||||||
|
labels := make(map[string]string)
|
||||||
|
for _, kv := range annotations {
|
||||||
|
labels[kv.Key] = kv.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
return labels
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *rktContainerHandler) ContainerReference() (info.ContainerReference, error) {
|
||||||
|
return info.ContainerReference{
|
||||||
|
Name: handler.name,
|
||||||
|
Aliases: handler.aliases,
|
||||||
|
Namespace: RktNamespace,
|
||||||
|
Labels: handler.labels,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *rktContainerHandler) Start() {
|
||||||
|
handler.fsHandler.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *rktContainerHandler) Cleanup() {
|
||||||
|
handler.fsHandler.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *rktContainerHandler) GetSpec() (info.ContainerSpec, error) {
|
||||||
|
hasNetwork := handler.hasNetwork && !handler.ignoreMetrics.Has(container.NetworkUsageMetrics)
|
||||||
|
hasFilesystem := !handler.ignoreMetrics.Has(container.DiskUsageMetrics)
|
||||||
|
return common.GetSpec(handler.cgroupPaths, handler.machineInfoFactory, hasNetwork, hasFilesystem)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *rktContainerHandler) getFsStats(stats *info.ContainerStats) error {
|
||||||
|
if handler.ignoreMetrics.Has(container.DiskUsageMetrics) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceInfo, err := handler.fsInfo.GetDirFsDevice(handler.rootfsStorageDir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mi, err := handler.machineInfoFactory.GetMachineInfo()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var limit uint64 = 0
|
||||||
|
|
||||||
|
// Use capacity as limit.
|
||||||
|
for _, fs := range mi.Filesystems {
|
||||||
|
if fs.Device == deviceInfo.Device {
|
||||||
|
limit = fs.Capacity
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fsStat := info.FsStats{Device: deviceInfo.Device, Limit: limit}
|
||||||
|
|
||||||
|
fsStat.BaseUsage, fsStat.Usage = handler.fsHandler.Usage()
|
||||||
|
|
||||||
|
stats.Filesystem = append(stats.Filesystem, fsStat)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *rktContainerHandler) GetStats() (*info.ContainerStats, error) {
|
||||||
|
stats, err := libcontainer.GetStats(handler.cgroupManager, handler.rootFs, handler.pid, handler.ignoreMetrics)
|
||||||
|
if err != nil {
|
||||||
|
return stats, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get filesystem stats.
|
||||||
|
err = handler.getFsStats(stats)
|
||||||
|
if err != nil {
|
||||||
|
return stats, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *rktContainerHandler) GetCgroupPath(resource string) (string, error) {
|
||||||
|
path, ok := handler.cgroupPaths[resource]
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("could not find path for resource %q for container %q\n", resource, handler.name)
|
||||||
|
}
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *rktContainerHandler) GetContainerLabels() map[string]string {
|
||||||
|
return handler.labels
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *rktContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) {
|
||||||
|
containers := make(map[string]struct{})
|
||||||
|
|
||||||
|
// Rkt containers do not have subcontainers, only the "Pod" does.
|
||||||
|
if handler.isPod == false {
|
||||||
|
var ret []info.ContainerReference
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Turn the system.slice cgroups into the Pod's subcontainers
|
||||||
|
for _, cgroupPath := range handler.cgroupPaths {
|
||||||
|
err := common.ListDirectories(path.Join(cgroupPath, "system.slice"), path.Join(handler.name, "system.slice"), listType == container.ListRecursive, containers)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the container references. for the Pod's subcontainers
|
||||||
|
ret := make([]info.ContainerReference, 0, len(handler.apiPod.Apps))
|
||||||
|
for cont := range containers {
|
||||||
|
aliases := make([]string, 1)
|
||||||
|
parsed, err := parseName(cont)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("this should be impossible!, unable to parse rkt subcontainer name = %s", cont)
|
||||||
|
}
|
||||||
|
aliases = append(aliases, parsed.Pod+":"+parsed.Container)
|
||||||
|
|
||||||
|
labels := make(map[string]string)
|
||||||
|
if annotations, ok := findAnnotations(handler.apiPod.Apps, parsed.Container); !ok {
|
||||||
|
glog.Warningf("couldn't find application in Pod matching %v", parsed.Container)
|
||||||
|
} else {
|
||||||
|
labels = createLabels(annotations)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, info.ContainerReference{
|
||||||
|
Name: cont,
|
||||||
|
Aliases: aliases,
|
||||||
|
Namespace: RktNamespace,
|
||||||
|
Labels: labels,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *rktContainerHandler) ListThreads(listType container.ListType) ([]int, error) {
|
||||||
|
// TODO(sjpotter): Implement? Not implemented with docker yet
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *rktContainerHandler) ListProcesses(listType container.ListType) ([]int, error) {
|
||||||
|
return libcontainer.GetProcesses(handler.cgroupManager)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *rktContainerHandler) WatchSubcontainers(events chan container.SubcontainerEvent) error {
|
||||||
|
return fmt.Errorf("watch is unimplemented in the Rkt container driver")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *rktContainerHandler) StopWatchingSubcontainers() error {
|
||||||
|
// No-op for Rkt driver.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *rktContainerHandler) Exists() bool {
|
||||||
|
return common.CgroupExists(handler.cgroupPaths)
|
||||||
|
}
|
93
Godeps/_workspace/src/github.com/google/cadvisor/container/rkt/helpers.go
generated
vendored
Normal file
93
Godeps/_workspace/src/github.com/google/cadvisor/container/rkt/helpers.go
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
package rkt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
)
|
||||||
|
|
||||||
|
type parsedName struct {
|
||||||
|
Pod string
|
||||||
|
Container string
|
||||||
|
}
|
||||||
|
|
||||||
|
func verifyName(name string) (bool, error) {
|
||||||
|
_, err := parseName(name)
|
||||||
|
return err == nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse cgroup name into a pod/container name struct
|
||||||
|
Example cgroup fs name
|
||||||
|
|
||||||
|
pod - /sys/fs/cgroup/cpu/machine.slice/machine-rkt\\x2df556b64a\\x2d17a7\\x2d47d7\\x2d93ec\\x2def2275c3d67e.scope/
|
||||||
|
container under pod - /sys/fs/cgroup/cpu/machine.slice/machine-rkt\\x2df556b64a\\x2d17a7\\x2d47d7\\x2d93ec\\x2def2275c3d67e.scope/system.slice/alpine-sh.service
|
||||||
|
*/
|
||||||
|
//TODO{sjpotter}: this currently only recognizes machined started pods, which actually doesn't help with k8s which uses them as systemd services, need a solution for both
|
||||||
|
func parseName(name string) (*parsedName, error) {
|
||||||
|
splits := strings.Split(name, "/")
|
||||||
|
if len(splits) == 3 || len(splits) == 5 {
|
||||||
|
parsed := &parsedName{}
|
||||||
|
|
||||||
|
if splits[1] == "machine.slice" {
|
||||||
|
replacer := strings.NewReplacer("machine-rkt\\x2d", "", ".scope", "", "\\x2d", "-")
|
||||||
|
parsed.Pod = replacer.Replace(splits[2])
|
||||||
|
if len(splits) == 3 {
|
||||||
|
return parsed, nil
|
||||||
|
}
|
||||||
|
if splits[3] == "system.slice" {
|
||||||
|
parsed.Container = strings.Replace(splits[4], ".service", "", -1)
|
||||||
|
return parsed, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("%s not handled by rkt handler", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets a Rkt container's overlay upper dir
|
||||||
|
func getRootFs(root string, parsed *parsedName) string {
|
||||||
|
/* Example of where it stores the upper dir key
|
||||||
|
for container
|
||||||
|
/var/lib/rkt/pods/run/bc793ec6-c48f-4480-99b5-6bec16d52210/appsinfo/alpine-sh/treeStoreID
|
||||||
|
for pod
|
||||||
|
/var/lib/rkt/pods/run/f556b64a-17a7-47d7-93ec-ef2275c3d67e/stage1TreeStoreID
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
var tree string
|
||||||
|
if parsed.Container == "" {
|
||||||
|
tree = path.Join(root, "pods/run", parsed.Pod, "stage1TreeStoreID")
|
||||||
|
} else {
|
||||||
|
tree = path.Join(root, "pods/run", parsed.Pod, "appsinfo", parsed.Container, "treeStoreID")
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes, err := ioutil.ReadFile(tree)
|
||||||
|
if err != nil {
|
||||||
|
glog.Infof("ReadFile failed, couldn't read %v to get upper dir: %v", tree, err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
s := string(bytes)
|
||||||
|
|
||||||
|
/* Example of where the upper dir is stored via key read above
|
||||||
|
/var/lib/rkt/pods/run/bc793ec6-c48f-4480-99b5-6bec16d52210/overlay/deps-sha512-82a099e560a596662b15dec835e9adabab539cad1f41776a30195a01a8f2f22b/
|
||||||
|
*/
|
||||||
|
return path.Join(root, "pods/run", parsed.Pod, "overlay", s)
|
||||||
|
}
|
57
Godeps/_workspace/src/github.com/google/cadvisor/container/systemd/factory.go
generated
vendored
Normal file
57
Godeps/_workspace/src/github.com/google/cadvisor/container/systemd/factory.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
package systemd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/cadvisor/container"
|
||||||
|
"github.com/google/cadvisor/fs"
|
||||||
|
info "github.com/google/cadvisor/info/v1"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
)
|
||||||
|
|
||||||
|
type systemdFactory struct{}
|
||||||
|
|
||||||
|
func (f *systemdFactory) String() string {
|
||||||
|
return "systemd"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *systemdFactory) NewContainerHandler(name string, inHostNamespace bool) (container.ContainerHandler, error) {
|
||||||
|
return nil, fmt.Errorf("Not yet supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *systemdFactory) CanHandleAndAccept(name string) (bool, bool, error) {
|
||||||
|
// on systemd using devicemapper each mount into the container has an associated cgroup that we ignore.
|
||||||
|
// for details on .mount units: http://man7.org/linux/man-pages/man5/systemd.mount.5.html
|
||||||
|
if strings.HasSuffix(name, ".mount") {
|
||||||
|
return true, false, nil
|
||||||
|
}
|
||||||
|
return false, false, fmt.Errorf("%s not handled by systemd handler", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *systemdFactory) DebugInfo() map[string][]string {
|
||||||
|
return map[string][]string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register registers the systemd container factory.
|
||||||
|
func Register(machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo, ignoreMetrics container.MetricSet) error {
|
||||||
|
glog.Infof("Registering systemd factory")
|
||||||
|
factory := &systemdFactory{}
|
||||||
|
container.RegisterContainerHandlerFactory(factory)
|
||||||
|
return nil
|
||||||
|
}
|
131
Godeps/_workspace/src/github.com/google/cadvisor/fs/fs.go
generated
vendored
131
Godeps/_workspace/src/github.com/google/cadvisor/fs/fs.go
generated
vendored
@@ -19,7 +19,6 @@ package fs
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@@ -40,6 +39,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
LabelSystemRoot = "root"
|
LabelSystemRoot = "root"
|
||||||
LabelDockerImages = "docker-images"
|
LabelDockerImages = "docker-images"
|
||||||
|
LabelRktImages = "rkt-images"
|
||||||
)
|
)
|
||||||
|
|
||||||
type partition struct {
|
type partition struct {
|
||||||
@@ -62,8 +62,14 @@ type RealFsInfo struct {
|
|||||||
|
|
||||||
type Context struct {
|
type Context struct {
|
||||||
// docker root directory.
|
// docker root directory.
|
||||||
DockerRoot string
|
Docker DockerContext
|
||||||
DockerInfo map[string]string
|
RktPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
type DockerContext struct {
|
||||||
|
Root string
|
||||||
|
Driver string
|
||||||
|
DriverStatus map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFsInfo(context Context) (FsInfo, error) {
|
func NewFsInfo(context Context) (FsInfo, error) {
|
||||||
@@ -76,6 +82,11 @@ func NewFsInfo(context Context) (FsInfo, error) {
|
|||||||
labels: make(map[string]string, 0),
|
labels: make(map[string]string, 0),
|
||||||
dmsetup: &defaultDmsetupClient{},
|
dmsetup: &defaultDmsetupClient{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fsInfo.addSystemRootLabel(mounts)
|
||||||
|
fsInfo.addDockerImagesLabel(context, mounts)
|
||||||
|
fsInfo.addRktImagesLabel(context, mounts)
|
||||||
|
|
||||||
supportedFsType := map[string]bool{
|
supportedFsType := map[string]bool{
|
||||||
// all ext systems are checked through prefix.
|
// all ext systems are checked through prefix.
|
||||||
"btrfs": true,
|
"btrfs": true,
|
||||||
@@ -102,12 +113,7 @@ func NewFsInfo(context Context) (FsInfo, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to call this before the log line below printing out the partitions, as this function may
|
|
||||||
// add a "partition" for devicemapper to fsInfo.partitions
|
|
||||||
fsInfo.addDockerImagesLabel(context)
|
|
||||||
|
|
||||||
glog.Infof("Filesystem partitions: %+v", fsInfo.partitions)
|
glog.Infof("Filesystem partitions: %+v", fsInfo.partitions)
|
||||||
fsInfo.addSystemRootLabel()
|
|
||||||
return fsInfo, nil
|
return fsInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,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
|
// 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
|
// 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.
|
// loopback file resides, inside of the loopback file itself.
|
||||||
func (self *RealFsInfo) getDockerDeviceMapperInfo(dockerInfo map[string]string) (string, *partition, error) {
|
func (self *RealFsInfo) getDockerDeviceMapperInfo(context DockerContext) (string, *partition, error) {
|
||||||
if storageDriver, ok := dockerInfo["Driver"]; ok && storageDriver != DeviceMapper.String() {
|
if context.Driver != DeviceMapper.String() {
|
||||||
return "", nil, nil
|
return "", nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var driverStatus [][]string
|
dataLoopFile := context.DriverStatus["Data loop file"]
|
||||||
if err := json.Unmarshal([]byte(dockerInfo["DriverStatus"]), &driverStatus); err != nil {
|
|
||||||
return "", nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
dataLoopFile := dockerStatusValue(driverStatus, "Data loop file")
|
|
||||||
if len(dataLoopFile) > 0 {
|
if len(dataLoopFile) > 0 {
|
||||||
return "", nil, nil
|
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 {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
@@ -144,19 +145,24 @@ func (self *RealFsInfo) getDockerDeviceMapperInfo(dockerInfo map[string]string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// addSystemRootLabel attempts to determine which device contains the mount for /.
|
// addSystemRootLabel attempts to determine which device contains the mount for /.
|
||||||
func (self *RealFsInfo) addSystemRootLabel() {
|
func (self *RealFsInfo) addSystemRootLabel(mounts []*mount.Info) {
|
||||||
for src, p := range self.partitions {
|
for _, m := range mounts {
|
||||||
if p.mountpoint == "/" {
|
if m.Mountpoint == "/" {
|
||||||
if _, ok := self.labels[LabelSystemRoot]; !ok {
|
self.partitions[m.Source] = partition{
|
||||||
self.labels[LabelSystemRoot] = src
|
fsType: m.Fstype,
|
||||||
|
mountpoint: m.Mountpoint,
|
||||||
|
major: uint(m.Major),
|
||||||
|
minor: uint(m.Minor),
|
||||||
}
|
}
|
||||||
|
self.labels[LabelSystemRoot] = m.Source
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// addDockerImagesLabel attempts to determine which device contains the mount for docker images.
|
// addDockerImagesLabel attempts to determine which device contains the mount for docker images.
|
||||||
func (self *RealFsInfo) addDockerImagesLabel(context Context) {
|
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 {
|
if err != nil {
|
||||||
glog.Warningf("Could not get Docker devicemapper device: %v", err)
|
glog.Warningf("Could not get Docker devicemapper device: %v", err)
|
||||||
}
|
}
|
||||||
@@ -164,48 +170,64 @@ func (self *RealFsInfo) addDockerImagesLabel(context Context) {
|
|||||||
self.partitions[dockerDev] = *dockerPartition
|
self.partitions[dockerDev] = *dockerPartition
|
||||||
self.labels[LabelDockerImages] = dockerDev
|
self.labels[LabelDockerImages] = dockerDev
|
||||||
} else {
|
} else {
|
||||||
dockerPaths := getDockerImagePaths(context)
|
self.updateContainerImagesPath(LabelDockerImages, mounts, getDockerImagePaths(context))
|
||||||
|
|
||||||
for src, p := range self.partitions {
|
|
||||||
self.updateDockerImagesPath(src, p.mountpoint, dockerPaths)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *RealFsInfo) addRktImagesLabel(context Context, mounts []*mount.Info) {
|
||||||
|
if context.RktPath != "" {
|
||||||
|
rktPath := context.RktPath
|
||||||
|
rktImagesPaths := map[string]struct{}{
|
||||||
|
"/": {},
|
||||||
|
}
|
||||||
|
for rktPath != "/" && rktPath != "." {
|
||||||
|
rktImagesPaths[rktPath] = struct{}{}
|
||||||
|
rktPath = filepath.Dir(rktPath)
|
||||||
|
}
|
||||||
|
self.updateContainerImagesPath(LabelRktImages, mounts, rktImagesPaths)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a list of possible mount points for docker image management from the docker root directory.
|
// Generate a list of possible mount points for docker image management from the docker root directory.
|
||||||
// Right now, we look for each type of supported graph driver directories, but we can do better by parsing
|
// Right now, we look for each type of supported graph driver directories, but we can do better by parsing
|
||||||
// some of the context from `docker info`.
|
// some of the context from `docker info`.
|
||||||
func getDockerImagePaths(context Context) []string {
|
func getDockerImagePaths(context Context) map[string]struct{} {
|
||||||
|
dockerImagePaths := map[string]struct{}{
|
||||||
|
"/": {},
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(rjnagal): Detect docker root and graphdriver directories from docker info.
|
// TODO(rjnagal): Detect docker root and graphdriver directories from docker info.
|
||||||
dockerRoot := context.DockerRoot
|
dockerRoot := context.Docker.Root
|
||||||
dockerImagePaths := []string{}
|
|
||||||
for _, dir := range []string{"devicemapper", "btrfs", "aufs", "overlay", "zfs"} {
|
for _, dir := range []string{"devicemapper", "btrfs", "aufs", "overlay", "zfs"} {
|
||||||
dockerImagePaths = append(dockerImagePaths, path.Join(dockerRoot, dir))
|
dockerImagePaths[path.Join(dockerRoot, dir)] = struct{}{}
|
||||||
}
|
}
|
||||||
for dockerRoot != "/" && dockerRoot != "." {
|
for dockerRoot != "/" && dockerRoot != "." {
|
||||||
dockerImagePaths = append(dockerImagePaths, dockerRoot)
|
dockerImagePaths[dockerRoot] = struct{}{}
|
||||||
dockerRoot = filepath.Dir(dockerRoot)
|
dockerRoot = filepath.Dir(dockerRoot)
|
||||||
}
|
}
|
||||||
dockerImagePaths = append(dockerImagePaths, "/")
|
|
||||||
return dockerImagePaths
|
return dockerImagePaths
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method compares the mountpoint with possible docker image mount points. If a match is found,
|
// This method compares the mountpoints with possible container image mount points. If a match is found,
|
||||||
// docker images label is added to the partition.
|
// the label is added to the partition.
|
||||||
func (self *RealFsInfo) updateDockerImagesPath(source string, mountpoint string, dockerImagePaths []string) {
|
func (self *RealFsInfo) updateContainerImagesPath(label string, mounts []*mount.Info, containerImagePaths map[string]struct{}) {
|
||||||
for _, v := range dockerImagePaths {
|
var useMount *mount.Info
|
||||||
if v == mountpoint {
|
for _, m := range mounts {
|
||||||
if i, ok := self.labels[LabelDockerImages]; ok {
|
if _, ok := containerImagePaths[m.Mountpoint]; ok {
|
||||||
// pick the innermost mountpoint.
|
if useMount == nil || (len(useMount.Mountpoint) < len(m.Mountpoint)) {
|
||||||
mnt := self.partitions[i].mountpoint
|
useMount = m
|
||||||
if len(mnt) < len(mountpoint) {
|
|
||||||
self.labels[LabelDockerImages] = source
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.labels[LabelDockerImages] = source
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if useMount != nil {
|
||||||
|
self.partitions[useMount.Source] = partition{
|
||||||
|
fsType: useMount.Fstype,
|
||||||
|
mountpoint: useMount.Mountpoint,
|
||||||
|
major: uint(useMount.Major),
|
||||||
|
minor: uint(useMount.Minor),
|
||||||
|
}
|
||||||
|
self.labels[label] = useMount.Source
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RealFsInfo) GetDeviceForLabel(label string) (string, error) {
|
func (self *RealFsInfo) GetDeviceForLabel(label string) (string, error) {
|
||||||
@@ -412,15 +434,6 @@ func getVfsStats(path string) (total uint64, free uint64, avail uint64, inodes u
|
|||||||
return total, free, avail, inodes, inodesFree, nil
|
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.
|
// dmsetupClient knows to to interact with dmsetup to retrieve information about devicemapper.
|
||||||
type dmsetupClient interface {
|
type dmsetupClient interface {
|
||||||
table(poolName string) ([]byte, error)
|
table(poolName string) ([]byte, error)
|
||||||
@@ -438,9 +451,9 @@ func (*defaultDmsetupClient) table(poolName string) ([]byte, error) {
|
|||||||
|
|
||||||
// Devicemapper thin provisioning is detailed at
|
// Devicemapper thin provisioning is detailed at
|
||||||
// https://www.kernel.org/doc/Documentation/device-mapper/thin-provisioning.txt
|
// https://www.kernel.org/doc/Documentation/device-mapper/thin-provisioning.txt
|
||||||
func dockerDMDevice(driverStatus [][]string, dmsetup dmsetupClient) (string, uint, uint, uint, error) {
|
func dockerDMDevice(driverStatus map[string]string, dmsetup dmsetupClient) (string, uint, uint, uint, error) {
|
||||||
poolName := dockerStatusValue(driverStatus, "Pool Name")
|
poolName, ok := driverStatus["Pool Name"]
|
||||||
if len(poolName) == 0 {
|
if !ok || len(poolName) == 0 {
|
||||||
return "", 0, 0, 0, fmt.Errorf("Could not get dm pool name")
|
return "", 0, 0, 0, fmt.Errorf("Could not get dm pool name")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
92
Godeps/_workspace/src/github.com/google/cadvisor/manager/manager.go
generated
vendored
92
Godeps/_workspace/src/github.com/google/cadvisor/manager/manager.go
generated
vendored
@@ -16,7 +16,6 @@
|
|||||||
package manager
|
package manager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@@ -31,6 +30,8 @@ import (
|
|||||||
"github.com/google/cadvisor/container"
|
"github.com/google/cadvisor/container"
|
||||||
"github.com/google/cadvisor/container/docker"
|
"github.com/google/cadvisor/container/docker"
|
||||||
"github.com/google/cadvisor/container/raw"
|
"github.com/google/cadvisor/container/raw"
|
||||||
|
"github.com/google/cadvisor/container/rkt"
|
||||||
|
"github.com/google/cadvisor/container/systemd"
|
||||||
"github.com/google/cadvisor/events"
|
"github.com/google/cadvisor/events"
|
||||||
"github.com/google/cadvisor/fs"
|
"github.com/google/cadvisor/fs"
|
||||||
info "github.com/google/cadvisor/info/v1"
|
info "github.com/google/cadvisor/info/v1"
|
||||||
@@ -60,7 +61,7 @@ type Manager interface {
|
|||||||
// Stops the manager.
|
// Stops the manager.
|
||||||
Stop() error
|
Stop() error
|
||||||
|
|
||||||
// Get information about a container.
|
// information about a container.
|
||||||
GetContainerInfo(containerName string, query *info.ContainerInfoRequest) (*info.ContainerInfo, error)
|
GetContainerInfo(containerName string, query *info.ContainerInfoRequest) (*info.ContainerInfo, error)
|
||||||
|
|
||||||
// Get V2 information about a container.
|
// Get V2 information about a container.
|
||||||
@@ -131,11 +132,23 @@ func New(memoryCache *memory.InMemoryCache, sysfs sysfs.SysFs, maxHousekeepingIn
|
|||||||
}
|
}
|
||||||
glog.Infof("cAdvisor running in container: %q", selfContainer)
|
glog.Infof("cAdvisor running in container: %q", selfContainer)
|
||||||
|
|
||||||
dockerInfo, err := docker.DockerInfo()
|
dockerInfo, err := dockerInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Warningf("Unable to connect to Docker: %v", err)
|
glog.Warningf("Unable to connect to Docker: %v", err)
|
||||||
}
|
}
|
||||||
context := fs.Context{DockerRoot: docker.RootDir(), DockerInfo: dockerInfo}
|
rktPath, err := rkt.RktPath()
|
||||||
|
if err != nil {
|
||||||
|
glog.Warningf("unable to connect to Rkt api service: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
context := fs.Context{
|
||||||
|
Docker: fs.DockerContext{
|
||||||
|
Root: docker.RootDir(),
|
||||||
|
Driver: dockerInfo.Driver,
|
||||||
|
DriverStatus: dockerInfo.DriverStatus,
|
||||||
|
},
|
||||||
|
RktPath: rktPath,
|
||||||
|
}
|
||||||
fsInfo, err := fs.NewFsInfo(context)
|
fsInfo, err := fs.NewFsInfo(context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -206,13 +219,21 @@ type manager struct {
|
|||||||
|
|
||||||
// Start the container manager.
|
// Start the container manager.
|
||||||
func (self *manager) Start() error {
|
func (self *manager) Start() error {
|
||||||
// Register Docker container factory.
|
|
||||||
err := docker.Register(self, self.fsInfo, self.ignoreMetrics)
|
err := docker.Register(self, self.fsInfo, self.ignoreMetrics)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Docker container factory registration failed: %v.", err)
|
glog.Errorf("Docker container factory registration failed: %v.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the raw driver.
|
err = rkt.Register(self, self.fsInfo, self.ignoreMetrics)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("Registration of the rkt container factory failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = systemd.Register(self, self.fsInfo, self.ignoreMetrics)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("Registration of the systemd container factory failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
err = raw.Register(self, self.fsInfo, self.ignoreMetrics)
|
err = raw.Register(self, self.fsInfo, self.ignoreMetrics)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("Registration of the raw container factory failed: %v", err)
|
glog.Errorf("Registration of the raw container factory failed: %v", err)
|
||||||
@@ -1150,59 +1171,32 @@ func (m *manager) DockerImages() ([]DockerImage, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *manager) DockerInfo() (DockerStatus, error) {
|
func (m *manager) DockerInfo() (DockerStatus, error) {
|
||||||
info, err := docker.DockerInfo()
|
return dockerInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
func dockerInfo() (DockerStatus, error) {
|
||||||
|
dockerInfo, err := docker.DockerInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DockerStatus{}, err
|
return DockerStatus{}, err
|
||||||
}
|
}
|
||||||
versionInfo, err := m.GetVersionInfo()
|
versionInfo, err := getVersionInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return DockerStatus{}, err
|
return DockerStatus{}, err
|
||||||
}
|
}
|
||||||
out := DockerStatus{}
|
out := DockerStatus{}
|
||||||
out.Version = versionInfo.DockerVersion
|
out.Version = versionInfo.DockerVersion
|
||||||
if val, ok := info["KernelVersion"]; ok {
|
out.KernelVersion = dockerInfo.KernelVersion
|
||||||
out.KernelVersion = val
|
out.OS = dockerInfo.OperatingSystem
|
||||||
}
|
out.Hostname = dockerInfo.Name
|
||||||
if val, ok := info["OperatingSystem"]; ok {
|
out.RootDir = dockerInfo.DockerRootDir
|
||||||
out.OS = val
|
out.Driver = dockerInfo.Driver
|
||||||
}
|
out.ExecDriver = dockerInfo.ExecutionDriver
|
||||||
if val, ok := info["Name"]; ok {
|
out.NumImages = dockerInfo.Images
|
||||||
out.Hostname = val
|
out.NumContainers = dockerInfo.Containers
|
||||||
}
|
out.DriverStatus = make(map[string]string, len(dockerInfo.DriverStatus))
|
||||||
if val, ok := info["DockerRootDir"]; ok {
|
for _, v := range dockerInfo.DriverStatus {
|
||||||
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.DriverStatus[v[0]] = v[1]
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
7
Godeps/_workspace/src/github.com/google/cadvisor/utils/cpuload/netlink/netlink.go
generated
vendored
7
Godeps/_workspace/src/github.com/google/cadvisor/utils/cpuload/netlink/netlink.go
generated
vendored
@@ -18,6 +18,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
info "github.com/google/cadvisor/info/v1"
|
info "github.com/google/cadvisor/info/v1"
|
||||||
@@ -219,10 +220,10 @@ func verifyHeader(msg syscall.NetlinkMessage) error {
|
|||||||
|
|
||||||
// Get load stats for a task group.
|
// Get load stats for a task group.
|
||||||
// id: family id for taskstats.
|
// id: family id for taskstats.
|
||||||
// fd: fd to path to the cgroup directory under cpu hierarchy.
|
// cfd: open file to path to the cgroup directory under cpu hierarchy.
|
||||||
// conn: open netlink connection used to communicate with kernel.
|
// conn: open netlink connection used to communicate with kernel.
|
||||||
func getLoadStats(id uint16, fd uintptr, conn *Connection) (info.LoadStats, error) {
|
func getLoadStats(id uint16, cfd *os.File, conn *Connection) (info.LoadStats, error) {
|
||||||
msg := prepareCmdMessage(id, fd)
|
msg := prepareCmdMessage(id, cfd.Fd())
|
||||||
err := conn.WriteMessage(msg.toRawMsg())
|
err := conn.WriteMessage(msg.toRawMsg())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return info.LoadStats{}, err
|
return info.LoadStats{}, err
|
||||||
|
3
Godeps/_workspace/src/github.com/google/cadvisor/utils/cpuload/netlink/reader.go
generated
vendored
3
Godeps/_workspace/src/github.com/google/cadvisor/utils/cpuload/netlink/reader.go
generated
vendored
@@ -66,11 +66,12 @@ func (self *NetlinkReader) GetCpuLoad(name string, path string) (info.LoadStats,
|
|||||||
}
|
}
|
||||||
|
|
||||||
cfd, err := os.Open(path)
|
cfd, err := os.Open(path)
|
||||||
|
defer cfd.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return info.LoadStats{}, fmt.Errorf("failed to open cgroup path %s: %q", path, err)
|
return info.LoadStats{}, fmt.Errorf("failed to open cgroup path %s: %q", path, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
stats, err := getLoadStats(self.familyId, cfd.Fd(), self.conn)
|
stats, err := getLoadStats(self.familyId, cfd, self.conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return info.LoadStats{}, err
|
return info.LoadStats{}, err
|
||||||
}
|
}
|
||||||
|
21
Godeps/_workspace/src/github.com/google/cadvisor/validate/validate.go
generated
vendored
21
Godeps/_workspace/src/github.com/google/cadvisor/validate/validate.go
generated
vendored
@@ -185,14 +185,12 @@ func validateCgroups() (string, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func validateDockerInfo() (string, string) {
|
func validateDockerInfo() (string, string) {
|
||||||
client, err := docker.Client()
|
info, err := docker.ValidateInfo()
|
||||||
if err == nil {
|
if err != nil {
|
||||||
info, err := client.Info()
|
return Unsupported, fmt.Sprintf("Docker setup is invalid: %v", err)
|
||||||
if err == nil {
|
}
|
||||||
execDriver := info.Get("ExecutionDriver")
|
|
||||||
storageDriver := info.Get("Driver")
|
desc := fmt.Sprintf("Docker exec driver is %s. Storage driver is %s.\n", info.ExecutionDriver, info.Driver)
|
||||||
desc := fmt.Sprintf("Docker exec driver is %s. Storage driver is %s.\n", execDriver, storageDriver)
|
|
||||||
if strings.Contains(execDriver, "native") {
|
|
||||||
stateFile := docker.DockerStateDir()
|
stateFile := docker.DockerStateDir()
|
||||||
if !utils.FileExists(stateFile) {
|
if !utils.FileExists(stateFile) {
|
||||||
desc += fmt.Sprintf("\tDocker container state directory %q is not accessible.\n", stateFile)
|
desc += fmt.Sprintf("\tDocker container state directory %q is not accessible.\n", stateFile)
|
||||||
@@ -200,13 +198,6 @@ func validateDockerInfo() (string, string) {
|
|||||||
}
|
}
|
||||||
desc += fmt.Sprintf("\tDocker container state directory is at %q and is accessible.\n", stateFile)
|
desc += fmt.Sprintf("\tDocker container state directory is at %q and is accessible.\n", stateFile)
|
||||||
return Recommended, desc
|
return Recommended, desc
|
||||||
} else if strings.Contains(execDriver, "lxc") {
|
|
||||||
return Supported, desc
|
|
||||||
}
|
|
||||||
return Unknown, desc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Unknown, "Docker remote API not reachable\n\t"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateCgroupMounts() (string, string) {
|
func validateCgroupMounts() (string, string) {
|
||||||
|
2
Godeps/_workspace/src/github.com/google/cadvisor/version/VERSION
generated
vendored
2
Godeps/_workspace/src/github.com/google/cadvisor/version/VERSION
generated
vendored
@@ -1 +1 @@
|
|||||||
0.22.0
|
0.23.0
|
||||||
|
Reference in New Issue
Block a user