Commit 94e77bd4 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #54408 from intelsdi-x/cpu-state-file

Automatic merge from submit-queue (batch tested with PRs 54656, 54552, 54389, 53634, 54408). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Add file backed state to cpu manager **What this PR does / why we need it**: Adds file backed `State` implementation to cpu manger with tests. Reads from `State` are done from memory, while each write triggers state save to a file. Any failure in reading the state file results in empty state Next PR: #54409
parents 6fbd2a1a 97e3f7bf
...@@ -32,7 +32,7 @@ import ( ...@@ -32,7 +32,7 @@ import (
) )
type mockState struct { type mockState struct {
assignments map[string]cpuset.CPUSet assignments state.ContainerCPUAssignments
defaultCPUSet cpuset.CPUSet defaultCPUSet cpuset.CPUSet
} }
...@@ -64,6 +64,19 @@ func (s *mockState) Delete(containerID string) { ...@@ -64,6 +64,19 @@ func (s *mockState) Delete(containerID string) {
delete(s.assignments, containerID) delete(s.assignments, containerID)
} }
func (s *mockState) ClearState() {
s.defaultCPUSet = cpuset.CPUSet{}
s.assignments = make(state.ContainerCPUAssignments)
}
func (s *mockState) SetCPUAssignments(a state.ContainerCPUAssignments) {
s.assignments = a.Clone()
}
func (s *mockState) GetCPUAssignments() state.ContainerCPUAssignments {
return s.assignments.Clone()
}
type mockPolicy struct { type mockPolicy struct {
err error err error
} }
...@@ -190,7 +203,7 @@ func TestCPUManagerAdd(t *testing.T) { ...@@ -190,7 +203,7 @@ func TestCPUManagerAdd(t *testing.T) {
err: testCase.regErr, err: testCase.regErr,
}, },
state: &mockState{ state: &mockState{
assignments: map[string]cpuset.CPUSet{}, assignments: state.ContainerCPUAssignments{},
defaultCPUSet: cpuset.NewCPUSet(), defaultCPUSet: cpuset.NewCPUSet(),
}, },
containerRuntime: mockRuntimeService{ containerRuntime: mockRuntimeService{
...@@ -216,7 +229,7 @@ func TestCPUManagerRemove(t *testing.T) { ...@@ -216,7 +229,7 @@ func TestCPUManagerRemove(t *testing.T) {
err: nil, err: nil,
}, },
state: &mockState{ state: &mockState{
assignments: map[string]cpuset.CPUSet{}, assignments: state.ContainerCPUAssignments{},
defaultCPUSet: cpuset.NewCPUSet(), defaultCPUSet: cpuset.NewCPUSet(),
}, },
containerRuntime: mockRuntimeService{}, containerRuntime: mockRuntimeService{},
...@@ -251,7 +264,7 @@ func TestReconcileState(t *testing.T) { ...@@ -251,7 +264,7 @@ func TestReconcileState(t *testing.T) {
activePods []*v1.Pod activePods []*v1.Pod
pspPS v1.PodStatus pspPS v1.PodStatus
pspFound bool pspFound bool
stAssignments map[string]cpuset.CPUSet stAssignments state.ContainerCPUAssignments
stDefaultCPUSet cpuset.CPUSet stDefaultCPUSet cpuset.CPUSet
updateErr error updateErr error
expectFailedContainerName string expectFailedContainerName string
...@@ -282,7 +295,7 @@ func TestReconcileState(t *testing.T) { ...@@ -282,7 +295,7 @@ func TestReconcileState(t *testing.T) {
}, },
}, },
pspFound: true, pspFound: true,
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID": cpuset.NewCPUSet(1, 2), "fakeID": cpuset.NewCPUSet(1, 2),
}, },
stDefaultCPUSet: cpuset.NewCPUSet(3, 4, 5, 6, 7), stDefaultCPUSet: cpuset.NewCPUSet(3, 4, 5, 6, 7),
...@@ -308,7 +321,7 @@ func TestReconcileState(t *testing.T) { ...@@ -308,7 +321,7 @@ func TestReconcileState(t *testing.T) {
}, },
pspPS: v1.PodStatus{}, pspPS: v1.PodStatus{},
pspFound: false, pspFound: false,
stAssignments: map[string]cpuset.CPUSet{}, stAssignments: state.ContainerCPUAssignments{},
stDefaultCPUSet: cpuset.NewCPUSet(), stDefaultCPUSet: cpuset.NewCPUSet(),
updateErr: nil, updateErr: nil,
expectFailedContainerName: "fakeName", expectFailedContainerName: "fakeName",
...@@ -339,7 +352,7 @@ func TestReconcileState(t *testing.T) { ...@@ -339,7 +352,7 @@ func TestReconcileState(t *testing.T) {
}, },
}, },
pspFound: true, pspFound: true,
stAssignments: map[string]cpuset.CPUSet{}, stAssignments: state.ContainerCPUAssignments{},
stDefaultCPUSet: cpuset.NewCPUSet(), stDefaultCPUSet: cpuset.NewCPUSet(),
updateErr: nil, updateErr: nil,
expectFailedContainerName: "fakeName", expectFailedContainerName: "fakeName",
...@@ -370,7 +383,7 @@ func TestReconcileState(t *testing.T) { ...@@ -370,7 +383,7 @@ func TestReconcileState(t *testing.T) {
}, },
}, },
pspFound: true, pspFound: true,
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID": cpuset.NewCPUSet(), "fakeID": cpuset.NewCPUSet(),
}, },
stDefaultCPUSet: cpuset.NewCPUSet(1, 2, 3, 4, 5, 6, 7), stDefaultCPUSet: cpuset.NewCPUSet(1, 2, 3, 4, 5, 6, 7),
...@@ -403,7 +416,7 @@ func TestReconcileState(t *testing.T) { ...@@ -403,7 +416,7 @@ func TestReconcileState(t *testing.T) {
}, },
}, },
pspFound: true, pspFound: true,
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID": cpuset.NewCPUSet(1, 2), "fakeID": cpuset.NewCPUSet(1, 2),
}, },
stDefaultCPUSet: cpuset.NewCPUSet(3, 4, 5, 6, 7), stDefaultCPUSet: cpuset.NewCPUSet(3, 4, 5, 6, 7),
......
...@@ -19,6 +19,7 @@ package cpumanager ...@@ -19,6 +19,7 @@ package cpumanager
import ( import (
"testing" "testing"
"k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/state"
"k8s.io/kubernetes/pkg/kubelet/cm/cpuset" "k8s.io/kubernetes/pkg/kubelet/cm/cpuset"
) )
...@@ -36,7 +37,7 @@ func TestNonePolicyAdd(t *testing.T) { ...@@ -36,7 +37,7 @@ func TestNonePolicyAdd(t *testing.T) {
policy := &nonePolicy{} policy := &nonePolicy{}
st := &mockState{ st := &mockState{
assignments: map[string]cpuset.CPUSet{}, assignments: state.ContainerCPUAssignments{},
defaultCPUSet: cpuset.NewCPUSet(1, 2, 3, 4, 5, 6, 7), defaultCPUSet: cpuset.NewCPUSet(1, 2, 3, 4, 5, 6, 7),
} }
...@@ -53,7 +54,7 @@ func TestNonePolicyRemove(t *testing.T) { ...@@ -53,7 +54,7 @@ func TestNonePolicyRemove(t *testing.T) {
policy := &nonePolicy{} policy := &nonePolicy{}
st := &mockState{ st := &mockState{
assignments: map[string]cpuset.CPUSet{}, assignments: state.ContainerCPUAssignments{},
defaultCPUSet: cpuset.NewCPUSet(1, 2, 3, 4, 5, 6, 7), defaultCPUSet: cpuset.NewCPUSet(1, 2, 3, 4, 5, 6, 7),
} }
......
...@@ -22,6 +22,7 @@ import ( ...@@ -22,6 +22,7 @@ import (
"testing" "testing"
"k8s.io/api/core/v1" "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/cpumanager/topology"
"k8s.io/kubernetes/pkg/kubelet/cm/cpuset" "k8s.io/kubernetes/pkg/kubelet/cm/cpuset"
) )
...@@ -31,7 +32,7 @@ type staticPolicyTest struct { ...@@ -31,7 +32,7 @@ type staticPolicyTest struct {
topo *topology.CPUTopology topo *topology.CPUTopology
numReservedCPUs int numReservedCPUs int
containerID string containerID string
stAssignments map[string]cpuset.CPUSet stAssignments state.ContainerCPUAssignments
stDefaultCPUSet cpuset.CPUSet stDefaultCPUSet cpuset.CPUSet
pod *v1.Pod pod *v1.Pod
expErr error expErr error
...@@ -53,7 +54,7 @@ func TestStaticPolicyStart(t *testing.T) { ...@@ -53,7 +54,7 @@ func TestStaticPolicyStart(t *testing.T) {
policy := NewStaticPolicy(topoSingleSocketHT, 1).(*staticPolicy) policy := NewStaticPolicy(topoSingleSocketHT, 1).(*staticPolicy)
st := &mockState{ st := &mockState{
assignments: map[string]cpuset.CPUSet{}, assignments: state.ContainerCPUAssignments{},
defaultCPUSet: cpuset.NewCPUSet(), defaultCPUSet: cpuset.NewCPUSet(),
} }
...@@ -88,7 +89,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -88,7 +89,7 @@ func TestStaticPolicyAdd(t *testing.T) {
topo: topoSingleSocketHT, topo: topoSingleSocketHT,
numReservedCPUs: 1, numReservedCPUs: 1,
containerID: "fakeID2", containerID: "fakeID2",
stAssignments: map[string]cpuset.CPUSet{}, stAssignments: state.ContainerCPUAssignments{},
stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7), stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
pod: makePod("8000m", "8000m"), pod: makePod("8000m", "8000m"),
expErr: fmt.Errorf("not enough cpus available to satisfy request"), expErr: fmt.Errorf("not enough cpus available to satisfy request"),
...@@ -100,7 +101,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -100,7 +101,7 @@ func TestStaticPolicyAdd(t *testing.T) {
topo: topoSingleSocketHT, topo: topoSingleSocketHT,
numReservedCPUs: 1, numReservedCPUs: 1,
containerID: "fakeID2", containerID: "fakeID2",
stAssignments: map[string]cpuset.CPUSet{}, stAssignments: state.ContainerCPUAssignments{},
stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7), stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
pod: makePod("1000m", "1000m"), pod: makePod("1000m", "1000m"),
expErr: nil, expErr: nil,
...@@ -112,7 +113,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -112,7 +113,7 @@ func TestStaticPolicyAdd(t *testing.T) {
topo: topoSingleSocketHT, topo: topoSingleSocketHT,
numReservedCPUs: 1, numReservedCPUs: 1,
containerID: "fakeID3", containerID: "fakeID3",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID100": cpuset.NewCPUSet(2, 3, 6, 7), "fakeID100": cpuset.NewCPUSet(2, 3, 6, 7),
}, },
stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 4, 5), stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 4, 5),
...@@ -126,7 +127,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -126,7 +127,7 @@ func TestStaticPolicyAdd(t *testing.T) {
topo: topoDualSocketHT, topo: topoDualSocketHT,
numReservedCPUs: 1, numReservedCPUs: 1,
containerID: "fakeID3", containerID: "fakeID3",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID100": cpuset.NewCPUSet(2), "fakeID100": cpuset.NewCPUSet(2),
}, },
stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11), stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11),
...@@ -140,7 +141,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -140,7 +141,7 @@ func TestStaticPolicyAdd(t *testing.T) {
topo: topoDualSocketHT, topo: topoDualSocketHT,
numReservedCPUs: 1, numReservedCPUs: 1,
containerID: "fakeID3", containerID: "fakeID3",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID100": cpuset.NewCPUSet(1, 5), "fakeID100": cpuset.NewCPUSet(1, 5),
}, },
stDefaultCPUSet: cpuset.NewCPUSet(0, 2, 3, 4, 6, 7, 8, 9, 10, 11), stDefaultCPUSet: cpuset.NewCPUSet(0, 2, 3, 4, 6, 7, 8, 9, 10, 11),
...@@ -154,7 +155,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -154,7 +155,7 @@ func TestStaticPolicyAdd(t *testing.T) {
topo: topoDualSocketNoHT, topo: topoDualSocketNoHT,
numReservedCPUs: 1, numReservedCPUs: 1,
containerID: "fakeID1", containerID: "fakeID1",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID100": cpuset.NewCPUSet(), "fakeID100": cpuset.NewCPUSet(),
}, },
stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 3, 4, 5, 6, 7), stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 3, 4, 5, 6, 7),
...@@ -168,7 +169,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -168,7 +169,7 @@ func TestStaticPolicyAdd(t *testing.T) {
topo: topoDualSocketNoHT, topo: topoDualSocketNoHT,
numReservedCPUs: 1, numReservedCPUs: 1,
containerID: "fakeID1", containerID: "fakeID1",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID100": cpuset.NewCPUSet(4, 5), "fakeID100": cpuset.NewCPUSet(4, 5),
}, },
stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 3, 6, 7), stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 3, 6, 7),
...@@ -182,7 +183,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -182,7 +183,7 @@ func TestStaticPolicyAdd(t *testing.T) {
topo: topoDualSocketHT, topo: topoDualSocketHT,
numReservedCPUs: 1, numReservedCPUs: 1,
containerID: "fakeID3", containerID: "fakeID3",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID100": cpuset.NewCPUSet(2), "fakeID100": cpuset.NewCPUSet(2),
}, },
stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11), stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11),
...@@ -196,7 +197,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -196,7 +197,7 @@ func TestStaticPolicyAdd(t *testing.T) {
topo: topoSingleSocketHT, topo: topoSingleSocketHT,
numReservedCPUs: 1, numReservedCPUs: 1,
containerID: "fakeID1", containerID: "fakeID1",
stAssignments: map[string]cpuset.CPUSet{}, stAssignments: state.ContainerCPUAssignments{},
stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7), stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
pod: makePod("1000m", "2000m"), pod: makePod("1000m", "2000m"),
expErr: nil, expErr: nil,
...@@ -208,7 +209,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -208,7 +209,7 @@ func TestStaticPolicyAdd(t *testing.T) {
topo: topoSingleSocketHT, topo: topoSingleSocketHT,
numReservedCPUs: 1, numReservedCPUs: 1,
containerID: "fakeID4", containerID: "fakeID4",
stAssignments: map[string]cpuset.CPUSet{}, stAssignments: state.ContainerCPUAssignments{},
stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7), stDefaultCPUSet: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7),
pod: makePod("977m", "977m"), pod: makePod("977m", "977m"),
expErr: nil, expErr: nil,
...@@ -220,7 +221,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -220,7 +221,7 @@ func TestStaticPolicyAdd(t *testing.T) {
topo: topoSingleSocketHT, topo: topoSingleSocketHT,
numReservedCPUs: 1, numReservedCPUs: 1,
containerID: "fakeID5", containerID: "fakeID5",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID100": cpuset.NewCPUSet(1, 2, 3, 4, 5, 6), "fakeID100": cpuset.NewCPUSet(1, 2, 3, 4, 5, 6),
}, },
stDefaultCPUSet: cpuset.NewCPUSet(0, 7), stDefaultCPUSet: cpuset.NewCPUSet(0, 7),
...@@ -234,7 +235,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -234,7 +235,7 @@ func TestStaticPolicyAdd(t *testing.T) {
topo: topoDualSocketHT, topo: topoDualSocketHT,
numReservedCPUs: 1, numReservedCPUs: 1,
containerID: "fakeID5", containerID: "fakeID5",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID100": cpuset.NewCPUSet(1, 2, 3), "fakeID100": cpuset.NewCPUSet(1, 2, 3),
}, },
stDefaultCPUSet: cpuset.NewCPUSet(0, 4, 5, 6, 7, 8, 9, 10, 11), stDefaultCPUSet: cpuset.NewCPUSet(0, 4, 5, 6, 7, 8, 9, 10, 11),
...@@ -250,7 +251,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -250,7 +251,7 @@ func TestStaticPolicyAdd(t *testing.T) {
description: "GuPodMultipleCores, topoQuadSocketFourWayHT, ExpectAllocSock0", description: "GuPodMultipleCores, topoQuadSocketFourWayHT, ExpectAllocSock0",
topo: topoQuadSocketFourWayHT, topo: topoQuadSocketFourWayHT,
containerID: "fakeID5", containerID: "fakeID5",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID100": cpuset.NewCPUSet(3, 11, 4, 5, 6, 7), "fakeID100": cpuset.NewCPUSet(3, 11, 4, 5, 6, 7),
}, },
stDefaultCPUSet: largeTopoCPUSet.Difference(cpuset.NewCPUSet(3, 11, 4, 5, 6, 7)), stDefaultCPUSet: largeTopoCPUSet.Difference(cpuset.NewCPUSet(3, 11, 4, 5, 6, 7)),
...@@ -265,7 +266,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -265,7 +266,7 @@ func TestStaticPolicyAdd(t *testing.T) {
description: "GuPodMultipleCores, topoQuadSocketFourWayHT, ExpectAllocAllFullCoresFromThreeSockets", description: "GuPodMultipleCores, topoQuadSocketFourWayHT, ExpectAllocAllFullCoresFromThreeSockets",
topo: topoQuadSocketFourWayHT, topo: topoQuadSocketFourWayHT,
containerID: "fakeID5", containerID: "fakeID5",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID100": largeTopoCPUSet.Difference(cpuset.NewCPUSet(1, 25, 13, 38, 2, 9, 11, 35, 23, 48, 12, 51, "fakeID100": largeTopoCPUSet.Difference(cpuset.NewCPUSet(1, 25, 13, 38, 2, 9, 11, 35, 23, 48, 12, 51,
53, 173, 113, 233, 54, 61)), 53, 173, 113, 233, 54, 61)),
}, },
...@@ -281,7 +282,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -281,7 +282,7 @@ func TestStaticPolicyAdd(t *testing.T) {
description: "GuPodMultipleCores, topoQuadSocketFourWayHT, ExpectAllocAllSock1+FullCore", description: "GuPodMultipleCores, topoQuadSocketFourWayHT, ExpectAllocAllSock1+FullCore",
topo: topoQuadSocketFourWayHT, topo: topoQuadSocketFourWayHT,
containerID: "fakeID5", containerID: "fakeID5",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID100": largeTopoCPUSet.Difference(largeTopoSock1CPUSet.Union(cpuset.NewCPUSet(10, 34, 22, 47, 53, "fakeID100": largeTopoCPUSet.Difference(largeTopoSock1CPUSet.Union(cpuset.NewCPUSet(10, 34, 22, 47, 53,
173, 61, 181, 108, 228, 115, 235))), 173, 61, 181, 108, 228, 115, 235))),
}, },
...@@ -298,7 +299,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -298,7 +299,7 @@ func TestStaticPolicyAdd(t *testing.T) {
description: "GuPodMultipleCores, topoQuadSocketFourWayHT, ExpectAllocCPUs", description: "GuPodMultipleCores, topoQuadSocketFourWayHT, ExpectAllocCPUs",
topo: topoQuadSocketFourWayHT, topo: topoQuadSocketFourWayHT,
containerID: "fakeID5", containerID: "fakeID5",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID100": largeTopoCPUSet.Difference(cpuset.NewCPUSet(10, 11, 53, 37, 55, 67, 52)), "fakeID100": largeTopoCPUSet.Difference(cpuset.NewCPUSet(10, 11, 53, 37, 55, 67, 52)),
}, },
stDefaultCPUSet: cpuset.NewCPUSet(10, 11, 53, 67, 52), stDefaultCPUSet: cpuset.NewCPUSet(10, 11, 53, 67, 52),
...@@ -314,7 +315,7 @@ func TestStaticPolicyAdd(t *testing.T) { ...@@ -314,7 +315,7 @@ func TestStaticPolicyAdd(t *testing.T) {
description: "GuPodMultipleCores, topoQuadSocketFourWayHT, NoAlloc", description: "GuPodMultipleCores, topoQuadSocketFourWayHT, NoAlloc",
topo: topoQuadSocketFourWayHT, topo: topoQuadSocketFourWayHT,
containerID: "fakeID5", containerID: "fakeID5",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID100": largeTopoCPUSet.Difference(cpuset.NewCPUSet(10, 11, 53, 37, 55, 67, 52)), "fakeID100": largeTopoCPUSet.Difference(cpuset.NewCPUSet(10, 11, 53, 37, 55, 67, 52)),
}, },
stDefaultCPUSet: cpuset.NewCPUSet(10, 11, 53, 37, 55, 67, 52), stDefaultCPUSet: cpuset.NewCPUSet(10, 11, 53, 37, 55, 67, 52),
...@@ -374,7 +375,7 @@ func TestStaticPolicyRemove(t *testing.T) { ...@@ -374,7 +375,7 @@ func TestStaticPolicyRemove(t *testing.T) {
description: "SingleSocketHT, DeAllocOneContainer", description: "SingleSocketHT, DeAllocOneContainer",
topo: topoSingleSocketHT, topo: topoSingleSocketHT,
containerID: "fakeID1", containerID: "fakeID1",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID1": cpuset.NewCPUSet(1, 2, 3), "fakeID1": cpuset.NewCPUSet(1, 2, 3),
}, },
stDefaultCPUSet: cpuset.NewCPUSet(4, 5, 6, 7), stDefaultCPUSet: cpuset.NewCPUSet(4, 5, 6, 7),
...@@ -384,7 +385,7 @@ func TestStaticPolicyRemove(t *testing.T) { ...@@ -384,7 +385,7 @@ func TestStaticPolicyRemove(t *testing.T) {
description: "SingleSocketHT, DeAllocOneContainer, BeginEmpty", description: "SingleSocketHT, DeAllocOneContainer, BeginEmpty",
topo: topoSingleSocketHT, topo: topoSingleSocketHT,
containerID: "fakeID1", containerID: "fakeID1",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID1": cpuset.NewCPUSet(1, 2, 3), "fakeID1": cpuset.NewCPUSet(1, 2, 3),
"fakeID2": cpuset.NewCPUSet(4, 5, 6, 7), "fakeID2": cpuset.NewCPUSet(4, 5, 6, 7),
}, },
...@@ -395,7 +396,7 @@ func TestStaticPolicyRemove(t *testing.T) { ...@@ -395,7 +396,7 @@ func TestStaticPolicyRemove(t *testing.T) {
description: "SingleSocketHT, DeAllocTwoContainer", description: "SingleSocketHT, DeAllocTwoContainer",
topo: topoSingleSocketHT, topo: topoSingleSocketHT,
containerID: "fakeID1", containerID: "fakeID1",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID1": cpuset.NewCPUSet(1, 3, 5), "fakeID1": cpuset.NewCPUSet(1, 3, 5),
"fakeID2": cpuset.NewCPUSet(2, 4), "fakeID2": cpuset.NewCPUSet(2, 4),
}, },
...@@ -406,7 +407,7 @@ func TestStaticPolicyRemove(t *testing.T) { ...@@ -406,7 +407,7 @@ func TestStaticPolicyRemove(t *testing.T) {
description: "SingleSocketHT, NoDeAlloc", description: "SingleSocketHT, NoDeAlloc",
topo: topoSingleSocketHT, topo: topoSingleSocketHT,
containerID: "fakeID2", containerID: "fakeID2",
stAssignments: map[string]cpuset.CPUSet{ stAssignments: state.ContainerCPUAssignments{
"fakeID1": cpuset.NewCPUSet(1, 3, 5), "fakeID1": cpuset.NewCPUSet(1, 3, 5),
}, },
stDefaultCPUSet: cpuset.NewCPUSet(2, 4, 6, 7), stDefaultCPUSet: cpuset.NewCPUSet(2, 4, 6, 7),
......
load("@io_bazel_rules_go//go:def.bzl", "go_library") load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"state.go", "state.go",
"state_file.go",
"state_mem.go", "state_mem.go",
], ],
importpath = "k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/state", importpath = "k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/state",
...@@ -14,6 +15,14 @@ go_library( ...@@ -14,6 +15,14 @@ go_library(
], ],
) )
go_test(
name = "go_default_test",
srcs = ["state_file_test.go"],
importpath = "k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/state",
library = ":go_default_library",
deps = ["//pkg/kubelet/cm/cpuset:go_default_library"],
)
filegroup( filegroup(
name = "package-srcs", name = "package-srcs",
srcs = glob(["**"]), srcs = glob(["**"]),
......
...@@ -20,17 +20,32 @@ import ( ...@@ -20,17 +20,32 @@ import (
"k8s.io/kubernetes/pkg/kubelet/cm/cpuset" "k8s.io/kubernetes/pkg/kubelet/cm/cpuset"
) )
// ContainerCPUAssignments type used in cpu manger state
type ContainerCPUAssignments map[string]cpuset.CPUSet
// Clone returns a copy of ContainerCPUAssignments
func (as ContainerCPUAssignments) Clone() ContainerCPUAssignments {
ret := make(ContainerCPUAssignments)
for key, val := range as {
ret[key] = val
}
return ret
}
// Reader interface used to read current cpu/pod assignment state // Reader interface used to read current cpu/pod assignment state
type Reader interface { type Reader interface {
GetCPUSet(containerID string) (cpuset.CPUSet, bool) GetCPUSet(containerID string) (cpuset.CPUSet, bool)
GetDefaultCPUSet() cpuset.CPUSet GetDefaultCPUSet() cpuset.CPUSet
GetCPUSetOrDefault(containerID string) cpuset.CPUSet GetCPUSetOrDefault(containerID string) cpuset.CPUSet
GetCPUAssignments() ContainerCPUAssignments
} }
type writer interface { type writer interface {
SetCPUSet(containerID string, cpuset cpuset.CPUSet) SetCPUSet(containerID string, cpuset cpuset.CPUSet)
SetDefaultCPUSet(cpuset cpuset.CPUSet) SetDefaultCPUSet(cpuset cpuset.CPUSet)
SetCPUAssignments(ContainerCPUAssignments)
Delete(containerID string) Delete(containerID string)
ClearState()
} }
// State interface provides methods for tracking and setting cpu/pod assignment // State interface provides methods for tracking and setting cpu/pod assignment
......
/*
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 state
import (
"encoding/json"
"github.com/golang/glog"
"io/ioutil"
"k8s.io/kubernetes/pkg/kubelet/cm/cpuset"
"os"
"sync"
)
type stateFileData struct {
DefaultCPUSet string `json:"defaultCpuSet"`
Entries map[string]string `json:"entries,omitempty"`
}
var _ State = &stateFile{}
type stateFile struct {
sync.RWMutex
stateFilePath string
cache State
}
// NewFileState creates new State for keeping track of cpu/pod assignment with file backend
func NewFileState(filePath string) State {
stateFile := &stateFile{
stateFilePath: filePath,
cache: NewMemoryState(),
}
if err := stateFile.tryRestoreState(); err != nil {
// could not restore state, init new state file
glog.Infof("[cpumanager] state file: initializing empty state file")
stateFile.cache.ClearState()
stateFile.storeState()
}
return stateFile
}
// tryRestoreState tries to read state file, upon any error,
// err message is logged and state is left clean. un-initialized
func (sf *stateFile) tryRestoreState() error {
sf.Lock()
defer sf.Unlock()
var err error
// used when all parsing is ok
tmpAssignments := make(ContainerCPUAssignments)
tmpDefaultCPUSet := cpuset.NewCPUSet()
tmpContainerCPUSet := cpuset.NewCPUSet()
var content []byte
if content, err = ioutil.ReadFile(sf.stateFilePath); os.IsNotExist(err) {
// Create file
if _, err = os.Create(sf.stateFilePath); err != nil {
glog.Errorf("[cpumanager] state file: unable to create state file \"%s\":%s", sf.stateFilePath, err.Error())
panic("[cpumanager] state file not created")
}
glog.Infof("[cpumanager] state file: created empty state file \"%s\"", sf.stateFilePath)
} else {
// File exists - try to read
var readState stateFileData
if err = json.Unmarshal(content, &readState); err != nil {
glog.Warningf("[cpumanager] state file: could not unmarshal, corrupted state file - \"%s\"", sf.stateFilePath)
return err
}
if tmpDefaultCPUSet, err = cpuset.Parse(readState.DefaultCPUSet); err != nil {
glog.Warningf("[cpumanager] state file: could not parse state file - [defaultCpuSet:\"%s\"]", readState.DefaultCPUSet)
return err
}
for containerID, cpuString := range readState.Entries {
if tmpContainerCPUSet, err = cpuset.Parse(cpuString); err != nil {
glog.Warningf("[cpumanager] state file: could not parse state file - container id: %s, cpuset: \"%s\"", containerID, cpuString)
return err
}
tmpAssignments[containerID] = tmpContainerCPUSet
}
sf.cache.SetDefaultCPUSet(tmpDefaultCPUSet)
sf.cache.SetCPUAssignments(tmpAssignments)
glog.V(2).Infof("[cpumanager] state file: restored state from state file \"%s\"", sf.stateFilePath)
glog.V(2).Infof("[cpumanager] state file: defaultCPUSet: %s", tmpDefaultCPUSet.String())
}
return nil
}
// saves state to a file, caller is responsible for locking
func (sf *stateFile) storeState() {
var content []byte
var err error
data := stateFileData{
DefaultCPUSet: sf.cache.GetDefaultCPUSet().String(),
Entries: map[string]string{},
}
for containerID, cset := range sf.cache.GetCPUAssignments() {
data.Entries[containerID] = cset.String()
}
if content, err = json.Marshal(data); err != nil {
panic("[cpumanager] state file: could not serialize state to json")
}
if err = ioutil.WriteFile(sf.stateFilePath, content, 0644); err != nil {
panic("[cpumanager] state file not written")
}
return
}
func (sf *stateFile) GetCPUSet(containerID string) (cpuset.CPUSet, bool) {
sf.RLock()
defer sf.RUnlock()
res, ok := sf.cache.GetCPUSet(containerID)
return res, ok
}
func (sf *stateFile) GetDefaultCPUSet() cpuset.CPUSet {
sf.RLock()
defer sf.RUnlock()
return sf.cache.GetDefaultCPUSet()
}
func (sf *stateFile) GetCPUSetOrDefault(containerID string) cpuset.CPUSet {
sf.RLock()
defer sf.RUnlock()
return sf.cache.GetCPUSetOrDefault(containerID)
}
func (sf *stateFile) GetCPUAssignments() ContainerCPUAssignments {
sf.RLock()
defer sf.RUnlock()
return sf.cache.GetCPUAssignments()
}
func (sf *stateFile) SetCPUSet(containerID string, cset cpuset.CPUSet) {
sf.Lock()
defer sf.Unlock()
sf.cache.SetCPUSet(containerID, cset)
sf.storeState()
}
func (sf *stateFile) SetDefaultCPUSet(cset cpuset.CPUSet) {
sf.Lock()
defer sf.Unlock()
sf.cache.SetDefaultCPUSet(cset)
sf.storeState()
}
func (sf *stateFile) SetCPUAssignments(a ContainerCPUAssignments) {
sf.Lock()
defer sf.Unlock()
sf.cache.SetCPUAssignments(a)
sf.storeState()
}
func (sf *stateFile) Delete(containerID string) {
sf.Lock()
defer sf.Unlock()
sf.cache.Delete(containerID)
sf.storeState()
}
func (sf *stateFile) ClearState() {
sf.Lock()
defer sf.Unlock()
sf.cache.ClearState()
sf.storeState()
}
...@@ -25,7 +25,7 @@ import ( ...@@ -25,7 +25,7 @@ import (
type stateMemory struct { type stateMemory struct {
sync.RWMutex sync.RWMutex
assignments map[string]cpuset.CPUSet assignments ContainerCPUAssignments
defaultCPUSet cpuset.CPUSet defaultCPUSet cpuset.CPUSet
} }
...@@ -35,7 +35,7 @@ var _ State = &stateMemory{} ...@@ -35,7 +35,7 @@ var _ State = &stateMemory{}
func NewMemoryState() State { func NewMemoryState() State {
glog.Infof("[cpumanager] initializing new in-memory state store") glog.Infof("[cpumanager] initializing new in-memory state store")
return &stateMemory{ return &stateMemory{
assignments: map[string]cpuset.CPUSet{}, assignments: ContainerCPUAssignments{},
defaultCPUSet: cpuset.NewCPUSet(), defaultCPUSet: cpuset.NewCPUSet(),
} }
} }
...@@ -65,6 +65,12 @@ func (s *stateMemory) GetCPUSetOrDefault(containerID string) cpuset.CPUSet { ...@@ -65,6 +65,12 @@ func (s *stateMemory) GetCPUSetOrDefault(containerID string) cpuset.CPUSet {
return s.GetDefaultCPUSet() return s.GetDefaultCPUSet()
} }
func (s *stateMemory) GetCPUAssignments() ContainerCPUAssignments {
s.RLock()
defer s.RUnlock()
return s.assignments.Clone()
}
func (s *stateMemory) SetCPUSet(containerID string, cset cpuset.CPUSet) { func (s *stateMemory) SetCPUSet(containerID string, cset cpuset.CPUSet) {
s.Lock() s.Lock()
defer s.Unlock() defer s.Unlock()
...@@ -81,6 +87,14 @@ func (s *stateMemory) SetDefaultCPUSet(cset cpuset.CPUSet) { ...@@ -81,6 +87,14 @@ func (s *stateMemory) SetDefaultCPUSet(cset cpuset.CPUSet) {
glog.Infof("[cpumanager] updated default cpuset: \"%s\"", cset) glog.Infof("[cpumanager] updated default cpuset: \"%s\"", cset)
} }
func (s *stateMemory) SetCPUAssignments(a ContainerCPUAssignments) {
s.Lock()
defer s.Unlock()
s.assignments = a.Clone()
glog.Infof("[cpumanager] updated cpuset assignments: \"%v\"", a)
}
func (s *stateMemory) Delete(containerID string) { func (s *stateMemory) Delete(containerID string) {
s.Lock() s.Lock()
defer s.Unlock() defer s.Unlock()
...@@ -88,3 +102,12 @@ func (s *stateMemory) Delete(containerID string) { ...@@ -88,3 +102,12 @@ func (s *stateMemory) Delete(containerID string) {
delete(s.assignments, containerID) delete(s.assignments, containerID)
glog.V(2).Infof("[cpumanager] deleted cpuset assignment (container id: %s)", containerID) glog.V(2).Infof("[cpumanager] deleted cpuset assignment (container id: %s)", containerID)
} }
func (s *stateMemory) ClearState() {
s.Lock()
defer s.Unlock()
s.defaultCPUSet = cpuset.CPUSet{}
s.assignments = make(ContainerCPUAssignments)
glog.V(2).Infof("[cpumanager] cleared state")
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment