volcano.sh/volcano@v1.9.0/pkg/scheduler/api/resource_info.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 api
    18  
    19  import (
    20  	"fmt"
    21  	"math"
    22  	"strings"
    23  
    24  	v1 "k8s.io/api/core/v1"
    25  	"k8s.io/apimachinery/pkg/api/resource"
    26  	"k8s.io/apimachinery/pkg/util/sets"
    27  	"k8s.io/klog/v2"
    28  	v1helper "k8s.io/kubernetes/pkg/scheduler/util"
    29  
    30  	"volcano.sh/volcano/pkg/scheduler/util/assert"
    31  )
    32  
    33  const (
    34  	// GPUResourceName need to follow https://github.com/NVIDIA/k8s-device-plugin/blob/66a35b71ac4b5cbfb04714678b548bd77e5ba719/server.go#L20
    35  	GPUResourceName = "nvidia.com/gpu"
    36  )
    37  
    38  const (
    39  	minResource float64 = 0.1
    40  )
    41  
    42  // DimensionDefaultValue means default value for black resource dimension
    43  type DimensionDefaultValue int
    44  
    45  const (
    46  	// Zero means resource dimension not defined will be treated as zero
    47  	Zero DimensionDefaultValue = 0
    48  	// Infinity means resource dimension not defined will be treated as infinity
    49  	Infinity DimensionDefaultValue = -1
    50  )
    51  
    52  // Resource struct defines all the resource type
    53  type Resource struct {
    54  	MilliCPU float64
    55  	Memory   float64
    56  
    57  	// ScalarResources
    58  	ScalarResources map[v1.ResourceName]float64
    59  
    60  	// MaxTaskNum is only used by predicates; it should NOT
    61  	// be accounted in other operators, e.g. Add.
    62  	MaxTaskNum int
    63  }
    64  
    65  // EmptyResource creates a empty resource object and returns
    66  func EmptyResource() *Resource {
    67  	return &Resource{}
    68  }
    69  
    70  // NewResource creates a new resource object from resource list
    71  func NewResource(rl v1.ResourceList) *Resource {
    72  	r := EmptyResource()
    73  	for rName, rQuant := range rl {
    74  		switch rName {
    75  		case v1.ResourceCPU:
    76  			r.MilliCPU += float64(rQuant.MilliValue())
    77  		case v1.ResourceMemory:
    78  			r.Memory += float64(rQuant.Value())
    79  		case v1.ResourcePods:
    80  			r.MaxTaskNum += int(rQuant.Value())
    81  			r.AddScalar(rName, float64(rQuant.Value()))
    82  		case v1.ResourceEphemeralStorage:
    83  			r.AddScalar(rName, float64(rQuant.MilliValue()))
    84  		default:
    85  			if IsCountQuota(rName) {
    86  				continue
    87  			}
    88  			//NOTE: When converting this back to k8s resource, we need record the format as well as / 1000
    89  			if v1helper.IsScalarResourceName(rName) {
    90  				ignore := false
    91  				IgnoredDevicesList.Range(func(_ int, val string) bool {
    92  					if rName.String() == val {
    93  						ignore = true
    94  						return false
    95  					}
    96  					return true
    97  				})
    98  				if !ignore {
    99  					r.AddScalar(rName, float64(rQuant.MilliValue()))
   100  				} else {
   101  					klog.V(4).Infof("Ignoring resource %s", rName.String())
   102  				}
   103  			}
   104  		}
   105  	}
   106  	return r
   107  }
   108  
   109  // ResFloat642Quantity transform resource quantity
   110  func ResFloat642Quantity(resName v1.ResourceName, quantity float64) resource.Quantity {
   111  	var resQuantity *resource.Quantity
   112  	switch resName {
   113  	case v1.ResourceCPU:
   114  		resQuantity = resource.NewMilliQuantity(int64(quantity), resource.DecimalSI)
   115  	default:
   116  		resQuantity = resource.NewQuantity(int64(quantity), resource.BinarySI)
   117  	}
   118  
   119  	return *resQuantity
   120  }
   121  
   122  // ResQuantity2Float64 transform resource quantity
   123  func ResQuantity2Float64(resName v1.ResourceName, quantity resource.Quantity) float64 {
   124  	var resQuantity float64
   125  	switch resName {
   126  	case v1.ResourceCPU:
   127  		resQuantity = float64(quantity.MilliValue())
   128  	default:
   129  		resQuantity = float64(quantity.Value())
   130  	}
   131  
   132  	return resQuantity
   133  }
   134  
   135  // Clone is used to clone a resource type, which is a deep copy function.
   136  func (r *Resource) Clone() *Resource {
   137  	clone := &Resource{
   138  		MilliCPU:   r.MilliCPU,
   139  		Memory:     r.Memory,
   140  		MaxTaskNum: r.MaxTaskNum,
   141  	}
   142  
   143  	if r.ScalarResources != nil {
   144  		clone.ScalarResources = make(map[v1.ResourceName]float64)
   145  		for k, v := range r.ScalarResources {
   146  			clone.ScalarResources[k] = v
   147  		}
   148  	}
   149  
   150  	return clone
   151  }
   152  
   153  // String returns resource details in string format
   154  func (r *Resource) String() string {
   155  	str := fmt.Sprintf("cpu %0.2f, memory %0.2f", r.MilliCPU, r.Memory)
   156  	for rName, rQuant := range r.ScalarResources {
   157  		str = fmt.Sprintf("%s, %s %0.2f", str, rName, rQuant)
   158  	}
   159  	return str
   160  }
   161  
   162  // ResourceNames returns all resource types
   163  func (r *Resource) ResourceNames() ResourceNameList {
   164  	resNames := ResourceNameList{}
   165  
   166  	if r.MilliCPU >= minResource {
   167  		resNames = append(resNames, v1.ResourceCPU)
   168  	}
   169  
   170  	if r.Memory >= minResource {
   171  		resNames = append(resNames, v1.ResourceMemory)
   172  	}
   173  
   174  	for rName, rMount := range r.ScalarResources {
   175  		if rMount >= minResource {
   176  			resNames = append(resNames, rName)
   177  		}
   178  	}
   179  
   180  	return resNames
   181  }
   182  
   183  // Get returns the resource value for that particular resource type
   184  func (r *Resource) Get(rn v1.ResourceName) float64 {
   185  	switch rn {
   186  	case v1.ResourceCPU:
   187  		return r.MilliCPU
   188  	case v1.ResourceMemory:
   189  		return r.Memory
   190  	default:
   191  		if r.ScalarResources == nil {
   192  			return 0
   193  		}
   194  		return r.ScalarResources[rn]
   195  	}
   196  }
   197  
   198  // Skip checking "pods" resource.
   199  // All pods request one "pods" resource now, no need to check it
   200  var ignoredScalarResources = sets.NewString(string(v1.ResourcePods))
   201  
   202  func IsIgnoredScalarResource(name v1.ResourceName) bool {
   203  	return ignoredScalarResources.Has(string(name))
   204  }
   205  
   206  // IsEmpty returns false if any kind of resource other than IgnoredResources is not less than min value, otherwise returns true
   207  func (r *Resource) IsEmpty() bool {
   208  	if !(r.MilliCPU < minResource && r.Memory < minResource) {
   209  		return false
   210  	}
   211  
   212  	for rName, rQuant := range r.ScalarResources {
   213  		if IsIgnoredScalarResource(rName) {
   214  			continue
   215  		}
   216  		if rQuant >= minResource {
   217  			return false
   218  		}
   219  	}
   220  
   221  	return true
   222  }
   223  
   224  // IsZero returns false if the given kind of resource is not less than min value
   225  func (r *Resource) IsZero(rn v1.ResourceName) bool {
   226  	switch rn {
   227  	case v1.ResourceCPU:
   228  		return r.MilliCPU < minResource
   229  	case v1.ResourceMemory:
   230  		return r.Memory < minResource
   231  	default:
   232  		if r.ScalarResources == nil {
   233  			return true
   234  		}
   235  
   236  		_, found := r.ScalarResources[rn]
   237  		assert.Assertf(found, "unknown resource %s", rn)
   238  
   239  		return r.ScalarResources[rn] < minResource
   240  	}
   241  }
   242  
   243  // Add is used to add two given resources
   244  func (r *Resource) Add(rr *Resource) *Resource {
   245  	r.MilliCPU += rr.MilliCPU
   246  	r.Memory += rr.Memory
   247  
   248  	for rName, rQuant := range rr.ScalarResources {
   249  		if r.ScalarResources == nil {
   250  			r.ScalarResources = map[v1.ResourceName]float64{}
   251  		}
   252  		r.ScalarResources[rName] += rQuant
   253  	}
   254  
   255  	return r
   256  }
   257  
   258  // Sub subtracts two Resource objects with assertion.
   259  func (r *Resource) Sub(rr *Resource) *Resource {
   260  	assert.Assertf(rr.LessEqual(r, Zero), "resource is not sufficient to do operation: <%v> sub <%v>", r, rr)
   261  	return r.sub(rr)
   262  }
   263  
   264  // SubWithoutAssert subtracts two Resource objects without assertion,
   265  // this function is added because some resource subtraction allows negative results, while others do not.
   266  func (r *Resource) SubWithoutAssert(rr *Resource) *Resource {
   267  	ok, resources := rr.LessEqualWithResourcesName(r, Zero)
   268  	if !ok {
   269  		klog.Errorf("resources <%v> are not sufficient to do operation: <%v> sub <%v>", resources, r, rr)
   270  	}
   271  	return r.sub(rr)
   272  }
   273  
   274  // sub subtracts two Resource objects.
   275  func (r *Resource) sub(rr *Resource) *Resource {
   276  	r.MilliCPU -= rr.MilliCPU
   277  	r.Memory -= rr.Memory
   278  
   279  	if r.ScalarResources == nil {
   280  		return r
   281  	}
   282  	for rrName, rrQuant := range rr.ScalarResources {
   283  		r.ScalarResources[rrName] -= rrQuant
   284  	}
   285  
   286  	return r
   287  }
   288  
   289  // Multi multiples the resource with ratio provided
   290  func (r *Resource) Multi(ratio float64) *Resource {
   291  	r.MilliCPU *= ratio
   292  	r.Memory *= ratio
   293  	for rName, rQuant := range r.ScalarResources {
   294  		r.ScalarResources[rName] = rQuant * ratio
   295  	}
   296  	return r
   297  }
   298  
   299  // SetMaxResource compares with ResourceList and takes max value for each Resource.
   300  func (r *Resource) SetMaxResource(rr *Resource) {
   301  	if r == nil || rr == nil {
   302  		return
   303  	}
   304  
   305  	if rr.MilliCPU > r.MilliCPU {
   306  		r.MilliCPU = rr.MilliCPU
   307  	}
   308  	if rr.Memory > r.Memory {
   309  		r.Memory = rr.Memory
   310  	}
   311  
   312  	for rrName, rrQuant := range rr.ScalarResources {
   313  		if r.ScalarResources == nil {
   314  			r.ScalarResources = make(map[v1.ResourceName]float64)
   315  			for k, v := range rr.ScalarResources {
   316  				r.ScalarResources[k] = v
   317  			}
   318  			return
   319  		}
   320  		_, ok := r.ScalarResources[rrName]
   321  		if !ok || rrQuant > r.ScalarResources[rrName] {
   322  			r.ScalarResources[rrName] = rrQuant
   323  		}
   324  	}
   325  }
   326  
   327  // FitDelta Computes the delta between a resource object representing available
   328  // resources an operand representing resources being requested.  Any
   329  // field that is less than 0 after the operation represents an
   330  // insufficient resource.
   331  func (r *Resource) FitDelta(rr *Resource) *Resource {
   332  	if rr.MilliCPU > 0 {
   333  		r.MilliCPU -= rr.MilliCPU + minResource
   334  	}
   335  
   336  	if rr.Memory > 0 {
   337  		r.Memory -= rr.Memory + minResource
   338  	}
   339  
   340  	if r.ScalarResources == nil {
   341  		r.ScalarResources = make(map[v1.ResourceName]float64)
   342  	}
   343  
   344  	for rrName, rrQuant := range rr.ScalarResources {
   345  		if rrQuant > 0 {
   346  			_, ok := r.ScalarResources[rrName]
   347  			if !ok {
   348  				r.ScalarResources[rrName] = 0
   349  			}
   350  			r.ScalarResources[rrName] -= rrQuant + minResource
   351  		}
   352  	}
   353  
   354  	return r
   355  }
   356  
   357  // Less returns true only on condition that all dimensions of resources in r are less than that of rr,
   358  // Otherwise returns false.
   359  // @param defaultValue "default value for resource dimension not defined in ScalarResources. Its value can only be one of 'Zero' and 'Infinity'"
   360  func (r *Resource) Less(rr *Resource, defaultValue DimensionDefaultValue) bool {
   361  	lessFunc := func(l, r float64) bool {
   362  		return l < r
   363  	}
   364  
   365  	if !lessFunc(r.MilliCPU, rr.MilliCPU) {
   366  		return false
   367  	}
   368  	if !lessFunc(r.Memory, rr.Memory) {
   369  		return false
   370  	}
   371  
   372  	if defaultValue == Infinity {
   373  		for name := range rr.ScalarResources {
   374  			if _, ok := r.ScalarResources[name]; !ok {
   375  				return false
   376  			}
   377  		}
   378  	}
   379  
   380  	for resourceName, leftValue := range r.ScalarResources {
   381  		rightValue, ok := rr.ScalarResources[resourceName]
   382  		if !ok && defaultValue == Infinity {
   383  			continue
   384  		}
   385  
   386  		if !lessFunc(leftValue, rightValue) {
   387  			return false
   388  		}
   389  	}
   390  	return true
   391  }
   392  
   393  // LessEqual returns true only on condition that all dimensions of resources in r are less than or equal with that of rr,
   394  // Otherwise returns false.
   395  // @param defaultValue "default value for resource dimension not defined in ScalarResources. Its value can only be one of 'Zero' and 'Infinity'"
   396  func (r *Resource) LessEqual(rr *Resource, defaultValue DimensionDefaultValue) bool {
   397  	lessEqualFunc := func(l, r, diff float64) bool {
   398  		if l < r || math.Abs(l-r) < diff {
   399  			return true
   400  		}
   401  		return false
   402  	}
   403  
   404  	if !lessEqualFunc(r.MilliCPU, rr.MilliCPU, minResource) {
   405  		return false
   406  	}
   407  	if !lessEqualFunc(r.Memory, rr.Memory, minResource) {
   408  		return false
   409  	}
   410  
   411  	if defaultValue == Infinity {
   412  		for name := range rr.ScalarResources {
   413  			if _, ok := r.ScalarResources[name]; !ok {
   414  				return false
   415  			}
   416  		}
   417  	}
   418  
   419  	for resourceName, leftValue := range r.ScalarResources {
   420  		rightValue, ok := rr.ScalarResources[resourceName]
   421  		if !ok && defaultValue == Infinity {
   422  			continue
   423  		}
   424  
   425  		if !lessEqualFunc(leftValue, rightValue, minResource) {
   426  			return false
   427  		}
   428  	}
   429  	return true
   430  }
   431  
   432  // LessEqualWithResourcesName returns true, []string{} only on condition that all dimensions of resources in r are less than or equal with that of rr,
   433  // Otherwise returns false and err string ,which show what resources are insufficient.
   434  // @param defaultValue "default value for resource dimension not defined in ScalarResources. Its value can only be one of 'Zero' and 'Infinity'"
   435  // this function is the same as LessEqual , and it will be merged to LessEqual in the future
   436  func (r *Resource) LessEqualWithResourcesName(rr *Resource, defaultValue DimensionDefaultValue) (bool, []string) {
   437  	resources := []string{}
   438  	lessEqualFunc := func(l, r, diff float64) bool {
   439  		if l < r || math.Abs(l-r) < diff {
   440  			return true
   441  		}
   442  		return false
   443  	}
   444  
   445  	if !lessEqualFunc(r.MilliCPU, rr.MilliCPU, minResource) {
   446  		resources = append(resources, "cpu")
   447  	}
   448  	if !lessEqualFunc(r.Memory, rr.Memory, minResource) {
   449  		resources = append(resources, "memory")
   450  	}
   451  
   452  	for resourceName, leftValue := range r.ScalarResources {
   453  		rightValue, ok := rr.ScalarResources[resourceName]
   454  		if !ok && defaultValue == Infinity {
   455  			continue
   456  		}
   457  
   458  		if !lessEqualFunc(leftValue, rightValue, minResource) {
   459  			resources = append(resources, string(resourceName))
   460  		}
   461  	}
   462  	if len(resources) > 0 {
   463  		return false, resources
   464  	}
   465  	return true, resources
   466  }
   467  
   468  // LessPartly returns true if there exists any dimension whose resource amount in r is less than that in rr.
   469  // Otherwise returns false.
   470  // @param defaultValue "default value for resource dimension not defined in ScalarResources. Its value can only be one of 'Zero' and 'Infinity'"
   471  func (r *Resource) LessPartly(rr *Resource, defaultValue DimensionDefaultValue) bool {
   472  	lessFunc := func(l, r float64) bool {
   473  		return l < r
   474  	}
   475  
   476  	if lessFunc(r.MilliCPU, rr.MilliCPU) || lessFunc(r.Memory, rr.Memory) {
   477  		return true
   478  	}
   479  
   480  	if defaultValue == Zero {
   481  		for name := range rr.ScalarResources {
   482  			if _, ok := r.ScalarResources[name]; !ok {
   483  				return true
   484  			}
   485  		}
   486  	}
   487  
   488  	for resourceName, leftValue := range r.ScalarResources {
   489  		rightValue, ok := rr.ScalarResources[resourceName]
   490  		if !ok && defaultValue == Infinity {
   491  			return true
   492  		}
   493  
   494  		if lessFunc(leftValue, rightValue) {
   495  			return true
   496  		}
   497  	}
   498  	return false
   499  }
   500  
   501  // LessEqualPartly returns true if there exists any dimension whose resource amount in r is less than or equal with that in rr.
   502  // Otherwise returns false.
   503  // @param defaultValue "default value for resource dimension not defined in ScalarResources. Its value can only be one of 'Zero' and 'Infinity'"
   504  func (r *Resource) LessEqualPartly(rr *Resource, defaultValue DimensionDefaultValue) bool {
   505  	lessEqualFunc := func(l, r, diff float64) bool {
   506  		if l < r || math.Abs(l-r) < diff {
   507  			return true
   508  		}
   509  		return false
   510  	}
   511  
   512  	if lessEqualFunc(r.MilliCPU, rr.MilliCPU, minResource) || lessEqualFunc(r.Memory, rr.Memory, minResource) {
   513  		return true
   514  	}
   515  
   516  	if defaultValue == Zero {
   517  		for name := range rr.ScalarResources {
   518  			if _, ok := r.ScalarResources[name]; !ok {
   519  				return true
   520  			}
   521  		}
   522  	}
   523  
   524  	for resourceName, leftValue := range r.ScalarResources {
   525  		rightValue, ok := rr.ScalarResources[resourceName]
   526  		if !ok && defaultValue == Infinity {
   527  			return true
   528  		}
   529  
   530  		if lessEqualFunc(leftValue, rightValue, minResource) {
   531  			return true
   532  		}
   533  	}
   534  	return false
   535  }
   536  
   537  // Equal returns true only on condition that values in all dimension are equal with each other for r and rr
   538  // Otherwise returns false.
   539  // @param defaultValue "default value for resource dimension not defined in ScalarResources. Its value can only be one of 'Zero' and 'Infinity'"
   540  func (r *Resource) Equal(rr *Resource, defaultValue DimensionDefaultValue) bool {
   541  	equalFunc := func(l, r, diff float64) bool {
   542  		return l == r || math.Abs(l-r) < diff
   543  	}
   544  
   545  	if !equalFunc(r.MilliCPU, rr.MilliCPU, minResource) || !equalFunc(r.Memory, rr.Memory, minResource) {
   546  		return false
   547  	}
   548  
   549  	for resourceName, leftValue := range r.ScalarResources {
   550  		rightValue := rr.ScalarResources[resourceName]
   551  		if !equalFunc(leftValue, rightValue, minResource) {
   552  			return false
   553  		}
   554  	}
   555  	return true
   556  }
   557  
   558  // Diff calculate the difference between two resource object
   559  // Note: if `defaultValue` equals `Infinity`, the difference between two values will be `Infinity`, marked as -1
   560  func (r *Resource) Diff(rr *Resource, defaultValue DimensionDefaultValue) (*Resource, *Resource) {
   561  	leftRes := r.Clone()
   562  	rightRes := rr.Clone()
   563  	increasedVal := EmptyResource()
   564  	decreasedVal := EmptyResource()
   565  	r.setDefaultValue(leftRes, rightRes, defaultValue)
   566  
   567  	if leftRes.MilliCPU > rightRes.MilliCPU {
   568  		increasedVal.MilliCPU = leftRes.MilliCPU - rightRes.MilliCPU
   569  	} else {
   570  		decreasedVal.MilliCPU = rightRes.MilliCPU - leftRes.MilliCPU
   571  	}
   572  
   573  	if leftRes.Memory > rightRes.Memory {
   574  		increasedVal.Memory = leftRes.Memory - rightRes.Memory
   575  	} else {
   576  		decreasedVal.Memory = rightRes.Memory - leftRes.Memory
   577  	}
   578  
   579  	increasedVal.ScalarResources = make(map[v1.ResourceName]float64)
   580  	decreasedVal.ScalarResources = make(map[v1.ResourceName]float64)
   581  	for lName, lQuant := range leftRes.ScalarResources {
   582  		rQuant := rightRes.ScalarResources[lName]
   583  		if lQuant == float64(Infinity) {
   584  			increasedVal.ScalarResources[lName] = lQuant
   585  			continue
   586  		}
   587  		if rQuant == float64(Infinity) {
   588  			decreasedVal.ScalarResources[lName] = rQuant
   589  			continue
   590  		}
   591  		if lQuant > rQuant {
   592  			increasedVal.ScalarResources[lName] = lQuant - rQuant
   593  		} else {
   594  			decreasedVal.ScalarResources[lName] = rQuant - lQuant
   595  		}
   596  	}
   597  
   598  	return increasedVal, decreasedVal
   599  }
   600  
   601  // AddScalar adds a resource by a scalar value of this resource.
   602  func (r *Resource) AddScalar(name v1.ResourceName, quantity float64) {
   603  	r.SetScalar(name, r.ScalarResources[name]+quantity)
   604  }
   605  
   606  // SetScalar sets a resource by a scalar value of this resource.
   607  func (r *Resource) SetScalar(name v1.ResourceName, quantity float64) {
   608  	// Lazily allocate scalar resource map.
   609  	if r.ScalarResources == nil {
   610  		r.ScalarResources = map[v1.ResourceName]float64{}
   611  	}
   612  	r.ScalarResources[name] = quantity
   613  }
   614  
   615  // MinDimensionResource is used to reset the r resource dimension which is less than rr
   616  // e.g r resource is <cpu 2000.00, memory 4047845376.00, hugepages-2Mi 0.00, hugepages-1Gi 0.00>
   617  // rr resource is <cpu 3000.00, memory 1000.00>
   618  // return r resource is <cpu 2000.00, memory 1000.00, hugepages-2Mi 0.00, hugepages-1Gi 0.00>
   619  // @param defaultValue "default value for resource dimension not defined in ScalarResources. Its value can only be one of 'Zero' and 'Infinity'"
   620  func (r *Resource) MinDimensionResource(rr *Resource, defaultValue DimensionDefaultValue) *Resource {
   621  	if rr.MilliCPU < r.MilliCPU {
   622  		r.MilliCPU = rr.MilliCPU
   623  	}
   624  	if rr.Memory < r.Memory {
   625  		r.Memory = rr.Memory
   626  	}
   627  
   628  	if r.ScalarResources == nil {
   629  		return r
   630  	}
   631  
   632  	if rr.ScalarResources == nil {
   633  		if defaultValue == Infinity {
   634  			return r
   635  		}
   636  
   637  		for name := range r.ScalarResources {
   638  			r.ScalarResources[name] = 0
   639  		}
   640  		return r
   641  	}
   642  
   643  	for name, quant := range r.ScalarResources {
   644  		rQuant, ok := rr.ScalarResources[name]
   645  		if ok {
   646  			r.ScalarResources[name] = math.Min(quant, rQuant)
   647  		} else {
   648  			if defaultValue == Infinity {
   649  				continue
   650  			}
   651  
   652  			r.ScalarResources[name] = 0
   653  		}
   654  	}
   655  	return r
   656  }
   657  
   658  // setDefaultValue sets default value for resource dimension not defined of ScalarResource in leftResource and rightResource
   659  // @param defaultValue "default value for resource dimension not defined in ScalarResources. It can only be one of 'Zero' or 'Infinity'"
   660  func (r *Resource) setDefaultValue(leftResource, rightResource *Resource, defaultValue DimensionDefaultValue) {
   661  	if leftResource.ScalarResources == nil {
   662  		leftResource.ScalarResources = map[v1.ResourceName]float64{}
   663  	}
   664  	if rightResource.ScalarResources == nil {
   665  		rightResource.ScalarResources = map[v1.ResourceName]float64{}
   666  	}
   667  	for resourceName := range leftResource.ScalarResources {
   668  		_, ok := rightResource.ScalarResources[resourceName]
   669  		if !ok {
   670  			rightResource.ScalarResources[resourceName] = float64(defaultValue)
   671  		}
   672  	}
   673  
   674  	for resourceName := range rightResource.ScalarResources {
   675  		_, ok := leftResource.ScalarResources[resourceName]
   676  		if !ok {
   677  			leftResource.ScalarResources[resourceName] = float64(defaultValue)
   678  		}
   679  	}
   680  }
   681  
   682  // ParseResourceList parses the given configuration map into an API
   683  // ResourceList or returns an error.
   684  func ParseResourceList(m map[string]string) (v1.ResourceList, error) {
   685  	if len(m) == 0 {
   686  		return nil, nil
   687  	}
   688  	rl := make(v1.ResourceList)
   689  	for k, v := range m {
   690  		switch v1.ResourceName(k) {
   691  		// CPU, memory, local storage, and PID resources are supported.
   692  		case v1.ResourceCPU, v1.ResourceMemory, v1.ResourceEphemeralStorage:
   693  			q, err := resource.ParseQuantity(v)
   694  			if err != nil {
   695  				return nil, err
   696  			}
   697  			if q.Sign() == -1 {
   698  				return nil, fmt.Errorf("resource quantity for %q cannot be negative: %v", k, v)
   699  			}
   700  			rl[v1.ResourceName(k)] = q
   701  		default:
   702  			return nil, fmt.Errorf("cannot reserve %q resource", k)
   703  		}
   704  	}
   705  	return rl, nil
   706  }
   707  
   708  func GetMinResource() float64 {
   709  	return minResource
   710  }
   711  
   712  // ResourceNameList struct defines resource name collection
   713  type ResourceNameList []v1.ResourceName
   714  
   715  // Contains judges whether rr is subset of r
   716  func (r ResourceNameList) Contains(rr ResourceNameList) bool {
   717  	for _, rrName := range ([]v1.ResourceName)(rr) {
   718  		isResourceExist := false
   719  		for _, rName := range ([]v1.ResourceName)(r) {
   720  			if rName == rrName {
   721  				isResourceExist = true
   722  				break
   723  			}
   724  		}
   725  		if !isResourceExist {
   726  			return false
   727  		}
   728  	}
   729  	return true
   730  }
   731  
   732  func IsCountQuota(name v1.ResourceName) bool {
   733  	return strings.HasPrefix(string(name), "count/")
   734  }