mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Added unit test for node operation in schedulercache.
This commit is contained in:
		@@ -27,6 +27,7 @@ go_library(
 | 
				
			|||||||
        "//plugin/pkg/scheduler/algorithm:go_default_library",
 | 
					        "//plugin/pkg/scheduler/algorithm:go_default_library",
 | 
				
			||||||
        "//plugin/pkg/scheduler/algorithm/priorities/util:go_default_library",
 | 
					        "//plugin/pkg/scheduler/algorithm/priorities/util:go_default_library",
 | 
				
			||||||
        "//plugin/pkg/scheduler/schedulercache:go_default_library",
 | 
					        "//plugin/pkg/scheduler/schedulercache:go_default_library",
 | 
				
			||||||
 | 
					        "//plugin/pkg/scheduler/util:go_default_library",
 | 
				
			||||||
        "//vendor/github.com/golang/glog:go_default_library",
 | 
					        "//vendor/github.com/golang/glog:go_default_library",
 | 
				
			||||||
        "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
 | 
					        "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
 | 
				
			||||||
        "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
					        "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
				
			||||||
@@ -52,6 +53,7 @@ go_test(
 | 
				
			|||||||
        "//plugin/pkg/scheduler/algorithm:go_default_library",
 | 
					        "//plugin/pkg/scheduler/algorithm:go_default_library",
 | 
				
			||||||
        "//plugin/pkg/scheduler/schedulercache:go_default_library",
 | 
					        "//plugin/pkg/scheduler/schedulercache:go_default_library",
 | 
				
			||||||
        "//plugin/pkg/scheduler/testing:go_default_library",
 | 
					        "//plugin/pkg/scheduler/testing:go_default_library",
 | 
				
			||||||
 | 
					        "//plugin/pkg/scheduler/util:go_default_library",
 | 
				
			||||||
        "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
 | 
					        "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
 | 
				
			||||||
        "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
					        "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
				
			||||||
        "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
 | 
					        "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,7 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/pkg/api/v1"
 | 
						"k8s.io/kubernetes/pkg/api/v1"
 | 
				
			||||||
	"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
 | 
						"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
 | 
				
			||||||
	"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
 | 
						"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
 | 
				
			||||||
 | 
						schedutil "k8s.io/kubernetes/plugin/pkg/scheduler/util"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type PredicateMetadataFactory struct {
 | 
					type PredicateMetadataFactory struct {
 | 
				
			||||||
@@ -48,7 +49,7 @@ func (pfactory *PredicateMetadataFactory) GetMetadata(pod *v1.Pod, nodeNameToInf
 | 
				
			|||||||
		pod:                       pod,
 | 
							pod:                       pod,
 | 
				
			||||||
		podBestEffort:             isPodBestEffort(pod),
 | 
							podBestEffort:             isPodBestEffort(pod),
 | 
				
			||||||
		podRequest:                GetResourceRequest(pod),
 | 
							podRequest:                GetResourceRequest(pod),
 | 
				
			||||||
		podPorts:                  GetUsedPorts(pod),
 | 
							podPorts:                  schedutil.GetUsedPorts(pod),
 | 
				
			||||||
		matchingAntiAffinityTerms: matchingTerms,
 | 
							matchingAntiAffinityTerms: matchingTerms,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for predicateName, precomputeFunc := range predicatePrecomputations {
 | 
						for predicateName, precomputeFunc := range predicatePrecomputations {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,6 +40,7 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
 | 
						"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
 | 
				
			||||||
	priorityutil "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/priorities/util"
 | 
						priorityutil "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/priorities/util"
 | 
				
			||||||
	"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
 | 
						"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
 | 
				
			||||||
 | 
						schedutil "k8s.io/kubernetes/plugin/pkg/scheduler/util"
 | 
				
			||||||
	"k8s.io/metrics/pkg/client/clientset_generated/clientset"
 | 
						"k8s.io/metrics/pkg/client/clientset_generated/clientset"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -835,7 +836,7 @@ func PodFitsHostPorts(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.No
 | 
				
			|||||||
		wantPorts = predicateMeta.podPorts
 | 
							wantPorts = predicateMeta.podPorts
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// We couldn't parse metadata - fallback to computing it.
 | 
							// We couldn't parse metadata - fallback to computing it.
 | 
				
			||||||
		wantPorts = GetUsedPorts(pod)
 | 
							wantPorts = schedutil.GetUsedPorts(pod)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if len(wantPorts) == 0 {
 | 
						if len(wantPorts) == 0 {
 | 
				
			||||||
		return true, nil, nil
 | 
							return true, nil, nil
 | 
				
			||||||
@@ -850,24 +851,6 @@ func PodFitsHostPorts(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.No
 | 
				
			|||||||
	return true, nil, nil
 | 
						return true, nil, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GetUsedPorts(pods ...*v1.Pod) map[int]bool {
 | 
					 | 
				
			||||||
	ports := make(map[int]bool)
 | 
					 | 
				
			||||||
	for _, pod := range pods {
 | 
					 | 
				
			||||||
		for j := range pod.Spec.Containers {
 | 
					 | 
				
			||||||
			container := &pod.Spec.Containers[j]
 | 
					 | 
				
			||||||
			for k := range container.Ports {
 | 
					 | 
				
			||||||
				podPort := &container.Ports[k]
 | 
					 | 
				
			||||||
				// "0" is explicitly ignored in PodFitsHostPorts,
 | 
					 | 
				
			||||||
				// which is the only function that uses this value.
 | 
					 | 
				
			||||||
				if podPort.HostPort != 0 {
 | 
					 | 
				
			||||||
					ports[int(podPort.HostPort)] = true
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return ports
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// search two arrays and return true if they have at least one common element; return false otherwise
 | 
					// search two arrays and return true if they have at least one common element; return false otherwise
 | 
				
			||||||
func haveSame(a1, a2 []string) bool {
 | 
					func haveSame(a1, a2 []string) bool {
 | 
				
			||||||
	for _, val1 := range a1 {
 | 
						for _, val1 := range a1 {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,7 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
 | 
						"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
 | 
				
			||||||
	"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
 | 
						"k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache"
 | 
				
			||||||
	schedulertesting "k8s.io/kubernetes/plugin/pkg/scheduler/testing"
 | 
						schedulertesting "k8s.io/kubernetes/plugin/pkg/scheduler/testing"
 | 
				
			||||||
 | 
						schedutil "k8s.io/kubernetes/plugin/pkg/scheduler/util"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type FakeNodeInfo v1.Node
 | 
					type FakeNodeInfo v1.Node
 | 
				
			||||||
@@ -563,7 +564,7 @@ func TestGetUsedPorts(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, test := range tests {
 | 
						for _, test := range tests {
 | 
				
			||||||
		ports := GetUsedPorts(test.pods...)
 | 
							ports := schedutil.GetUsedPorts(test.pods...)
 | 
				
			||||||
		if !reflect.DeepEqual(test.ports, ports) {
 | 
							if !reflect.DeepEqual(test.ports, ports) {
 | 
				
			||||||
			t.Errorf("%s: expected %v, got %v", "test get used ports", test.ports, ports)
 | 
								t.Errorf("%s: expected %v, got %v", "test get used ports", test.ports, ports)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,7 +42,9 @@ go_test(
 | 
				
			|||||||
    tags = ["automanaged"],
 | 
					    tags = ["automanaged"],
 | 
				
			||||||
    deps = [
 | 
					    deps = [
 | 
				
			||||||
        "//pkg/api/v1:go_default_library",
 | 
					        "//pkg/api/v1:go_default_library",
 | 
				
			||||||
 | 
					        "//pkg/api/v1/helper:go_default_library",
 | 
				
			||||||
        "//plugin/pkg/scheduler/algorithm/priorities/util:go_default_library",
 | 
					        "//plugin/pkg/scheduler/algorithm/priorities/util:go_default_library",
 | 
				
			||||||
 | 
					        "//plugin/pkg/scheduler/util:go_default_library",
 | 
				
			||||||
        "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
 | 
					        "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
 | 
				
			||||||
        "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
					        "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
				
			||||||
        "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
 | 
					        "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,9 @@ import (
 | 
				
			|||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/labels"
 | 
						"k8s.io/apimachinery/pkg/labels"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/api/v1"
 | 
						"k8s.io/kubernetes/pkg/api/v1"
 | 
				
			||||||
 | 
						v1helper "k8s.io/kubernetes/pkg/api/v1/helper"
 | 
				
			||||||
	priorityutil "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/priorities/util"
 | 
						priorityutil "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/priorities/util"
 | 
				
			||||||
 | 
						schedutil "k8s.io/kubernetes/plugin/pkg/scheduler/util"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func deepEqualWithoutGeneration(t *testing.T, testcase int, actual, expected *NodeInfo) {
 | 
					func deepEqualWithoutGeneration(t *testing.T, testcase int, actual, expected *NodeInfo) {
 | 
				
			||||||
@@ -438,7 +440,6 @@ func TestRemovePod(t *testing.T) {
 | 
				
			|||||||
	basePod := makeBasePod(nodeName, "test", "100m", "500", []v1.ContainerPort{{HostPort: 80}})
 | 
						basePod := makeBasePod(nodeName, "test", "100m", "500", []v1.ContainerPort{{HostPort: 80}})
 | 
				
			||||||
	tests := []struct {
 | 
						tests := []struct {
 | 
				
			||||||
		pod       *v1.Pod
 | 
							pod       *v1.Pod
 | 
				
			||||||
 | 
					 | 
				
			||||||
		wNodeInfo *NodeInfo
 | 
							wNodeInfo *NodeInfo
 | 
				
			||||||
	}{{
 | 
						}{{
 | 
				
			||||||
		pod: basePod,
 | 
							pod: basePod,
 | 
				
			||||||
@@ -506,6 +507,265 @@ func TestForgetPod(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// addResource adds ResourceList into Resource.
 | 
				
			||||||
 | 
					func addResource(r *Resource, rl v1.ResourceList) {
 | 
				
			||||||
 | 
						if r == nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for rName, rQuant := range rl {
 | 
				
			||||||
 | 
							switch rName {
 | 
				
			||||||
 | 
							case v1.ResourceCPU:
 | 
				
			||||||
 | 
								r.MilliCPU += rQuant.MilliValue()
 | 
				
			||||||
 | 
							case v1.ResourceMemory:
 | 
				
			||||||
 | 
								r.Memory += rQuant.Value()
 | 
				
			||||||
 | 
							case v1.ResourceNvidiaGPU:
 | 
				
			||||||
 | 
								r.NvidiaGPU += rQuant.Value()
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								if v1helper.IsOpaqueIntResourceName(rName) {
 | 
				
			||||||
 | 
									r.AddOpaque(rName, rQuant.Value())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// getResourceRequest returns the resource request of all containers in Pods;
 | 
				
			||||||
 | 
					// excuding initContainers.
 | 
				
			||||||
 | 
					func getResourceRequest(pod *v1.Pod) v1.ResourceList {
 | 
				
			||||||
 | 
						result := &Resource{}
 | 
				
			||||||
 | 
						for _, container := range pod.Spec.Containers {
 | 
				
			||||||
 | 
							addResource(result, container.Resources.Requests)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return result.ResourceList()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// newResource returns a new Resource by ResourceList.
 | 
				
			||||||
 | 
					func newResource(rl v1.ResourceList) *Resource {
 | 
				
			||||||
 | 
						res := &Resource{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for rName, rQuantity := range rl {
 | 
				
			||||||
 | 
							switch rName {
 | 
				
			||||||
 | 
							case v1.ResourceMemory:
 | 
				
			||||||
 | 
								res.Memory = rQuantity.Value()
 | 
				
			||||||
 | 
							case v1.ResourceCPU:
 | 
				
			||||||
 | 
								res.MilliCPU = rQuantity.MilliValue()
 | 
				
			||||||
 | 
							case v1.ResourceNvidiaGPU:
 | 
				
			||||||
 | 
								res.NvidiaGPU += rQuantity.Value()
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								if v1helper.IsOpaqueIntResourceName(rName) {
 | 
				
			||||||
 | 
									res.SetOpaque(rName, rQuantity.Value())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return res
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// buildNodeInfo creates a NodeInfo by simulating node operations in cache.
 | 
				
			||||||
 | 
					func buildNodeInfo(node *v1.Node, pods []*v1.Pod) *NodeInfo {
 | 
				
			||||||
 | 
						expected := NewNodeInfo()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Simulate SetNode.
 | 
				
			||||||
 | 
						expected.node = node
 | 
				
			||||||
 | 
						expected.allocatableResource = newResource(node.Status.Allocatable)
 | 
				
			||||||
 | 
						expected.taints = node.Spec.Taints
 | 
				
			||||||
 | 
						expected.generation++
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, pod := range pods {
 | 
				
			||||||
 | 
							// Simulate AddPod
 | 
				
			||||||
 | 
							expected.pods = append(expected.pods, pod)
 | 
				
			||||||
 | 
							addResource(expected.requestedResource, getResourceRequest(pod))
 | 
				
			||||||
 | 
							addResource(expected.nonzeroRequest, getResourceRequest(pod))
 | 
				
			||||||
 | 
							expected.usedPorts = schedutil.GetUsedPorts(pod)
 | 
				
			||||||
 | 
							expected.generation++
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return expected
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TestNodeOperators tests node operations of cache, including add, update
 | 
				
			||||||
 | 
					// and remove.
 | 
				
			||||||
 | 
					func TestNodeOperators(t *testing.T) {
 | 
				
			||||||
 | 
						// Test datas
 | 
				
			||||||
 | 
						nodeName := "test-node"
 | 
				
			||||||
 | 
						cpu_1 := resource.MustParse("1000m")
 | 
				
			||||||
 | 
						mem_100m := resource.MustParse("100m")
 | 
				
			||||||
 | 
						cpu_half := resource.MustParse("500m")
 | 
				
			||||||
 | 
						mem_50m := resource.MustParse("50m")
 | 
				
			||||||
 | 
						resourceFooName := "pod.alpha.kubernetes.io/opaque-int-resource-foo"
 | 
				
			||||||
 | 
						resourceFoo := resource.MustParse("1")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							node *v1.Node
 | 
				
			||||||
 | 
							pods []*v1.Pod
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								node: &v1.Node{
 | 
				
			||||||
 | 
									ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
 | 
										Name: nodeName,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Status: v1.NodeStatus{
 | 
				
			||||||
 | 
										Allocatable: v1.ResourceList{
 | 
				
			||||||
 | 
											v1.ResourceCPU:                   cpu_1,
 | 
				
			||||||
 | 
											v1.ResourceMemory:                mem_100m,
 | 
				
			||||||
 | 
											v1.ResourceName(resourceFooName): resourceFoo,
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Spec: v1.NodeSpec{
 | 
				
			||||||
 | 
										Taints: []v1.Taint{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Key:    "test-key",
 | 
				
			||||||
 | 
												Value:  "test-value",
 | 
				
			||||||
 | 
												Effect: v1.TaintEffectPreferNoSchedule,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								pods: []*v1.Pod{
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
 | 
											Name: "pod1",
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										Spec: v1.PodSpec{
 | 
				
			||||||
 | 
											NodeName: nodeName,
 | 
				
			||||||
 | 
											Containers: []v1.Container{
 | 
				
			||||||
 | 
												{
 | 
				
			||||||
 | 
													Resources: v1.ResourceRequirements{
 | 
				
			||||||
 | 
														Requests: v1.ResourceList{
 | 
				
			||||||
 | 
															v1.ResourceCPU:    cpu_half,
 | 
				
			||||||
 | 
															v1.ResourceMemory: mem_50m,
 | 
				
			||||||
 | 
														},
 | 
				
			||||||
 | 
													},
 | 
				
			||||||
 | 
													Ports: []v1.ContainerPort{
 | 
				
			||||||
 | 
														{
 | 
				
			||||||
 | 
															Name:          "http",
 | 
				
			||||||
 | 
															HostPort:      80,
 | 
				
			||||||
 | 
															ContainerPort: 80,
 | 
				
			||||||
 | 
														},
 | 
				
			||||||
 | 
													},
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								node: &v1.Node{
 | 
				
			||||||
 | 
									ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
 | 
										Name: nodeName,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Status: v1.NodeStatus{
 | 
				
			||||||
 | 
										Allocatable: v1.ResourceList{
 | 
				
			||||||
 | 
											v1.ResourceCPU:                   cpu_1,
 | 
				
			||||||
 | 
											v1.ResourceMemory:                mem_100m,
 | 
				
			||||||
 | 
											v1.ResourceName(resourceFooName): resourceFoo,
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Spec: v1.NodeSpec{
 | 
				
			||||||
 | 
										Taints: []v1.Taint{
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												Key:    "test-key",
 | 
				
			||||||
 | 
												Value:  "test-value",
 | 
				
			||||||
 | 
												Effect: v1.TaintEffectPreferNoSchedule,
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								pods: []*v1.Pod{
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
 | 
											Name: "pod1",
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										Spec: v1.PodSpec{
 | 
				
			||||||
 | 
											NodeName: nodeName,
 | 
				
			||||||
 | 
											Containers: []v1.Container{
 | 
				
			||||||
 | 
												{
 | 
				
			||||||
 | 
													Resources: v1.ResourceRequirements{
 | 
				
			||||||
 | 
														Requests: v1.ResourceList{
 | 
				
			||||||
 | 
															v1.ResourceCPU:    cpu_half,
 | 
				
			||||||
 | 
															v1.ResourceMemory: mem_50m,
 | 
				
			||||||
 | 
														},
 | 
				
			||||||
 | 
													},
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
 | 
											Name: "pod2",
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										Spec: v1.PodSpec{
 | 
				
			||||||
 | 
											NodeName: nodeName,
 | 
				
			||||||
 | 
											Containers: []v1.Container{
 | 
				
			||||||
 | 
												{
 | 
				
			||||||
 | 
													Resources: v1.ResourceRequirements{
 | 
				
			||||||
 | 
														Requests: v1.ResourceList{
 | 
				
			||||||
 | 
															v1.ResourceCPU:    cpu_half,
 | 
				
			||||||
 | 
															v1.ResourceMemory: mem_50m,
 | 
				
			||||||
 | 
														},
 | 
				
			||||||
 | 
													},
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, test := range tests {
 | 
				
			||||||
 | 
							expected := buildNodeInfo(test.node, test.pods)
 | 
				
			||||||
 | 
							node := test.node
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							cache := newSchedulerCache(time.Second, time.Second, nil)
 | 
				
			||||||
 | 
							cache.AddNode(node)
 | 
				
			||||||
 | 
							for _, pod := range test.pods {
 | 
				
			||||||
 | 
								cache.AddPod(pod)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Case 1: the node was added into cache successfully.
 | 
				
			||||||
 | 
							got, found := cache.nodes[node.Name]
 | 
				
			||||||
 | 
							if !found {
 | 
				
			||||||
 | 
								t.Errorf("Failed to find node %v in schedulercache.", node.Name)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !reflect.DeepEqual(got, expected) {
 | 
				
			||||||
 | 
								t.Errorf("Failed to add node into schedulercache:\n got: %+v \nexpected: %+v", got, expected)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Case 2: dump cached nodes successfully.
 | 
				
			||||||
 | 
							cachedNodes := map[string]*NodeInfo{}
 | 
				
			||||||
 | 
							cache.UpdateNodeNameToInfoMap(cachedNodes)
 | 
				
			||||||
 | 
							newNode, found := cachedNodes[node.Name]
 | 
				
			||||||
 | 
							if !found || len(cachedNodes) != 1 {
 | 
				
			||||||
 | 
								t.Errorf("failed to dump cached nodes:\n got: %v \nexpected: %v", cachedNodes, cache.nodes)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !reflect.DeepEqual(newNode, expected) {
 | 
				
			||||||
 | 
								t.Errorf("Failed to clone node:\n got: %+v, \n expected: %+v", newNode, expected)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Case 3: update node attribute successfully.
 | 
				
			||||||
 | 
							node.Status.Allocatable[v1.ResourceMemory] = mem_50m
 | 
				
			||||||
 | 
							expected.allocatableResource.Memory = mem_50m.Value()
 | 
				
			||||||
 | 
							expected.generation++
 | 
				
			||||||
 | 
							cache.UpdateNode(nil, node)
 | 
				
			||||||
 | 
							got, found = cache.nodes[node.Name]
 | 
				
			||||||
 | 
							if !found {
 | 
				
			||||||
 | 
								t.Errorf("Failed to find node %v in schedulercache after UpdateNode.", node.Name)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !reflect.DeepEqual(got, expected) {
 | 
				
			||||||
 | 
								t.Errorf("Failed to update node in schedulercache:\n got: %+v \nexpected: %+v", got, expected)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Case 4: the node can not be removed if pods is not empty.
 | 
				
			||||||
 | 
							cache.RemoveNode(node)
 | 
				
			||||||
 | 
							if _, found := cache.nodes[node.Name]; !found {
 | 
				
			||||||
 | 
								t.Errorf("The node %v should not be removed if pods is not empty.", node.Name)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func BenchmarkList1kNodes30kPods(b *testing.B) {
 | 
					func BenchmarkList1kNodes30kPods(b *testing.B) {
 | 
				
			||||||
	cache := setupCacheOf1kNodes30kPods(b)
 | 
						cache := setupCacheOf1kNodes30kPods(b)
 | 
				
			||||||
	b.ResetTimer()
 | 
						b.ResetTimer()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -90,10 +90,12 @@ func (r *Resource) Clone() *Resource {
 | 
				
			|||||||
		Memory:    r.Memory,
 | 
							Memory:    r.Memory,
 | 
				
			||||||
		NvidiaGPU: r.NvidiaGPU,
 | 
							NvidiaGPU: r.NvidiaGPU,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if r.OpaqueIntResources != nil {
 | 
				
			||||||
		res.OpaqueIntResources = make(map[v1.ResourceName]int64)
 | 
							res.OpaqueIntResources = make(map[v1.ResourceName]int64)
 | 
				
			||||||
		for k, v := range r.OpaqueIntResources {
 | 
							for k, v := range r.OpaqueIntResources {
 | 
				
			||||||
			res.OpaqueIntResources[k] = v
 | 
								res.OpaqueIntResources[k] = v
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return res
 | 
						return res
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -220,13 +222,13 @@ func (n *NodeInfo) Clone() *NodeInfo {
 | 
				
			|||||||
		taintsErr:               n.taintsErr,
 | 
							taintsErr:               n.taintsErr,
 | 
				
			||||||
		memoryPressureCondition: n.memoryPressureCondition,
 | 
							memoryPressureCondition: n.memoryPressureCondition,
 | 
				
			||||||
		diskPressureCondition:   n.diskPressureCondition,
 | 
							diskPressureCondition:   n.diskPressureCondition,
 | 
				
			||||||
 | 
							usedPorts:               make(map[int]bool),
 | 
				
			||||||
		generation:              n.generation,
 | 
							generation:              n.generation,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if len(n.pods) > 0 {
 | 
						if len(n.pods) > 0 {
 | 
				
			||||||
		clone.pods = append([]*v1.Pod(nil), n.pods...)
 | 
							clone.pods = append([]*v1.Pod(nil), n.pods...)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if len(n.usedPorts) > 0 {
 | 
						if len(n.usedPorts) > 0 {
 | 
				
			||||||
		clone.usedPorts = make(map[int]bool)
 | 
					 | 
				
			||||||
		for k, v := range n.usedPorts {
 | 
							for k, v := range n.usedPorts {
 | 
				
			||||||
			clone.usedPorts[k] = v
 | 
								clone.usedPorts[k] = v
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,9 +18,13 @@ go_test(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
go_library(
 | 
					go_library(
 | 
				
			||||||
    name = "go_default_library",
 | 
					    name = "go_default_library",
 | 
				
			||||||
    srcs = ["backoff_utils.go"],
 | 
					    srcs = [
 | 
				
			||||||
 | 
					        "backoff_utils.go",
 | 
				
			||||||
 | 
					        "utils.go",
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
    tags = ["automanaged"],
 | 
					    tags = ["automanaged"],
 | 
				
			||||||
    deps = [
 | 
					    deps = [
 | 
				
			||||||
 | 
					        "//pkg/api/v1:go_default_library",
 | 
				
			||||||
        "//vendor/github.com/golang/glog:go_default_library",
 | 
					        "//vendor/github.com/golang/glog:go_default_library",
 | 
				
			||||||
        "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
 | 
					        "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										41
									
								
								plugin/pkg/scheduler/util/utils.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								plugin/pkg/scheduler/util/utils.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2017 The Kubernetes Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 util
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/api/v1"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetUsedPorts returns the used host ports of Pods: if 'port' was used, a 'port:true' pair
 | 
				
			||||||
 | 
					// will be in the result; but it does not resolve port conflict.
 | 
				
			||||||
 | 
					func GetUsedPorts(pods ...*v1.Pod) map[int]bool {
 | 
				
			||||||
 | 
						ports := make(map[int]bool)
 | 
				
			||||||
 | 
						for _, pod := range pods {
 | 
				
			||||||
 | 
							for j := range pod.Spec.Containers {
 | 
				
			||||||
 | 
								container := &pod.Spec.Containers[j]
 | 
				
			||||||
 | 
								for k := range container.Ports {
 | 
				
			||||||
 | 
									podPort := &container.Ports[k]
 | 
				
			||||||
 | 
									// "0" is explicitly ignored in PodFitsHostPorts,
 | 
				
			||||||
 | 
									// which is the only function that uses this value.
 | 
				
			||||||
 | 
									if podPort.HostPort != 0 {
 | 
				
			||||||
 | 
										ports[int(podPort.HostPort)] = true
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ports
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user