From 6bfceed4ab5e4c366e08162cc4cb7829ef8c48ed Mon Sep 17 00:00:00 2001 From: Klaudiusz Dembler Date: Thu, 1 Feb 2018 19:35:14 +0100 Subject: [PATCH 01/12] Migrate cpumanager to use checkpointing manager --- pkg/kubelet/cm/cpumanager/cpu_manager.go | 7 +- pkg/kubelet/cm/cpumanager/state/checkpoint.go | 72 +++++++ .../cm/cpumanager/state/state_checkpoint.go | 185 ++++++++++++++++++ 3 files changed, 261 insertions(+), 3 deletions(-) create mode 100644 pkg/kubelet/cm/cpumanager/state/checkpoint.go create mode 100644 pkg/kubelet/cm/cpumanager/state/state_checkpoint.go diff --git a/pkg/kubelet/cm/cpumanager/cpu_manager.go b/pkg/kubelet/cm/cpumanager/cpu_manager.go index b52fe59a12d..ed185bc2cc5 100644 --- a/pkg/kubelet/cm/cpumanager/cpu_manager.go +++ b/pkg/kubelet/cm/cpumanager/cpu_manager.go @@ -137,9 +137,10 @@ func NewManager(cpuPolicyName string, reconcilePeriod time.Duration, machineInfo policy = NewNonePolicy() } - stateImpl := state.NewFileState( - path.Join(stateFileDirecory, CPUManagerStateFileName), - policy.Name()) + stateImpl, err := state.NewCheckpointState(stateFileDirecory, policy.Name()) + if err != nil { + return nil, fmt.Errorf("could not initialize checkpoint manager: %v", err) + } manager := &manager{ policy: policy, diff --git a/pkg/kubelet/cm/cpumanager/state/checkpoint.go b/pkg/kubelet/cm/cpumanager/state/checkpoint.go new file mode 100644 index 00000000000..e1a86b1b021 --- /dev/null +++ b/pkg/kubelet/cm/cpumanager/state/checkpoint.go @@ -0,0 +1,72 @@ +/* +Copyright 2018 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" + "hash/fnv" + + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors" + hashutil "k8s.io/kubernetes/pkg/util/hash" +) + +var _ checkpointmanager.Checkpoint = &cpuManagerCheckpoint {} + +// cpuManagerCheckpoint struct is used to store cpu/pod assignments in a checkpoint +type cpuManagerCheckpoint struct { + PolicyName string + DefaultCPUSet string + Entries map[string]string + Checksum uint64 +} + +// NewCPUManagerCheckpoint returns an instance of Checkpoint +func NewCPUManagerCheckpoint() *cpuManagerCheckpoint { + return &cpuManagerCheckpoint{Entries: make(map[string]string)} +} + +// MarshalCheckpoint returns marshalled checkpoint +func (cp *cpuManagerCheckpoint) MarshalCheckpoint() ([]byte, error) { + return json.Marshal(*cp) +} + +// UnmarshalCheckpoint tries to unmarshal passed bytes to checkpoint +func (cp *cpuManagerCheckpoint) UnmarshalCheckpoint(blob []byte) error { + if err := json.Unmarshal(blob, cp); err != nil { + return err + } + if cp.Checksum != cp.GetChecksum() { + return errors.ErrCorruptCheckpoint + } + return nil +} + +// GetChecksum returns calculated checksum of checkpoint +func (cp *cpuManagerCheckpoint) GetChecksum() uint64 { + orig := cp.Checksum + cp.Checksum = 0 + hash := fnv.New32a() + hashutil.DeepHashObject(hash, *cp) + cp.Checksum = orig + return uint64(hash.Sum32()) +} + +// UpdateChecksum calculates and updates checksum of the checkpoint +func (cp *cpuManagerCheckpoint) UpdateChecksum() { + cp.Checksum = cp.GetChecksum() +} diff --git a/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go b/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go new file mode 100644 index 00000000000..0656fa9954f --- /dev/null +++ b/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go @@ -0,0 +1,185 @@ +/* +Copyright 2018 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 ( + "fmt" + "github.com/golang/glog" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors" + "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" + "path" + "sync" +) + +// cpuManagerCheckpointName is the name of checkpoint file +const cpuManagerCheckpointName = "cpu_manager_state" + +var _ State = &stateCheckpoint{} + +type stateCheckpoint struct { + mux sync.RWMutex + policyName string + cache State + checkpointManager checkpointmanager.CheckpointManager +} + +// NewCheckpointState creates new State for keeping track of cpu/pod assignment with checkpoint backend +func NewCheckpointState(stateDir string, policyName string) (State, error) { + checkpointManager, err := checkpointmanager.NewCheckpointManager(stateDir) + if err != nil { + return nil, fmt.Errorf("failed to initialize checkpoint manager: %v", err) + } + stateCheckpoint := &stateCheckpoint{ + cache: NewMemoryState(), + policyName: policyName, + checkpointManager: checkpointManager, + } + + if err := stateCheckpoint.tryRestoreState(); err != nil { + return nil, fmt.Errorf("unable to restore state from checkpoint: %v\n"+ + "Please drain this node and delete the CPU manager checkpoint file %q before restarting Kubelet.", + err, path.Join(stateDir, cpuManagerCheckpointName)) + } + + return stateCheckpoint, nil +} + +// tryRestoreState tries to read checkpoint and creates it if it doesn't exist +func (sc *stateCheckpoint) tryRestoreState() error { + sc.mux.Lock() + defer sc.mux.Unlock() + var err error + + // used when all parsing is ok + tmpAssignments := make(ContainerCPUAssignments) + tmpDefaultCPUSet := cpuset.NewCPUSet() + tmpContainerCPUSet := cpuset.NewCPUSet() + + checkpoint := NewCPUManagerCheckpoint() + if err = sc.checkpointManager.GetCheckpoint(cpuManagerCheckpointName, checkpoint); err != nil { + if err == errors.ErrCheckpointNotFound { + sc.storeState() + return nil + } + return err + } + + if sc.policyName != checkpoint.PolicyName { + return fmt.Errorf("policy configured %q != policy from state checkpoint %q", sc.policyName, checkpoint.PolicyName) + } + + if tmpDefaultCPUSet, err = cpuset.Parse(checkpoint.DefaultCPUSet); err != nil { + return fmt.Errorf("could not parse state checkpoint - [defaultCpuSet: %q]", checkpoint.DefaultCPUSet) + } + + for containerID, cpuString := range checkpoint.Entries { + if tmpContainerCPUSet, err = cpuset.Parse(cpuString); err != nil { + return fmt.Errorf("could not parse state checkpoint - container id: %q, cpuset: %q", containerID, cpuString) + } + tmpAssignments[containerID] = tmpContainerCPUSet + } + + sc.cache.SetDefaultCPUSet(tmpDefaultCPUSet) + sc.cache.SetCPUAssignments(tmpAssignments) + + glog.V(2).Info("[cpumanager] state checkpoint: restored state from checkpoint") + glog.V(2).Infof("[cpumanager] state checkpoint: defaultCPUSet: %s", tmpDefaultCPUSet.String()) + + return nil +} + +// saves state to a checkpoint, caller is responsible for locking +func (sc *stateCheckpoint) storeState() { + checkpoint := NewCPUManagerCheckpoint() + checkpoint.PolicyName = sc.policyName + checkpoint.DefaultCPUSet = sc.cache.GetDefaultCPUSet().String() + + for containerID, cset := range sc.cache.GetCPUAssignments() { + checkpoint.Entries[containerID] = cset.String() + } + + err := sc.checkpointManager.CreateCheckpoint(cpuManagerCheckpointName, checkpoint) + + if err != nil { + panic("[cpumanager] could not save checkpoint: " + err.Error()) + } +} + +func (sc *stateCheckpoint) GetCPUSet(containerID string) (cpuset.CPUSet, bool) { + sc.mux.RLock() + defer sc.mux.RUnlock() + + res, ok := sc.cache.GetCPUSet(containerID) + return res, ok +} + +func (sc *stateCheckpoint) GetDefaultCPUSet() cpuset.CPUSet { + sc.mux.RLock() + defer sc.mux.RUnlock() + + return sc.cache.GetDefaultCPUSet() +} + +func (sc *stateCheckpoint) GetCPUSetOrDefault(containerID string) cpuset.CPUSet { + sc.mux.RLock() + defer sc.mux.RUnlock() + + return sc.cache.GetCPUSetOrDefault(containerID) +} + +func (sc *stateCheckpoint) GetCPUAssignments() ContainerCPUAssignments { + sc.mux.RLock() + defer sc.mux.RUnlock() + + return sc.cache.GetCPUAssignments() +} + +func (sc *stateCheckpoint) SetCPUSet(containerID string, cset cpuset.CPUSet) { + sc.mux.Lock() + defer sc.mux.Unlock() + sc.cache.SetCPUSet(containerID, cset) + sc.storeState() +} + +func (sc *stateCheckpoint) SetDefaultCPUSet(cset cpuset.CPUSet) { + sc.mux.Lock() + defer sc.mux.Unlock() + sc.cache.SetDefaultCPUSet(cset) + sc.storeState() +} + +func (sc *stateCheckpoint) SetCPUAssignments(a ContainerCPUAssignments) { + sc.mux.Lock() + defer sc.mux.Unlock() + sc.cache.SetCPUAssignments(a) + sc.storeState() +} + +func (sc *stateCheckpoint) Delete(containerID string) { + sc.mux.Lock() + defer sc.mux.Unlock() + sc.cache.Delete(containerID) + sc.storeState() +} + +func (sc *stateCheckpoint) ClearState() { + sc.mux.Lock() + defer sc.mux.Unlock() + sc.cache.ClearState() + sc.storeState() +} From 3991ed5d2f6e93df0bf4aae284afc5aeccde0ed0 Mon Sep 17 00:00:00 2001 From: Klaudiusz Dembler Date: Thu, 8 Feb 2018 17:43:56 +0100 Subject: [PATCH 02/12] Add tests --- pkg/kubelet/cm/cpumanager/state/BUILD | 22 +- .../cm/cpumanager/state/state_checkpoint.go | 38 +- .../cpumanager/state/state_checkpoint_test.go | 325 ++++++++++++++++++ .../cm/cpumanager/state/state_file_test.go | 8 +- pkg/kubelet/cm/cpumanager/state/testing/BUILD | 23 ++ .../cm/cpumanager/state/testing/util.go | 41 +++ 6 files changed, 432 insertions(+), 25 deletions(-) create mode 100644 pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go create mode 100644 pkg/kubelet/cm/cpumanager/state/testing/BUILD create mode 100644 pkg/kubelet/cm/cpumanager/state/testing/util.go diff --git a/pkg/kubelet/cm/cpumanager/state/BUILD b/pkg/kubelet/cm/cpumanager/state/BUILD index bcaf0045a08..e3d2e77a966 100644 --- a/pkg/kubelet/cm/cpumanager/state/BUILD +++ b/pkg/kubelet/cm/cpumanager/state/BUILD @@ -3,23 +3,36 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ + "checkpoint.go", "state.go", + "state_checkpoint.go", "state_file.go", "state_mem.go", ], importpath = "k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/state", visibility = ["//visibility:public"], deps = [ + "//pkg/kubelet/checkpointmanager:go_default_library", + "//pkg/kubelet/checkpointmanager/errors:go_default_library", "//pkg/kubelet/cm/cpuset:go_default_library", + "//pkg/kubelet/util/store:go_default_library", + "//pkg/util/hash:go_default_library", "//vendor/github.com/golang/glog:go_default_library", ], ) go_test( name = "go_default_test", - srcs = ["state_file_test.go"], + srcs = [ + "state_checkpoint_test.go", + "state_file_test.go", + ], embed = [":go_default_library"], - deps = ["//pkg/kubelet/cm/cpuset:go_default_library"], + deps = [ + "//pkg/kubelet/checkpointmanager:go_default_library", + "//pkg/kubelet/cm/cpumanager/state/testing:go_default_library", + "//pkg/kubelet/cm/cpuset:go_default_library", + ], ) filegroup( @@ -31,7 +44,10 @@ filegroup( filegroup( name = "all-srcs", - srcs = [":package-srcs"], + srcs = [ + ":package-srcs", + "//pkg/kubelet/cm/cpumanager/state/testing:all-srcs", + ], tags = ["automanaged"], visibility = ["//visibility:public"], ) diff --git a/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go b/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go index 0656fa9954f..ee0ead3eadb 100644 --- a/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go +++ b/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go @@ -18,21 +18,22 @@ package state import ( "fmt" - "github.com/golang/glog" - "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" - "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors" - "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" "path" "sync" + + "github.com/golang/glog" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" + "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" + utilstore "k8s.io/kubernetes/pkg/kubelet/util/store" ) -// cpuManagerCheckpointName is the name of checkpoint file -const cpuManagerCheckpointName = "cpu_manager_state" +// CPUManagerCheckpointName is the name of checkpoint file +const CPUManagerCheckpointName = "cpu_manager_state" var _ State = &stateCheckpoint{} type stateCheckpoint struct { - mux sync.RWMutex + mux sync.RWMutex policyName string cache State checkpointManager checkpointmanager.CheckpointManager @@ -50,17 +51,17 @@ func NewCheckpointState(stateDir string, policyName string) (State, error) { checkpointManager: checkpointManager, } - if err := stateCheckpoint.tryRestoreState(); err != nil { - return nil, fmt.Errorf("unable to restore state from checkpoint: %v\n"+ + if err := stateCheckpoint.restoreState(); err != nil { + return nil, fmt.Errorf("could not restore state from checkpoint: %v\n"+ "Please drain this node and delete the CPU manager checkpoint file %q before restarting Kubelet.", - err, path.Join(stateDir, cpuManagerCheckpointName)) + err, path.Join(stateDir, CPUManagerCheckpointName)) } return stateCheckpoint, nil } -// tryRestoreState tries to read checkpoint and creates it if it doesn't exist -func (sc *stateCheckpoint) tryRestoreState() error { +// restores state from a checkpoint and creates it if it doesn't exist +func (sc *stateCheckpoint) restoreState() error { sc.mux.Lock() defer sc.mux.Unlock() var err error @@ -71,8 +72,9 @@ func (sc *stateCheckpoint) tryRestoreState() error { tmpContainerCPUSet := cpuset.NewCPUSet() checkpoint := NewCPUManagerCheckpoint() - if err = sc.checkpointManager.GetCheckpoint(cpuManagerCheckpointName, checkpoint); err != nil { - if err == errors.ErrCheckpointNotFound { + if err = sc.checkpointManager.GetCheckpoint(CPUManagerCheckpointName, checkpoint); err != nil { + // TODO: change to errors.ErrCheckpointNotFound may be required after issue in checkpointing PR is resolved + if err == utilstore.ErrKeyNotFound { sc.storeState() return nil } @@ -80,16 +82,16 @@ func (sc *stateCheckpoint) tryRestoreState() error { } if sc.policyName != checkpoint.PolicyName { - return fmt.Errorf("policy configured %q != policy from state checkpoint %q", sc.policyName, checkpoint.PolicyName) + return fmt.Errorf("configured policy %q differs from state checkpoint policy %q", sc.policyName, checkpoint.PolicyName) } if tmpDefaultCPUSet, err = cpuset.Parse(checkpoint.DefaultCPUSet); err != nil { - return fmt.Errorf("could not parse state checkpoint - [defaultCpuSet: %q]", checkpoint.DefaultCPUSet) + return fmt.Errorf("could not parse default cpu set %q: %v", checkpoint.DefaultCPUSet, err) } for containerID, cpuString := range checkpoint.Entries { if tmpContainerCPUSet, err = cpuset.Parse(cpuString); err != nil { - return fmt.Errorf("could not parse state checkpoint - container id: %q, cpuset: %q", containerID, cpuString) + return fmt.Errorf("could not parse cpuset %q for container id %q: %v", cpuString, containerID, err) } tmpAssignments[containerID] = tmpContainerCPUSet } @@ -113,7 +115,7 @@ func (sc *stateCheckpoint) storeState() { checkpoint.Entries[containerID] = cset.String() } - err := sc.checkpointManager.CreateCheckpoint(cpuManagerCheckpointName, checkpoint) + err := sc.checkpointManager.CreateCheckpoint(CPUManagerCheckpointName, checkpoint) if err != nil { panic("[cpumanager] could not save checkpoint: " + err.Error()) diff --git a/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go b/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go new file mode 100644 index 00000000000..01cb7ed6afb --- /dev/null +++ b/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go @@ -0,0 +1,325 @@ +/* +Copyright 2018 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 ( + "strings" + "testing" + + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" + testutil "k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/state/testing" + "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" +) + +const testingDir = "/tmp" + +func TestCheckpointStateRestore(t *testing.T) { + testCases := []struct { + description string + checkpointContent string + policyName string + expectedError string + expectedState *stateMemory + }{ + { + "Restore non-existing checkpoint", + "", + "none", + "", + &stateMemory{}, + }, + { + "Restore default cpu set", + `{ + "PolicyName": "none", + "DefaultCPUSet": "4-6", + "Entries": {}, + "Checksum": 861251554 + }`, + "none", + "", + &stateMemory{ + defaultCPUSet: cpuset.NewCPUSet(4, 5, 6), + }, + }, + { + "Restore valid checkpoint", + `{ + "PolicyName": "none", + "DefaultCPUSet": "1-3", + "Entries": { + "container1": "4-6", + "container2": "1-3" + }, + "Checksum": 2604807655 + }`, + "none", + "", + &stateMemory{ + assignments: ContainerCPUAssignments{ + "container1": cpuset.NewCPUSet(4, 5, 6), + "container2": cpuset.NewCPUSet(1, 2, 3), + }, + defaultCPUSet: cpuset.NewCPUSet(1, 2, 3), + }, + }, + { + "Restore checkpoint with invalid checksum", + `{ + "PolicyName": "none", + "DefaultCPUSet": "4-6", + "Entries": {}, + "Checksum": 1337 + }`, + "none", + "checkpoint is corrupted", + &stateMemory{}, + }, + { + "Restore checkpoint with invalid JSON", + `{`, + "none", + "unexpected end of JSON input", + &stateMemory{}, + }, + { + "Restore checkpoint with invalid policy name", + `{ + "PolicyName": "other", + "DefaultCPUSet": "1-3", + "Entries": {}, + "Checksum": 4266067046 + }`, + "none", + `configured policy "none" differs from state checkpoint policy "other"`, + &stateMemory{}, + }, + { + "Restore checkpoint with unparsable default cpu set", + `{ + "PolicyName": "none", + "DefaultCPUSet": "1.3", + "Entries": {}, + "Checksum": 4073769779 + }`, + "none", + `could not parse default cpu set "1.3": strconv.Atoi: parsing "1.3": invalid syntax`, + &stateMemory{}, + }, + { + "Restore checkpoint with unparsable assignment entry", + `{ + "PolicyName": "none", + "DefaultCPUSet": "1-3", + "Entries": { + "container1": "4-6", + "container2": "asd" + }, + "Checksum": 3835486974 + }`, + "none", + `could not parse cpuset "asd" for container id "container2": strconv.Atoi: parsing "asd": invalid syntax`, + &stateMemory{}, + }, + } + + // create checkpoint manager for testing + cpm, err := checkpointmanager.NewCheckpointManager(testingDir) + if err != nil { + t.Fatalf("could not create testing checkpoint manager: %v", err) + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + // ensure there is no previous checkpoint + cpm.RemoveCheckpoint(CPUManagerCheckpointName) + + // prepare checkpoint for testing + var checkpoint *testutil.MockCheckpoint = nil + if strings.TrimSpace(tc.checkpointContent) != "" { + checkpoint = &testutil.MockCheckpoint{Content: tc.checkpointContent} + } + if checkpoint != nil { + if err := cpm.CreateCheckpoint(CPUManagerCheckpointName, checkpoint); err != nil { + t.Fatalf("could not create testing checkpoint: %v", err) + } + } + + restoredState, err := NewCheckpointState(testingDir, tc.policyName) + if err != nil { + if strings.TrimSpace(tc.expectedError) != "" { + tc.expectedError = "could not restore state from checkpoint: " + tc.expectedError + if strings.HasPrefix(err.Error(), tc.expectedError) { + t.Logf("got expected error: %v", err) + return + } + } + t.Fatalf("unexpected error while creatng checkpointState: %v", err) + } + + // compare state after restoration with the one expected + AssertStateEqual(t, restoredState, tc.expectedState) + }) + } +} + +func TestCheckpointStateStore(t *testing.T) { + testCases := []struct { + description string + expectedState *stateMemory + }{ + { + "Store default cpu set", + &stateMemory{defaultCPUSet: cpuset.NewCPUSet(1, 2, 3)}, + }, + { + "Store assignments", + &stateMemory{ + assignments: map[string]cpuset.CPUSet{ + "container1": cpuset.NewCPUSet(1, 5, 8), + }, + }, + }, + } + + cpm, err := checkpointmanager.NewCheckpointManager(testingDir) + if err != nil { + t.Fatalf("could not create testing checkpoint manager: %v", err) + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + // ensure there is no previous checkpoint + cpm.RemoveCheckpoint(CPUManagerCheckpointName) + + cs1, err := NewCheckpointState(testingDir, "none") + if err != nil { + t.Fatalf("could not create testing checkpointState instance: %v", err) + } + + cs1.SetDefaultCPUSet(tc.expectedState.defaultCPUSet) + cs1.SetCPUAssignments(tc.expectedState.assignments) + + cs2, err := NewCheckpointState(testingDir, "none") + if err != nil { + t.Fatalf("could not create testing checkpointState instance: %v", err) + } + + AssertStateEqual(t, cs2, tc.expectedState) + }) + } +} + +func TestCheckpointStateHelpers(t *testing.T) { + testCases := []struct { + description string + defaultCPUset cpuset.CPUSet + containers map[string]cpuset.CPUSet + }{ + { + description: "One container", + defaultCPUset: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7, 8), + containers: map[string]cpuset.CPUSet{ + "c1": cpuset.NewCPUSet(0, 1), + }, + }, + { + description: "Two containers", + defaultCPUset: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7, 8), + containers: map[string]cpuset.CPUSet{ + "c1": cpuset.NewCPUSet(0, 1), + "c2": cpuset.NewCPUSet(2, 3, 4, 5), + }, + }, + { + description: "Container without assigned cpus", + defaultCPUset: cpuset.NewCPUSet(0, 1, 2, 3, 4, 5, 6, 7, 8), + containers: map[string]cpuset.CPUSet{ + "c1": cpuset.NewCPUSet(), + }, + }, + } + + cpm, err := checkpointmanager.NewCheckpointManager(testingDir) + if err != nil { + t.Fatalf("could not create testing checkpoint manager: %v", err) + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + // ensure there is no previous checkpoint + cpm.RemoveCheckpoint(CPUManagerCheckpointName) + + state, err := NewCheckpointState(testingDir, "none") + if err != nil { + t.Fatalf("could not create testing checkpointState instance: %v", err) + } + state.SetDefaultCPUSet(tc.defaultCPUset) + + for container, set := range tc.containers { + state.SetCPUSet(container, set) + if cpus, _ := state.GetCPUSet(container); !cpus.Equals(set) { + t.Fatalf("state inconsistent, got %q instead of %q", set, cpus) + } + + state.Delete(container) + if cpus := state.GetCPUSetOrDefault(container); !cpus.Equals(tc.defaultCPUset) { + t.Fatal("deleted container still existing in state") + } + } + + }) + } +} + +func TestCheckpointStateClear(t *testing.T) { + testCases := []struct { + description string + defaultCPUset cpuset.CPUSet + containers map[string]cpuset.CPUSet + }{ + { + "Valid state", + cpuset.NewCPUSet(1, 5, 10), + map[string]cpuset.CPUSet{ + "container1": cpuset.NewCPUSet(1, 4), + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + state, err := NewCheckpointState(testingDir, "none") + if err != nil { + t.Fatalf("could not create testing checkpointState instance: %v", err) + } + + state.SetDefaultCPUSet(tc.defaultCPUset) + state.SetCPUAssignments(tc.containers) + + state.ClearState() + if !cpuset.NewCPUSet().Equals(state.GetDefaultCPUSet()) { + t.Fatal("cleared state with non-empty default cpu set") + } + for container := range tc.containers { + if !cpuset.NewCPUSet().Equals(state.GetCPUSetOrDefault(container)) { + t.Fatalf("container %q with non-default cpu set in cleared state", container) + } + } + }) + } +} diff --git a/pkg/kubelet/cm/cpumanager/state/state_file_test.go b/pkg/kubelet/cm/cpumanager/state/state_file_test.go index edccf87998c..232c47f3875 100644 --- a/pkg/kubelet/cm/cpumanager/state/state_file_test.go +++ b/pkg/kubelet/cm/cpumanager/state/state_file_test.go @@ -34,7 +34,8 @@ func writeToStateFile(statefile string, content string) { ioutil.WriteFile(statefile, []byte(content), 0644) } -func stateEqual(t *testing.T, sf State, sm State) { +// AssertStateEqual marks provided test as failed if provided states differ +func AssertStateEqual(t *testing.T, sf State, sm State) { cpusetSf := sf.GetDefaultCPUSet() cpusetSm := sm.GetDefaultCPUSet() if !cpusetSf.Equals(cpusetSm) { @@ -253,7 +254,7 @@ func TestFileStateTryRestore(t *testing.T) { } } - stateEqual(t, fileState, tc.expectedState) + AssertStateEqual(t, fileState, tc.expectedState) }) } } @@ -363,7 +364,7 @@ func TestUpdateStateFile(t *testing.T) { } } newFileState := NewFileState(sfilePath.Name(), "static") - stateEqual(t, newFileState, tc.expectedState) + AssertStateEqual(t, newFileState, tc.expectedState) }) } } @@ -471,7 +472,6 @@ func TestClearStateStateFile(t *testing.T) { t.Error("cleared state shoudn't has got information about containers") } } - }) } } diff --git a/pkg/kubelet/cm/cpumanager/state/testing/BUILD b/pkg/kubelet/cm/cpumanager/state/testing/BUILD new file mode 100644 index 00000000000..41c6d772329 --- /dev/null +++ b/pkg/kubelet/cm/cpumanager/state/testing/BUILD @@ -0,0 +1,23 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["util.go"], + importpath = "k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/state/testing", + visibility = ["//visibility:public"], + deps = ["//pkg/kubelet/checkpointmanager:go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/pkg/kubelet/cm/cpumanager/state/testing/util.go b/pkg/kubelet/cm/cpumanager/state/testing/util.go new file mode 100644 index 00000000000..6222c161cb1 --- /dev/null +++ b/pkg/kubelet/cm/cpumanager/state/testing/util.go @@ -0,0 +1,41 @@ +/* +Copyright 2018 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 testing + +import "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" + +var _ checkpointmanager.Checkpoint = &MockCheckpoint{} + +// MockCheckpoint struct is used for mocking checkpoint values in testing +type MockCheckpoint struct { + Content string +} + +// MarshalCheckpoint returns fake content +func (mc *MockCheckpoint) MarshalCheckpoint() ([]byte, error) { + return []byte(mc.Content), nil +} + +func (mc *MockCheckpoint) UnmarshalCheckpoint(blob []byte) error { + return nil +} + +func (mc *MockCheckpoint) GetChecksum() uint64 { + return 0 +} + +func (mc *MockCheckpoint) UpdateChecksum() {} From 0fbd19bc063e874b6c571d62101e819afc387475 Mon Sep 17 00:00:00 2001 From: Klaudiusz Dembler Date: Fri, 9 Feb 2018 10:05:13 +0100 Subject: [PATCH 03/12] Tweaks --- pkg/kubelet/cm/cpumanager/cpu_manager.go | 1 - .../cm/cpumanager/state/state_checkpoint.go | 10 +++++----- .../cpumanager/state/state_checkpoint_test.go | 20 +++++++++---------- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/pkg/kubelet/cm/cpumanager/cpu_manager.go b/pkg/kubelet/cm/cpumanager/cpu_manager.go index ed185bc2cc5..c7ad7d8e55f 100644 --- a/pkg/kubelet/cm/cpumanager/cpu_manager.go +++ b/pkg/kubelet/cm/cpumanager/cpu_manager.go @@ -33,7 +33,6 @@ import ( "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/status" - "path" ) // ActivePodsFunc is a function that returns a list of pods to reconcile. diff --git a/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go b/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go index ee0ead3eadb..f55ed4f1253 100644 --- a/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go +++ b/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go @@ -27,8 +27,8 @@ import ( utilstore "k8s.io/kubernetes/pkg/kubelet/util/store" ) -// CPUManagerCheckpointName is the name of checkpoint file -const CPUManagerCheckpointName = "cpu_manager_state" +// cpuManagerCheckpointName is the name of checkpoint file +const cpuManagerCheckpointName = "cpu_manager_state" var _ State = &stateCheckpoint{} @@ -54,7 +54,7 @@ func NewCheckpointState(stateDir string, policyName string) (State, error) { if err := stateCheckpoint.restoreState(); err != nil { return nil, fmt.Errorf("could not restore state from checkpoint: %v\n"+ "Please drain this node and delete the CPU manager checkpoint file %q before restarting Kubelet.", - err, path.Join(stateDir, CPUManagerCheckpointName)) + err, path.Join(stateDir, cpuManagerCheckpointName)) } return stateCheckpoint, nil @@ -72,7 +72,7 @@ func (sc *stateCheckpoint) restoreState() error { tmpContainerCPUSet := cpuset.NewCPUSet() checkpoint := NewCPUManagerCheckpoint() - if err = sc.checkpointManager.GetCheckpoint(CPUManagerCheckpointName, checkpoint); err != nil { + if err = sc.checkpointManager.GetCheckpoint(cpuManagerCheckpointName, checkpoint); err != nil { // TODO: change to errors.ErrCheckpointNotFound may be required after issue in checkpointing PR is resolved if err == utilstore.ErrKeyNotFound { sc.storeState() @@ -115,7 +115,7 @@ func (sc *stateCheckpoint) storeState() { checkpoint.Entries[containerID] = cset.String() } - err := sc.checkpointManager.CreateCheckpoint(CPUManagerCheckpointName, checkpoint) + err := sc.checkpointManager.CreateCheckpoint(cpuManagerCheckpointName, checkpoint) if err != nil { panic("[cpumanager] could not save checkpoint: " + err.Error()) diff --git a/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go b/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go index 01cb7ed6afb..9d30d5dca05 100644 --- a/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go +++ b/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go @@ -146,15 +146,12 @@ func TestCheckpointStateRestore(t *testing.T) { for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { // ensure there is no previous checkpoint - cpm.RemoveCheckpoint(CPUManagerCheckpointName) + cpm.RemoveCheckpoint(cpuManagerCheckpointName) // prepare checkpoint for testing - var checkpoint *testutil.MockCheckpoint = nil if strings.TrimSpace(tc.checkpointContent) != "" { - checkpoint = &testutil.MockCheckpoint{Content: tc.checkpointContent} - } - if checkpoint != nil { - if err := cpm.CreateCheckpoint(CPUManagerCheckpointName, checkpoint); err != nil { + checkpoint := &testutil.MockCheckpoint{Content: tc.checkpointContent} + if err := cpm.CreateCheckpoint(cpuManagerCheckpointName, checkpoint); err != nil { t.Fatalf("could not create testing checkpoint: %v", err) } } @@ -204,16 +201,18 @@ func TestCheckpointStateStore(t *testing.T) { for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { // ensure there is no previous checkpoint - cpm.RemoveCheckpoint(CPUManagerCheckpointName) + cpm.RemoveCheckpoint(cpuManagerCheckpointName) cs1, err := NewCheckpointState(testingDir, "none") if err != nil { t.Fatalf("could not create testing checkpointState instance: %v", err) } + // set values of cs1 instance so they are stored in checkpoint and can be read by cs2 cs1.SetDefaultCPUSet(tc.expectedState.defaultCPUSet) cs1.SetCPUAssignments(tc.expectedState.assignments) + // restore checkpoint with previously stored values cs2, err := NewCheckpointState(testingDir, "none") if err != nil { t.Fatalf("could not create testing checkpointState instance: %v", err) @@ -262,7 +261,7 @@ func TestCheckpointStateHelpers(t *testing.T) { for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { // ensure there is no previous checkpoint - cpm.RemoveCheckpoint(CPUManagerCheckpointName) + cpm.RemoveCheckpoint(cpuManagerCheckpointName) state, err := NewCheckpointState(testingDir, "none") if err != nil { @@ -277,11 +276,10 @@ func TestCheckpointStateHelpers(t *testing.T) { } state.Delete(container) - if cpus := state.GetCPUSetOrDefault(container); !cpus.Equals(tc.defaultCPUset) { + if _, ok := state.GetCPUSet(container); ok { t.Fatal("deleted container still existing in state") } } - }) } } @@ -316,7 +314,7 @@ func TestCheckpointStateClear(t *testing.T) { t.Fatal("cleared state with non-empty default cpu set") } for container := range tc.containers { - if !cpuset.NewCPUSet().Equals(state.GetCPUSetOrDefault(container)) { + if _, ok := state.GetCPUSet(container); ok { t.Fatalf("container %q with non-default cpu set in cleared state", container) } } From cc3fa67bdabc65350c9436b19b7b16532471c502 Mon Sep 17 00:00:00 2001 From: Klaudiusz Dembler Date: Fri, 9 Feb 2018 10:35:54 +0100 Subject: [PATCH 04/12] Add comments to MockCheckpoint functions and gofmt --- pkg/kubelet/cm/cpumanager/state/checkpoint.go | 8 ++++---- pkg/kubelet/cm/cpumanager/state/testing/util.go | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pkg/kubelet/cm/cpumanager/state/checkpoint.go b/pkg/kubelet/cm/cpumanager/state/checkpoint.go index e1a86b1b021..aba9e074b28 100644 --- a/pkg/kubelet/cm/cpumanager/state/checkpoint.go +++ b/pkg/kubelet/cm/cpumanager/state/checkpoint.go @@ -25,14 +25,14 @@ import ( hashutil "k8s.io/kubernetes/pkg/util/hash" ) -var _ checkpointmanager.Checkpoint = &cpuManagerCheckpoint {} +var _ checkpointmanager.Checkpoint = &cpuManagerCheckpoint{} // cpuManagerCheckpoint struct is used to store cpu/pod assignments in a checkpoint type cpuManagerCheckpoint struct { - PolicyName string + PolicyName string DefaultCPUSet string - Entries map[string]string - Checksum uint64 + Entries map[string]string + Checksum uint64 } // NewCPUManagerCheckpoint returns an instance of Checkpoint diff --git a/pkg/kubelet/cm/cpumanager/state/testing/util.go b/pkg/kubelet/cm/cpumanager/state/testing/util.go index 6222c161cb1..c18c64cc10f 100644 --- a/pkg/kubelet/cm/cpumanager/state/testing/util.go +++ b/pkg/kubelet/cm/cpumanager/state/testing/util.go @@ -30,12 +30,15 @@ func (mc *MockCheckpoint) MarshalCheckpoint() ([]byte, error) { return []byte(mc.Content), nil } +// UnmarshalCheckpoint fakes unmarshaling func (mc *MockCheckpoint) UnmarshalCheckpoint(blob []byte) error { return nil } +// GetChecksum fakes getting checksum func (mc *MockCheckpoint) GetChecksum() uint64 { return 0 } +// UpdateChecksum fakes updating cheksum func (mc *MockCheckpoint) UpdateChecksum() {} From 0b1a73e94bbf262c30677dd968cd050599e74127 Mon Sep 17 00:00:00 2001 From: Klaudiusz Dembler Date: Fri, 9 Feb 2018 10:37:18 +0100 Subject: [PATCH 05/12] Make cpuManagerCheckpoint exported --- pkg/kubelet/cm/cpumanager/state/checkpoint.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pkg/kubelet/cm/cpumanager/state/checkpoint.go b/pkg/kubelet/cm/cpumanager/state/checkpoint.go index aba9e074b28..11cfec257ab 100644 --- a/pkg/kubelet/cm/cpumanager/state/checkpoint.go +++ b/pkg/kubelet/cm/cpumanager/state/checkpoint.go @@ -25,10 +25,10 @@ import ( hashutil "k8s.io/kubernetes/pkg/util/hash" ) -var _ checkpointmanager.Checkpoint = &cpuManagerCheckpoint{} +var _ checkpointmanager.Checkpoint = &CPUManagerCheckpoint{} -// cpuManagerCheckpoint struct is used to store cpu/pod assignments in a checkpoint -type cpuManagerCheckpoint struct { +// CPUManagerCheckpoint struct is used to store cpu/pod assignments in a checkpoint +type CPUManagerCheckpoint struct { PolicyName string DefaultCPUSet string Entries map[string]string @@ -36,17 +36,17 @@ type cpuManagerCheckpoint struct { } // NewCPUManagerCheckpoint returns an instance of Checkpoint -func NewCPUManagerCheckpoint() *cpuManagerCheckpoint { - return &cpuManagerCheckpoint{Entries: make(map[string]string)} +func NewCPUManagerCheckpoint() *CPUManagerCheckpoint { + return &CPUManagerCheckpoint{Entries: make(map[string]string)} } // MarshalCheckpoint returns marshalled checkpoint -func (cp *cpuManagerCheckpoint) MarshalCheckpoint() ([]byte, error) { +func (cp *CPUManagerCheckpoint) MarshalCheckpoint() ([]byte, error) { return json.Marshal(*cp) } // UnmarshalCheckpoint tries to unmarshal passed bytes to checkpoint -func (cp *cpuManagerCheckpoint) UnmarshalCheckpoint(blob []byte) error { +func (cp *CPUManagerCheckpoint) UnmarshalCheckpoint(blob []byte) error { if err := json.Unmarshal(blob, cp); err != nil { return err } @@ -57,7 +57,7 @@ func (cp *cpuManagerCheckpoint) UnmarshalCheckpoint(blob []byte) error { } // GetChecksum returns calculated checksum of checkpoint -func (cp *cpuManagerCheckpoint) GetChecksum() uint64 { +func (cp *CPUManagerCheckpoint) GetChecksum() uint64 { orig := cp.Checksum cp.Checksum = 0 hash := fnv.New32a() @@ -67,6 +67,6 @@ func (cp *cpuManagerCheckpoint) GetChecksum() uint64 { } // UpdateChecksum calculates and updates checksum of the checkpoint -func (cp *cpuManagerCheckpoint) UpdateChecksum() { +func (cp *CPUManagerCheckpoint) UpdateChecksum() { cp.Checksum = cp.GetChecksum() } From ba8d82c96a8f867204fdc852224c76a7a02f96d9 Mon Sep 17 00:00:00 2001 From: Klaudiusz Dembler Date: Wed, 21 Feb 2018 11:50:07 +0100 Subject: [PATCH 06/12] Update error indicating unexistent checkpoint --- pkg/kubelet/cm/cpumanager/state/state_checkpoint.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go b/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go index f55ed4f1253..d660a1ecb05 100644 --- a/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go +++ b/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go @@ -23,6 +23,7 @@ import ( "github.com/golang/glog" "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors" "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" utilstore "k8s.io/kubernetes/pkg/kubelet/util/store" ) @@ -73,8 +74,7 @@ func (sc *stateCheckpoint) restoreState() error { checkpoint := NewCPUManagerCheckpoint() if err = sc.checkpointManager.GetCheckpoint(cpuManagerCheckpointName, checkpoint); err != nil { - // TODO: change to errors.ErrCheckpointNotFound may be required after issue in checkpointing PR is resolved - if err == utilstore.ErrKeyNotFound { + if err == errors.ErrCheckpointNotFound { sc.storeState() return nil } From 7bb047ec75a15fa3fe6915808e3d6d80fbc14435 Mon Sep 17 00:00:00 2001 From: Klaudiusz Dembler Date: Tue, 15 May 2018 18:34:53 +0200 Subject: [PATCH 07/12] Rebase and backward compatibility --- pkg/kubelet/cm/cpumanager/state/BUILD | 3 +- pkg/kubelet/cm/cpumanager/state/checkpoint.go | 49 +++++++++---------- .../cm/cpumanager/state/state_checkpoint.go | 1 - .../cpumanager/state/state_checkpoint_test.go | 10 ++-- .../cm/cpumanager/state/testing/util.go | 9 ++-- 5 files changed, 31 insertions(+), 41 deletions(-) diff --git a/pkg/kubelet/cm/cpumanager/state/BUILD b/pkg/kubelet/cm/cpumanager/state/BUILD index e3d2e77a966..ae3d7681c0e 100644 --- a/pkg/kubelet/cm/cpumanager/state/BUILD +++ b/pkg/kubelet/cm/cpumanager/state/BUILD @@ -13,10 +13,9 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/kubelet/checkpointmanager:go_default_library", + "//pkg/kubelet/checkpointmanager/checksum:go_default_library", "//pkg/kubelet/checkpointmanager/errors:go_default_library", "//pkg/kubelet/cm/cpuset:go_default_library", - "//pkg/kubelet/util/store:go_default_library", - "//pkg/util/hash:go_default_library", "//vendor/github.com/golang/glog:go_default_library", ], ) diff --git a/pkg/kubelet/cm/cpumanager/state/checkpoint.go b/pkg/kubelet/cm/cpumanager/state/checkpoint.go index 11cfec257ab..40e0fc81ad3 100644 --- a/pkg/kubelet/cm/cpumanager/state/checkpoint.go +++ b/pkg/kubelet/cm/cpumanager/state/checkpoint.go @@ -18,55 +18,50 @@ package state import ( "encoding/json" - "hash/fnv" "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" - "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors" - hashutil "k8s.io/kubernetes/pkg/util/hash" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum" ) var _ checkpointmanager.Checkpoint = &CPUManagerCheckpoint{} // CPUManagerCheckpoint struct is used to store cpu/pod assignments in a checkpoint type CPUManagerCheckpoint struct { - PolicyName string - DefaultCPUSet string - Entries map[string]string - Checksum uint64 + PolicyName string `json:"policyName"` + DefaultCPUSet string `json:"defaultCpuSet"` + Entries map[string]string `json:"entries,omitempty"` + Checksum checksum.Checksum `json:"checksum"` } // NewCPUManagerCheckpoint returns an instance of Checkpoint func NewCPUManagerCheckpoint() *CPUManagerCheckpoint { - return &CPUManagerCheckpoint{Entries: make(map[string]string)} + return &CPUManagerCheckpoint{ + Entries: make(map[string]string), + } } // MarshalCheckpoint returns marshalled checkpoint func (cp *CPUManagerCheckpoint) MarshalCheckpoint() ([]byte, error) { + // make sure checksum wasn't set before so it doesn't affect output checksum + cp.Checksum = 0 + cp.Checksum = checksum.New(cp) return json.Marshal(*cp) } // UnmarshalCheckpoint tries to unmarshal passed bytes to checkpoint func (cp *CPUManagerCheckpoint) UnmarshalCheckpoint(blob []byte) error { - if err := json.Unmarshal(blob, cp); err != nil { - return err - } - if cp.Checksum != cp.GetChecksum() { - return errors.ErrCorruptCheckpoint - } - return nil + return json.Unmarshal(blob, cp) } -// GetChecksum returns calculated checksum of checkpoint -func (cp *CPUManagerCheckpoint) GetChecksum() uint64 { - orig := cp.Checksum +// VerifyChecksum verifies that current checksum of checkpoint is valid +func (cp *CPUManagerCheckpoint) VerifyChecksum() error { + if cp.Checksum == 0 { + // accept empty checksum for compatibility with old file backend + return nil + } + ck := cp.Checksum cp.Checksum = 0 - hash := fnv.New32a() - hashutil.DeepHashObject(hash, *cp) - cp.Checksum = orig - return uint64(hash.Sum32()) -} - -// UpdateChecksum calculates and updates checksum of the checkpoint -func (cp *CPUManagerCheckpoint) UpdateChecksum() { - cp.Checksum = cp.GetChecksum() + err := ck.Verify(cp) + cp.Checksum = ck + return err } diff --git a/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go b/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go index d660a1ecb05..8f3e5112cae 100644 --- a/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go +++ b/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go @@ -25,7 +25,6 @@ import ( "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors" "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" - utilstore "k8s.io/kubernetes/pkg/kubelet/util/store" ) // cpuManagerCheckpointName is the name of checkpoint file diff --git a/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go b/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go index 9d30d5dca05..199d035c6eb 100644 --- a/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go +++ b/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go @@ -48,7 +48,7 @@ func TestCheckpointStateRestore(t *testing.T) { "PolicyName": "none", "DefaultCPUSet": "4-6", "Entries": {}, - "Checksum": 861251554 + "Checksum": 2912033808 }`, "none", "", @@ -65,7 +65,7 @@ func TestCheckpointStateRestore(t *testing.T) { "container1": "4-6", "container2": "1-3" }, - "Checksum": 2604807655 + "Checksum": 1535905563 }`, "none", "", @@ -102,7 +102,7 @@ func TestCheckpointStateRestore(t *testing.T) { "PolicyName": "other", "DefaultCPUSet": "1-3", "Entries": {}, - "Checksum": 4266067046 + "Checksum": 4195836012 }`, "none", `configured policy "none" differs from state checkpoint policy "other"`, @@ -114,7 +114,7 @@ func TestCheckpointStateRestore(t *testing.T) { "PolicyName": "none", "DefaultCPUSet": "1.3", "Entries": {}, - "Checksum": 4073769779 + "Checksum": 1025273327 }`, "none", `could not parse default cpu set "1.3": strconv.Atoi: parsing "1.3": invalid syntax`, @@ -129,7 +129,7 @@ func TestCheckpointStateRestore(t *testing.T) { "container1": "4-6", "container2": "asd" }, - "Checksum": 3835486974 + "Checksum": 2764213924 }`, "none", `could not parse cpuset "asd" for container id "container2": strconv.Atoi: parsing "asd": invalid syntax`, diff --git a/pkg/kubelet/cm/cpumanager/state/testing/util.go b/pkg/kubelet/cm/cpumanager/state/testing/util.go index c18c64cc10f..d39e3321a08 100644 --- a/pkg/kubelet/cm/cpumanager/state/testing/util.go +++ b/pkg/kubelet/cm/cpumanager/state/testing/util.go @@ -35,10 +35,7 @@ func (mc *MockCheckpoint) UnmarshalCheckpoint(blob []byte) error { return nil } -// GetChecksum fakes getting checksum -func (mc *MockCheckpoint) GetChecksum() uint64 { - return 0 +// VerifyChecksum fakes verifying checksum +func (mc *MockCheckpoint) VerifyChecksum() error { + return nil } - -// UpdateChecksum fakes updating cheksum -func (mc *MockCheckpoint) UpdateChecksum() {} From aa325ec2d9ae98addee1e0f38293b6b44770a367 Mon Sep 17 00:00:00 2001 From: Klaudiusz Dembler Date: Tue, 15 May 2018 18:43:48 +0200 Subject: [PATCH 08/12] Change JSON letter case in tests --- .../cpumanager/state/state_checkpoint_test.go | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go b/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go index 199d035c6eb..ed3891085f4 100644 --- a/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go +++ b/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go @@ -45,10 +45,10 @@ func TestCheckpointStateRestore(t *testing.T) { { "Restore default cpu set", `{ - "PolicyName": "none", - "DefaultCPUSet": "4-6", - "Entries": {}, - "Checksum": 2912033808 + "policyName": "none", + "defaultCPUSet": "4-6", + "entries": {}, + "checksum": 2912033808 }`, "none", "", @@ -59,13 +59,13 @@ func TestCheckpointStateRestore(t *testing.T) { { "Restore valid checkpoint", `{ - "PolicyName": "none", - "DefaultCPUSet": "1-3", - "Entries": { + "policyName": "none", + "defaultCPUSet": "1-3", + "entries": { "container1": "4-6", "container2": "1-3" }, - "Checksum": 1535905563 + "checksum": 1535905563 }`, "none", "", @@ -80,10 +80,10 @@ func TestCheckpointStateRestore(t *testing.T) { { "Restore checkpoint with invalid checksum", `{ - "PolicyName": "none", - "DefaultCPUSet": "4-6", - "Entries": {}, - "Checksum": 1337 + "policyName": "none", + "defaultCPUSet": "4-6", + "entries": {}, + "checksum": 1337 }`, "none", "checkpoint is corrupted", @@ -99,10 +99,10 @@ func TestCheckpointStateRestore(t *testing.T) { { "Restore checkpoint with invalid policy name", `{ - "PolicyName": "other", - "DefaultCPUSet": "1-3", - "Entries": {}, - "Checksum": 4195836012 + "policyName": "other", + "defaultCPUSet": "1-3", + "entries": {}, + "checksum": 4195836012 }`, "none", `configured policy "none" differs from state checkpoint policy "other"`, @@ -111,10 +111,10 @@ func TestCheckpointStateRestore(t *testing.T) { { "Restore checkpoint with unparsable default cpu set", `{ - "PolicyName": "none", - "DefaultCPUSet": "1.3", - "Entries": {}, - "Checksum": 1025273327 + "policyName": "none", + "defaultCPUSet": "1.3", + "entries": {}, + "checksum": 1025273327 }`, "none", `could not parse default cpu set "1.3": strconv.Atoi: parsing "1.3": invalid syntax`, @@ -123,13 +123,13 @@ func TestCheckpointStateRestore(t *testing.T) { { "Restore checkpoint with unparsable assignment entry", `{ - "PolicyName": "none", - "DefaultCPUSet": "1-3", - "Entries": { + "policyName": "none", + "defaultCPUSet": "1-3", + "entries": { "container1": "4-6", "container2": "asd" }, - "Checksum": 2764213924 + "checksum": 2764213924 }`, "none", `could not parse cpuset "asd" for container id "container2": strconv.Atoi: parsing "asd": invalid syntax`, From 3d09101b6ff404da9530a3d3cf1383987dc20482 Mon Sep 17 00:00:00 2001 From: Klaudiusz Dembler Date: Mon, 21 May 2018 11:40:04 +0200 Subject: [PATCH 09/12] Add docstrings --- pkg/kubelet/cm/cpumanager/state/state_checkpoint.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go b/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go index 8f3e5112cae..bf1302e2432 100644 --- a/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go +++ b/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go @@ -121,6 +121,7 @@ func (sc *stateCheckpoint) storeState() { } } +// GetCPUSet returns current CPU set func (sc *stateCheckpoint) GetCPUSet(containerID string) (cpuset.CPUSet, bool) { sc.mux.RLock() defer sc.mux.RUnlock() @@ -129,6 +130,7 @@ func (sc *stateCheckpoint) GetCPUSet(containerID string) (cpuset.CPUSet, bool) { return res, ok } +// GetDefaultCPUSet returns default CPU set func (sc *stateCheckpoint) GetDefaultCPUSet() cpuset.CPUSet { sc.mux.RLock() defer sc.mux.RUnlock() @@ -136,6 +138,7 @@ func (sc *stateCheckpoint) GetDefaultCPUSet() cpuset.CPUSet { return sc.cache.GetDefaultCPUSet() } +// GetCPUSetOrDefault returns current CPU set, or default one if it wasn't changed func (sc *stateCheckpoint) GetCPUSetOrDefault(containerID string) cpuset.CPUSet { sc.mux.RLock() defer sc.mux.RUnlock() @@ -143,6 +146,7 @@ func (sc *stateCheckpoint) GetCPUSetOrDefault(containerID string) cpuset.CPUSet return sc.cache.GetCPUSetOrDefault(containerID) } +// GetCPUAssignments returns current CPU to pod assignments func (sc *stateCheckpoint) GetCPUAssignments() ContainerCPUAssignments { sc.mux.RLock() defer sc.mux.RUnlock() @@ -150,6 +154,7 @@ func (sc *stateCheckpoint) GetCPUAssignments() ContainerCPUAssignments { return sc.cache.GetCPUAssignments() } +// SetCPUSet sets CPU set func (sc *stateCheckpoint) SetCPUSet(containerID string, cset cpuset.CPUSet) { sc.mux.Lock() defer sc.mux.Unlock() @@ -157,6 +162,7 @@ func (sc *stateCheckpoint) SetCPUSet(containerID string, cset cpuset.CPUSet) { sc.storeState() } +// SetDefaultCPUSet sets default CPU set func (sc *stateCheckpoint) SetDefaultCPUSet(cset cpuset.CPUSet) { sc.mux.Lock() defer sc.mux.Unlock() @@ -164,6 +170,7 @@ func (sc *stateCheckpoint) SetDefaultCPUSet(cset cpuset.CPUSet) { sc.storeState() } +// SetCPUAssignments sets CPU to pod assignments func (sc *stateCheckpoint) SetCPUAssignments(a ContainerCPUAssignments) { sc.mux.Lock() defer sc.mux.Unlock() @@ -171,6 +178,7 @@ func (sc *stateCheckpoint) SetCPUAssignments(a ContainerCPUAssignments) { sc.storeState() } +// Delete deletes assignment for specified pod func (sc *stateCheckpoint) Delete(containerID string) { sc.mux.Lock() defer sc.mux.Unlock() @@ -178,6 +186,7 @@ func (sc *stateCheckpoint) Delete(containerID string) { sc.storeState() } +// ClearState clears the state and saves it in a checkpoint func (sc *stateCheckpoint) ClearState() { sc.mux.Lock() defer sc.mux.Unlock() From de1063bc7ddb41c7ee3d1dd3504ff468549744c1 Mon Sep 17 00:00:00 2001 From: Klaudiusz Dembler Date: Mon, 21 May 2018 14:50:31 +0200 Subject: [PATCH 10/12] Add compatibility tests --- pkg/kubelet/cm/cpumanager/cpu_manager.go | 6 +- .../cm/cpumanager/state/state_checkpoint.go | 13 ++-- .../cpumanager/state/state_checkpoint_test.go | 23 +++--- .../state/state_compatibility_test.go | 78 +++++++++++++++++++ 4 files changed, 100 insertions(+), 20 deletions(-) create mode 100644 pkg/kubelet/cm/cpumanager/state/state_compatibility_test.go diff --git a/pkg/kubelet/cm/cpumanager/cpu_manager.go b/pkg/kubelet/cm/cpumanager/cpu_manager.go index c7ad7d8e55f..05936184052 100644 --- a/pkg/kubelet/cm/cpumanager/cpu_manager.go +++ b/pkg/kubelet/cm/cpumanager/cpu_manager.go @@ -44,8 +44,8 @@ type runtimeService interface { type policyName string -// CPUManagerStateFileName is the name file name where cpu manager stores it's state -const CPUManagerStateFileName = "cpu_manager_state" +// cpuManagerStateFileName is the name file name where cpu manager stores it's state +const cpuManagerStateFileName = "cpu_manager_state" // Manager interface provides methods for Kubelet to manage pod cpus. type Manager interface { @@ -136,7 +136,7 @@ func NewManager(cpuPolicyName string, reconcilePeriod time.Duration, machineInfo policy = NewNonePolicy() } - stateImpl, err := state.NewCheckpointState(stateFileDirecory, policy.Name()) + stateImpl, err := state.NewCheckpointState(stateFileDirecory, cpuManagerStateFileName, policy.Name()) if err != nil { return nil, fmt.Errorf("could not initialize checkpoint manager: %v", err) } diff --git a/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go b/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go index bf1302e2432..6d92573b866 100644 --- a/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go +++ b/pkg/kubelet/cm/cpumanager/state/state_checkpoint.go @@ -27,9 +27,6 @@ import ( "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" ) -// cpuManagerCheckpointName is the name of checkpoint file -const cpuManagerCheckpointName = "cpu_manager_state" - var _ State = &stateCheckpoint{} type stateCheckpoint struct { @@ -37,10 +34,11 @@ type stateCheckpoint struct { policyName string cache State checkpointManager checkpointmanager.CheckpointManager + checkpointName string } // NewCheckpointState creates new State for keeping track of cpu/pod assignment with checkpoint backend -func NewCheckpointState(stateDir string, policyName string) (State, error) { +func NewCheckpointState(stateDir, checkpointName, policyName string) (State, error) { checkpointManager, err := checkpointmanager.NewCheckpointManager(stateDir) if err != nil { return nil, fmt.Errorf("failed to initialize checkpoint manager: %v", err) @@ -49,12 +47,13 @@ func NewCheckpointState(stateDir string, policyName string) (State, error) { cache: NewMemoryState(), policyName: policyName, checkpointManager: checkpointManager, + checkpointName: checkpointName, } if err := stateCheckpoint.restoreState(); err != nil { return nil, fmt.Errorf("could not restore state from checkpoint: %v\n"+ "Please drain this node and delete the CPU manager checkpoint file %q before restarting Kubelet.", - err, path.Join(stateDir, cpuManagerCheckpointName)) + err, path.Join(stateDir, checkpointName)) } return stateCheckpoint, nil @@ -72,7 +71,7 @@ func (sc *stateCheckpoint) restoreState() error { tmpContainerCPUSet := cpuset.NewCPUSet() checkpoint := NewCPUManagerCheckpoint() - if err = sc.checkpointManager.GetCheckpoint(cpuManagerCheckpointName, checkpoint); err != nil { + if err = sc.checkpointManager.GetCheckpoint(sc.checkpointName, checkpoint); err != nil { if err == errors.ErrCheckpointNotFound { sc.storeState() return nil @@ -114,7 +113,7 @@ func (sc *stateCheckpoint) storeState() { checkpoint.Entries[containerID] = cset.String() } - err := sc.checkpointManager.CreateCheckpoint(cpuManagerCheckpointName, checkpoint) + err := sc.checkpointManager.CreateCheckpoint(sc.checkpointName, checkpoint) if err != nil { panic("[cpumanager] could not save checkpoint: " + err.Error()) diff --git a/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go b/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go index ed3891085f4..2471ecdf341 100644 --- a/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go +++ b/pkg/kubelet/cm/cpumanager/state/state_checkpoint_test.go @@ -17,6 +17,7 @@ limitations under the License. package state import ( + "os" "strings" "testing" @@ -25,7 +26,9 @@ import ( "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" ) -const testingDir = "/tmp" +const testingCheckpoint = "cpumanager_checkpoint_test" + +var testingDir = os.TempDir() func TestCheckpointStateRestore(t *testing.T) { testCases := []struct { @@ -146,17 +149,17 @@ func TestCheckpointStateRestore(t *testing.T) { for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { // ensure there is no previous checkpoint - cpm.RemoveCheckpoint(cpuManagerCheckpointName) + cpm.RemoveCheckpoint(testingCheckpoint) // prepare checkpoint for testing if strings.TrimSpace(tc.checkpointContent) != "" { checkpoint := &testutil.MockCheckpoint{Content: tc.checkpointContent} - if err := cpm.CreateCheckpoint(cpuManagerCheckpointName, checkpoint); err != nil { + if err := cpm.CreateCheckpoint(testingCheckpoint, checkpoint); err != nil { t.Fatalf("could not create testing checkpoint: %v", err) } } - restoredState, err := NewCheckpointState(testingDir, tc.policyName) + restoredState, err := NewCheckpointState(testingDir, testingCheckpoint, tc.policyName) if err != nil { if strings.TrimSpace(tc.expectedError) != "" { tc.expectedError = "could not restore state from checkpoint: " + tc.expectedError @@ -201,9 +204,9 @@ func TestCheckpointStateStore(t *testing.T) { for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { // ensure there is no previous checkpoint - cpm.RemoveCheckpoint(cpuManagerCheckpointName) + cpm.RemoveCheckpoint(testingCheckpoint) - cs1, err := NewCheckpointState(testingDir, "none") + cs1, err := NewCheckpointState(testingDir, testingCheckpoint, "none") if err != nil { t.Fatalf("could not create testing checkpointState instance: %v", err) } @@ -213,7 +216,7 @@ func TestCheckpointStateStore(t *testing.T) { cs1.SetCPUAssignments(tc.expectedState.assignments) // restore checkpoint with previously stored values - cs2, err := NewCheckpointState(testingDir, "none") + cs2, err := NewCheckpointState(testingDir, testingCheckpoint, "none") if err != nil { t.Fatalf("could not create testing checkpointState instance: %v", err) } @@ -261,9 +264,9 @@ func TestCheckpointStateHelpers(t *testing.T) { for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { // ensure there is no previous checkpoint - cpm.RemoveCheckpoint(cpuManagerCheckpointName) + cpm.RemoveCheckpoint(testingCheckpoint) - state, err := NewCheckpointState(testingDir, "none") + state, err := NewCheckpointState(testingDir, testingCheckpoint, "none") if err != nil { t.Fatalf("could not create testing checkpointState instance: %v", err) } @@ -301,7 +304,7 @@ func TestCheckpointStateClear(t *testing.T) { for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { - state, err := NewCheckpointState(testingDir, "none") + state, err := NewCheckpointState(testingDir, testingCheckpoint, "none") if err != nil { t.Fatalf("could not create testing checkpointState instance: %v", err) } diff --git a/pkg/kubelet/cm/cpumanager/state/state_compatibility_test.go b/pkg/kubelet/cm/cpumanager/state/state_compatibility_test.go new file mode 100644 index 00000000000..6c2e375af6f --- /dev/null +++ b/pkg/kubelet/cm/cpumanager/state/state_compatibility_test.go @@ -0,0 +1,78 @@ +/* +Copyright 2018 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 ( + "os" + "path" + "testing" + + "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" + "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" +) + +const compatibilityTestingCheckpoint = "cpumanager_state_compatibility_test" + +var state = &stateMemory{ + assignments: ContainerCPUAssignments{ + "container1": cpuset.NewCPUSet(4, 5, 6), + "container2": cpuset.NewCPUSet(1, 2, 3), + }, + defaultCPUSet: cpuset.NewCPUSet(1, 2, 3), +} + +func TestFileToCheckpointCompatibility(t *testing.T) { + statePath := path.Join(testingDir, compatibilityTestingCheckpoint) + + // ensure there is no previous state saved at testing path + os.Remove(statePath) + // ensure testing state is removed after testing + defer os.Remove(statePath) + + fileState := NewFileState(statePath, "none") + + fileState.SetDefaultCPUSet(state.defaultCPUSet) + fileState.SetCPUAssignments(state.assignments) + + restoredState, err := NewCheckpointState(testingDir, compatibilityTestingCheckpoint, "none") + if err != nil { + t.Fatalf("could not restore file state: %v", err) + } + + AssertStateEqual(t, restoredState, state) +} + +func TestCheckpointToFileCompatibility(t *testing.T) { + cpm, err := checkpointmanager.NewCheckpointManager(testingDir) + if err != nil { + t.Fatalf("could not create testing checkpoint manager: %v", err) + } + + // ensure there is no previous checkpoint + cpm.RemoveCheckpoint(compatibilityTestingCheckpoint) + // ensure testing checkpoint is removed after testing + defer cpm.RemoveCheckpoint(compatibilityTestingCheckpoint) + + checkpointState, err := NewCheckpointState(testingDir, compatibilityTestingCheckpoint, "none") + + checkpointState.SetDefaultCPUSet(state.defaultCPUSet) + checkpointState.SetCPUAssignments(state.assignments) + + restoredState := NewFileState(path.Join(testingDir, compatibilityTestingCheckpoint), "none") + + AssertStateEqual(t, restoredState, state) +} From 9384937f2f8afb31fc5ecb4f79d8a4cb7e1ee988 Mon Sep 17 00:00:00 2001 From: Klaudiusz Dembler Date: Mon, 21 May 2018 16:13:21 +0200 Subject: [PATCH 11/12] Update bazel --- pkg/kubelet/cm/cpumanager/state/BUILD | 1 + pkg/kubelet/cm/cpumanager/state/state_compatibility_test.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/kubelet/cm/cpumanager/state/BUILD b/pkg/kubelet/cm/cpumanager/state/BUILD index ae3d7681c0e..d39211962e8 100644 --- a/pkg/kubelet/cm/cpumanager/state/BUILD +++ b/pkg/kubelet/cm/cpumanager/state/BUILD @@ -24,6 +24,7 @@ go_test( name = "go_default_test", srcs = [ "state_checkpoint_test.go", + "state_compatibility_test.go", "state_file_test.go", ], embed = [":go_default_library"], diff --git a/pkg/kubelet/cm/cpumanager/state/state_compatibility_test.go b/pkg/kubelet/cm/cpumanager/state/state_compatibility_test.go index 6c2e375af6f..228fe0274f4 100644 --- a/pkg/kubelet/cm/cpumanager/state/state_compatibility_test.go +++ b/pkg/kubelet/cm/cpumanager/state/state_compatibility_test.go @@ -21,8 +21,8 @@ import ( "path" "testing" - "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" "k8s.io/kubernetes/pkg/kubelet/checkpointmanager" + "k8s.io/kubernetes/pkg/kubelet/cm/cpuset" ) const compatibilityTestingCheckpoint = "cpumanager_state_compatibility_test" From a9df2acc4b4be2182c4ef001ce4cc9788ef4c5c7 Mon Sep 17 00:00:00 2001 From: Klaudiusz Dembler Date: Thu, 7 Jun 2018 12:08:48 +0200 Subject: [PATCH 12/12] Typo fix --- pkg/kubelet/cm/cpumanager/cpu_manager.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/kubelet/cm/cpumanager/cpu_manager.go b/pkg/kubelet/cm/cpumanager/cpu_manager.go index 05936184052..1f3953e41be 100644 --- a/pkg/kubelet/cm/cpumanager/cpu_manager.go +++ b/pkg/kubelet/cm/cpumanager/cpu_manager.go @@ -97,7 +97,7 @@ type manager struct { var _ Manager = &manager{} // NewManager creates new cpu manager based on provided policy -func NewManager(cpuPolicyName string, reconcilePeriod time.Duration, machineInfo *cadvisorapi.MachineInfo, nodeAllocatableReservation v1.ResourceList, stateFileDirecory string) (Manager, error) { +func NewManager(cpuPolicyName string, reconcilePeriod time.Duration, machineInfo *cadvisorapi.MachineInfo, nodeAllocatableReservation v1.ResourceList, stateFileDirectory string) (Manager, error) { var policy Policy switch policyName(cpuPolicyName) { @@ -136,7 +136,7 @@ func NewManager(cpuPolicyName string, reconcilePeriod time.Duration, machineInfo policy = NewNonePolicy() } - stateImpl, err := state.NewCheckpointState(stateFileDirecory, cpuManagerStateFileName, policy.Name()) + stateImpl, err := state.NewCheckpointState(stateFileDirectory, cpuManagerStateFileName, policy.Name()) if err != nil { return nil, fmt.Errorf("could not initialize checkpoint manager: %v", err) }