From f174fac0d67066bda1e23ea07424d3412efe2afc Mon Sep 17 00:00:00 2001 From: Eric Ernst Date: Fri, 22 Jul 2022 19:35:34 -0700 Subject: [PATCH] sandbox_test: Add test to verify memory hotplug behavior Augment the mock hypervisor so that we can validate that ACPI memory hotplug is carried out as expected. We'll augment the number of memory slots in the hypervisor config each time the memory of the hypervisor is changed. In this way we can ensure that large memory hotplugs are broken up into appropriately sized pieces in the unit test. Signed-off-by: Eric Ernst --- src/runtime/virtcontainers/mock_hypervisor.go | 13 ++++++--- .../virtcontainers/mock_hypervisor_test.go | 2 +- src/runtime/virtcontainers/sandbox_test.go | 27 ++++++++++++------- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/runtime/virtcontainers/mock_hypervisor.go b/src/runtime/virtcontainers/mock_hypervisor.go index 19b818dff8..7d6da561fa 100644 --- a/src/runtime/virtcontainers/mock_hypervisor.go +++ b/src/runtime/virtcontainers/mock_hypervisor.go @@ -17,6 +17,7 @@ import ( var MockHybridVSockPath = "/tmp/kata-mock-hybrid-vsock.socket" type mockHypervisor struct { + config HypervisorConfig mockPid int } @@ -27,10 +28,11 @@ func (m *mockHypervisor) Capabilities(ctx context.Context) types.Capabilities { } func (m *mockHypervisor) HypervisorConfig() HypervisorConfig { - return HypervisorConfig{} + return m.config } func (m *mockHypervisor) setConfig(config *HypervisorConfig) error { + m.config = *config return nil } @@ -38,7 +40,7 @@ func (m *mockHypervisor) CreateVM(ctx context.Context, id string, network Networ if err := m.setConfig(hypervisorConfig); err != nil { return err } - + m.config.MemSlots = 0 return nil } @@ -92,6 +94,11 @@ func (m *mockHypervisor) GetVMConsole(ctx context.Context, sandboxID string) (st } func (m *mockHypervisor) ResizeMemory(ctx context.Context, memMB uint32, memorySectionSizeMB uint32, probe bool) (uint32, MemoryDevice, error) { + if m.config.MemorySize != memMB { + // For testing, we'll use MemSlots to track how many times we resized memory + m.config.MemSlots += 1 + m.config.MemorySize = memMB + } return 0, MemoryDevice{}, nil } func (m *mockHypervisor) ResizeVCPUs(ctx context.Context, cpus uint32) (uint32, uint32, error) { @@ -99,7 +106,7 @@ func (m *mockHypervisor) ResizeVCPUs(ctx context.Context, cpus uint32) (uint32, } func (m *mockHypervisor) GetTotalMemoryMB(ctx context.Context) uint32 { - return 0 + return m.config.MemorySize } func (m *mockHypervisor) Disconnect(ctx context.Context) { } diff --git a/src/runtime/virtcontainers/mock_hypervisor_test.go b/src/runtime/virtcontainers/mock_hypervisor_test.go index 0159a993dd..ba4435f13b 100644 --- a/src/runtime/virtcontainers/mock_hypervisor_test.go +++ b/src/runtime/virtcontainers/mock_hypervisor_test.go @@ -14,7 +14,7 @@ import ( ) func TestMockHypervisorCreateVM(t *testing.T) { - var m *mockHypervisor + m := &mockHypervisor{} assert := assert.New(t) sandbox := &Sandbox{ diff --git a/src/runtime/virtcontainers/sandbox_test.go b/src/runtime/virtcontainers/sandbox_test.go index 331094ee39..59ed24c1aa 100644 --- a/src/runtime/virtcontainers/sandbox_test.go +++ b/src/runtime/virtcontainers/sandbox_test.go @@ -41,6 +41,7 @@ func newHypervisorConfig(kernelParams []Param, hParams []Param) HypervisorConfig HypervisorPath: filepath.Join(testDir, testHypervisor), KernelParams: kernelParams, HypervisorParams: hParams, + MemorySize: 1, } } @@ -1360,7 +1361,6 @@ func TestSandboxUpdateResources(t *testing.T) { contConfig1 := newTestContainerConfigNoop("cont-00001") contConfig2 := newTestContainerConfigNoop("cont-00002") hConfig := newHypervisorConfig(nil, nil) - defer cleanUp() // create a sandbox s, err := testCreateSandbox(t, @@ -1370,28 +1370,37 @@ func TestSandboxUpdateResources(t *testing.T) { NetworkConfig{}, []ContainerConfig{contConfig1, contConfig2}, nil) - assert.NoError(t, err) + err = s.updateResources(context.Background()) assert.NoError(t, err) - containerMemLimit := int64(1000) + // For mock hypervisor, we MemSlots to be 0 since the memory wasn't changed. + assert.Equal(t, s.hypervisor.HypervisorConfig().MemSlots, uint32(0)) + + containerMemLimit := int64(4 * 1024 * 1024 * 1024) containerCPUPeriod := uint64(1000) containerCPUQouta := int64(5) - for _, c := range s.config.Containers { - c.Resources.Memory = &specs.LinuxMemory{ + for idx := range s.config.Containers { + s.config.Containers[idx].Resources.Memory = &specs.LinuxMemory{ Limit: new(int64), } - c.Resources.CPU = &specs.LinuxCPU{ + s.config.Containers[idx].Resources.CPU = &specs.LinuxCPU{ Period: new(uint64), Quota: new(int64), } - c.Resources.Memory.Limit = &containerMemLimit - c.Resources.CPU.Period = &containerCPUPeriod - c.Resources.CPU.Quota = &containerCPUQouta + s.config.Containers[idx].Resources.Memory.Limit = &containerMemLimit + s.config.Containers[idx].Resources.CPU.Period = &containerCPUPeriod + s.config.Containers[idx].Resources.CPU.Quota = &containerCPUQouta } err = s.updateResources(context.Background()) assert.NoError(t, err) + + // Since we're starting with a memory of 1 MB, we expect it to take 3 hotplugs to add 4GiB of memory when using ACPI hotplug: + // +48MB + // +2352MB + // +the remaining + assert.Equal(t, s.hypervisor.HypervisorConfig().MemSlots, uint32(3)) } func TestSandboxExperimentalFeature(t *testing.T) {