lib: libcontainer references are linux only
Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
This commit is contained in:
parent
cdc468afa8
commit
ef6aa87c75
|
@ -17,7 +17,6 @@ import (
|
|||
"github.com/kubernetes-incubator/cri-o/pkg/annotations"
|
||||
"github.com/kubernetes-incubator/cri-o/pkg/registrar"
|
||||
"github.com/kubernetes-incubator/cri-o/pkg/storage"
|
||||
"github.com/opencontainers/runc/libcontainer"
|
||||
rspec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/opencontainers/selinux/go-selinux/label"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -771,20 +770,3 @@ func (c *ContainerServer) RemoveSandbox(id string) {
|
|||
func (c *ContainerServer) ListSandboxes() []*sandbox.Sandbox {
|
||||
return c.state.sandboxes.List()
|
||||
}
|
||||
|
||||
// LibcontainerStats gets the stats for the container with the given id from runc/libcontainer
|
||||
func (c *ContainerServer) LibcontainerStats(ctr *oci.Container) (*libcontainer.Stats, error) {
|
||||
// TODO: make this not hardcoded
|
||||
// was: c.runtime.Path(ociContainer) but that returns /usr/bin/runc - how do we get /run/runc?
|
||||
// runroot is /var/run/runc
|
||||
// Hardcoding probably breaks ClearContainers compatibility
|
||||
factory, err := loadFactory("/run/runc")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
container, err := factory.Load(ctr.ID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return container.Stats()
|
||||
}
|
||||
|
|
|
@ -3,11 +3,33 @@
|
|||
package lib
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/kubernetes-incubator/cri-o/lib/sandbox"
|
||||
"github.com/kubernetes-incubator/cri-o/oci"
|
||||
"github.com/opencontainers/runc/libcontainer"
|
||||
selinux "github.com/opencontainers/selinux/go-selinux"
|
||||
"github.com/opencontainers/selinux/go-selinux/label"
|
||||
)
|
||||
|
||||
// libcontainerStats gets the stats for the container with the given id from runc/libcontainer
|
||||
func (c *ContainerServer) libcontainerStats(ctr *oci.Container) (*libcontainer.Stats, error) {
|
||||
// TODO: make this not hardcoded
|
||||
// was: c.runtime.Path(ociContainer) but that returns /usr/bin/runc - how do we get /run/runc?
|
||||
// runroot is /var/run/runc
|
||||
// Hardcoding probably breaks ClearContainers compatibility
|
||||
factory, err := loadFactory("/run/runc")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
container, err := factory.Load(ctr.ID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return container.Stats()
|
||||
}
|
||||
|
||||
func (c *ContainerServer) addSandboxPlatform(sb *sandbox.Sandbox) {
|
||||
c.state.processLevels[selinux.NewContext(sb.ProcessLabel())["level"]]++
|
||||
}
|
||||
|
@ -24,3 +46,35 @@ func (c *ContainerServer) removeSandboxPlatform(sb *sandbox.Sandbox) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func loadFactory(root string) (libcontainer.Factory, error) {
|
||||
abs, err := filepath.Abs(root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cgroupManager := libcontainer.Cgroupfs
|
||||
return libcontainer.New(abs, cgroupManager, libcontainer.CriuPath(""))
|
||||
}
|
||||
|
||||
func (c *ContainerServer) getContainerStats(ctr *oci.Container, previousStats *ContainerStats) (*ContainerStats, error) {
|
||||
previousCPU := previousStats.CPUNano
|
||||
previousSystem := previousStats.SystemNano
|
||||
libcontainerStats, err := c.libcontainerStats(ctr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cgroupStats := libcontainerStats.CgroupStats
|
||||
stats := new(ContainerStats)
|
||||
stats.Container = ctr.ID()
|
||||
stats.CPUNano = cgroupStats.CpuStats.CpuUsage.TotalUsage
|
||||
stats.SystemNano = time.Now().UnixNano()
|
||||
stats.CPU = calculateCPUPercent(libcontainerStats, previousCPU, previousSystem)
|
||||
stats.MemUsage = cgroupStats.MemoryStats.Usage.Usage
|
||||
stats.MemLimit = getMemLimit(cgroupStats.MemoryStats.Usage.Limit)
|
||||
stats.MemPerc = float64(stats.MemUsage) / float64(stats.MemLimit)
|
||||
stats.PIDs = cgroupStats.PidsStats.Current
|
||||
stats.BlockInput, stats.BlockOutput = calculateBlockIO(libcontainerStats)
|
||||
stats.NetInput, stats.NetOutput = getContainerNetIO(libcontainerStats)
|
||||
|
||||
return stats, nil
|
||||
}
|
||||
|
|
|
@ -2,7 +2,11 @@
|
|||
|
||||
package lib
|
||||
|
||||
import "github.com/kubernetes-incubator/cri-o/lib/sandbox"
|
||||
import (
|
||||
"github.com/kubernetes-incubator/cri-o/lib/sandbox"
|
||||
"github.com/kubernetes-incubator/cri-o/oci"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (c *ContainerServer) addSandboxPlatform(sb *sandbox.Sandbox) {
|
||||
// nothin' doin'
|
||||
|
@ -11,3 +15,8 @@ func (c *ContainerServer) addSandboxPlatform(sb *sandbox.Sandbox) {
|
|||
func (c *ContainerServer) removeSandboxPlatform(sb *sandbox.Sandbox) {
|
||||
// nothin' doin'
|
||||
}
|
||||
|
||||
func (c *ContainerServer) getContainerStats(ctr *oci.Container, previousStats *ContainerStats) (*ContainerStats, error) {
|
||||
// nothin' doin'
|
||||
return nil, errors.New("container stats not supported")
|
||||
}
|
||||
|
|
89
lib/stats.go
89
lib/stats.go
|
@ -1,14 +1,7 @@
|
|||
package lib
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"strings"
|
||||
|
||||
"github.com/kubernetes-incubator/cri-o/oci"
|
||||
"github.com/opencontainers/runc/libcontainer"
|
||||
)
|
||||
|
||||
// ContainerStats contains the statistics information for a running container
|
||||
|
@ -29,85 +22,5 @@ type ContainerStats struct {
|
|||
|
||||
// GetContainerStats gets the running stats for a given container
|
||||
func (c *ContainerServer) GetContainerStats(ctr *oci.Container, previousStats *ContainerStats) (*ContainerStats, error) {
|
||||
previousCPU := previousStats.CPUNano
|
||||
previousSystem := previousStats.SystemNano
|
||||
libcontainerStats, err := c.LibcontainerStats(ctr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cgroupStats := libcontainerStats.CgroupStats
|
||||
stats := new(ContainerStats)
|
||||
stats.Container = ctr.ID()
|
||||
stats.CPUNano = cgroupStats.CpuStats.CpuUsage.TotalUsage
|
||||
stats.SystemNano = time.Now().UnixNano()
|
||||
stats.CPU = calculateCPUPercent(libcontainerStats, previousCPU, previousSystem)
|
||||
stats.MemUsage = cgroupStats.MemoryStats.Usage.Usage
|
||||
stats.MemLimit = getMemLimit(cgroupStats.MemoryStats.Usage.Limit)
|
||||
stats.MemPerc = float64(stats.MemUsage) / float64(stats.MemLimit)
|
||||
stats.PIDs = cgroupStats.PidsStats.Current
|
||||
stats.BlockInput, stats.BlockOutput = calculateBlockIO(libcontainerStats)
|
||||
stats.NetInput, stats.NetOutput = getContainerNetIO(libcontainerStats)
|
||||
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
func loadFactory(root string) (libcontainer.Factory, error) {
|
||||
abs, err := filepath.Abs(root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cgroupManager := libcontainer.Cgroupfs
|
||||
return libcontainer.New(abs, cgroupManager, libcontainer.CriuPath(""))
|
||||
}
|
||||
|
||||
// getMemory limit returns the memory limit for a given cgroup
|
||||
// If the configured memory limit is larger than the total memory on the sys, the
|
||||
// physical system memory size is returned
|
||||
func getMemLimit(cgroupLimit uint64) uint64 {
|
||||
si := &syscall.Sysinfo_t{}
|
||||
err := syscall.Sysinfo(si)
|
||||
if err != nil {
|
||||
return cgroupLimit
|
||||
}
|
||||
|
||||
physicalLimit := uint64(si.Totalram)
|
||||
if cgroupLimit > physicalLimit {
|
||||
return physicalLimit
|
||||
}
|
||||
return cgroupLimit
|
||||
}
|
||||
|
||||
// Returns the total number of bytes transmitted and received for the given container stats
|
||||
func getContainerNetIO(stats *libcontainer.Stats) (received uint64, transmitted uint64) {
|
||||
for _, iface := range stats.Interfaces {
|
||||
received += iface.RxBytes
|
||||
transmitted += iface.TxBytes
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func calculateCPUPercent(stats *libcontainer.Stats, previousCPU uint64, previousSystem int64) float64 {
|
||||
var (
|
||||
cpuPercent = 0.0
|
||||
cpuDelta = float64(stats.CgroupStats.CpuStats.CpuUsage.TotalUsage - previousCPU)
|
||||
systemDelta = float64(uint64(time.Now().UnixNano()) - uint64(previousSystem))
|
||||
)
|
||||
if systemDelta > 0.0 && cpuDelta > 0.0 {
|
||||
// gets a ratio of container cpu usage total, multiplies it by the number of cores (4 cores running
|
||||
// at 100% utilization should be 400% utilization), and multiplies that by 100 to get a percentage
|
||||
cpuPercent = (cpuDelta / systemDelta) * float64(len(stats.CgroupStats.CpuStats.CpuUsage.PercpuUsage)) * 100
|
||||
}
|
||||
return cpuPercent
|
||||
}
|
||||
|
||||
func calculateBlockIO(stats *libcontainer.Stats) (read uint64, write uint64) {
|
||||
for _, blkIOEntry := range stats.CgroupStats.BlkioStats.IoServiceBytesRecursive {
|
||||
switch strings.ToLower(blkIOEntry.Op) {
|
||||
case "read":
|
||||
read += blkIOEntry.Value
|
||||
case "write":
|
||||
write += blkIOEntry.Value
|
||||
}
|
||||
}
|
||||
return
|
||||
return c.getContainerStats(ctr, previousStats)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
package lib
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer"
|
||||
)
|
||||
|
||||
// Returns the total number of bytes transmitted and received for the given container stats
|
||||
func getContainerNetIO(stats *libcontainer.Stats) (received uint64, transmitted uint64) {
|
||||
for _, iface := range stats.Interfaces {
|
||||
received += iface.RxBytes
|
||||
transmitted += iface.TxBytes
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func calculateCPUPercent(stats *libcontainer.Stats, previousCPU uint64, previousSystem int64) float64 {
|
||||
var (
|
||||
cpuPercent = 0.0
|
||||
cpuDelta = float64(stats.CgroupStats.CpuStats.CpuUsage.TotalUsage - previousCPU)
|
||||
systemDelta = float64(uint64(time.Now().UnixNano()) - uint64(previousSystem))
|
||||
)
|
||||
if systemDelta > 0.0 && cpuDelta > 0.0 {
|
||||
// gets a ratio of container cpu usage total, multiplies it by the number of cores (4 cores running
|
||||
// at 100% utilization should be 400% utilization), and multiplies that by 100 to get a percentage
|
||||
cpuPercent = (cpuDelta / systemDelta) * float64(len(stats.CgroupStats.CpuStats.CpuUsage.PercpuUsage)) * 100
|
||||
}
|
||||
return cpuPercent
|
||||
}
|
||||
|
||||
func calculateBlockIO(stats *libcontainer.Stats) (read uint64, write uint64) {
|
||||
for _, blkIOEntry := range stats.CgroupStats.BlkioStats.IoServiceBytesRecursive {
|
||||
switch strings.ToLower(blkIOEntry.Op) {
|
||||
case "read":
|
||||
read += blkIOEntry.Value
|
||||
case "write":
|
||||
write += blkIOEntry.Value
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// getMemory limit returns the memory limit for a given cgroup
|
||||
// If the configured memory limit is larger than the total memory on the sys, the
|
||||
// physical system memory size is returned
|
||||
func getMemLimit(cgroupLimit uint64) uint64 {
|
||||
si := &syscall.Sysinfo_t{}
|
||||
err := syscall.Sysinfo(si)
|
||||
if err != nil {
|
||||
return cgroupLimit
|
||||
}
|
||||
|
||||
physicalLimit := uint64(si.Totalram)
|
||||
if cgroupLimit > physicalLimit {
|
||||
return physicalLimit
|
||||
}
|
||||
return cgroupLimit
|
||||
}
|
Loading…
Reference in New Issue