Merge pull request #220 from vmarmol/coreos

Fix name resolution in Systemd systems
This commit is contained in:
Vish Kannan 2014-09-29 11:28:23 -07:00
commit 1ed9d122c1
3 changed files with 42 additions and 28 deletions

View File

@ -17,7 +17,6 @@ package docker
import ( import (
"flag" "flag"
"fmt" "fmt"
"path"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
@ -77,11 +76,12 @@ func (self *dockerFactory) CanHandle(name string) (bool, error) {
} else if !strings.HasPrefix(name, "/docker/") { } else if !strings.HasPrefix(name, "/docker/") {
return false, nil return false, nil
} }
// Check if the container is known to docker and it is active. // Check if the container is known to docker and it is active.
id := path.Base(name) id := containerNameToDockerId(name, self.useSystemd)
ctnr, err := self.client.InspectContainer(id)
// 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.
// TODO(vishh): Detect lxc containers and avoid handling them. ctnr, err := self.client.InspectContainer(id)
if err != nil || !ctnr.State.Running { if err != nil || !ctnr.State.Running {
return false, fmt.Errorf("error inspecting container: %v", err) return false, fmt.Errorf("error inspecting container: %v", err)
} }
@ -156,7 +156,6 @@ func Register(factory info.MachineInfoFactory) error {
if f.useSystemd { if f.useSystemd {
glog.Infof("System is using systemd") glog.Infof("System is using systemd")
} }
glog.Infof("Registering Docker factory")
container.RegisterContainerHandlerFactory(f) container.RegisterContainerHandlerFactory(f)
return nil return nil
} }

View File

@ -42,12 +42,12 @@ var fileNotFound = errors.New("file not found")
type dockerContainerHandler struct { type dockerContainerHandler struct {
client *docker.Client client *docker.Client
name string name string
parent string
id string id string
aliases []string aliases []string
machineInfoFactory info.MachineInfoFactory machineInfoFactory info.MachineInfoFactory
useSystemd bool useSystemd bool
libcontainerStateDir string libcontainerStateDir string
cgroup cgroups.Cgroup
} }
func newDockerContainerHandler( func newDockerContainerHandler(
@ -63,12 +63,15 @@ func newDockerContainerHandler(
machineInfoFactory: machineInfoFactory, machineInfoFactory: machineInfoFactory,
useSystemd: useSystemd, useSystemd: useSystemd,
libcontainerStateDir: path.Join(dockerRootDir, pathToLibcontainerState), libcontainerStateDir: path.Join(dockerRootDir, pathToLibcontainerState),
cgroup: cgroups.Cgroup{
Parent: "/",
Name: name,
},
} }
if handler.isDockerRoot() { if handler.isDockerRoot() {
return handler, nil return handler, nil
} }
id := path.Base(name) id := containerNameToDockerId(name, useSystemd)
handler.parent = path.Dir(name)
handler.id = id handler.id = id
ctnr, err := client.InspectContainer(id) ctnr, err := client.InspectContainer(id)
// 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.
@ -79,6 +82,25 @@ func newDockerContainerHandler(
return handler, nil 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) { func (self *dockerContainerHandler) ContainerReference() (info.ContainerReference, error) {
return info.ContainerReference{ return info.ContainerReference{
Name: self.name, Name: self.name,
@ -112,8 +134,7 @@ func (self *dockerContainerHandler) readLibcontainerConfig() (config *libcontain
config = retConfig config = retConfig
// Replace cgroup parent and name with our own since we may be running in a different context. // Replace cgroup parent and name with our own since we may be running in a different context.
config.Cgroups.Parent = self.parent *config.Cgroups = self.cgroup
config.Cgroups.Name = self.id
return return
} }
@ -199,14 +220,6 @@ func (self *dockerContainerHandler) GetStats() (stats *info.ContainerStats, err
if self.isDockerRoot() { if self.isDockerRoot() {
return &info.ContainerStats{}, nil 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() state, err := self.readLibcontainerState()
if err != nil { if err != nil {
if err == fileNotFound { if err == fileNotFound {
@ -216,7 +229,7 @@ func (self *dockerContainerHandler) GetStats() (stats *info.ContainerStats, err
return return
} }
return containerLibcontainer.GetStats(config, state) return containerLibcontainer.GetStats(&self.cgroup, state)
} }
func (self *dockerContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) { 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) { func (self *dockerContainerHandler) ListProcesses(listType container.ListType) ([]int, error) {
c := &cgroups.Cgroup{ return fs.GetPids(&self.cgroup)
Parent: self.parent,
Name: self.id,
}
return fs.GetPids(c)
} }
func (self *dockerContainerHandler) WatchSubcontainers(events chan container.SubcontainerEvent) error { func (self *dockerContainerHandler) WatchSubcontainers(events chan container.SubcontainerEvent) error {

View File

@ -20,17 +20,23 @@ import (
"github.com/docker/libcontainer" "github.com/docker/libcontainer"
"github.com/docker/libcontainer/cgroups" "github.com/docker/libcontainer/cgroups"
cgroupfs "github.com/docker/libcontainer/cgroups/fs" cgroupfs "github.com/docker/libcontainer/cgroups/fs"
"github.com/docker/libcontainer/network"
"github.com/google/cadvisor/info" "github.com/google/cadvisor/info"
) )
// Get stats of the specified container // 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. // 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 { 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) { func GetStatsCgroupOnly(cgroup *cgroups.Cgroup) (*info.ContainerStats, error) {