From f82fc6009e6e62f3428a606d39287191f993f82f Mon Sep 17 00:00:00 2001 From: WANG Chao Date: Thu, 17 Aug 2017 12:25:44 +0800 Subject: [PATCH] pkg: oci: support OCI spec cpu quota/period We should run VM(container) regarding OCI spec config.json cpu quota and period. The number of VM VCPUs is defined by quota/period (round up to 1). Signed-off-by: WANG Chao --- pkg/oci/utils.go | 32 +++++++++++++++++++++++++------- pkg/oci/utils_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/pkg/oci/utils.go b/pkg/oci/utils.go index 0e95347b..edad4f7c 100644 --- a/pkg/oci/utils.go +++ b/pkg/oci/utils.go @@ -286,13 +286,14 @@ func (spec *CompatOCISpec) PodID() (string, error) { return "", fmt.Errorf("Could not find pod ID") } -// TODO: calculate number of VCPUs from OCI spec func vmConfig(ocispec CompatOCISpec, config RuntimeConfig) (vc.Resources, error) { + resources := config.VMConfig + if ocispec.Linux == nil || ocispec.Linux.Resources == nil || ocispec.Linux.Resources.Memory == nil || ocispec.Linux.Resources.Memory.Limit == nil { - return config.VMConfig, nil + return resources, nil } memBytes := *ocispec.Linux.Resources.Memory.Limit @@ -302,12 +303,29 @@ func vmConfig(ocispec CompatOCISpec, config RuntimeConfig) (vc.Resources, error) } // round up memory to 1MB - mem := uint((memBytes + (1024*1024 - 1)) / (1024 * 1024)) + resources.Memory = uint((memBytes + (1024*1024 - 1)) / (1024 * 1024)) + + if ocispec.Linux.Resources.CPU == nil || + ocispec.Linux.Resources.CPU.Quota == nil || + ocispec.Linux.Resources.CPU.Period == nil { + return resources, nil + } + + quota := *ocispec.Linux.Resources.CPU.Quota + period := *ocispec.Linux.Resources.CPU.Period + + if quota <= 0 { + return vc.Resources{}, fmt.Errorf("Invalid OCI cpu quota %d", quota) + } + + if period == 0 { + return vc.Resources{}, fmt.Errorf("Invalid OCI cpu period %d", period) + } + + // round up to 1 CPU + resources.VCPUs = uint((uint64(quota) + (period - 1)) / period) - return vc.Resources{ - VCPUs: config.VMConfig.VCPUs, - Memory: mem, - }, nil + return resources, nil } // PodConfig converts an OCI compatible runtime configuration file diff --git a/pkg/oci/utils_test.go b/pkg/oci/utils_test.go index f5fb6a9e..680b999c 100644 --- a/pkg/oci/utils_test.go +++ b/pkg/oci/utils_test.go @@ -163,6 +163,8 @@ func TestMinimalPodConfig(t *testing.T) { func TestVmConfig(t *testing.T) { var limitBytes int64 = 128 * 1024 * 1024 + var quota int64 = 200000 + var period uint64 = 100000 config := RuntimeConfig{ VMConfig: vc.Resources{ @@ -172,6 +174,7 @@ func TestVmConfig(t *testing.T) { expectedResources := vc.Resources{ Memory: 128, + VCPUs: 2, } ocispec := CompatOCISpec{ @@ -181,6 +184,10 @@ func TestVmConfig(t *testing.T) { Memory: &specs.LinuxMemory{ Limit: &limitBytes, }, + CPU: &specs.LinuxCPU{ + Quota: "a, + Period: &period, + }, }, }, }, @@ -202,6 +209,24 @@ func TestVmConfig(t *testing.T) { if err == nil { t.Fatalf("Got %v\n expecting error", resources) } + + limitBytes = 128 * 1024 * 1024 + quota = -1 + ocispec.Linux.Resources.CPU.Quota = "a + + resources, err = vmConfig(ocispec, config) + if err == nil { + t.Fatalf("Got %v\n expecting error", resources) + } + + quota = 100000 + period = 0 + ocispec.Linux.Resources.CPU.Quota = "a + + resources, err = vmConfig(ocispec, config) + if err == nil { + t.Fatalf("Got %v\n expecting error", resources) + } } func testStatusToOCIStateSuccessful(t *testing.T, cStatus vc.ContainerStatus, expected specs.State) {