volcano.sh/volcano@v1.9.0/pkg/scheduler/cache/event_handlers.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 cache
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"math"
    23  	"reflect"
    24  	"strconv"
    25  
    26  	v1 "k8s.io/api/core/v1"
    27  	schedulingv1 "k8s.io/api/scheduling/v1"
    28  	sv1 "k8s.io/api/storage/v1"
    29  	"k8s.io/apimachinery/pkg/api/errors"
    30  	"k8s.io/apimachinery/pkg/api/resource"
    31  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    32  	"k8s.io/apimachinery/pkg/util/sets"
    33  	"k8s.io/client-go/tools/cache"
    34  	"k8s.io/component-helpers/storage/ephemeral"
    35  	storagehelpers "k8s.io/component-helpers/storage/volume"
    36  	"k8s.io/klog/v2"
    37  	"k8s.io/kubernetes/pkg/kubelet/cm/cpumanager/topology"
    38  	"k8s.io/kubernetes/pkg/scheduler/framework"
    39  	volumeutil "k8s.io/kubernetes/pkg/volume/util"
    40  	"k8s.io/utils/cpuset"
    41  
    42  	nodeinfov1alpha1 "volcano.sh/apis/pkg/apis/nodeinfo/v1alpha1"
    43  	"volcano.sh/apis/pkg/apis/scheduling"
    44  	"volcano.sh/apis/pkg/apis/scheduling/scheme"
    45  	schedulingv1beta1 "volcano.sh/apis/pkg/apis/scheduling/v1beta1"
    46  	"volcano.sh/apis/pkg/apis/utils"
    47  
    48  	schedulingapi "volcano.sh/volcano/pkg/scheduler/api"
    49  	"volcano.sh/volcano/pkg/scheduler/metrics"
    50  	commonutil "volcano.sh/volcano/pkg/util"
    51  )
    52  
    53  var DefaultAttachableVolumeQuantity int64 = math.MaxInt32
    54  
    55  func isTerminated(status schedulingapi.TaskStatus) bool {
    56  	return status == schedulingapi.Succeeded || status == schedulingapi.Failed
    57  }
    58  
    59  // getOrCreateJob will return corresponding Job for pi if it exists, or it will create a Job and return it if
    60  // pi.Pod.Spec.SchedulerName is same as volcano scheduler's name, otherwise it will return nil.
    61  func (sc *SchedulerCache) getOrCreateJob(pi *schedulingapi.TaskInfo) *schedulingapi.JobInfo {
    62  	if len(pi.Job) == 0 {
    63  		if !commonutil.Contains(sc.schedulerNames, pi.Pod.Spec.SchedulerName) {
    64  			klog.V(4).Infof("Pod %s/%s will not scheduled by %#v, skip creating PodGroup and Job for it",
    65  				pi.Pod.Namespace, pi.Pod.Name, sc.schedulerNames)
    66  		}
    67  		return nil
    68  	}
    69  
    70  	if _, found := sc.Jobs[pi.Job]; !found {
    71  		sc.Jobs[pi.Job] = schedulingapi.NewJobInfo(pi.Job)
    72  	}
    73  
    74  	return sc.Jobs[pi.Job]
    75  }
    76  
    77  // addPodCSIVolumesToTask counts the csi volumes used by task
    78  // @Lily922 TODO: support counting shared volumes. Currently, if two different pods use the same attachable volume
    79  // and scheduled on the same nodes the volume will be count twice, but actually only use one attachable limit resource
    80  func (sc *SchedulerCache) addPodCSIVolumesToTask(pi *schedulingapi.TaskInfo) error {
    81  	volumes, err := sc.getPodCSIVolumes(pi.Pod)
    82  	if err != nil {
    83  		klog.Errorf("got pod csi attachment persistent volumes count error: %s", err.Error())
    84  		return err
    85  	}
    86  
    87  	for key, count := range volumes {
    88  		pi.Resreq.AddScalar(key, float64(count))
    89  	}
    90  	return nil
    91  }
    92  
    93  func (sc *SchedulerCache) getPodCSIVolumes(pod *v1.Pod) (map[v1.ResourceName]int64, error) {
    94  	volumes := make(map[v1.ResourceName]int64)
    95  	for _, vol := range pod.Spec.Volumes {
    96  		pvcName := ""
    97  		isEphemeral := false
    98  		switch {
    99  		case vol.PersistentVolumeClaim != nil:
   100  			// Normal CSI volume can only be used through PVC
   101  			pvcName = vol.PersistentVolumeClaim.ClaimName
   102  		case vol.Ephemeral != nil:
   103  			// Generic ephemeral inline volumes also use a PVC,
   104  			// just with a computed name and certain ownership.
   105  			// That is checked below once the pvc object is
   106  			// retrieved.
   107  			pvcName = ephemeral.VolumeClaimName(pod, &vol)
   108  			isEphemeral = true
   109  		default:
   110  			// @Lily922 TODO: support Inline volumes.
   111  			// Inline volume is not supported now
   112  			continue
   113  		}
   114  		if pvcName == "" {
   115  			return volumes, fmt.Errorf("PersistentVolumeClaim had no name")
   116  		}
   117  
   118  		pvc, err := sc.pvcInformer.Lister().PersistentVolumeClaims(pod.Namespace).Get(pvcName)
   119  		if err != nil {
   120  			// The PVC is required to proceed with
   121  			// scheduling of a new pod because it cannot
   122  			// run without it. Bail out immediately.
   123  			return volumes, fmt.Errorf("looking up PVC %s/%s: %v", pod.Namespace, pvcName, err)
   124  		}
   125  		// The PVC for an ephemeral volume must be owned by the pod.
   126  		if isEphemeral {
   127  			if err := ephemeral.VolumeIsForPod(pod, pvc); err != nil {
   128  				return volumes, err
   129  			}
   130  		}
   131  
   132  		driverName := sc.getCSIDriverInfo(pvc)
   133  		if sc.isIgnoredProvisioner(driverName) {
   134  			klog.V(5).InfoS("Provisioner ignored, skip count pod pvc num", "driverName", driverName)
   135  			continue
   136  		}
   137  		if driverName == "" {
   138  			klog.V(5).InfoS("Could not find a CSI driver name for pvc(%s/%s), not counting volume", pvc.Namespace, pvc.Name)
   139  			continue
   140  		}
   141  
   142  		// Count all csi volumes in cache, because the storage may change from unattachable volumes to attachable volumes after
   143  		// the cache set up, in this case it is very difficult to refresh all task caches.
   144  		// For unattachable volume, set the limits number to a very large value, in this way, scheduling will never
   145  		// be limited due to insufficient quantity of it.
   146  		k := v1.ResourceName(volumeutil.GetCSIAttachLimitKey(driverName))
   147  		if _, ok := volumes[k]; !ok {
   148  			volumes[k] = 1
   149  		} else {
   150  			volumes[k] += 1
   151  		}
   152  	}
   153  	return volumes, nil
   154  }
   155  
   156  func (sc *SchedulerCache) isIgnoredProvisioner(driverName string) bool {
   157  	return sc.IgnoredCSIProvisioners.Has(driverName)
   158  }
   159  
   160  func (sc *SchedulerCache) getCSIDriverInfo(pvc *v1.PersistentVolumeClaim) string {
   161  	pvName := pvc.Spec.VolumeName
   162  
   163  	if pvName == "" {
   164  		klog.V(5).Infof("PV had no name for pvc <%s>", klog.KObj(pvc))
   165  		return sc.getCSIDriverInfoFromSC(pvc)
   166  	}
   167  
   168  	pv, err := sc.pvInformer.Lister().Get(pvName)
   169  	if err != nil {
   170  		klog.V(5).InfoS("Failed to get pv <%s> for pvc <%s>: %v", klog.KRef("", pvName), klog.KObj(pvc), err)
   171  		// If we can't fetch PV associated with PVC, may be it got deleted
   172  		// or PVC was prebound to a PVC that hasn't been created yet.
   173  		// fallback to using StorageClass for volume counting
   174  		return sc.getCSIDriverInfoFromSC(pvc)
   175  	}
   176  
   177  	csiSource := pv.Spec.PersistentVolumeSource.CSI
   178  	if csiSource == nil {
   179  		// @Lily922 TODO: support non-CSI volumes and migrating pvc
   180  		// CSIMigration is not supported now.
   181  		klog.Warningf("Not support non-csi pvc.")
   182  		return ""
   183  	}
   184  
   185  	return csiSource.Driver
   186  }
   187  
   188  // getCSIDriverInfoFromSC get the name of the csi driver through the sc of the pvc.
   189  func (sc *SchedulerCache) getCSIDriverInfoFromSC(pvc *v1.PersistentVolumeClaim) string {
   190  	scName := storagehelpers.GetPersistentVolumeClaimClass(pvc)
   191  
   192  	// If StorageClass is not set or not found, then PVC must be using immediate binding mode
   193  	// and hence it must be bound before scheduling. So it is safe to not count it.
   194  	if scName == "" {
   195  		klog.V(3).Infof("PVC <%s> has no StorageClass", klog.KObj(pvc))
   196  		return ""
   197  	}
   198  
   199  	storageClass, err := sc.scInformer.Lister().Get(scName)
   200  	if err != nil {
   201  		klog.Errorf("Failed to get StorageClass for pvc <%s>: %v", klog.KObj(pvc), err)
   202  		return ""
   203  	}
   204  
   205  	if driverName, ok := storageClass.Parameters["csi.storage.k8s.io/csi-driver-name"]; ok {
   206  		return driverName
   207  	}
   208  	return storageClass.Provisioner
   209  }
   210  
   211  func (sc *SchedulerCache) addTask(pi *schedulingapi.TaskInfo) error {
   212  	if len(pi.NodeName) != 0 {
   213  		if _, found := sc.Nodes[pi.NodeName]; !found {
   214  			sc.Nodes[pi.NodeName] = schedulingapi.NewNodeInfo(nil)
   215  			sc.Nodes[pi.NodeName].Name = pi.NodeName
   216  		}
   217  
   218  		node := sc.Nodes[pi.NodeName]
   219  		if !isTerminated(pi.Status) {
   220  			if err := node.AddTask(pi); err != nil {
   221  				return err
   222  			}
   223  		} else {
   224  			klog.V(4).Infof("Pod <%v/%v> is in status %s.", pi.Namespace, pi.Name, pi.Status.String())
   225  		}
   226  	}
   227  
   228  	job := sc.getOrCreateJob(pi)
   229  	if job != nil {
   230  		job.AddTaskInfo(pi)
   231  	}
   232  
   233  	return nil
   234  }
   235  
   236  func (sc *SchedulerCache) NewTaskInfo(pod *v1.Pod) (*schedulingapi.TaskInfo, error) {
   237  	taskInfo := schedulingapi.NewTaskInfo(pod)
   238  	if err := sc.addPodCSIVolumesToTask(taskInfo); err != nil {
   239  		return taskInfo, err
   240  	}
   241  	// Update BestEffort because the InitResreq maybe changes
   242  	taskInfo.BestEffort = taskInfo.InitResreq.IsEmpty()
   243  	return taskInfo, nil
   244  }
   245  
   246  // Assumes that lock is already acquired.
   247  func (sc *SchedulerCache) addPod(pod *v1.Pod) error {
   248  	pi, err := sc.NewTaskInfo(pod)
   249  	if err != nil {
   250  		klog.Errorf("generate taskInfo for pod(%s) failed: %v", pod.Name, err)
   251  		sc.resyncTask(pi)
   252  	}
   253  
   254  	return sc.addTask(pi)
   255  }
   256  
   257  func (sc *SchedulerCache) syncTask(oldTask *schedulingapi.TaskInfo) error {
   258  	newPod, err := sc.kubeClient.CoreV1().Pods(oldTask.Namespace).Get(context.TODO(), oldTask.Name, metav1.GetOptions{})
   259  	if err != nil {
   260  		if errors.IsNotFound(err) {
   261  			err := sc.deleteTask(oldTask)
   262  			if err != nil {
   263  				klog.Errorf("Failed to delete Pod <%v/%v> and remove from cache: %s", oldTask.Namespace, oldTask.Name, err.Error())
   264  				return err
   265  			}
   266  			klog.V(3).Infof("Pod <%v/%v> was deleted, removed from cache.", oldTask.Namespace, oldTask.Name)
   267  
   268  			return nil
   269  		}
   270  		return fmt.Errorf("failed to get Pod <%v/%v>: err %v", oldTask.Namespace, oldTask.Name, err)
   271  	}
   272  
   273  	newTask, err := sc.NewTaskInfo(newPod)
   274  	if err != nil {
   275  		return fmt.Errorf("failed to generate taskInfo of pod(%s), error: %v", newPod.Name, err)
   276  	}
   277  
   278  	sc.Mutex.Lock()
   279  	defer sc.Mutex.Unlock()
   280  	return sc.updateTask(oldTask, newTask)
   281  }
   282  
   283  func (sc *SchedulerCache) updateTask(oldTask, newTask *schedulingapi.TaskInfo) error {
   284  	if err := sc.deleteTask(oldTask); err != nil {
   285  		klog.Warningf("Failed to delete task: %v", err)
   286  	}
   287  
   288  	return sc.addTask(newTask)
   289  }
   290  
   291  // Check the pod allocated status in cache
   292  func (sc *SchedulerCache) allocatedPodInCache(pod *v1.Pod) bool {
   293  	pi := schedulingapi.NewTaskInfo(pod)
   294  
   295  	if job, found := sc.Jobs[pi.Job]; found {
   296  		if t, found := job.Tasks[pi.UID]; found {
   297  			return schedulingapi.AllocatedStatus(t.Status)
   298  		}
   299  	}
   300  
   301  	return false
   302  }
   303  
   304  // Assumes that lock is already acquired.
   305  func (sc *SchedulerCache) updatePod(oldPod, newPod *v1.Pod) error {
   306  	//ignore the update event if pod is allocated in cache but not present in NodeName
   307  	if sc.allocatedPodInCache(newPod) && newPod.Spec.NodeName == "" {
   308  		klog.V(4).Infof("Pod <%s/%v> already in cache with allocated status, ignore the update event", newPod.Namespace, newPod.Name)
   309  		return nil
   310  	}
   311  
   312  	if err := sc.deletePod(oldPod); err != nil {
   313  		return err
   314  	}
   315  	//when delete pod, the ownerreference of pod will be set nil,just as orphan pod
   316  	if len(utils.GetController(newPod)) == 0 {
   317  		newPod.OwnerReferences = oldPod.OwnerReferences
   318  	}
   319  	return sc.addPod(newPod)
   320  }
   321  
   322  func (sc *SchedulerCache) deleteTask(pi *schedulingapi.TaskInfo) error {
   323  	var jobErr, nodeErr, numaErr error
   324  
   325  	if len(pi.Job) != 0 {
   326  		if job, found := sc.Jobs[pi.Job]; found {
   327  			jobErr = job.DeleteTaskInfo(pi)
   328  		} else {
   329  			klog.Warningf("Failed to find job <%v> for Task <%v/%v>", pi.Job, pi.Namespace, pi.Name)
   330  		}
   331  	}
   332  
   333  	if len(pi.NodeName) != 0 {
   334  		node := sc.Nodes[pi.NodeName]
   335  		if node != nil {
   336  			nodeErr = node.RemoveTask(pi)
   337  		}
   338  	}
   339  
   340  	if jobErr != nil || nodeErr != nil {
   341  		return schedulingapi.MergeErrors(jobErr, nodeErr, numaErr)
   342  	}
   343  
   344  	return nil
   345  }
   346  
   347  // Assumes that lock is already acquired.
   348  func (sc *SchedulerCache) deletePod(pod *v1.Pod) error {
   349  	pi := schedulingapi.NewTaskInfo(pod)
   350  
   351  	// Delete the Task in cache to handle Binding status.
   352  	task := pi
   353  	if job, found := sc.Jobs[pi.Job]; found {
   354  		if t, found := job.Tasks[pi.UID]; found {
   355  			task = t
   356  		}
   357  	}
   358  	if err := sc.deleteTask(task); err != nil {
   359  		klog.Warningf("Failed to delete task: %v", err)
   360  	}
   361  
   362  	// If job was terminated, delete it.
   363  	if job, found := sc.Jobs[pi.Job]; found && schedulingapi.JobTerminated(job) {
   364  		sc.deleteJob(job)
   365  	}
   366  
   367  	return nil
   368  }
   369  
   370  // AddPod add pod to scheduler cache
   371  func (sc *SchedulerCache) AddPod(obj interface{}) {
   372  	pod, ok := obj.(*v1.Pod)
   373  	if !ok {
   374  		klog.Errorf("Cannot convert to *v1.Pod: %v", obj)
   375  		return
   376  	}
   377  
   378  	sc.Mutex.Lock()
   379  	defer sc.Mutex.Unlock()
   380  
   381  	err := sc.addPod(pod)
   382  	if err != nil {
   383  		klog.Errorf("Failed to add pod <%s/%s> into cache: %v",
   384  			pod.Namespace, pod.Name, err)
   385  		return
   386  	}
   387  	klog.V(3).Infof("Added pod <%s/%v> into cache.", pod.Namespace, pod.Name)
   388  }
   389  
   390  // UpdatePod update pod to scheduler cache
   391  func (sc *SchedulerCache) UpdatePod(oldObj, newObj interface{}) {
   392  	oldPod, ok := oldObj.(*v1.Pod)
   393  	if !ok {
   394  		klog.Errorf("Cannot convert oldObj to *v1.Pod: %v", oldObj)
   395  		return
   396  	}
   397  	newPod, ok := newObj.(*v1.Pod)
   398  	if !ok {
   399  		klog.Errorf("Cannot convert newObj to *v1.Pod: %v", newObj)
   400  		return
   401  	}
   402  
   403  	sc.Mutex.Lock()
   404  	defer sc.Mutex.Unlock()
   405  
   406  	err := sc.updatePod(oldPod, newPod)
   407  	if err != nil {
   408  		klog.Errorf("Failed to update pod %v in cache: %v", oldPod.Name, err)
   409  		return
   410  	}
   411  
   412  	klog.V(4).Infof("Updated pod <%s/%v> in cache.", oldPod.Namespace, oldPod.Name)
   413  }
   414  
   415  // DeletePod delete pod from scheduler cache
   416  func (sc *SchedulerCache) DeletePod(obj interface{}) {
   417  	var pod *v1.Pod
   418  	switch t := obj.(type) {
   419  	case *v1.Pod:
   420  		pod = t
   421  	case cache.DeletedFinalStateUnknown:
   422  		var ok bool
   423  		pod, ok = t.Obj.(*v1.Pod)
   424  		if !ok {
   425  			klog.Errorf("Cannot convert to *v1.Pod: %v", t.Obj)
   426  			return
   427  		}
   428  	default:
   429  		klog.Errorf("Cannot convert to *v1.Pod: %v", t)
   430  		return
   431  	}
   432  
   433  	sc.Mutex.Lock()
   434  	defer sc.Mutex.Unlock()
   435  
   436  	err := sc.deletePod(pod)
   437  	if err != nil {
   438  		klog.Errorf("Failed to delete pod %v from cache: %v", pod.Name, err)
   439  		return
   440  	}
   441  
   442  	klog.V(3).Infof("Deleted pod <%s/%v> from cache.", pod.Namespace, pod.Name)
   443  }
   444  
   445  // addNodeImageStates adds states of the images on given node to the given nodeInfo and update the imageStates in
   446  // scheduler cache. This function assumes the lock to scheduler cache has been acquired.
   447  func (sc *SchedulerCache) addNodeImageStates(node *v1.Node, nodeInfo *schedulingapi.NodeInfo) {
   448  	newSum := make(map[string]*framework.ImageStateSummary)
   449  
   450  	for _, image := range node.Status.Images {
   451  		for _, name := range image.Names {
   452  			// update the entry in imageStates
   453  			state, ok := sc.imageStates[name]
   454  			if !ok {
   455  				state = &imageState{
   456  					size:  image.SizeBytes,
   457  					nodes: sets.NewString(node.Name),
   458  				}
   459  				sc.imageStates[name] = state
   460  			} else {
   461  				state.nodes.Insert(node.Name)
   462  			}
   463  			// create the imageStateSummary for this image
   464  			if _, ok := newSum[name]; !ok {
   465  				newSum[name] = sc.createImageStateSummary(state)
   466  			}
   467  		}
   468  	}
   469  	nodeInfo.ImageStates = newSum
   470  }
   471  
   472  // removeNodeImageStates removes the given node record from image entries having the node
   473  // in imageStates cache. After the removal, if any image becomes free, i.e., the image
   474  // is no longer available on any node, the image entry will be removed from imageStates.
   475  func (sc *SchedulerCache) removeNodeImageStates(node string) {
   476  	for image, state := range sc.imageStates {
   477  		state.nodes.Delete(node)
   478  		if len(state.nodes) == 0 {
   479  			// Remove the unused image to make sure the length of
   480  			// imageStates represents the total number of different
   481  			// images on all nodes
   482  			delete(sc.imageStates, image)
   483  		}
   484  	}
   485  }
   486  
   487  // AddOrUpdateNode adds or updates node info in cache.
   488  func (sc *SchedulerCache) AddOrUpdateNode(node *v1.Node) error {
   489  	sc.Mutex.Lock()
   490  	defer sc.Mutex.Unlock()
   491  
   492  	if sc.Nodes[node.Name] != nil {
   493  		sc.Nodes[node.Name].SetNode(node)
   494  		sc.removeNodeImageStates(node.Name)
   495  	} else {
   496  		sc.Nodes[node.Name] = schedulingapi.NewNodeInfo(node)
   497  	}
   498  	sc.addNodeImageStates(node, sc.Nodes[node.Name])
   499  
   500  	var nodeExisted bool
   501  	for _, name := range sc.NodeList {
   502  		if name == node.Name {
   503  			nodeExisted = true
   504  			break
   505  		}
   506  	}
   507  	if !nodeExisted {
   508  		sc.NodeList = append(sc.NodeList, node.Name)
   509  	}
   510  	return nil
   511  }
   512  
   513  // RemoveNode removes node info from cache
   514  func (sc *SchedulerCache) RemoveNode(nodeName string) error {
   515  	sc.Mutex.Lock()
   516  	defer sc.Mutex.Unlock()
   517  
   518  	for i, name := range sc.NodeList {
   519  		if name == nodeName {
   520  			sc.NodeList = append(sc.NodeList[:i], sc.NodeList[i+1:]...)
   521  			break
   522  		}
   523  	}
   524  	sc.removeNodeImageStates(nodeName)
   525  
   526  	if _, ok := sc.Nodes[nodeName]; !ok {
   527  		return fmt.Errorf("node <%s> does not exist", nodeName)
   528  	}
   529  
   530  	numaInfo := sc.Nodes[nodeName].NumaInfo
   531  	if numaInfo != nil {
   532  		klog.V(3).Infof("delete numatopo <%s/%s>", numaInfo.Namespace, numaInfo.Name)
   533  		err := sc.vcClient.NodeinfoV1alpha1().Numatopologies().Delete(context.TODO(), numaInfo.Name, metav1.DeleteOptions{})
   534  		if err != nil {
   535  			klog.Errorf("delete numatopo <%s/%s> failed.", numaInfo.Namespace, numaInfo.Name)
   536  		}
   537  	}
   538  	delete(sc.Nodes, nodeName)
   539  	return nil
   540  }
   541  
   542  // AddNode add node to scheduler cache
   543  func (sc *SchedulerCache) AddNode(obj interface{}) {
   544  	node, ok := obj.(*v1.Node)
   545  	if !ok {
   546  		klog.Errorf("Cannot convert to *v1.Node: %v", obj)
   547  		return
   548  	}
   549  	sc.nodeQueue.Add(node.Name)
   550  }
   551  
   552  // UpdateNode update node to scheduler cache
   553  func (sc *SchedulerCache) UpdateNode(oldObj, newObj interface{}) {
   554  	_, ok := oldObj.(*v1.Node)
   555  	if !ok {
   556  		klog.Errorf("Cannot convert oldObj to *v1.Node: %v", oldObj)
   557  		return
   558  	}
   559  	newNode, ok := newObj.(*v1.Node)
   560  	if !ok {
   561  		klog.Errorf("Cannot convert newObj to *v1.Node: %v", newObj)
   562  		return
   563  	}
   564  	sc.nodeQueue.Add(newNode.Name)
   565  }
   566  
   567  // DeleteNode delete node from scheduler cache
   568  func (sc *SchedulerCache) DeleteNode(obj interface{}) {
   569  	var node *v1.Node
   570  	switch t := obj.(type) {
   571  	case *v1.Node:
   572  		node = t
   573  	case cache.DeletedFinalStateUnknown:
   574  		var ok bool
   575  		node, ok = t.Obj.(*v1.Node)
   576  		if !ok {
   577  			klog.Errorf("Cannot convert to *v1.Node: %v", t.Obj)
   578  			return
   579  		}
   580  	default:
   581  		klog.Errorf("Cannot convert to *v1.Node: %v", t)
   582  		return
   583  	}
   584  	sc.nodeQueue.Add(node.Name)
   585  }
   586  
   587  func (sc *SchedulerCache) SyncNode(nodeName string) error {
   588  	node, err := sc.nodeInformer.Lister().Get(nodeName)
   589  	if err != nil {
   590  		if errors.IsNotFound(err) {
   591  			deleteErr := sc.RemoveNode(nodeName)
   592  			if deleteErr != nil {
   593  				klog.Errorf("Failed to delete node <%s> and remove from cache: %s", nodeName, deleteErr.Error())
   594  				return deleteErr
   595  			}
   596  
   597  			klog.V(3).Infof("Node <%s> was deleted, removed from cache.", nodeName)
   598  			return nil
   599  		}
   600  		klog.Errorf("Failed to get node %s, error: %v", nodeName, err)
   601  		return err
   602  	}
   603  
   604  	csiNode, err := sc.csiNodeInformer.Lister().Get(nodeName)
   605  	if err == nil {
   606  		sc.setCSIResourceOnNode(csiNode, node)
   607  	} else if !errors.IsNotFound(err) {
   608  		return err
   609  	}
   610  	return sc.AddOrUpdateNode(node)
   611  }
   612  
   613  func (sc *SchedulerCache) AddOrUpdateCSINode(obj interface{}) {
   614  	csiNode, ok := obj.(*sv1.CSINode)
   615  	if !ok {
   616  		return
   617  	}
   618  
   619  	csiNodeStatus := &schedulingapi.CSINodeStatusInfo{
   620  		CSINodeName:  csiNode.Name,
   621  		DriverStatus: make(map[string]bool),
   622  	}
   623  	sc.Mutex.Lock()
   624  	defer sc.Mutex.Unlock()
   625  
   626  	for i := range csiNode.Spec.Drivers {
   627  		d := csiNode.Spec.Drivers[i]
   628  		csiNodeStatus.DriverStatus[d.Name] = d.Allocatable != nil && d.Allocatable.Count != nil
   629  	}
   630  	sc.CSINodesStatus[csiNode.Name] = csiNodeStatus
   631  	sc.nodeQueue.Add(csiNode.Name)
   632  }
   633  
   634  func (sc *SchedulerCache) UpdateCSINode(oldObj, newObj interface{}) {
   635  	oldCSINode, ok := oldObj.(*sv1.CSINode)
   636  	if !ok {
   637  		return
   638  	}
   639  	newCSINode, ok := newObj.(*sv1.CSINode)
   640  	if !ok {
   641  		return
   642  	}
   643  	if reflect.DeepEqual(oldCSINode.Spec, newCSINode.Spec) {
   644  		return
   645  	}
   646  	sc.AddOrUpdateCSINode(newObj)
   647  }
   648  
   649  func (sc *SchedulerCache) DeleteCSINode(obj interface{}) {
   650  	var csiNode *sv1.CSINode
   651  	switch t := obj.(type) {
   652  	case *sv1.CSINode:
   653  		csiNode = obj.(*sv1.CSINode)
   654  	case cache.DeletedFinalStateUnknown:
   655  		var ok bool
   656  		csiNode, ok = t.Obj.(*sv1.CSINode)
   657  		if !ok {
   658  			klog.Errorf("Cannot convert to *sv1.CSINode: %v", obj)
   659  			return
   660  		}
   661  	default:
   662  		klog.Errorf("Cannot convert to *sv1.CSINode: %v", obj)
   663  		return
   664  	}
   665  
   666  	sc.Mutex.Lock()
   667  	delete(sc.CSINodesStatus, csiNode.Name)
   668  	sc.Mutex.Unlock()
   669  	sc.nodeQueue.Add(csiNode.Name)
   670  }
   671  
   672  func getJobID(pg *schedulingapi.PodGroup) schedulingapi.JobID {
   673  	return schedulingapi.JobID(fmt.Sprintf("%s/%s", pg.Namespace, pg.Name))
   674  }
   675  
   676  // Assumes that lock is already acquired.
   677  func (sc *SchedulerCache) setPodGroup(ss *schedulingapi.PodGroup) error {
   678  	job := getJobID(ss)
   679  	if _, found := sc.Jobs[job]; !found {
   680  		sc.Jobs[job] = schedulingapi.NewJobInfo(job)
   681  	}
   682  
   683  	sc.Jobs[job].SetPodGroup(ss)
   684  
   685  	// TODO(k82cn): set default queue in admission.
   686  	if len(ss.Spec.Queue) == 0 {
   687  		sc.Jobs[job].Queue = schedulingapi.QueueID(sc.defaultQueue)
   688  	}
   689  
   690  	metrics.UpdateE2eSchedulingStartTimeByJob(sc.Jobs[job].Name, string(sc.Jobs[job].Queue), sc.Jobs[job].Namespace,
   691  		sc.Jobs[job].CreationTimestamp.Time)
   692  	return nil
   693  }
   694  
   695  // Assumes that lock is already acquired.
   696  func (sc *SchedulerCache) updatePodGroup(newPodGroup *schedulingapi.PodGroup) error {
   697  	return sc.setPodGroup(newPodGroup)
   698  }
   699  
   700  // Assumes that lock is already acquired.
   701  func (sc *SchedulerCache) deletePodGroup(id schedulingapi.JobID) error {
   702  	job, found := sc.Jobs[id]
   703  	if !found {
   704  		return fmt.Errorf("can not found job %v", id)
   705  	}
   706  
   707  	// Unset SchedulingSpec
   708  	job.UnsetPodGroup()
   709  
   710  	sc.deleteJob(job)
   711  
   712  	return nil
   713  }
   714  
   715  // AddPodGroupV1beta1 add podgroup to scheduler cache
   716  func (sc *SchedulerCache) AddPodGroupV1beta1(obj interface{}) {
   717  	ss, ok := obj.(*schedulingv1beta1.PodGroup)
   718  	if !ok {
   719  		klog.Errorf("Cannot convert to *schedulingv1beta1.PodGroup: %v", obj)
   720  		return
   721  	}
   722  
   723  	podgroup := scheduling.PodGroup{}
   724  	if err := scheme.Scheme.Convert(ss, &podgroup, nil); err != nil {
   725  		klog.Errorf("Failed to convert podgroup from %T to %T", ss, podgroup)
   726  		return
   727  	}
   728  
   729  	pg := &schedulingapi.PodGroup{PodGroup: podgroup, Version: schedulingapi.PodGroupVersionV1Beta1}
   730  	klog.V(4).Infof("Add PodGroup(%s) into cache, spec(%#v)", ss.Name, ss.Spec)
   731  
   732  	sc.Mutex.Lock()
   733  	defer sc.Mutex.Unlock()
   734  
   735  	if err := sc.setPodGroup(pg); err != nil {
   736  		klog.Errorf("Failed to add PodGroup %s into cache: %v", ss.Name, err)
   737  		return
   738  	}
   739  }
   740  
   741  // UpdatePodGroupV1beta1 add podgroup to scheduler cache
   742  func (sc *SchedulerCache) UpdatePodGroupV1beta1(oldObj, newObj interface{}) {
   743  	oldSS, ok := oldObj.(*schedulingv1beta1.PodGroup)
   744  	if !ok {
   745  		klog.Errorf("Cannot convert oldObj to *schedulingv1beta1.SchedulingSpec: %v", oldObj)
   746  		return
   747  	}
   748  	newSS, ok := newObj.(*schedulingv1beta1.PodGroup)
   749  	if !ok {
   750  		klog.Errorf("Cannot convert newObj to *schedulingv1beta1.SchedulingSpec: %v", newObj)
   751  		return
   752  	}
   753  
   754  	if oldSS.ResourceVersion == newSS.ResourceVersion {
   755  		return
   756  	}
   757  
   758  	podgroup := scheduling.PodGroup{}
   759  	if err := scheme.Scheme.Convert(newSS, &podgroup, nil); err != nil {
   760  		klog.Errorf("Failed to convert podgroup from %T to %T", newSS, podgroup)
   761  		return
   762  	}
   763  
   764  	pg := &schedulingapi.PodGroup{PodGroup: podgroup, Version: schedulingapi.PodGroupVersionV1Beta1}
   765  
   766  	sc.Mutex.Lock()
   767  	defer sc.Mutex.Unlock()
   768  
   769  	if err := sc.updatePodGroup(pg); err != nil {
   770  		klog.Errorf("Failed to update SchedulingSpec %s into cache: %v", pg.Name, err)
   771  		return
   772  	}
   773  }
   774  
   775  // DeletePodGroupV1beta1 delete podgroup from scheduler cache
   776  func (sc *SchedulerCache) DeletePodGroupV1beta1(obj interface{}) {
   777  	var ss *schedulingv1beta1.PodGroup
   778  	switch t := obj.(type) {
   779  	case *schedulingv1beta1.PodGroup:
   780  		ss = t
   781  	case cache.DeletedFinalStateUnknown:
   782  		var ok bool
   783  		ss, ok = t.Obj.(*schedulingv1beta1.PodGroup)
   784  		if !ok {
   785  			klog.Errorf("Cannot convert to podgroup: %v", t.Obj)
   786  			return
   787  		}
   788  	default:
   789  		klog.Errorf("Cannot convert to podgroup: %v", t)
   790  		return
   791  	}
   792  
   793  	jobID := schedulingapi.JobID(fmt.Sprintf("%s/%s", ss.Namespace, ss.Name))
   794  
   795  	sc.Mutex.Lock()
   796  	defer sc.Mutex.Unlock()
   797  
   798  	if err := sc.deletePodGroup(jobID); err != nil {
   799  		klog.Errorf("Failed to delete podgroup %s from cache: %v", ss.Name, err)
   800  		return
   801  	}
   802  }
   803  
   804  // AddQueueV1beta1 add queue to scheduler cache
   805  func (sc *SchedulerCache) AddQueueV1beta1(obj interface{}) {
   806  	ss, ok := obj.(*schedulingv1beta1.Queue)
   807  	if !ok {
   808  		klog.Errorf("Cannot convert to *schedulingv1beta1.Queue: %v", obj)
   809  		return
   810  	}
   811  
   812  	queue := &scheduling.Queue{}
   813  	if err := scheme.Scheme.Convert(ss, queue, nil); err != nil {
   814  		klog.Errorf("Failed to convert queue from %T to %T", ss, queue)
   815  		return
   816  	}
   817  
   818  	sc.Mutex.Lock()
   819  	defer sc.Mutex.Unlock()
   820  
   821  	klog.V(4).Infof("Add Queue(%s) into cache, spec(%#v)", ss.Name, ss.Spec)
   822  	sc.addQueue(queue)
   823  }
   824  
   825  // UpdateQueueV1beta1 update queue to scheduler cache
   826  func (sc *SchedulerCache) UpdateQueueV1beta1(oldObj, newObj interface{}) {
   827  	oldSS, ok := oldObj.(*schedulingv1beta1.Queue)
   828  	if !ok {
   829  		klog.Errorf("Cannot convert oldObj to *schedulingv1beta1.Queue: %v", oldObj)
   830  		return
   831  	}
   832  	newSS, ok := newObj.(*schedulingv1beta1.Queue)
   833  	if !ok {
   834  		klog.Errorf("Cannot convert newObj to *schedulingv1beta1.Queue: %v", newObj)
   835  		return
   836  	}
   837  
   838  	if oldSS.ResourceVersion == newSS.ResourceVersion {
   839  		return
   840  	}
   841  
   842  	newQueue := &scheduling.Queue{}
   843  	if err := scheme.Scheme.Convert(newSS, newQueue, nil); err != nil {
   844  		klog.Errorf("Failed to convert queue from %T to %T", newSS, newQueue)
   845  		return
   846  	}
   847  
   848  	sc.Mutex.Lock()
   849  	defer sc.Mutex.Unlock()
   850  	sc.updateQueue(newQueue)
   851  }
   852  
   853  // DeleteQueueV1beta1 delete queue from the scheduler cache
   854  func (sc *SchedulerCache) DeleteQueueV1beta1(obj interface{}) {
   855  	var ss *schedulingv1beta1.Queue
   856  	switch t := obj.(type) {
   857  	case *schedulingv1beta1.Queue:
   858  		ss = t
   859  	case cache.DeletedFinalStateUnknown:
   860  		var ok bool
   861  		ss, ok = t.Obj.(*schedulingv1beta1.Queue)
   862  		if !ok {
   863  			klog.Errorf("Cannot convert to *schedulingv1beta1.Queue: %v", t.Obj)
   864  			return
   865  		}
   866  	default:
   867  		klog.Errorf("Cannot convert to *schedulingv1beta1.Queue: %v", t)
   868  		return
   869  	}
   870  
   871  	sc.Mutex.Lock()
   872  	defer sc.Mutex.Unlock()
   873  	sc.deleteQueue(schedulingapi.QueueID(ss.Name))
   874  }
   875  
   876  func (sc *SchedulerCache) addQueue(queue *scheduling.Queue) {
   877  	qi := schedulingapi.NewQueueInfo(queue)
   878  	sc.Queues[qi.UID] = qi
   879  }
   880  
   881  func (sc *SchedulerCache) updateQueue(queue *scheduling.Queue) {
   882  	sc.addQueue(queue)
   883  }
   884  
   885  func (sc *SchedulerCache) deleteQueue(id schedulingapi.QueueID) {
   886  	if queue, ok := sc.Queues[id]; ok {
   887  		delete(sc.Queues, id)
   888  		metrics.DeleteQueueMetrics(queue.Name)
   889  	}
   890  }
   891  
   892  // DeletePriorityClass delete priorityclass from the scheduler cache
   893  func (sc *SchedulerCache) DeletePriorityClass(obj interface{}) {
   894  	var ss *schedulingv1.PriorityClass
   895  	switch t := obj.(type) {
   896  	case *schedulingv1.PriorityClass:
   897  		ss = t
   898  	case cache.DeletedFinalStateUnknown:
   899  		var ok bool
   900  		ss, ok = t.Obj.(*schedulingv1.PriorityClass)
   901  		if !ok {
   902  			klog.Errorf("Cannot convert to *schedulingv1.PriorityClass: %v", t.Obj)
   903  			return
   904  		}
   905  	default:
   906  		klog.Errorf("Cannot convert to *schedulingv1.PriorityClass: %v", t)
   907  		return
   908  	}
   909  
   910  	sc.Mutex.Lock()
   911  	defer sc.Mutex.Unlock()
   912  
   913  	sc.deletePriorityClass(ss)
   914  }
   915  
   916  // UpdatePriorityClass update priorityclass to scheduler cache
   917  func (sc *SchedulerCache) UpdatePriorityClass(oldObj, newObj interface{}) {
   918  	oldSS, ok := oldObj.(*schedulingv1.PriorityClass)
   919  	if !ok {
   920  		klog.Errorf("Cannot convert oldObj to *schedulingv1.PriorityClass: %v", oldObj)
   921  
   922  		return
   923  	}
   924  
   925  	newSS, ok := newObj.(*schedulingv1.PriorityClass)
   926  	if !ok {
   927  		klog.Errorf("Cannot convert newObj to *schedulingv1.PriorityClass: %v", newObj)
   928  		return
   929  	}
   930  
   931  	sc.Mutex.Lock()
   932  	defer sc.Mutex.Unlock()
   933  
   934  	sc.deletePriorityClass(oldSS)
   935  	sc.addPriorityClass(newSS)
   936  }
   937  
   938  // AddPriorityClass add priorityclass to scheduler cache
   939  func (sc *SchedulerCache) AddPriorityClass(obj interface{}) {
   940  	ss, ok := obj.(*schedulingv1.PriorityClass)
   941  	if !ok {
   942  		klog.Errorf("Cannot convert to *schedulingv1.PriorityClass: %v", obj)
   943  		return
   944  	}
   945  
   946  	sc.Mutex.Lock()
   947  	defer sc.Mutex.Unlock()
   948  
   949  	sc.addPriorityClass(ss)
   950  }
   951  
   952  func (sc *SchedulerCache) deletePriorityClass(pc *schedulingv1.PriorityClass) {
   953  	if pc.GlobalDefault {
   954  		sc.defaultPriorityClass = nil
   955  		sc.defaultPriority = 0
   956  	}
   957  
   958  	delete(sc.PriorityClasses, pc.Name)
   959  }
   960  
   961  func (sc *SchedulerCache) addPriorityClass(pc *schedulingv1.PriorityClass) {
   962  	if pc.GlobalDefault {
   963  		if sc.defaultPriorityClass != nil {
   964  			klog.Errorf("Updated default priority class from <%s> to <%s> forcefully.",
   965  				sc.defaultPriorityClass.Name, pc.Name)
   966  		}
   967  		sc.defaultPriorityClass = pc
   968  		sc.defaultPriority = pc.Value
   969  	}
   970  
   971  	sc.PriorityClasses[pc.Name] = pc
   972  }
   973  
   974  func (sc *SchedulerCache) updateResourceQuota(quota *v1.ResourceQuota) {
   975  	collection, ok := sc.NamespaceCollection[quota.Namespace]
   976  	if !ok {
   977  		collection = schedulingapi.NewNamespaceCollection(quota.Namespace)
   978  		sc.NamespaceCollection[quota.Namespace] = collection
   979  	}
   980  
   981  	collection.Update(quota)
   982  }
   983  
   984  func (sc *SchedulerCache) deleteResourceQuota(quota *v1.ResourceQuota) {
   985  	collection, ok := sc.NamespaceCollection[quota.Namespace]
   986  	if !ok {
   987  		return
   988  	}
   989  
   990  	collection.Delete(quota)
   991  }
   992  
   993  // DeleteResourceQuota delete ResourceQuota from the scheduler cache
   994  func (sc *SchedulerCache) DeleteResourceQuota(obj interface{}) {
   995  	var r *v1.ResourceQuota
   996  	switch t := obj.(type) {
   997  	case *v1.ResourceQuota:
   998  		r = t
   999  	case cache.DeletedFinalStateUnknown:
  1000  		var ok bool
  1001  		r, ok = t.Obj.(*v1.ResourceQuota)
  1002  		if !ok {
  1003  			klog.Errorf("Cannot convert to *v1.ResourceQuota: %v", t.Obj)
  1004  			return
  1005  		}
  1006  	default:
  1007  		klog.Errorf("Cannot convert to *v1.ResourceQuota: %v", t)
  1008  		return
  1009  	}
  1010  
  1011  	sc.Mutex.Lock()
  1012  	defer sc.Mutex.Unlock()
  1013  
  1014  	klog.V(3).Infof("Delete ResourceQuota <%s/%v> in cache", r.Namespace, r.Name)
  1015  	sc.deleteResourceQuota(r)
  1016  }
  1017  
  1018  // UpdateResourceQuota update ResourceQuota to scheduler cache
  1019  func (sc *SchedulerCache) UpdateResourceQuota(oldObj, newObj interface{}) {
  1020  	newR, ok := newObj.(*v1.ResourceQuota)
  1021  	if !ok {
  1022  		klog.Errorf("Cannot convert newObj to *v1.ResourceQuota: %v", newObj)
  1023  		return
  1024  	}
  1025  
  1026  	sc.Mutex.Lock()
  1027  	defer sc.Mutex.Unlock()
  1028  
  1029  	klog.V(3).Infof("Update ResourceQuota <%s/%v> in cache, with spec: %v.", newR.Namespace, newR.Name, newR.Spec.Hard)
  1030  	sc.updateResourceQuota(newR)
  1031  }
  1032  
  1033  // AddResourceQuota add ResourceQuota to scheduler cache
  1034  func (sc *SchedulerCache) AddResourceQuota(obj interface{}) {
  1035  	var r *v1.ResourceQuota
  1036  	switch t := obj.(type) {
  1037  	case *v1.ResourceQuota:
  1038  		r = t
  1039  	default:
  1040  		klog.Errorf("Cannot convert to *v1.ResourceQuota: %v", t)
  1041  		return
  1042  	}
  1043  
  1044  	sc.Mutex.Lock()
  1045  	defer sc.Mutex.Unlock()
  1046  
  1047  	klog.V(3).Infof("Add ResourceQuota <%s/%v> in cache, with spec: %v.", r.Namespace, r.Name, r.Spec.Hard)
  1048  	sc.updateResourceQuota(r)
  1049  }
  1050  
  1051  func getNumaInfo(srcInfo *nodeinfov1alpha1.Numatopology) *schedulingapi.NumatopoInfo {
  1052  	numaInfo := &schedulingapi.NumatopoInfo{
  1053  		Namespace:   srcInfo.Namespace,
  1054  		Name:        srcInfo.Name,
  1055  		Policies:    make(map[nodeinfov1alpha1.PolicyName]string),
  1056  		NumaResMap:  make(map[string]*schedulingapi.ResourceInfo),
  1057  		CPUDetail:   topology.CPUDetails{},
  1058  		ResReserved: make(v1.ResourceList),
  1059  	}
  1060  
  1061  	policies := srcInfo.Spec.Policies
  1062  	for name, policy := range policies {
  1063  		numaInfo.Policies[name] = policy
  1064  	}
  1065  
  1066  	numaResMap := srcInfo.Spec.NumaResMap
  1067  	for name, resInfo := range numaResMap {
  1068  		tmp := schedulingapi.ResourceInfo{}
  1069  		tmp.Capacity = resInfo.Capacity
  1070  		allocatable, err := cpuset.Parse(resInfo.Allocatable)
  1071  		if err != nil {
  1072  			klog.ErrorS(err, "Failed to parse input as CPUSet", resInfo.Allocatable)
  1073  		}
  1074  		tmp.Allocatable = allocatable
  1075  		numaInfo.NumaResMap[name] = &tmp
  1076  	}
  1077  
  1078  	cpuDetail := srcInfo.Spec.CPUDetail
  1079  	for key, detail := range cpuDetail {
  1080  		cpuID, _ := strconv.Atoi(key)
  1081  		numaInfo.CPUDetail[cpuID] = topology.CPUInfo{
  1082  			NUMANodeID: detail.NUMANodeID,
  1083  			SocketID:   detail.SocketID,
  1084  			CoreID:     detail.CoreID,
  1085  		}
  1086  	}
  1087  
  1088  	resReserved, err := schedulingapi.ParseResourceList(srcInfo.Spec.ResReserved)
  1089  	if err != nil {
  1090  		klog.Errorf("ParseResourceList failed, err=%v", err)
  1091  	} else {
  1092  		numaInfo.ResReserved = resReserved
  1093  	}
  1094  
  1095  	return numaInfo
  1096  }
  1097  
  1098  // Assumes that lock is already acquired.
  1099  func (sc *SchedulerCache) addNumaInfo(info *nodeinfov1alpha1.Numatopology) error {
  1100  	if sc.Nodes[info.Name] == nil {
  1101  		sc.Nodes[info.Name] = schedulingapi.NewNodeInfo(nil)
  1102  		sc.Nodes[info.Name].Name = info.Name
  1103  	}
  1104  
  1105  	if sc.Nodes[info.Name].NumaInfo == nil {
  1106  		sc.Nodes[info.Name].NumaInfo = getNumaInfo(info)
  1107  		sc.Nodes[info.Name].NumaChgFlag = schedulingapi.NumaInfoMoreFlag
  1108  	} else {
  1109  		newLocalInfo := getNumaInfo(info)
  1110  		if sc.Nodes[info.Name].NumaInfo.Compare(newLocalInfo) {
  1111  			sc.Nodes[info.Name].NumaChgFlag = schedulingapi.NumaInfoMoreFlag
  1112  		} else {
  1113  			sc.Nodes[info.Name].NumaChgFlag = schedulingapi.NumaInfoLessFlag
  1114  		}
  1115  
  1116  		sc.Nodes[info.Name].NumaInfo = newLocalInfo
  1117  	}
  1118  
  1119  	for resName, NumaResInfo := range sc.Nodes[info.Name].NumaInfo.NumaResMap {
  1120  		klog.V(3).Infof("resource %s Allocatable %v on node[%s] into cache", resName, NumaResInfo, info.Name)
  1121  	}
  1122  
  1123  	klog.V(3).Infof("Policies %v on node[%s] into cache, change= %v",
  1124  		sc.Nodes[info.Name].NumaInfo.Policies, info.Name, sc.Nodes[info.Name].NumaChgFlag)
  1125  	return nil
  1126  }
  1127  
  1128  // Assumes that lock is already acquired.
  1129  func (sc *SchedulerCache) deleteNumaInfo(info *nodeinfov1alpha1.Numatopology) {
  1130  	if sc.Nodes[info.Name] != nil {
  1131  		sc.Nodes[info.Name].NumaInfo = nil
  1132  		sc.Nodes[info.Name].NumaChgFlag = schedulingapi.NumaInfoResetFlag
  1133  		klog.V(3).Infof("delete numainfo in cahce for node<%s>", info.Name)
  1134  	}
  1135  }
  1136  
  1137  // AddNumaInfoV1alpha1 add numa information to scheduler cache
  1138  func (sc *SchedulerCache) AddNumaInfoV1alpha1(obj interface{}) {
  1139  	ss, ok := obj.(*nodeinfov1alpha1.Numatopology)
  1140  	if !ok {
  1141  		klog.Errorf("Cannot convert oldObj to *nodeinfov1alpha1.Numatopology: %v", obj)
  1142  		return
  1143  	}
  1144  
  1145  	sc.Mutex.Lock()
  1146  	defer sc.Mutex.Unlock()
  1147  
  1148  	sc.addNumaInfo(ss)
  1149  }
  1150  
  1151  // UpdateNumaInfoV1alpha1 update numa information to scheduler cache
  1152  func (sc *SchedulerCache) UpdateNumaInfoV1alpha1(oldObj, newObj interface{}) {
  1153  	ss, ok := newObj.(*nodeinfov1alpha1.Numatopology)
  1154  	if !ok {
  1155  		klog.Errorf("Cannot convert oldObj to *nodeinfov1alpha1.Numatopology: %v", newObj)
  1156  		return
  1157  	}
  1158  
  1159  	sc.Mutex.Lock()
  1160  	defer sc.Mutex.Unlock()
  1161  	sc.addNumaInfo(ss)
  1162  	klog.V(3).Infof("update numaInfo<%s> in cahce, with spec: Policy: %v, resMap: %v", ss.Name, ss.Spec.Policies, ss.Spec.NumaResMap)
  1163  }
  1164  
  1165  // DeleteNumaInfoV1alpha1 delete numa information from scheduler cache
  1166  func (sc *SchedulerCache) DeleteNumaInfoV1alpha1(obj interface{}) {
  1167  	var ss *nodeinfov1alpha1.Numatopology
  1168  	switch t := obj.(type) {
  1169  	case *nodeinfov1alpha1.Numatopology:
  1170  		ss = t
  1171  	case cache.DeletedFinalStateUnknown:
  1172  		var ok bool
  1173  		ss, ok = t.Obj.(*nodeinfov1alpha1.Numatopology)
  1174  		if !ok {
  1175  			klog.Errorf("Cannot convert to Numatopo: %v", t.Obj)
  1176  			return
  1177  		}
  1178  	default:
  1179  		klog.Errorf("Cannot convert to Numatopo: %v", t)
  1180  		return
  1181  	}
  1182  
  1183  	sc.Mutex.Lock()
  1184  	defer sc.Mutex.Unlock()
  1185  
  1186  	sc.deleteNumaInfo(ss)
  1187  	klog.V(3).Infof("Delete numaInfo<%s> from cahce, with spec: Policy: %v, resMap: %v", ss.Name, ss.Spec.Policies, ss.Spec.NumaResMap)
  1188  }
  1189  
  1190  // AddJob add job to scheduler cache
  1191  func (sc *SchedulerCache) AddJob(obj interface{}) {
  1192  	job, ok := obj.(*schedulingapi.JobInfo)
  1193  	if !ok {
  1194  		klog.Errorf("Cannot convert to *api.JobInfo: %v", obj)
  1195  		return
  1196  	}
  1197  	sc.Mutex.Lock()
  1198  	defer sc.Mutex.Unlock()
  1199  	sc.Jobs[job.UID] = job
  1200  }
  1201  
  1202  func (sc *SchedulerCache) setCSIResourceOnNode(csiNode *sv1.CSINode, node *v1.Node) {
  1203  	if csiNode == nil || node == nil {
  1204  		return
  1205  	}
  1206  
  1207  	csiResources := make(map[v1.ResourceName]resource.Quantity)
  1208  	for i := range csiNode.Spec.Drivers {
  1209  		d := csiNode.Spec.Drivers[i]
  1210  		k := v1.ResourceName(volumeutil.GetCSIAttachLimitKey(d.Name))
  1211  		if d.Allocatable != nil && d.Allocatable.Count != nil {
  1212  			csiResources[k] = *resource.NewScaledQuantity(int64(*d.Allocatable.Count), -3)
  1213  		} else {
  1214  			// Count all csi volumes in cache, because the storage may change from unattachable volumes to attachable volumes after
  1215  			// the cache set up, in this case it is very difficult to refresh all task caches.
  1216  			// For unattachable volume, set the limits number to a very large value, in this way, scheduling will never
  1217  			// be limited due to insufficient quantity of it.
  1218  			csiResources[k] = *resource.NewScaledQuantity(DefaultAttachableVolumeQuantity, -3)
  1219  		}
  1220  	}
  1221  
  1222  	if len(csiResources) == 0 {
  1223  		return
  1224  	}
  1225  
  1226  	if node.Status.Allocatable == nil {
  1227  		node.Status.Allocatable = make(map[v1.ResourceName]resource.Quantity)
  1228  	}
  1229  
  1230  	if node.Status.Capacity == nil {
  1231  		node.Status.Capacity = make(map[v1.ResourceName]resource.Quantity)
  1232  	}
  1233  
  1234  	for resourceName, quantity := range csiResources {
  1235  		node.Status.Allocatable[resourceName] = quantity
  1236  		node.Status.Capacity[resourceName] = quantity
  1237  	}
  1238  }