From bac206ee5b4ccb90fd8c06c0b6244ba163ac82b9 Mon Sep 17 00:00:00 2001
From: holyfei <yangfeiyu2@huawei.com>
Date: Sun, 15 Nov 2020 21:31:49 +0800
Subject: [PATCH] kata-runtime: fix get sandbox cpu resources problem

reason: If sandox_cgroup_with_emulator config is enabled,
kata-runtime should get cpu resources by cpuResourcesWithEmulator
func instead of the original cpuResource func.

Signed-off-by: holyfei <yangfeiyu2@huawei.com>
---
 virtcontainers/cgroups.go |  2 ++
 virtcontainers/sandbox.go | 34 +++++++++++++++++++++++++++++++++-
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/virtcontainers/cgroups.go b/virtcontainers/cgroups.go
index 1b6b04da..21708ebf 100644
--- a/virtcontainers/cgroups.go
+++ b/virtcontainers/cgroups.go
@@ -40,6 +40,8 @@ const (
 
 	defaultMinFilesLimit uint64 = 1024
 	defaultMaxContainers uint64 = 200
+	defaultCPUPeriod     uint64 = 1000000
+	defaultCPUShares     uint64 = 1024
 
 	procFileMaxPath = "/proc/sys/fs/file-max"
 
diff --git a/virtcontainers/sandbox.go b/virtcontainers/sandbox.go
index 9f5d3c08..d3c64b4f 100644
--- a/virtcontainers/sandbox.go
+++ b/virtcontainers/sandbox.go
@@ -14,6 +14,7 @@ import (
 	"net"
 	"os"
 	"path/filepath"
+	"strconv"
 	"strings"
 	"sync"
 	"syscall"
@@ -2351,6 +2352,37 @@ func (s *Sandbox) cpuResources() *specs.LinuxCPU {
 	return validCPUResources(cpu)
 }
 
+func (s *Sandbox) cpuResourcesWithEmulator() *specs.LinuxCPU {
+	// Use default period and quota if they are not specified.
+	// Container will inherit the constraints from its parent.
+	quota := int64(0)
+	period := uint64(0)
+	shares := uint64(0)
+
+	cpu := &specs.LinuxCPU{
+		Quota:  &quota,
+		Period: &period,
+		Shares: &shares,
+	}
+
+	period = defaultCPUPeriod
+
+	cpuValue, exist := s.config.Annotations[annotations.StaticCPUTypeKey]
+	if exist {
+		// If sandbox_cpu is set, we have validate at first, so we don't need to check it again
+		cpuNum, _ := strconv.ParseFloat(cpuValue, 64)
+		quota = int64(cpuNum * float64(period))
+		shares = uint64(cpuNum * float64(defaultCPUShares))
+	} else {
+		// If sandbox_cpu is not set, we use the hypervisor's cpu number as cpu limit
+		hypervisorConfig := s.hypervisor.hypervisorConfig()
+		quota = int64(uint64(hypervisorConfig.NumVCPUs) * period)
+		shares = uint64(hypervisorConfig.NumVCPUs) * defaultCPUShares
+	}
+
+	return cpu
+}
+
 // setupSandboxCgroup creates and joins sandbox cgroups for the sandbox config
 func (s *Sandbox) setupSandboxCgroup() error {
 	var err error
@@ -2424,7 +2456,7 @@ func (s *Sandbox) setupHostCgroupsWithEmulator() error {
 	// limit cpu to "<path>/vcpu"
 	vcpuCgroupPath := filepath.Join(s.state.CgroupPath, vcpuCgroupName)
 	vcpuResources := specs.LinuxResources{
-		CPU: s.cpuResources(),
+		CPU: s.cpuResourcesWithEmulator(),
 	}
 	if err := applyResourceLimit(&vcpuResources, vcpuCgroupPath); err != nil {
 		return err
-- 
2.11.0

