@@ -28,6 +28,7 @@ import (
2828 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2929 intstr "k8s.io/apimachinery/pkg/util/intstr"
3030 framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
31+ "k8s.io/klog/v2"
3132
3233 apiconfig "sigs.k8s.io/scheduler-plugins/pkg/apis/config"
3334)
@@ -40,11 +41,45 @@ func makePodByResourceList(resources *v1.ResourceList) *v1.Pod {
4041 return & v1.Pod {Spec : v1.PodSpec {Containers : []v1.Container {{
4142 Resources : v1.ResourceRequirements {
4243 Requests : * resources ,
44+ Limits : * resources ,
4345 },
4446 }},
4547 }}
4648}
4749
50+ func makeResourceListFromZones (zones topologyv1alpha1.ZoneList ) v1.ResourceList {
51+ result := make (v1.ResourceList )
52+ for _ , zone := range zones {
53+ for _ , resInfo := range zone .Resources {
54+ resQuantity , err := resource .ParseQuantity (resInfo .Allocatable .String ())
55+ if err != nil {
56+ klog .Errorf ("Failed to parse %s" , resInfo .Allocatable .String ())
57+ continue
58+ }
59+ if quantity , ok := result [v1 .ResourceName (resInfo .Name )]; ok {
60+ resQuantity .Add (quantity )
61+ }
62+ result [v1 .ResourceName (resInfo .Name )] = resQuantity
63+ }
64+ }
65+ return result
66+ }
67+
68+
69+ func makePodByResourceListWithManyContainers (resources * v1.ResourceList , containerCount int ) * v1.Pod {
70+ containers := []v1.Container {}
71+
72+ for i := 0 ; i < containerCount ; i ++ {
73+ containers = append (containers , v1.Container {
74+ Resources : v1.ResourceRequirements {
75+ Requests : * resources ,
76+ Limits : * resources ,
77+ },
78+ })
79+ }
80+ return & v1.Pod {Spec : v1.PodSpec {Containers : containers },}
81+ }
82+
4883func TestTopologyRequests (t * testing.T ) {
4984 nodes := nodeTopologyMap {}
5085 nodes ["node1" ] = topologyv1alpha1.NodeResourceTopology {
@@ -92,7 +127,7 @@ func TestTopologyRequests(t *testing.T) {
92127 }
93128
94129 nodes ["node2" ] = topologyv1alpha1.NodeResourceTopology {
95- ObjectMeta : metav1.ObjectMeta {Name : "node1 " },
130+ ObjectMeta : metav1.ObjectMeta {Name : "node2 " },
96131 TopologyPolicies : []string {string (apiconfig .SingleNUMANodeTopologyManagerPolicy )},
97132 Zones : topologyv1alpha1.ZoneList {
98133 topologyv1alpha1.Zone {
@@ -134,12 +169,52 @@ func TestTopologyRequests(t *testing.T) {
134169 },
135170 },
136171 }
137- node1Resources := v1.ResourceList {
138- v1 .ResourceCPU : * resource .NewQuantity (12 , resource .DecimalSI ),
139- v1 .ResourceMemory : resource .MustParse ("16Gi" ),
140- v1 .ResourcePods : * resource .NewQuantity (20 , resource .DecimalSI ),
141- nicResourceName : * resource .NewQuantity (14 , resource .DecimalSI ),
172+
173+
174+ nodes ["node3" ] = topologyv1alpha1.NodeResourceTopology {
175+ ObjectMeta : metav1.ObjectMeta {Name : "node3" },
176+ TopologyPolicies : []string {string (apiconfig .PodTopologyScope )},
177+ Zones : topologyv1alpha1.ZoneList {
178+ topologyv1alpha1.Zone {
179+ Name : "node-0" ,
180+ Type : "Node" ,
181+ Resources : topologyv1alpha1.ResourceInfoList {
182+ topologyv1alpha1.ResourceInfo {
183+ Name : "cpu" ,
184+ Capacity : intstr .Parse ("20" ),
185+ Allocatable : intstr .Parse ("2" ),
186+ }, topologyv1alpha1.ResourceInfo {
187+ Name : "memory" ,
188+ Capacity : intstr .Parse ("8Gi" ),
189+ Allocatable : intstr .Parse ("4Gi" ),
190+ }, topologyv1alpha1.ResourceInfo {
191+ Name : nicResourceName ,
192+ Capacity : intstr .Parse ("30" ),
193+ Allocatable : intstr .Parse ("5" ),
194+ },
195+ },
196+ }, topologyv1alpha1.Zone {
197+ Name : "node-1" ,
198+ Type : "Node" ,
199+ Resources : topologyv1alpha1.ResourceInfoList {
200+ topologyv1alpha1.ResourceInfo {
201+ Name : "cpu" ,
202+ Capacity : intstr .Parse ("30" ),
203+ Allocatable : intstr .Parse ("4" ),
204+ }, topologyv1alpha1.ResourceInfo {
205+ Name : "memory" ,
206+ Capacity : intstr .Parse ("8Gi" ),
207+ Allocatable : intstr .Parse ("4Gi" ),
208+ }, topologyv1alpha1.ResourceInfo {
209+ Name : nicResourceName ,
210+ Capacity : intstr .Parse ("30" ),
211+ Allocatable : intstr .Parse ("2" ),
212+ },
213+ },
214+ },
215+ },
142216 }
217+ node1Resources := makeResourceListFromZones (nodes ["node1" ].Zones )
143218 node1 := v1.Node {
144219 ObjectMeta : metav1.ObjectMeta {Name : "node1" },
145220 Status : v1.NodeStatus {
@@ -148,18 +223,21 @@ func TestTopologyRequests(t *testing.T) {
148223 },
149224 }
150225
151- node2Resources := v1.ResourceList {
152- v1 .ResourceCPU : * resource .NewQuantity (6 , resource .DecimalSI ),
153- v1 .ResourceMemory : resource .MustParse ("8Gi" ),
154- v1 .ResourcePods : * resource .NewQuantity (20 , resource .DecimalSI ),
155- nicResourceName : * resource .NewQuantity (7 , resource .DecimalSI ),
156- }
157- node2 := v1.Node {ObjectMeta : metav1.ObjectMeta {Name : "node1" }, Status : v1.NodeStatus {
226+ node2Resources := makeResourceListFromZones (nodes ["node2" ].Zones )
227+ node2 := v1.Node {ObjectMeta : metav1.ObjectMeta {Name : "node2" }, Status : v1.NodeStatus {
158228 Capacity : node2Resources ,
159229 Allocatable : node2Resources ,
160230 },
161231 }
162232
233+ node3Resources := makeResourceListFromZones (nodes ["node3" ].Zones )
234+
235+ node3 := v1.Node {ObjectMeta : metav1.ObjectMeta {Name : "node3" }, Status : v1.NodeStatus {
236+ Capacity : node3Resources ,
237+ Allocatable : node3Resources ,
238+ },
239+ }
240+
163241 // Test different QoS Guaranteed/Burstable/BestEffort
164242 topologyTests := []struct {
165243 pod * v1.Pod
@@ -230,23 +308,47 @@ func TestTopologyRequests(t *testing.T) {
230308 nodeTopologies : & nodes ,
231309 name : "Guaranteed QoS, pod fit" ,
232310 node : node1 ,
233- wantStatus : nil , //topology_match has to skip request of 0 resources
311+ wantStatus : nil ,
312+ },
313+ {
314+ pod : makePodByResourceListWithManyContainers (& v1.ResourceList {
315+ v1 .ResourceCPU : * resource .NewQuantity (3 , resource .DecimalSI ),
316+ v1 .ResourceMemory : resource .MustParse ("1Gi" ),
317+ notExistingNICResourceName : * resource .NewQuantity (0 , resource .DecimalSI )}, 3 ),
318+ nodeTopologies : & nodes ,
319+ name : "Guaranteed QoS Topology Scope, pod doesn't fit" ,
320+ node : node3 ,
321+ wantStatus : framework .NewStatus (framework .Unschedulable , "Can't align pod: " ),
322+ },
323+ {
324+ pod : makePodByResourceListWithManyContainers (& v1.ResourceList {
325+ v1 .ResourceCPU : * resource .NewQuantity (1 , resource .DecimalSI ),
326+ v1 .ResourceMemory : resource .MustParse ("1Gi" ),
327+ notExistingNICResourceName : * resource .NewQuantity (0 , resource .DecimalSI )}, 3 ),
328+ nodeTopologies : & nodes ,
329+ name : "Guaranteed QoS Topology Scope, pod fit" ,
330+ node : node3 ,
331+ wantStatus : nil ,
234332 },
235333 }
236334
237335 nodeInfo := framework .NewNodeInfo ()
238336 for _ , test := range topologyTests {
239337 t .Run (test .name , func (t * testing.T ) {
240338 tm := NodeResourceTopologyMatch {}
241- tm .nodeTopologies = nodes
339+ tm .nodeTopologies = * test . nodeTopologies
242340 tm .topologyPolicyHandlers = make (PolicyHandlerMap )
243- tm .topologyPolicyHandlers [apiconfig .SingleNUMANodeTopologyManagerPolicy ] = tm
341+ tm .topologyPolicyHandlers [apiconfig .SingleNUMANodeTopologyManagerPolicy ] = SingleNUMANodeHandler {match : & tm }
342+ tm .topologyPolicyHandlers [apiconfig .PodTopologyScope ] = PodLevelResourceHandler {match : & tm }
244343 nodeInfo .SetNode (& test .node )
245344 test .pod .Spec .Containers [0 ].Name = containerName
246- test .pod .Spec .Containers [0 ].Resources .Limits = test .pod .Spec .Containers [0 ].Resources .Requests
345+ // this was done to make pod's QoS Guaranted
346+ //test.pod.Spec.Containers[0].Resources.Limits = test.pod.Spec.Containers[0].Resources.Requests
247347 gotStatus := tm .Filter (context .Background (), framework .NewCycleState (), test .pod , nodeInfo )
348+
349+ fmt .Printf ("test.Name: %v; status: %v\n " , test .name , gotStatus )
248350 if ! reflect .DeepEqual (gotStatus , test .wantStatus ) {
249- t .Errorf ("status does not match: %v, want: %v" , gotStatus , test .wantStatus )
351+ t .Errorf ("status does not match: %v, want: %v\n " , gotStatus , test .wantStatus )
250352 }
251353 })
252354 }
0 commit comments