k8s.io/kubernetes@v1.29.3/pkg/kubelet/cm/devicemanager/checkpoint/checkpointv1.go (about) 1 /* 2 Copyright 2017 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package checkpoint 18 19 import ( 20 "encoding/json" 21 "fmt" 22 "hash/fnv" 23 "strings" 24 25 "k8s.io/apimachinery/pkg/util/dump" 26 "k8s.io/klog/v2" 27 "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum" 28 "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors" 29 ) 30 31 // PodDevicesEntryV1 connects pod information to devices, without topology information (k8s <= 1.19) 32 type PodDevicesEntryV1 struct { 33 PodUID string 34 ContainerName string 35 ResourceName string 36 DeviceIDs []string 37 AllocResp []byte 38 } 39 40 // checkpointDataV1 struct is used to store pod to device allocation information 41 // in a checkpoint file, without topology information (k8s <= 1.19) 42 type checkpointDataV1 struct { 43 PodDeviceEntries []PodDevicesEntryV1 44 RegisteredDevices map[string][]string 45 } 46 47 // checksum compute the checksum using the same algorithms (and data type names) k8s 1.19 used. 48 // We need this special code path to be able to correctly validate the checksum k8s 1.19 wrote. 49 // credits to https://github.com/kubernetes/kubernetes/pull/102717/commits/353f93895118d2ffa2d59a29a1fbc225160ea1d6 50 func (cp checkpointDataV1) checksum() checksum.Checksum { 51 object := dump.ForHash(cp) 52 object = strings.Replace(object, "checkpointDataV1", "checkpointData", 1) 53 object = strings.Replace(object, "PodDevicesEntryV1", "PodDevicesEntry", -1) 54 hash := fnv.New32a() 55 fmt.Fprintf(hash, "%v", object) 56 return checksum.Checksum(hash.Sum32()) 57 } 58 59 // DataV1 holds checkpoint data and its checksum, in V1 (k8s <= 1.19) format 60 type DataV1 struct { 61 Data checkpointDataV1 62 Checksum checksum.Checksum 63 } 64 65 // NewV1 returns an instance of Checkpoint, in V1 (k8s <= 1.19) format. 66 // Users should avoid creating checkpoints in formats different than the most recent one, 67 // use the old formats only to validate existing checkpoint and convert them to most recent 68 // format. The only exception should be test code. 69 func NewV1(devEntries []PodDevicesEntryV1, 70 devices map[string][]string) DeviceManagerCheckpoint { 71 return &DataV1{ 72 Data: checkpointDataV1{ 73 PodDeviceEntries: devEntries, 74 RegisteredDevices: devices, 75 }, 76 } 77 } 78 79 // MarshalCheckpoint is needed to implement the Checkpoint interface, but should not be called anymore 80 func (cp *DataV1) MarshalCheckpoint() ([]byte, error) { 81 klog.InfoS("Marshalling a device manager V1 checkpoint") 82 cp.Checksum = cp.Data.checksum() 83 return json.Marshal(*cp) 84 } 85 86 // UnmarshalCheckpoint returns unmarshalled data 87 func (cp *DataV1) UnmarshalCheckpoint(blob []byte) error { 88 return json.Unmarshal(blob, cp) 89 } 90 91 // VerifyChecksum verifies that passed checksum is same as calculated checksum 92 func (cp *DataV1) VerifyChecksum() error { 93 if cp.Checksum != cp.Data.checksum() { 94 return errors.ErrCorruptCheckpoint 95 } 96 return nil 97 } 98 99 // GetDataInLatestFormat returns device entries and registered devices in the *most recent* 100 // checkpoint format, *not* in the original format stored on disk. 101 func (cp *DataV1) GetDataInLatestFormat() ([]PodDevicesEntry, map[string][]string) { 102 var podDevs []PodDevicesEntry 103 for _, entryV1 := range cp.Data.PodDeviceEntries { 104 devsPerNuma := NewDevicesPerNUMA() 105 // no NUMA cell affinity was recorded. The only possible choice 106 // is to set all the devices affine to node 0. 107 devsPerNuma[0] = entryV1.DeviceIDs 108 podDevs = append(podDevs, PodDevicesEntry{ 109 PodUID: entryV1.PodUID, 110 ContainerName: entryV1.ContainerName, 111 ResourceName: entryV1.ResourceName, 112 DeviceIDs: devsPerNuma, 113 AllocResp: entryV1.AllocResp, 114 }) 115 } 116 return podDevs, cp.Data.RegisteredDevices 117 }