...

Source file src/k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/checkpoint/checkpointv1.go

Documentation: k8s.io/kubernetes/pkg/kubelet/cm/devicemanager/checkpoint

     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 from 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  }
   118  

View as plain text