Skip to content
This repository has been archived by the owner on May 12, 2021. It is now read-only.

Commit

Permalink
virtcontainers: add StatsSandbox to vc API
Browse files Browse the repository at this point in the history
StatsSandbox is used to gather metrics for the sandbox (host cgroup) as
well as from the individual containers (from the guest cgroups). This is
intended to be used for easily calculating Kata sandbox overheads.

Fixes: #2096

Signed-off-by: Jose Carlos Venegas Munoz <[email protected]>
Signed-off-by: Eric Ernst <[email protected]>
  • Loading branch information
jcvenegas authored and Eric Ernst committed Oct 31, 2019
1 parent 569bd78 commit 1bbc1d5
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 1 deletion.
40 changes: 40 additions & 0 deletions virtcontainers/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,46 @@ func StatsContainer(ctx context.Context, sandboxID, containerID string) (Contain
return s.StatsContainer(containerID)
}

// StatsSandbox is the virtcontainers sandbox stats entry point.
// StatsSandbox returns a detailed sandbox stats.
func StatsSandbox(ctx context.Context, sandboxID string) (SandboxStats, []ContainerStats, error) {
span, ctx := trace(ctx, "StatsSandbox")
defer span.Finish()

if sandboxID == "" {
return SandboxStats{}, []ContainerStats{}, vcTypes.ErrNeedSandboxID
}

lockFile, err := rLockSandbox(ctx, sandboxID)
if err != nil {
return SandboxStats{}, []ContainerStats{}, err
}

defer unlockSandbox(ctx, sandboxID, lockFile)

s, err := fetchSandbox(ctx, sandboxID)
if err != nil {
return SandboxStats{}, []ContainerStats{}, err
}
defer s.releaseStatelessSandbox()

sandboxStats, err := s.Stats()
if err != nil {
return SandboxStats{}, []ContainerStats{}, err
}

containerStats := []ContainerStats{}
for _, c := range s.containers {
cstats, err := s.StatsContainer(c.id)
if err != nil {
return SandboxStats{}, []ContainerStats{}, err
}
containerStats = append(containerStats, cstats)
}

return sandboxStats, containerStats, nil
}

func togglePauseContainer(ctx context.Context, sandboxID, containerID string, pause bool) error {
if sandboxID == "" {
return vcTypes.ErrNeedSandboxID
Expand Down
5 changes: 5 additions & 0 deletions virtcontainers/implementation.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ func (impl *VCImpl) StatsContainer(ctx context.Context, sandboxID, containerID s
return StatsContainer(ctx, sandboxID, containerID)
}

// StatsSandbox implements the VC function of the same name.
func (impl *VCImpl) StatsSandbox(ctx context.Context, sandboxID string) (SandboxStats, []ContainerStats, error) {
return StatsSandbox(ctx, sandboxID)
}

// KillContainer implements the VC function of the same name.
func (impl *VCImpl) KillContainer(ctx context.Context, sandboxID, containerID string, signal syscall.Signal, all bool) error {
return KillContainer(ctx, sandboxID, containerID, signal, all)
Expand Down
1 change: 1 addition & 0 deletions virtcontainers/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type VC interface {
StartContainer(ctx context.Context, sandboxID, containerID string) (VCContainer, error)
StatusContainer(ctx context.Context, sandboxID, containerID string) (ContainerStatus, error)
StatsContainer(ctx context.Context, sandboxID, containerID string) (ContainerStats, error)
StatsSandbox(ctx context.Context, sandboxID string) (SandboxStats, []ContainerStats, error)
StopContainer(ctx context.Context, sandboxID, containerID string) (VCContainer, error)
ProcessListContainer(ctx context.Context, sandboxID, containerID string, options ProcessListOptions) (ProcessList, error)
UpdateContainer(ctx context.Context, sandboxID, containerID string, resources specs.LinuxResources) error
Expand Down
9 changes: 9 additions & 0 deletions virtcontainers/pkg/vcmock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,15 @@ func (m *VCMock) StatsContainer(ctx context.Context, sandboxID, containerID stri
return vc.ContainerStats{}, fmt.Errorf("%s: %s (%+v): sandboxID: %v, containerID: %v", mockErrorPrefix, getSelf(), m, sandboxID, containerID)
}

// StatsSandbox implements the VC function of the same name.
func (m *VCMock) StatsSandbox(ctx context.Context, sandboxID string) (vc.SandboxStats, []vc.ContainerStats, error) {
if m.StatsContainerFunc != nil {
return m.StatsSandboxFunc(ctx, sandboxID)
}

return vc.SandboxStats{}, []vc.ContainerStats{}, fmt.Errorf("%s: %s (%+v): sandboxID: %v", mockErrorPrefix, getSelf(), m, sandboxID)
}

// KillContainer implements the VC function of the same name.
func (m *VCMock) KillContainer(ctx context.Context, sandboxID, containerID string, signal syscall.Signal, all bool) error {
if m.KillContainerFunc != nil {
Expand Down
1 change: 1 addition & 0 deletions virtcontainers/pkg/vcmock/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type VCMock struct {
StartSandboxFunc func(ctx context.Context, sandboxID string) (vc.VCSandbox, error)
StatusSandboxFunc func(ctx context.Context, sandboxID string) (vc.SandboxStatus, error)
StatsContainerFunc func(ctx context.Context, sandboxID, containerID string) (vc.ContainerStats, error)
StatsSandboxFunc func(ctx context.Context, sandboxID string) (vc.SandboxStats, []vc.ContainerStats, error)
StopSandboxFunc func(ctx context.Context, sandboxID string, force bool) (vc.VCSandbox, error)

CreateContainerFunc func(ctx context.Context, sandboxID string, containerConfig vc.ContainerConfig) (vc.VCSandbox, vc.VCContainer, error)
Expand Down
47 changes: 46 additions & 1 deletion virtcontainers/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ type SandboxStatus struct {
Annotations map[string]string
}

// SandboxStats describes a sandbox's stats
type SandboxStats struct {
CgroupStats CgroupStats
Cpus int
}

// SandboxConfig is a Sandbox configuration.
type SandboxConfig struct {
ID string
Expand Down Expand Up @@ -1367,6 +1373,46 @@ func (s *Sandbox) StatsContainer(containerID string) (ContainerStats, error) {
return *stats, nil
}

// Stats returns the stats of a running sandbox
func (s *Sandbox) Stats() (SandboxStats, error) {
if s.state.CgroupPath == "" {
return SandboxStats{}, fmt.Errorf("sandbox cgroup path is emtpy")
}

var path string
var cgroupSubsystems cgroups.Hierarchy

if s.config.SandboxCgroupOnly {
cgroupSubsystems = cgroups.V1
path = s.state.CgroupPath
} else {
cgroupSubsystems = V1NoConstraints
path = cgroupNoConstraintsPath(s.state.CgroupPath)
}

cgroup, err := cgroupsLoadFunc(cgroupSubsystems, cgroups.StaticPath(path))
if err != nil {
return SandboxStats{}, fmt.Errorf("Could not load sandbox cgroup in %v: %v", s.state.CgroupPath, err)
}

metrics, err := cgroup.Stat(cgroups.ErrorHandler(cgroups.IgnoreNotExist))
if err != nil {
return SandboxStats{}, err
}

stats := SandboxStats{}

stats.CgroupStats.CPUStats.CPUUsage.TotalUsage = metrics.CPU.Usage.Total
stats.CgroupStats.MemoryStats.Usage.Usage = metrics.Memory.Usage.Usage
tids, err := s.hypervisor.getThreadIDs()
if err != nil {
return stats, err
}
stats.Cpus = len(tids.vcpus)

return stats, nil
}

// PauseContainer pauses a running container.
func (s *Sandbox) PauseContainer(containerID string) error {
// Fetch the container.
Expand Down Expand Up @@ -2125,7 +2171,6 @@ func (s *Sandbox) setupSandboxCgroup() error {
if err := cgroup.Add(cgroups.Process{Pid: runtimePid}); err != nil {
return fmt.Errorf("Could not add runtime PID %d to sandbox cgroup: %v", runtimePid, err)
}

return nil
}

Expand Down

0 comments on commit 1bbc1d5

Please sign in to comment.