Merge pull request #93 from vmarmol/systemd
Initial version of the raw container driver.
This commit is contained in:
commit
d1dc27bf43
@ -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)
|
||||
|
@ -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) {
|
||||
|
63
container/libcontainer/helpers.go
Normal file
63
container/libcontainer/helpers.go
Normal 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
43
container/raw/factory.go
Normal 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
68
container/raw/handler.go
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user