From ebf231e4df6ec7e14817da60f5f3670f8cb1f843 Mon Sep 17 00:00:00 2001 From: Victor Marmol Date: Fri, 5 Sep 2014 16:35:39 -0700 Subject: [PATCH] Fix name resolution in Systemd systems --- container/docker/factory.go | 9 +++--- container/docker/handler.go | 47 ++++++++++++++++++------------- container/libcontainer/helpers.go | 14 ++++++--- 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/container/docker/factory.go b/container/docker/factory.go index 6b7271e6..e4d02d72 100644 --- a/container/docker/factory.go +++ b/container/docker/factory.go @@ -17,7 +17,6 @@ package docker import ( "flag" "fmt" - "path" "regexp" "strconv" "strings" @@ -78,11 +77,12 @@ func (self *dockerFactory) CanHandle(name string) bool { } else if !strings.HasPrefix(name, "/docker/") { return false } + // Check if the container is known to docker and it is active. - id := path.Base(name) - ctnr, err := self.client.InspectContainer(id) + id := containerNameToDockerId(name, self.useSystemd) + // We assume that if Inspect fails then the container is not known to docker. - // TODO(vishh): Detect lxc containers and avoid handling them. + ctnr, err := self.client.InspectContainer(id) if err != nil || !ctnr.State.Running { return false } @@ -157,7 +157,6 @@ func Register(factory info.MachineInfoFactory) error { if f.useSystemd { glog.Infof("System is using systemd") } - glog.Infof("Registering Docker factory") container.RegisterContainerHandlerFactory(f) return nil } diff --git a/container/docker/handler.go b/container/docker/handler.go index d1be0862..958e0080 100644 --- a/container/docker/handler.go +++ b/container/docker/handler.go @@ -42,12 +42,12 @@ var fileNotFound = errors.New("file not found") type dockerContainerHandler struct { client *docker.Client name string - parent string id string aliases []string machineInfoFactory info.MachineInfoFactory useSystemd bool libcontainerStateDir string + cgroup cgroups.Cgroup } func newDockerContainerHandler( @@ -63,12 +63,15 @@ func newDockerContainerHandler( machineInfoFactory: machineInfoFactory, useSystemd: useSystemd, libcontainerStateDir: path.Join(dockerRootDir, pathToLibcontainerState), + cgroup: cgroups.Cgroup{ + Parent: "/", + Name: name, + }, } if handler.isDockerRoot() { return handler, nil } - id := path.Base(name) - handler.parent = path.Dir(name) + id := containerNameToDockerId(name, useSystemd) handler.id = id ctnr, err := client.InspectContainer(id) // We assume that if Inspect fails then the container is not known to docker. @@ -79,6 +82,25 @@ func newDockerContainerHandler( return handler, nil } +func containerNameToDockerId(name string, useSystemd bool) string { + id := path.Base(name) + + // Turn systemd cgroup name into Docker ID. + if useSystemd { + const systemdDockerPrefix = "docker-" + if strings.HasPrefix(id, systemdDockerPrefix) { + id = id[len(systemdDockerPrefix):] + } + + const systemdScopeSuffix = ".scope" + if strings.HasSuffix(id, systemdScopeSuffix) { + id = id[:len(id)-len(systemdScopeSuffix)] + } + } + + return id +} + func (self *dockerContainerHandler) ContainerReference() (info.ContainerReference, error) { return info.ContainerReference{ Name: self.name, @@ -112,8 +134,7 @@ func (self *dockerContainerHandler) readLibcontainerConfig() (config *libcontain config = retConfig // Replace cgroup parent and name with our own since we may be running in a different context. - config.Cgroups.Parent = self.parent - config.Cgroups.Name = self.id + *config.Cgroups = self.cgroup return } @@ -199,14 +220,6 @@ func (self *dockerContainerHandler) GetStats() (stats *info.ContainerStats, err if self.isDockerRoot() { return &info.ContainerStats{}, nil } - config, err := self.readLibcontainerConfig() - if err != nil { - if err == fileNotFound { - glog.Errorf("Libcontainer config not found for container %q", self.name) - return &info.ContainerStats{}, nil - } - return - } state, err := self.readLibcontainerState() if err != nil { if err == fileNotFound { @@ -216,7 +229,7 @@ func (self *dockerContainerHandler) GetStats() (stats *info.ContainerStats, err return } - return containerLibcontainer.GetStats(config, state) + return containerLibcontainer.GetStats(&self.cgroup, state) } func (self *dockerContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) { @@ -258,11 +271,7 @@ func (self *dockerContainerHandler) ListThreads(listType container.ListType) ([] } func (self *dockerContainerHandler) ListProcesses(listType container.ListType) ([]int, error) { - c := &cgroups.Cgroup{ - Parent: self.parent, - Name: self.id, - } - return fs.GetPids(c) + return fs.GetPids(&self.cgroup) } func (self *dockerContainerHandler) WatchSubcontainers(events chan container.SubcontainerEvent) error { diff --git a/container/libcontainer/helpers.go b/container/libcontainer/helpers.go index 6fd47a44..25fa6e61 100644 --- a/container/libcontainer/helpers.go +++ b/container/libcontainer/helpers.go @@ -20,17 +20,23 @@ import ( "github.com/docker/libcontainer" "github.com/docker/libcontainer/cgroups" cgroupfs "github.com/docker/libcontainer/cgroups/fs" + "github.com/docker/libcontainer/network" "github.com/google/cadvisor/info" ) // Get stats of the specified container -func GetStats(config *libcontainer.Config, state *libcontainer.State) (*info.ContainerStats, error) { +func GetStats(cgroup *cgroups.Cgroup, state *libcontainer.State) (*info.ContainerStats, error) { // TODO(vmarmol): Use libcontainer's Stats() in the new API when that is ready. - libcontainerStats, err := libcontainer.GetStats(config, state) + stats := &libcontainer.ContainerStats{} + + var err error + stats.CgroupStats, err = cgroupfs.GetStats(cgroup) if err != nil { - return nil, err + return &info.ContainerStats{}, err } - return toContainerStats(libcontainerStats), nil + + stats.NetworkStats, err = network.GetStats(&state.NetworkState) + return toContainerStats(stats), nil } func GetStatsCgroupOnly(cgroup *cgroups.Cgroup) (*info.ContainerStats, error) {