From 5988b7a82b2ee663963d003fc05d1f44c0de239b Mon Sep 17 00:00:00 2001 From: Abdul Halim Date: Tue, 18 Sep 2018 13:14:58 +0100 Subject: [PATCH] only create resourceMap on demand making resourceMap a singleton object and only initialize it once if one or more CRDs have a resourceName annotation in them. Added copyright header for checkpoint/checkpoint.go. Replaced fmt.Errorf with logging. Change-Id: I54628d69324833e70a75dcf6533e6642dedde9b5 --- checkpoint/checkpoint.go | 42 +++++++++++++++++++++++++++++++++------- k8sclient/k8sclient.go | 30 ++++++++++++++++++---------- 2 files changed, 55 insertions(+), 17 deletions(-) diff --git a/checkpoint/checkpoint.go b/checkpoint/checkpoint.go index 2180aebdd..a6577e175 100644 --- a/checkpoint/checkpoint.go +++ b/checkpoint/checkpoint.go @@ -1,10 +1,25 @@ +// Copyright (c) 2018 Intel Corporation +// +// 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 checkpoint import ( "encoding/json" - "fmt" "io/ioutil" + "github.com/intel/multus-cni/logging" "github.com/intel/multus-cni/types" ) @@ -38,27 +53,41 @@ func getPodEntries() ([]PodDevicesEntry, error) { cpd := &Data{} rawBytes, err := ioutil.ReadFile(checkPointfile) if err != nil { - return podEntries, fmt.Errorf("getPodEntries(): error reading file %s\n%v\n", checkPointfile, err) + return podEntries, logging.Errorf("getPodEntries(): error reading file %s\n%v\n", checkPointfile, err) } if err = json.Unmarshal(rawBytes, cpd); err != nil { - return podEntries, fmt.Errorf("getPodEntries(): error unmarshalling raw bytes %v", err) + return podEntries, logging.Errorf("getPodEntries(): error unmarshalling raw bytes %v", err) } return cpd.Data.PodDeviceEntries, nil } -// GetComputeDeviceMap returns a map of resourceName to list of device IDs +var instance map[string]*types.ResourceInfo + +// GetComputeDeviceMap returns an instance of a map of ResourceInfo func GetComputeDeviceMap(podID string) (map[string]*types.ResourceInfo, error) { + if instance == nil { + if resourceMap, err := getResourceMapFromFile(podID); err == nil { + logging.Debugf("GetComputeDeviceMap(): created new instance of resourceMap for Pod: %s", podID) + instance = resourceMap + } else { + logging.Errorf("GetComputeDeviceMap(): error creating resourceMap instance %v", err) + return nil, err + } + } + logging.Debugf("GetComputeDeviceMap(): resourceMap instance: %+v", instance) + return instance, nil +} + +func getResourceMapFromFile(podID string) (map[string]*types.ResourceInfo, error) { resourceMap := make(map[string]*types.ResourceInfo) podEntires, err := getPodEntries() - if err != nil { return nil, err } - for _, pod := range podEntires { if pod.PodUID == podID { entry, ok := resourceMap[pod.ResourceName] @@ -71,6 +100,5 @@ func GetComputeDeviceMap(podID string) (map[string]*types.ResourceInfo, error) { } } } - return resourceMap, nil } diff --git a/k8sclient/k8sclient.go b/k8sclient/k8sclient.go index ba9435bf7..f239a78f4 100644 --- a/k8sclient/k8sclient.go +++ b/k8sclient/k8sclient.go @@ -331,29 +331,36 @@ func cniConfigFromNetworkResource(customResource *types.NetworkAttachmentDefinit return config, nil } -func getKubernetesDelegate(client KubeClient, net *types.NetworkSelectionElement, confdir string, resourceMap map[string]*types.ResourceInfo) (*types.DelegateNetConf, error) { +func getKubernetesDelegate(client KubeClient, net *types.NetworkSelectionElement, confdir string, podID string, resourceMap map[string]*types.ResourceInfo) (*types.DelegateNetConf, map[string]*types.ResourceInfo, error) { logging.Debugf("getKubernetesDelegate: %v, %v, %s", client, net, confdir) rawPath := fmt.Sprintf("/apis/k8s.cni.cncf.io/v1/namespaces/%s/network-attachment-definitions/%s", net.Namespace, net.Name) netData, err := client.GetRawWithPath(rawPath) if err != nil { - return nil, logging.Errorf("getKubernetesDelegate: failed to get network resource, refer Multus README.md for the usage guide: %v", err) + return nil, resourceMap, logging.Errorf("getKubernetesDelegate: failed to get network resource, refer Multus README.md for the usage guide: %v", err) } customResource := &types.NetworkAttachmentDefinition{} if err := json.Unmarshal(netData, customResource); err != nil { - return nil, logging.Errorf("getKubernetesDelegate: failed to get the netplugin data: %v", err) + return nil, resourceMap, logging.Errorf("getKubernetesDelegate: failed to get the netplugin data: %v", err) } // Get resourceName annotation from NetDefinition deviceID := "" resourceName, ok := customResource.Metadata.Annotations[resourceNameAnnot] - if ok { + if ok && podID != "" { + logging.Debugf("getKubernetesDelegate: found resourceName annotation : %s", resourceName) // ResourceName annotation is found; try to get device info from resourceMap + resourceMap, err := checkpoint.GetComputeDeviceMap(podID) + if err != nil { + return nil, resourceMap, logging.Errorf("getKubernetesDelegate: failed to get resourceMap from kubelet checkpoint file: %v", err) + } + entry, ok := resourceMap[resourceName] if ok { if idCount := len(entry.DeviceIDs); idCount > 0 && idCount > entry.Index { deviceID = entry.DeviceIDs[entry.Index] + logging.Debugf("getKubernetesDelegate: podID: %s deviceID: %s", podID, deviceID) entry.Index++ // increment Index for next delegate } } @@ -361,15 +368,15 @@ func getKubernetesDelegate(client KubeClient, net *types.NetworkSelectionElement configBytes, err := cniConfigFromNetworkResource(customResource, confdir) if err != nil { - return nil, err + return nil, resourceMap, err } delegate, err := types.LoadDelegateNetConf(configBytes, net.InterfaceRequest, deviceID) if err != nil { - return nil, err + return nil, resourceMap, err } - return delegate, nil + return delegate, resourceMap, nil } type KubeClient interface { @@ -472,8 +479,6 @@ func GetK8sNetwork(k8sclient KubeClient, k8sArgs *types.K8sArgs, confdir string) return nil, err } - // Get Pod ComputeDevices info - resourceMap, err := checkpoint.GetComputeDeviceMap(podID) if err != nil { return nil, logging.Errorf("GetK8sNetwork: failed to get resourceMap for PodUID: %v %v", podID, err) } @@ -487,14 +492,19 @@ func GetK8sNetwork(k8sclient KubeClient, k8sArgs *types.K8sArgs, confdir string) return nil, err } + // resourceMap holds Pod device allocation information; only initizized if CRD contains 'resourceName' annotation. + // This is only initialized once and all delegate objects can reference this to look up device info. + var resourceMap map[string]*types.ResourceInfo + // Read all network objects referenced by 'networks' var delegates []*types.DelegateNetConf for _, net := range networks { - delegate, err := getKubernetesDelegate(k8sclient, net, confdir, resourceMap) + delegate, resourceMap, err := getKubernetesDelegate(k8sclient, net, confdir, podID, resourceMap) if err != nil { return nil, logging.Errorf("GetK8sNetwork: failed getting the delegate: %v", err) } delegates = append(delegates, delegate) + _ = resourceMap // workaround for 'Go' error: 'resourceMap' declared and not used. } return delegates, nil