Skip to content

Commit

Permalink
Merge pull request openshift#87 from crosbymichael/systemd-stats
Browse files Browse the repository at this point in the history
Add cgroup status for systemd implementation
  • Loading branch information
vmarmol committed Jul 11, 2014
2 parents b3f798f + 7e1cfc1 commit 8c0303d
Show file tree
Hide file tree
Showing 15 changed files with 178 additions and 126 deletions.
24 changes: 15 additions & 9 deletions api_temp.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,30 @@ package libcontainer

import (
"github.com/docker/libcontainer/cgroups/fs"
"github.com/docker/libcontainer/cgroups/systemd"
"github.com/docker/libcontainer/network"
)

// TODO(vmarmol): Complete Stats() in final libcontainer API and move users to that.
// DEPRECATED: The below portions are only to be used during the transition to the official API.
// Returns all available stats for the given container.
func GetStats(container *Config, state *State) (*ContainerStats, error) {
var containerStats ContainerStats
stats, err := fs.GetStats(container.Cgroups)
if err != nil {
return &containerStats, err
var (
err error
stats = &ContainerStats{}
)

if systemd.UseSystemd() {
stats.CgroupStats, err = systemd.GetStats(container.Cgroups)
} else {
stats.CgroupStats, err = fs.GetStats(container.Cgroups)
}
containerStats.CgroupStats = stats
networkStats, err := network.GetStats(&state.NetworkState)

if err != nil {
return &containerStats, err
return stats, err
}
containerStats.NetworkStats = networkStats

return &containerStats, nil
stats.NetworkStats, err = network.GetStats(&state.NetworkState)

return stats, err
}
35 changes: 22 additions & 13 deletions cgroups/fs/apply_raw.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,21 @@ import (

var (
subsystems = map[string]subsystem{
"devices": &devicesGroup{},
"memory": &memoryGroup{},
"cpu": &cpuGroup{},
"cpuset": &cpusetGroup{},
"cpuacct": &cpuacctGroup{},
"blkio": &blkioGroup{},
"perf_event": &perfEventGroup{},
"freezer": &freezerGroup{},
"devices": &DevicesGroup{},
"memory": &MemoryGroup{},
"cpu": &CpuGroup{},
"cpuset": &CpusetGroup{},
"cpuacct": &CpuacctGroup{},
"blkio": &BlkioGroup{},
"perf_event": &PerfEventGroup{},
"freezer": &FreezerGroup{},
}
)

type subsystem interface {
Set(*data) error
Remove(*data) error
GetStats(*data, *cgroups.Stats) error
GetStats(string, *cgroups.Stats) error
}

type data struct {
Expand Down Expand Up @@ -68,10 +68,19 @@ func GetStats(c *cgroups.Cgroup) (*cgroups.Stats, error) {
return nil, fmt.Errorf("getting CgroupData %s", err)
}

for sysName, sys := range subsystems {
// Don't fail if a cgroup hierarchy was not found.
if err := sys.GetStats(d, stats); err != nil && err != cgroups.ErrNotFound {
return nil, fmt.Errorf("getting stats for system %q %s", sysName, err)
for sysname, sys := range subsystems {
path, err := d.path(sysname)
if err != nil {
// Don't fail if a cgroup hierarchy was not found, just skip this subsystem
if err == cgroups.ErrNotFound {
continue
}

return nil, err
}

if err := sys.GetStats(path, stats); err != nil {
return nil, err
}
}

Expand Down
12 changes: 4 additions & 8 deletions cgroups/fs/blkio.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@ import (
"github.com/docker/libcontainer/cgroups"
)

type blkioGroup struct {
type BlkioGroup struct {
}

func (s *blkioGroup) Set(d *data) error {
func (s *BlkioGroup) Set(d *data) error {
// we just want to join this group even though we don't set anything
if _, err := d.join("blkio"); err != nil && err != cgroups.ErrNotFound {
return err
}
return nil
}

func (s *blkioGroup) Remove(d *data) error {
func (s *BlkioGroup) Remove(d *data) error {
return removePath(d.path("blkio"))
}

Expand Down Expand Up @@ -113,13 +113,9 @@ func getBlkioStat(path string) ([]cgroups.BlkioStatEntry, error) {
return blkioStats, nil
}

func (s *blkioGroup) GetStats(d *data, stats *cgroups.Stats) error {
func (s *BlkioGroup) GetStats(path string, stats *cgroups.Stats) error {
var blkioStats []cgroups.BlkioStatEntry
var err error
path, err := d.path("blkio")
if err != nil {
return err
}

if blkioStats, err = getBlkioStat(filepath.Join(path, "blkio.sectors_recursive")); err != nil {
return err
Expand Down
28 changes: 14 additions & 14 deletions cgroups/fs/blkio_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ func TestBlkioStats(t *testing.T) {
"blkio.sectors_recursive": sectorsRecursiveContents,
})

blkio := &blkioGroup{}
err := blkio.GetStats(helper.CgroupData, &actualStats)
blkio := &BlkioGroup{}
err := blkio.GetStats(helper.CgroupPath, &actualStats)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -84,8 +84,8 @@ func TestBlkioStatsNoSectorsFile(t *testing.T) {
"blkio.io_queued_recursive": queuedRecursiveContents,
})

blkio := &blkioGroup{}
err := blkio.GetStats(helper.CgroupData, &actualStats)
blkio := &BlkioGroup{}
err := blkio.GetStats(helper.CgroupPath, &actualStats)
if err != nil {
t.Fatalf("Failed unexpectedly: %s", err)
}
Expand All @@ -100,8 +100,8 @@ func TestBlkioStatsNoServiceBytesFile(t *testing.T) {
"blkio.sectors_recursive": sectorsRecursiveContents,
})

blkio := &blkioGroup{}
err := blkio.GetStats(helper.CgroupData, &actualStats)
blkio := &BlkioGroup{}
err := blkio.GetStats(helper.CgroupPath, &actualStats)
if err != nil {
t.Fatalf("Failed unexpectedly: %s", err)
}
Expand All @@ -116,8 +116,8 @@ func TestBlkioStatsNoServicedFile(t *testing.T) {
"blkio.sectors_recursive": sectorsRecursiveContents,
})

blkio := &blkioGroup{}
err := blkio.GetStats(helper.CgroupData, &actualStats)
blkio := &BlkioGroup{}
err := blkio.GetStats(helper.CgroupPath, &actualStats)
if err != nil {
t.Fatalf("Failed unexpectedly: %s", err)
}
Expand All @@ -132,8 +132,8 @@ func TestBlkioStatsNoQueuedFile(t *testing.T) {
"blkio.sectors_recursive": sectorsRecursiveContents,
})

blkio := &blkioGroup{}
err := blkio.GetStats(helper.CgroupData, &actualStats)
blkio := &BlkioGroup{}
err := blkio.GetStats(helper.CgroupPath, &actualStats)
if err != nil {
t.Fatalf("Failed unexpectedly: %s", err)
}
Expand All @@ -149,8 +149,8 @@ func TestBlkioStatsUnexpectedNumberOfFields(t *testing.T) {
"blkio.sectors_recursive": sectorsRecursiveContents,
})

blkio := &blkioGroup{}
err := blkio.GetStats(helper.CgroupData, &actualStats)
blkio := &BlkioGroup{}
err := blkio.GetStats(helper.CgroupPath, &actualStats)
if err == nil {
t.Fatal("Expected to fail, but did not")
}
Expand All @@ -166,8 +166,8 @@ func TestBlkioStatsUnexpectedFieldType(t *testing.T) {
"blkio.sectors_recursive": sectorsRecursiveContents,
})

blkio := &blkioGroup{}
err := blkio.GetStats(helper.CgroupData, &actualStats)
blkio := &BlkioGroup{}
err := blkio.GetStats(helper.CgroupPath, &actualStats)
if err == nil {
t.Fatal("Expected to fail, but did not")
}
Expand Down
13 changes: 4 additions & 9 deletions cgroups/fs/cpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import (
"github.com/docker/libcontainer/cgroups"
)

type cpuGroup struct {
type CpuGroup struct {
}

func (s *cpuGroup) Set(d *data) error {
func (s *CpuGroup) Set(d *data) error {
// We always want to join the cpu group, to allow fair cpu scheduling
// on a container basis
dir, err := d.join("cpu")
Expand All @@ -37,16 +37,11 @@ func (s *cpuGroup) Set(d *data) error {
return nil
}

func (s *cpuGroup) Remove(d *data) error {
func (s *CpuGroup) Remove(d *data) error {
return removePath(d.path("cpu"))
}

func (s *cpuGroup) GetStats(d *data, stats *cgroups.Stats) error {
path, err := d.path("cpu")
if err != nil {
return err
}

func (s *CpuGroup) GetStats(path string, stats *cgroups.Stats) error {
f, err := os.Open(filepath.Join(path, "cpu.stat"))
if err != nil {
if os.IsNotExist(err) {
Expand Down
12 changes: 6 additions & 6 deletions cgroups/fs/cpu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ func TestCpuStats(t *testing.T) {
"cpu.stat": cpuStatContent,
})

cpu := &cpuGroup{}
err := cpu.GetStats(helper.CgroupData, &actualStats)
cpu := &CpuGroup{}
err := cpu.GetStats(helper.CgroupPath, &actualStats)
if err != nil {
t.Fatal(err)
}
Expand All @@ -41,8 +41,8 @@ func TestNoCpuStatFile(t *testing.T) {
helper := NewCgroupTestUtil("cpu", t)
defer helper.cleanup()

cpu := &cpuGroup{}
err := cpu.GetStats(helper.CgroupData, &actualStats)
cpu := &CpuGroup{}
err := cpu.GetStats(helper.CgroupPath, &actualStats)
if err != nil {
t.Fatal("Expected not to fail, but did")
}
Expand All @@ -58,8 +58,8 @@ func TestInvalidCpuStat(t *testing.T) {
"cpu.stat": cpuStatContent,
})

cpu := &cpuGroup{}
err := cpu.GetStats(helper.CgroupData, &actualStats)
cpu := &CpuGroup{}
err := cpu.GetStats(helper.CgroupPath, &actualStats)
if err == nil {
t.Fatal("Expected failed stat parsing.")
}
Expand Down
26 changes: 13 additions & 13 deletions cgroups/fs/cpuacct.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,31 @@ var (

const nanosecondsInSecond = 1000000000

type cpuacctGroup struct {
type CpuacctGroup struct {
}

func (s *cpuacctGroup) Set(d *data) error {
func (s *CpuacctGroup) Set(d *data) error {
// we just want to join this group even though we don't set anything
if _, err := d.join("cpuacct"); err != nil && err != cgroups.ErrNotFound {
return err
}
return nil
}

func (s *cpuacctGroup) Remove(d *data) error {
func (s *CpuacctGroup) Remove(d *data) error {
return removePath(d.path("cpuacct"))
}

func (s *cpuacctGroup) GetStats(d *data, stats *cgroups.Stats) error {
func (s *CpuacctGroup) GetStats(path string, stats *cgroups.Stats) error {
var (
err error
startCpu, lastCpu, startSystem, lastSystem, startUsage, lastUsage, kernelModeUsage, userModeUsage, percentage uint64
)
path, err := d.path("cpuacct")
if kernelModeUsage, userModeUsage, err = s.getCpuUsage(d, path); err != nil {
if kernelModeUsage, userModeUsage, err = getCpuUsage(path); err != nil {
return err
}
startCpu = kernelModeUsage + userModeUsage
if startSystem, err = s.getSystemCpuUsage(d); err != nil {
if startSystem, err = getSystemCpuUsage(); err != nil {
return err
}
startUsageTime := time.Now()
Expand All @@ -55,11 +55,11 @@ func (s *cpuacctGroup) GetStats(d *data, stats *cgroups.Stats) error {
}
// sample for 100ms
time.Sleep(100 * time.Millisecond)
if kernelModeUsage, userModeUsage, err = s.getCpuUsage(d, path); err != nil {
if kernelModeUsage, userModeUsage, err = getCpuUsage(path); err != nil {
return err
}
lastCpu = kernelModeUsage + userModeUsage
if lastSystem, err = s.getSystemCpuUsage(d); err != nil {
if lastSystem, err = getSystemCpuUsage(); err != nil {
return err
}
usageSampleDuration := time.Since(startUsageTime)
Expand All @@ -80,7 +80,7 @@ func (s *cpuacctGroup) GetStats(d *data, stats *cgroups.Stats) error {
stats.CpuStats.CpuUsage.PercentUsage = percentage
// Delta usage is in nanoseconds of CPU time so get the usage (in cores) over the sample time.
stats.CpuStats.CpuUsage.CurrentUsage = deltaUsage / uint64(usageSampleDuration.Nanoseconds())
percpuUsage, err := s.getPercpuUsage(path)
percpuUsage, err := getPercpuUsage(path)
if err != nil {
return err
}
Expand All @@ -92,7 +92,7 @@ func (s *cpuacctGroup) GetStats(d *data, stats *cgroups.Stats) error {
}

// TODO(vmarmol): Use cgroups stats.
func (s *cpuacctGroup) getSystemCpuUsage(d *data) (uint64, error) {
func getSystemCpuUsage() (uint64, error) {

f, err := os.Open("/proc/stat")
if err != nil {
Expand Down Expand Up @@ -125,7 +125,7 @@ func (s *cpuacctGroup) getSystemCpuUsage(d *data) (uint64, error) {
return 0, fmt.Errorf("invalid stat format")
}

func (s *cpuacctGroup) getCpuUsage(d *data, path string) (uint64, uint64, error) {
func getCpuUsage(path string) (uint64, uint64, error) {
kernelModeUsage := uint64(0)
userModeUsage := uint64(0)
data, err := ioutil.ReadFile(filepath.Join(path, "cpuacct.stat"))
Expand All @@ -146,7 +146,7 @@ func (s *cpuacctGroup) getCpuUsage(d *data, path string) (uint64, uint64, error)
return kernelModeUsage, userModeUsage, nil
}

func (s *cpuacctGroup) getPercpuUsage(path string) ([]uint64, error) {
func getPercpuUsage(path string) ([]uint64, error) {
percpuUsage := []uint64{}
data, err := ioutil.ReadFile(filepath.Join(path, "cpuacct.usage_percpu"))
if err != nil {
Expand Down

0 comments on commit 8c0303d

Please sign in to comment.