Merge pull request #93 from vmarmol/systemd

Initial version of the raw container driver.
This commit is contained in:
monnand 2014-07-17 14:30:46 -04:00
commit d1dc27bf43
5 changed files with 183 additions and 56 deletions

View File

@ -34,7 +34,7 @@ type dockerFactory struct {
machineInfoFactory info.MachineInfoFactory
// Whether this system is using systemd.
hasSystemd bool
useSystemd bool
}
func (self *dockerFactory) String() string {
@ -50,6 +50,7 @@ func (self *dockerFactory) NewContainerHandler(name string) (handler container.C
client,
name,
self.machineInfoFactory,
self.useSystemd,
)
return
}
@ -57,7 +58,7 @@ func (self *dockerFactory) NewContainerHandler(name string) (handler container.C
// Docker handles all containers under /docker
func (self *dockerFactory) CanHandle(name string) bool {
// In systemd systems the containers are: /docker-{ID}
if self.hasSystemd {
if self.useSystemd {
return strings.HasPrefix(name, "/docker-")
}
return name == "/docker" || strings.HasPrefix(name, "/docker/")
@ -107,7 +108,7 @@ func Register(factory info.MachineInfoFactory) error {
}
f := &dockerFactory{
machineInfoFactory: factory,
hasSystemd: systemd.UseSystemd(),
useSystemd: systemd.UseSystemd(),
}
log.Printf("Registering Docker factory")
container.RegisterContainerHandlerFactory(f)

View File

@ -27,10 +27,9 @@ import (
"github.com/docker/libcontainer"
"github.com/docker/libcontainer/cgroups"
"github.com/docker/libcontainer/cgroups/fs"
"github.com/docker/libcontainer/cgroups/systemd"
"github.com/fsouza/go-dockerclient"
"github.com/google/cadvisor/container"
containerLibcontainer "github.com/google/cadvisor/container/libcontainer"
"github.com/google/cadvisor/info"
)
@ -39,17 +38,20 @@ type dockerContainerHandler struct {
name string
aliases []string
machineInfoFactory info.MachineInfoFactory
useSystemd bool
}
func newDockerContainerHandler(
client *docker.Client,
name string,
machineInfoFactory info.MachineInfoFactory,
useSystemd bool,
) (container.ContainerHandler, error) {
handler := &dockerContainerHandler{
client: client,
name: name,
machineInfoFactory: machineInfoFactory,
useSystemd: useSystemd,
}
if !handler.isDockerContainer() {
return handler, nil
@ -190,39 +192,6 @@ func (self *dockerContainerHandler) GetSpec() (spec *info.ContainerSpec, err err
return
}
func libcontainerToContainerStats(s *cgroups.Stats, mi *info.MachineInfo) *info.ContainerStats {
ret := new(info.ContainerStats)
ret.Timestamp = time.Now()
ret.Cpu = new(info.CpuStats)
ret.Cpu.Usage.User = s.CpuStats.CpuUsage.UsageInUsermode
ret.Cpu.Usage.System = s.CpuStats.CpuUsage.UsageInKernelmode
n := len(s.CpuStats.CpuUsage.PercpuUsage)
ret.Cpu.Usage.PerCpu = make([]uint64, n)
ret.Cpu.Usage.Total = 0
for i := 0; i < n; i++ {
ret.Cpu.Usage.PerCpu[i] = s.CpuStats.CpuUsage.PercpuUsage[i]
ret.Cpu.Usage.Total += s.CpuStats.CpuUsage.PercpuUsage[i]
}
ret.Memory = new(info.MemoryStats)
ret.Memory.Usage = s.MemoryStats.Usage
if v, ok := s.MemoryStats.Stats["pgfault"]; ok {
ret.Memory.ContainerData.Pgfault = v
ret.Memory.HierarchicalData.Pgfault = v
}
if v, ok := s.MemoryStats.Stats["pgmajfault"]; ok {
ret.Memory.ContainerData.Pgmajfault = v
ret.Memory.HierarchicalData.Pgmajfault = v
}
if v, ok := s.MemoryStats.Stats["total_inactive_anon"]; ok {
ret.Memory.WorkingSet = ret.Memory.Usage - v
if v, ok := s.MemoryStats.Stats["total_active_file"]; ok {
ret.Memory.WorkingSet -= v
}
}
return ret
}
func (self *dockerContainerHandler) GetStats() (stats *info.ContainerStats, err error) {
if !self.isDockerContainer() {
// Return empty stats for root containers.
@ -230,10 +199,6 @@ func (self *dockerContainerHandler) GetStats() (stats *info.ContainerStats, err
stats.Timestamp = time.Now()
return
}
mi, err := self.machineInfoFactory.GetMachineInfo()
if err != nil {
return
}
parent, id, err := self.splitName()
if err != nil {
return
@ -242,20 +207,7 @@ func (self *dockerContainerHandler) GetStats() (stats *info.ContainerStats, err
Parent: parent,
Name: id,
}
// TODO(vmarmol): Use libcontainer's Stats() in the new API when that is ready.
// Use systemd paths if systemd is being used.
var s *cgroups.Stats
if systemd.UseSystemd() {
s, err = systemd.GetStats(cg)
} else {
s, err = fs.GetStats(cg)
}
if err != nil {
return
}
stats = libcontainerToContainerStats(s, mi)
return
return containerLibcontainer.GetStats(cg, self.useSystemd)
}
func (self *dockerContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) {

View File

@ -0,0 +1,63 @@
package libcontainer
import (
"time"
"github.com/docker/libcontainer/cgroups"
"github.com/docker/libcontainer/cgroups/fs"
"github.com/docker/libcontainer/cgroups/systemd"
"github.com/google/cadvisor/info"
)
// Get stats of the specified cgroup
func GetStats(cgroup *cgroups.Cgroup, useSystemd bool) (*info.ContainerStats, error) {
// TODO(vmarmol): Use libcontainer's Stats() in the new API when that is ready.
// Use systemd paths if systemd is being used.
var (
s *cgroups.Stats
err error
)
if useSystemd {
s, err = systemd.GetStats(cgroup)
} else {
s, err = fs.GetStats(cgroup)
}
if err != nil {
return nil, err
}
return toContainerStats(s), nil
}
// Convert libcontainer stats to info.ContainerStats.
func toContainerStats(s *cgroups.Stats) *info.ContainerStats {
ret := new(info.ContainerStats)
ret.Timestamp = time.Now()
ret.Cpu = new(info.CpuStats)
ret.Cpu.Usage.User = s.CpuStats.CpuUsage.UsageInUsermode
ret.Cpu.Usage.System = s.CpuStats.CpuUsage.UsageInKernelmode
n := len(s.CpuStats.CpuUsage.PercpuUsage)
ret.Cpu.Usage.PerCpu = make([]uint64, n)
ret.Cpu.Usage.Total = 0
for i := 0; i < n; i++ {
ret.Cpu.Usage.PerCpu[i] = s.CpuStats.CpuUsage.PercpuUsage[i]
ret.Cpu.Usage.Total += s.CpuStats.CpuUsage.PercpuUsage[i]
}
ret.Memory = new(info.MemoryStats)
ret.Memory.Usage = s.MemoryStats.Usage
if v, ok := s.MemoryStats.Stats["pgfault"]; ok {
ret.Memory.ContainerData.Pgfault = v
ret.Memory.HierarchicalData.Pgfault = v
}
if v, ok := s.MemoryStats.Stats["pgmajfault"]; ok {
ret.Memory.ContainerData.Pgmajfault = v
ret.Memory.HierarchicalData.Pgmajfault = v
}
if v, ok := s.MemoryStats.Stats["total_inactive_anon"]; ok {
ret.Memory.WorkingSet = ret.Memory.Usage - v
if v, ok := s.MemoryStats.Stats["total_active_file"]; ok {
ret.Memory.WorkingSet -= v
}
}
return ret
}

43
container/raw/factory.go Normal file
View File

@ -0,0 +1,43 @@
// Copyright 2014 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 raw
import (
"log"
"github.com/google/cadvisor/container"
)
type rawFactory struct {
}
func (self *rawFactory) String() string {
return "raw"
}
func (self *rawFactory) NewContainerHandler(name string) (container.ContainerHandler, error) {
return newRawContainerHandler(name)
}
// The raw factory can handle any container.
func (self *rawFactory) CanHandle(name string) bool {
return true
}
func Register() error {
log.Printf("Registering Raw factory")
container.RegisterContainerHandlerFactory(new(rawFactory))
return nil
}

68
container/raw/handler.go Normal file
View File

@ -0,0 +1,68 @@
// Copyright 2014 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 raw
import (
"github.com/docker/libcontainer/cgroups"
"github.com/google/cadvisor/container"
"github.com/google/cadvisor/container/libcontainer"
"github.com/google/cadvisor/info"
)
type rawContainerHandler struct {
name string
}
func newRawContainerHandler(name string) (container.ContainerHandler, error) {
return &rawContainerHandler{
name: name,
}, nil
}
func (self *rawContainerHandler) ContainerReference() (info.ContainerReference, error) {
// We only know the container by its one name.
return info.ContainerReference{
Name: self.name,
}, nil
}
func (self *rawContainerHandler) GetSpec() (*info.ContainerSpec, error) {
// TODO(vmarmol): Implement
return new(info.ContainerSpec), nil
}
func (self *rawContainerHandler) GetStats() (stats *info.ContainerStats, err error) {
cgroup := &cgroups.Cgroup{
Parent: "/",
Name: self.name,
}
return libcontainer.GetStats(cgroup, false)
}
func (self *rawContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) {
// TODO(vmarmol): Implement
return make([]info.ContainerReference, 0, 0), nil
}
func (self *rawContainerHandler) ListThreads(listType container.ListType) ([]int, error) {
// TODO(vmarmol): Implement
return nil, nil
}
func (self *rawContainerHandler) ListProcesses(listType container.ListType) ([]int, error) {
// TODO(vmarmol): Implement
return nil, nil
}