123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515 |
- /*
- Copyright 2017 The Kubernetes Authors.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- package cpumanager
- import (
- "fmt"
- "reflect"
- "testing"
- "k8s.io/api/core/v1"
- "k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/state"
- "k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/topology"
- "k8s.io/kubernetes/pkg/kubelet/cm/cpuset"
- )
- type staticPolicyTest struct {
- description string
- topo *topology.CPUTopology
- numReservedCPUs int
- containerID string
- stAssignments state.ContainerCPUAssignments
- stDefaultCPUSet cpuset.CPUSet
- pod *v1.Pod
- expErr error
- expCPUAlloc bool
- expCSet cpuset.CPUSet
- expPanic bool
- }
- func TestStaticPolicyName(t *testing.T) {
- policy := NewStaticPolicy(topoSingleSocketHT, 1)
- policyName := policy.Name()
- if policyName != "static" {
- t.Errorf("StaticPolicy Name() error. expected: static, returned: %v",
- policyName)
- }
- }
- func TestStaticPolicyStart(t *testing.T) {
- testCases := []staticPolicyTest{
- {
- description: "non-corrupted state",
- topo: topoDualSocketHT,
- stAssignments: state.ContainerCPUAssignments{
- "0": cpuset.NewCPUSet(0),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11),
- expCSet: cpuset.NewCPUSet(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11),
- },
- {
- description: "empty cpuset",
- topo: topoDualSocketHT,
- numReservedCPUs: 1,
- stAssignments: state.ContainerCPUAssignments{},
- stDefaultCPUSet: cpuset.NewCPUSet(),
- expCSet: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11),
- },
- {
- description: "reserved cores 0 & 6 are not present in available cpuset",
- topo: topoDualSocketHT,
- numReservedCPUs: 2,
- stAssignments: state.ContainerCPUAssignments{},
- stDefaultCPUSet: cpuset.NewCPUSet(0, 1),
- expPanic: true,
- },
- {
- description: "assigned core 2 is still present in available cpuset",
- topo: topoDualSocketHT,
- stAssignments: state.ContainerCPUAssignments{
- "0": cpuset.NewCPUSet(0, 1, 2),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(2, 3, 4, 5, 6, 7, 8, 9, 10, 11),
- expPanic: true,
- },
- {
- description: "core 12 is not present in topology but is in state cpuset",
- topo: topoDualSocketHT,
- stAssignments: state.ContainerCPUAssignments{
- "0": cpuset.NewCPUSet(0, 1, 2),
- "1": cpuset.NewCPUSet(3, 4),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(5, 6, 7, 8, 9, 10, 11, 12),
- expPanic: true,
- },
- {
- description: "core 11 is present in topology but is not in state cpuset",
- topo: topoDualSocketHT,
- stAssignments: state.ContainerCPUAssignments{
- "0": cpuset.NewCPUSet(0, 1, 2),
- "1": cpuset.NewCPUSet(3, 4),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(5, 6, 7, 8, 9, 10),
- expPanic: true,
- },
- }
- for _, testCase := range testCases {
- t.Run(testCase.description, func(t *testing.T) {
- defer func() {
- if err := recover(); err != nil {
- if !testCase.expPanic {
- t.Errorf("unexpected panic occurred: %q", err)
- }
- } else if testCase.expPanic {
- t.Error("expected panic doesn't occurred")
- }
- }()
- policy := NewStaticPolicy(testCase.topo, testCase.numReservedCPUs).(*staticPolicy)
- st := &mockState{
- assignments: testCase.stAssignments,
- defaultCPUSet: testCase.stDefaultCPUSet,
- }
- policy.Start(st)
- if !testCase.stDefaultCPUSet.IsEmpty() {
- for cpuid := 1; cpuid < policy.topology.NumCPUs; cpuid++ {
- if !st.defaultCPUSet.Contains(cpuid) {
- t.Errorf("StaticPolicy Start() error. expected cpuid %d to be present in defaultCPUSet", cpuid)
- }
- }
- }
- if !st.GetDefaultCPUSet().Equals(testCase.expCSet) {
- t.Errorf("State CPUSet is different than expected. Have %q wants: %q", st.GetDefaultCPUSet(),
- testCase.expCSet)
- }
- })
- }
- }
- func TestStaticPolicyAdd(t *testing.T) {
- largeTopoBuilder := cpuset.NewBuilder()
- largeTopoSock0Builder := cpuset.NewBuilder()
- largeTopoSock1Builder := cpuset.NewBuilder()
- largeTopo := *topoQuadSocketFourWayHT
- for cpuid, val := range largeTopo.CPUDetails {
- largeTopoBuilder.Add(cpuid)
- if val.SocketID == 0 {
- largeTopoSock0Builder.Add(cpuid)
- } else if val.SocketID == 1 {
- largeTopoSock1Builder.Add(cpuid)
- }
- }
- largeTopoCPUSet := largeTopoBuilder.Result()
- largeTopoSock0CPUSet := largeTopoSock0Builder.Result()
- largeTopoSock1CPUSet := largeTopoSock1Builder.Result()
- testCases := []staticPolicyTest{
- {
- description: "GuPodSingleCore, SingleSocketHT, ExpectError",
- topo: topoSingleSocketHT,
- numReservedCPUs: 1,
- containerID: "fakeID2",
- stAssignments: state.ContainerCPUAssignments{},
- stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
- pod: makePod("8000m", "8000m"),
- expErr: fmt.Errorf("not enough cpus available to satisfy request"),
- expCPUAlloc: false,
- expCSet: cpuset.NewCPUSet(),
- },
- {
- description: "GuPodSingleCore, SingleSocketHT, ExpectAllocOneCPU",
- topo: topoSingleSocketHT,
- numReservedCPUs: 1,
- containerID: "fakeID2",
- stAssignments: state.ContainerCPUAssignments{},
- stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
- pod: makePod("1000m", "1000m"),
- expErr: nil,
- expCPUAlloc: true,
- expCSet: cpuset.NewCPUSet(4), // expect sibling of partial core
- },
- {
- description: "GuPodMultipleCores, SingleSocketHT, ExpectAllocOneCore",
- topo: topoSingleSocketHT,
- numReservedCPUs: 1,
- containerID: "fakeID3",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID100": cpuset.NewCPUSet(2, 3, 6, 7),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 4, 5),
- pod: makePod("2000m", "2000m"),
- expErr: nil,
- expCPUAlloc: true,
- expCSet: cpuset.NewCPUSet(1, 5),
- },
- {
- description: "GuPodMultipleCores, DualSocketHT, ExpectAllocOneSocket",
- topo: topoDualSocketHT,
- numReservedCPUs: 1,
- containerID: "fakeID3",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID100": cpuset.NewCPUSet(2),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11),
- pod: makePod("6000m", "6000m"),
- expErr: nil,
- expCPUAlloc: true,
- expCSet: cpuset.NewCPUSet(1, 3, 5, 7, 9, 11),
- },
- {
- description: "GuPodMultipleCores, DualSocketHT, ExpectAllocThreeCores",
- topo: topoDualSocketHT,
- numReservedCPUs: 1,
- containerID: "fakeID3",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID100": cpuset.NewCPUSet(1, 5),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(0, 2, 3, 4, 6, 7, 8, 9, 10, 11),
- pod: makePod("6000m", "6000m"),
- expErr: nil,
- expCPUAlloc: true,
- expCSet: cpuset.NewCPUSet(2, 3, 4, 8, 9, 10),
- },
- {
- description: "GuPodMultipleCores, DualSocketNoHT, ExpectAllocOneSocket",
- topo: topoDualSocketNoHT,
- numReservedCPUs: 1,
- containerID: "fakeID1",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID100": cpuset.NewCPUSet(),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 3, 4, 5, 6, 7),
- pod: makePod("4000m", "4000m"),
- expErr: nil,
- expCPUAlloc: true,
- expCSet: cpuset.NewCPUSet(4, 5, 6, 7),
- },
- {
- description: "GuPodMultipleCores, DualSocketNoHT, ExpectAllocFourCores",
- topo: topoDualSocketNoHT,
- numReservedCPUs: 1,
- containerID: "fakeID1",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID100": cpuset.NewCPUSet(4, 5),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 3, 6, 7),
- pod: makePod("4000m", "4000m"),
- expErr: nil,
- expCPUAlloc: true,
- expCSet: cpuset.NewCPUSet(1, 3, 6, 7),
- },
- {
- description: "GuPodMultipleCores, DualSocketHT, ExpectAllocOneSocketOneCore",
- topo: topoDualSocketHT,
- numReservedCPUs: 1,
- containerID: "fakeID3",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID100": cpuset.NewCPUSet(2),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11),
- pod: makePod("8000m", "8000m"),
- expErr: nil,
- expCPUAlloc: true,
- expCSet: cpuset.NewCPUSet(1, 3, 4, 5, 7, 9, 10, 11),
- },
- {
- description: "NonGuPod, SingleSocketHT, NoAlloc",
- topo: topoSingleSocketHT,
- numReservedCPUs: 1,
- containerID: "fakeID1",
- stAssignments: state.ContainerCPUAssignments{},
- stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
- pod: makePod("1000m", "2000m"),
- expErr: nil,
- expCPUAlloc: false,
- expCSet: cpuset.NewCPUSet(),
- },
- {
- description: "GuPodNonIntegerCore, SingleSocketHT, NoAlloc",
- topo: topoSingleSocketHT,
- numReservedCPUs: 1,
- containerID: "fakeID4",
- stAssignments: state.ContainerCPUAssignments{},
- stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
- pod: makePod("977m", "977m"),
- expErr: nil,
- expCPUAlloc: false,
- expCSet: cpuset.NewCPUSet(),
- },
- {
- description: "GuPodMultipleCores, SingleSocketHT, NoAllocExpectError",
- topo: topoSingleSocketHT,
- numReservedCPUs: 1,
- containerID: "fakeID5",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID100": cpuset.NewCPUSet(1, 2, 3, 4, 5, 6),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(0, 7),
- pod: makePod("2000m", "2000m"),
- expErr: fmt.Errorf("not enough cpus available to satisfy request"),
- expCPUAlloc: false,
- expCSet: cpuset.NewCPUSet(),
- },
- {
- description: "GuPodMultipleCores, DualSocketHT, NoAllocExpectError",
- topo: topoDualSocketHT,
- numReservedCPUs: 1,
- containerID: "fakeID5",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID100": cpuset.NewCPUSet(1, 2, 3),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(0, 4, 5, 6, 7, 8, 9, 10, 11),
- pod: makePod("10000m", "10000m"),
- expErr: fmt.Errorf("not enough cpus available to satisfy request"),
- expCPUAlloc: false,
- expCSet: cpuset.NewCPUSet(),
- },
- {
- // All the CPUs from Socket 0 are available. Some CPUs from each
- // Socket have been already assigned.
- // Expect all CPUs from Socket 0.
- description: "GuPodMultipleCores, topoQuadSocketFourWayHT, ExpectAllocSock0",
- topo: topoQuadSocketFourWayHT,
- containerID: "fakeID5",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID100": cpuset.NewCPUSet(3, 11, 4, 5, 6, 7),
- },
- stDefaultCPUSet: largeTopoCPUSet.Difference(cpuset.NewCPUSet(3, 11, 4, 5, 6, 7)),
- pod: makePod("72000m", "72000m"),
- expErr: nil,
- expCPUAlloc: true,
- expCSet: largeTopoSock0CPUSet,
- },
- {
- // Only 2 full cores from three Sockets and some partial cores are available.
- // Expect CPUs from the 2 full cores available from the three Sockets.
- description: "GuPodMultipleCores, topoQuadSocketFourWayHT, ExpectAllocAllFullCoresFromThreeSockets",
- topo: topoQuadSocketFourWayHT,
- containerID: "fakeID5",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID100": largeTopoCPUSet.Difference(cpuset.NewCPUSet(1, 25, 13, 38, 2, 9, 11, 35, 23, 48, 12, 51,
- 53, 173, 113, 233, 54, 61)),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(1, 25, 13, 38, 2, 9, 11, 35, 23, 48, 12, 51, 53, 173, 113, 233, 54, 61),
- pod: makePod("12000m", "12000m"),
- expErr: nil,
- expCPUAlloc: true,
- expCSet: cpuset.NewCPUSet(1, 25, 13, 38, 11, 35, 23, 48, 53, 173, 113, 233),
- },
- {
- // All CPUs from Socket 1, 1 full core and some partial cores are available.
- // Expect all CPUs from Socket 1 and the hyper-threads from the full core.
- description: "GuPodMultipleCores, topoQuadSocketFourWayHT, ExpectAllocAllSock1+FullCore",
- topo: topoQuadSocketFourWayHT,
- containerID: "fakeID5",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID100": largeTopoCPUSet.Difference(largeTopoSock1CPUSet.Union(cpuset.NewCPUSet(10, 34, 22, 47, 53,
- 173, 61, 181, 108, 228, 115, 235))),
- },
- stDefaultCPUSet: largeTopoSock1CPUSet.Union(cpuset.NewCPUSet(10, 34, 22, 47, 53, 173, 61, 181, 108, 228,
- 115, 235)),
- pod: makePod("76000m", "76000m"),
- expErr: nil,
- expCPUAlloc: true,
- expCSet: largeTopoSock1CPUSet.Union(cpuset.NewCPUSet(10, 34, 22, 47)),
- },
- {
- // Only partial cores are available in the entire system.
- // Expect allocation of all the CPUs from the partial cores.
- description: "GuPodMultipleCores, topoQuadSocketFourWayHT, ExpectAllocCPUs",
- topo: topoQuadSocketFourWayHT,
- containerID: "fakeID5",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID100": largeTopoCPUSet.Difference(cpuset.NewCPUSet(10, 11, 53, 37, 55, 67, 52)),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(10, 11, 53, 67, 52),
- pod: makePod("5000m", "5000m"),
- expErr: nil,
- expCPUAlloc: true,
- expCSet: cpuset.NewCPUSet(10, 11, 53, 67, 52),
- },
- {
- // Only 7 CPUs are available.
- // Pod requests 76 cores.
- // Error is expect since available CPUs are less than the request.
- description: "GuPodMultipleCores, topoQuadSocketFourWayHT, NoAlloc",
- topo: topoQuadSocketFourWayHT,
- containerID: "fakeID5",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID100": largeTopoCPUSet.Difference(cpuset.NewCPUSet(10, 11, 53, 37, 55, 67, 52)),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(10, 11, 53, 37, 55, 67, 52),
- pod: makePod("76000m", "76000m"),
- expErr: fmt.Errorf("not enough cpus available to satisfy request"),
- expCPUAlloc: false,
- expCSet: cpuset.NewCPUSet(),
- },
- }
- for _, testCase := range testCases {
- policy := NewStaticPolicy(testCase.topo, testCase.numReservedCPUs)
- st := &mockState{
- assignments: testCase.stAssignments,
- defaultCPUSet: testCase.stDefaultCPUSet,
- }
- container := &testCase.pod.Spec.Containers[0]
- err := policy.AddContainer(st, testCase.pod, container, testCase.containerID)
- if !reflect.DeepEqual(err, testCase.expErr) {
- t.Errorf("StaticPolicy AddContainer() error (%v). expected add error: %v but got: %v",
- testCase.description, testCase.expErr, err)
- }
- if testCase.expCPUAlloc {
- cset, found := st.assignments[testCase.containerID]
- if !found {
- t.Errorf("StaticPolicy AddContainer() error (%v). expected container id %v to be present in assignments %v",
- testCase.description, testCase.containerID, st.assignments)
- }
- if !reflect.DeepEqual(cset, testCase.expCSet) {
- t.Errorf("StaticPolicy AddContainer() error (%v). expected cpuset %v but got %v",
- testCase.description, testCase.expCSet, cset)
- }
- if !cset.Intersection(st.defaultCPUSet).IsEmpty() {
- t.Errorf("StaticPolicy AddContainer() error (%v). expected cpuset %v to be disoint from the shared cpuset %v",
- testCase.description, cset, st.defaultCPUSet)
- }
- }
- if !testCase.expCPUAlloc {
- _, found := st.assignments[testCase.containerID]
- if found {
- t.Errorf("StaticPolicy AddContainer() error (%v). Did not expect container id %v to be present in assignments %v",
- testCase.description, testCase.containerID, st.assignments)
- }
- }
- }
- }
- func TestStaticPolicyRemove(t *testing.T) {
- testCases := []staticPolicyTest{
- {
- description: "SingleSocketHT, DeAllocOneContainer",
- topo: topoSingleSocketHT,
- containerID: "fakeID1",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID1": cpuset.NewCPUSet(1, 2, 3),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(4, 5, 6, 7),
- expCSet: cpuset.NewCPUSet(1, 2, 3, 4, 5, 6, 7),
- },
- {
- description: "SingleSocketHT, DeAllocOneContainer, BeginEmpty",
- topo: topoSingleSocketHT,
- containerID: "fakeID1",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID1": cpuset.NewCPUSet(1, 2, 3),
- "fakeID2": cpuset.NewCPUSet(4, 5, 6, 7),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(),
- expCSet: cpuset.NewCPUSet(1, 2, 3),
- },
- {
- description: "SingleSocketHT, DeAllocTwoContainer",
- topo: topoSingleSocketHT,
- containerID: "fakeID1",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID1": cpuset.NewCPUSet(1, 3, 5),
- "fakeID2": cpuset.NewCPUSet(2, 4),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(6, 7),
- expCSet: cpuset.NewCPUSet(1, 3, 5, 6, 7),
- },
- {
- description: "SingleSocketHT, NoDeAlloc",
- topo: topoSingleSocketHT,
- containerID: "fakeID2",
- stAssignments: state.ContainerCPUAssignments{
- "fakeID1": cpuset.NewCPUSet(1, 3, 5),
- },
- stDefaultCPUSet: cpuset.NewCPUSet(2, 4, 6, 7),
- expCSet: cpuset.NewCPUSet(2, 4, 6, 7),
- },
- }
- for _, testCase := range testCases {
- policy := NewStaticPolicy(testCase.topo, testCase.numReservedCPUs)
- st := &mockState{
- assignments: testCase.stAssignments,
- defaultCPUSet: testCase.stDefaultCPUSet,
- }
- policy.RemoveContainer(st, testCase.containerID)
- if !reflect.DeepEqual(st.defaultCPUSet, testCase.expCSet) {
- t.Errorf("StaticPolicy RemoveContainer() error (%v). expected default cpuset %v but got %v",
- testCase.description, testCase.expCSet, st.defaultCPUSet)
- }
- if _, found := st.assignments[testCase.containerID]; found {
- t.Errorf("StaticPolicy RemoveContainer() error (%v). expected containerID %v not be in assignments %v",
- testCase.description, testCase.containerID, st.assignments)
- }
- }
- }
|