Skip to content

Commit f44284c

Browse files
Use hv1 effective capacity for weighing + filtering
1 parent 26b3615 commit f44284c

7 files changed

Lines changed: 73 additions & 65 deletions

File tree

internal/scheduling/nova/integration_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func newHypervisor(name, cpuCap, cpuAlloc, memCap, memAlloc string) *hv1.Hypervi
4848
Name: name,
4949
},
5050
Status: hv1.HypervisorStatus{
51-
Capacity: map[hv1.ResourceName]resource.Quantity{
51+
EffectiveCapacity: map[hv1.ResourceName]resource.Quantity{
5252
hv1.ResourceCPU: resource.MustParse(cpuCap),
5353
hv1.ResourceMemory: resource.MustParse(memCap),
5454
},

internal/scheduling/nova/plugins/filters/filter_has_enough_capacity.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,14 @@ func (s *FilterHasEnoughCapacity) Run(traceLog *slog.Logger, request api.Externa
5656
return nil, err
5757
}
5858
for _, hv := range hvs.Items {
59-
// Start with the total capacity.
60-
freeResourcesByHost[hv.Name] = hv.Status.Capacity
59+
// This case would be caught below, but we want to log this explicitly.
60+
if hv.Status.EffectiveCapacity == nil {
61+
traceLog.Warn("hypervisor with nil effective capacity, skipping", "host", hv.Name)
62+
continue
63+
}
64+
65+
// Start with the total effective capacity which is capacity * overcommit ratio.
66+
freeResourcesByHost[hv.Name] = hv.Status.EffectiveCapacity
6167

6268
// Subtract allocated resources.
6369
for resourceName, allocated := range hv.Status.Allocation {

internal/scheduling/nova/plugins/filters/filter_has_enough_capacity_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func newHypervisor(name, cpuCap, cpuAlloc, memCap, memAlloc string) *hv1.Hypervi
3939
Name: name,
4040
},
4141
Status: hv1.HypervisorStatus{
42-
Capacity: map[hv1.ResourceName]resource.Quantity{
42+
EffectiveCapacity: map[hv1.ResourceName]resource.Quantity{
4343
hv1.ResourceCPU: resource.MustParse(cpuCap),
4444
hv1.ResourceMemory: resource.MustParse(memCap),
4545
},

internal/scheduling/nova/plugins/weighers/kvm_binpack.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,15 @@ func (s *KVMBinpackStep) Run(traceLog *slog.Logger, request api.ExternalSchedule
9393
var totalWeightedUtilization, totalWeight float64
9494

9595
for resourceName, weight := range s.Options.ResourceWeights {
96-
capacity, ok := hv.Status.Capacity[resourceName]
96+
// Effective capacity = capacity * overcommit ratio.
97+
capacity, ok := hv.Status.EffectiveCapacity[resourceName]
9798
if !ok {
98-
traceLog.Warn("no capacity in status, skipping",
99+
traceLog.Warn("no effective capacity in status, skipping",
99100
"host", host, "resource", resourceName)
100101
continue
101102
}
102103
if capacity.IsZero() {
103-
traceLog.Warn("capacity is zero, skipping",
104+
traceLog.Warn("effective capacity is zero, skipping",
104105
"host", host, "resource", resourceName)
105106
continue
106107
}

internal/scheduling/nova/plugins/weighers/kvm_binpack_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func newHypervisor(name, capacityCPU, capacityMem, allocationCPU, allocationMem
2222
Name: name,
2323
},
2424
Status: hv1.HypervisorStatus{
25-
Capacity: map[hv1.ResourceName]resource.Quantity{
25+
EffectiveCapacity: map[hv1.ResourceName]resource.Quantity{
2626
hv1.ResourceCPU: resource.MustParse(capacityCPU),
2727
hv1.ResourceMemory: resource.MustParse(capacityMem),
2828
},
@@ -343,7 +343,7 @@ func TestKVMBinpackStep_Run(t *testing.T) {
343343
{
344344
ObjectMeta: metav1.ObjectMeta{Name: "host1"},
345345
Status: hv1.HypervisorStatus{
346-
Capacity: map[hv1.ResourceName]resource.Quantity{
346+
EffectiveCapacity: map[hv1.ResourceName]resource.Quantity{
347347
hv1.ResourceCPU: resource.MustParse("0"),
348348
hv1.ResourceMemory: resource.MustParse("100Gi"),
349349
},
@@ -371,7 +371,7 @@ func TestKVMBinpackStep_Run(t *testing.T) {
371371
{
372372
ObjectMeta: metav1.ObjectMeta{Name: "host1"},
373373
Status: hv1.HypervisorStatus{
374-
Capacity: map[hv1.ResourceName]resource.Quantity{
374+
EffectiveCapacity: map[hv1.ResourceName]resource.Quantity{
375375
hv1.ResourceCPU: resource.MustParse("100"),
376376
},
377377
Allocation: map[hv1.ResourceName]resource.Quantity{
@@ -397,7 +397,7 @@ func TestKVMBinpackStep_Run(t *testing.T) {
397397
{
398398
ObjectMeta: metav1.ObjectMeta{Name: "host1"},
399399
Status: hv1.HypervisorStatus{
400-
Capacity: map[hv1.ResourceName]resource.Quantity{
400+
EffectiveCapacity: map[hv1.ResourceName]resource.Quantity{
401401
// No CPU capacity
402402
},
403403
Allocation: map[hv1.ResourceName]resource.Quantity{

internal/scheduling/nova/plugins/weighers/kvm_prefer_smaller_hosts.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,10 @@ func (s *KVMPreferSmallerHostsStep) Run(traceLog *slog.Logger, request api.Exter
8181
if _, ok := result.Activations[hv.Name]; !ok {
8282
continue
8383
}
84-
capacity, ok := hv.Status.Capacity[resourceName]
84+
// Effective capacity = capacity * overcommit ratio.
85+
capacity, ok := hv.Status.EffectiveCapacity[resourceName]
8586
if !ok {
86-
traceLog.Warn("hypervisor has no capacity for resource, skipping",
87+
traceLog.Warn("hypervisor has no effective capacity for resource, skipping",
8788
"host", hv.Name, "resource", resourceName)
8889
continue
8990
}
@@ -106,9 +107,9 @@ func (s *KVMPreferSmallerHostsStep) Run(traceLog *slog.Logger, request api.Exter
106107
var totalWeightedScore, totalWeight float64
107108

108109
for resourceName, weight := range s.Options.ResourceWeights {
109-
capacity, ok := hv.Status.Capacity[resourceName]
110+
capacity, ok := hv.Status.EffectiveCapacity[resourceName]
110111
if !ok {
111-
traceLog.Warn("hypervisor has no capacity for resource, skipping",
112+
traceLog.Warn("hypervisor has no effective capacity for resource, skipping",
112113
"host", hv.Name, "resource", resourceName)
113114
continue
114115
}
@@ -117,14 +118,14 @@ func (s *KVMPreferSmallerHostsStep) Run(traceLog *slog.Logger, request api.Exter
117118
largestCap := largest[resourceName]
118119

119120
if smallestCap == nil || largestCap == nil {
120-
traceLog.Warn("no capacity range found for resource, skipping",
121+
traceLog.Warn("no effective capacity range found for resource, skipping",
121122
"resource", resourceName)
122123
continue
123124
}
124125

125-
// If all hosts have the same capacity for this resource, skip it
126+
// If all hosts have the same effective capacity for this resource, skip it
126127
if smallestCap.Cmp(*largestCap) == 0 {
127-
traceLog.Info("all hypervisors have the same capacity for resource, skipping",
128+
traceLog.Info("all hypervisors have the same effective capacity for resource, skipping",
128129
"resource", resourceName)
129130
continue
130131
}

internal/scheduling/nova/plugins/weighers/kvm_prefer_smaller_hosts_test.go

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ import (
1616
"sigs.k8s.io/controller-runtime/pkg/client/fake"
1717
)
1818

19-
func newHypervisorWithCapacity(name, capacityCPU, capacityMem string) *hv1.Hypervisor {
19+
func newHypervisorWithEffectiveCapacity(name, capacityCPU, capacityMem string) *hv1.Hypervisor {
2020
return &hv1.Hypervisor{
2121
ObjectMeta: metav1.ObjectMeta{
2222
Name: name,
2323
},
2424
Status: hv1.HypervisorStatus{
25-
Capacity: map[hv1.ResourceName]resource.Quantity{
25+
EffectiveCapacity: map[hv1.ResourceName]resource.Quantity{
2626
hv1.ResourceCPU: resource.MustParse(capacityCPU),
2727
hv1.ResourceMemory: resource.MustParse(capacityMem),
2828
},
@@ -189,9 +189,9 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
189189
{
190190
name: "smallest host gets highest score with memory weight only",
191191
hypervisors: []*hv1.Hypervisor{
192-
newHypervisorWithCapacity("host1", "100", "64Gi"), // smallest memory
193-
newHypervisorWithCapacity("host2", "100", "128Gi"), // middle memory
194-
newHypervisorWithCapacity("host3", "100", "256Gi"), // largest memory
192+
newHypervisorWithEffectiveCapacity("host1", "100", "64Gi"), // smallest memory
193+
newHypervisorWithEffectiveCapacity("host2", "100", "128Gi"), // middle memory
194+
newHypervisorWithEffectiveCapacity("host3", "100", "256Gi"), // largest memory
195195
},
196196
request: newPreferSmallerHostsRequest([]string{"host1", "host2", "host3"}),
197197
opts: KVMPreferSmallerHostsStepOpts{
@@ -209,9 +209,9 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
209209
{
210210
name: "smallest host gets highest score with cpu weight only",
211211
hypervisors: []*hv1.Hypervisor{
212-
newHypervisorWithCapacity("host1", "64", "100Gi"), // smallest CPU
213-
newHypervisorWithCapacity("host2", "128", "100Gi"), // middle CPU
214-
newHypervisorWithCapacity("host3", "256", "100Gi"), // largest CPU
212+
newHypervisorWithEffectiveCapacity("host1", "64", "100Gi"), // smallest CPU
213+
newHypervisorWithEffectiveCapacity("host2", "128", "100Gi"), // middle CPU
214+
newHypervisorWithEffectiveCapacity("host3", "256", "100Gi"), // largest CPU
215215
},
216216
request: newPreferSmallerHostsRequest([]string{"host1", "host2", "host3"}),
217217
opts: KVMPreferSmallerHostsStepOpts{
@@ -230,11 +230,11 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
230230
name: "weighted average with both cpu and memory weights",
231231
hypervisors: []*hv1.Hypervisor{
232232
// host1: smallest memory (64Gi), largest CPU (256) -> mem score=1.0, cpu score=0.0
233-
newHypervisorWithCapacity("host1", "256", "64Gi"),
233+
newHypervisorWithEffectiveCapacity("host1", "256", "64Gi"),
234234
// host2: middle memory (128Gi), middle CPU (128) -> mem score=0.667, cpu score=0.667
235-
newHypervisorWithCapacity("host2", "128", "128Gi"),
235+
newHypervisorWithEffectiveCapacity("host2", "128", "128Gi"),
236236
// host3: largest memory (256Gi), smallest CPU (64) -> mem score=0.0, cpu score=1.0
237-
newHypervisorWithCapacity("host3", "64", "256Gi"),
237+
newHypervisorWithEffectiveCapacity("host3", "64", "256Gi"),
238238
},
239239
request: newPreferSmallerHostsRequest([]string{"host1", "host2", "host3"}),
240240
opts: KVMPreferSmallerHostsStepOpts{
@@ -257,9 +257,9 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
257257
name: "different weights for cpu and memory",
258258
hypervisors: []*hv1.Hypervisor{
259259
// host1: smallest memory (64Gi), largest CPU (256) -> mem score=1.0, cpu score=0.0
260-
newHypervisorWithCapacity("host1", "256", "64Gi"),
260+
newHypervisorWithEffectiveCapacity("host1", "256", "64Gi"),
261261
// host2: largest memory (256Gi), smallest CPU (64) -> mem score=0.0, cpu score=1.0
262-
newHypervisorWithCapacity("host2", "64", "256Gi"),
262+
newHypervisorWithEffectiveCapacity("host2", "64", "256Gi"),
263263
},
264264
request: newPreferSmallerHostsRequest([]string{"host1", "host2"}),
265265
opts: KVMPreferSmallerHostsStepOpts{
@@ -279,8 +279,8 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
279279
{
280280
name: "two hosts with different sizes",
281281
hypervisors: []*hv1.Hypervisor{
282-
newHypervisorWithCapacity("host1", "100", "100Gi"),
283-
newHypervisorWithCapacity("host2", "100", "200Gi"),
282+
newHypervisorWithEffectiveCapacity("host1", "100", "100Gi"),
283+
newHypervisorWithEffectiveCapacity("host2", "100", "200Gi"),
284284
},
285285
request: newPreferSmallerHostsRequest([]string{"host1", "host2"}),
286286
opts: KVMPreferSmallerHostsStepOpts{
@@ -297,9 +297,9 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
297297
{
298298
name: "all hosts have same memory capacity",
299299
hypervisors: []*hv1.Hypervisor{
300-
newHypervisorWithCapacity("host1", "100", "128Gi"),
301-
newHypervisorWithCapacity("host2", "100", "128Gi"),
302-
newHypervisorWithCapacity("host3", "100", "128Gi"),
300+
newHypervisorWithEffectiveCapacity("host1", "100", "128Gi"),
301+
newHypervisorWithEffectiveCapacity("host2", "100", "128Gi"),
302+
newHypervisorWithEffectiveCapacity("host3", "100", "128Gi"),
303303
},
304304
request: newPreferSmallerHostsRequest([]string{"host1", "host2", "host3"}),
305305
opts: KVMPreferSmallerHostsStepOpts{
@@ -318,7 +318,7 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
318318
{
319319
name: "single host",
320320
hypervisors: []*hv1.Hypervisor{
321-
newHypervisorWithCapacity("host1", "100", "128Gi"),
321+
newHypervisorWithEffectiveCapacity("host1", "100", "128Gi"),
322322
},
323323
request: newPreferSmallerHostsRequest([]string{"host1"}),
324324
opts: KVMPreferSmallerHostsStepOpts{
@@ -351,8 +351,8 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
351351
{
352352
name: "hypervisor missing for one host",
353353
hypervisors: []*hv1.Hypervisor{
354-
newHypervisorWithCapacity("host1", "100", "64Gi"),
355-
newHypervisorWithCapacity("host2", "100", "128Gi"),
354+
newHypervisorWithEffectiveCapacity("host1", "100", "64Gi"),
355+
newHypervisorWithEffectiveCapacity("host2", "100", "128Gi"),
356356
// host3 hypervisor is missing
357357
},
358358
request: newPreferSmallerHostsRequest([]string{"host1", "host2", "host3"}),
@@ -371,12 +371,12 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
371371
{
372372
name: "hypervisor without memory capacity",
373373
hypervisors: []*hv1.Hypervisor{
374-
newHypervisorWithCapacity("host1", "100", "64Gi"),
375-
newHypervisorWithCapacity("host2", "100", "128Gi"),
374+
newHypervisorWithEffectiveCapacity("host1", "100", "64Gi"),
375+
newHypervisorWithEffectiveCapacity("host2", "100", "128Gi"),
376376
{
377377
ObjectMeta: metav1.ObjectMeta{Name: "host3"},
378378
Status: hv1.HypervisorStatus{
379-
Capacity: map[hv1.ResourceName]resource.Quantity{
379+
EffectiveCapacity: map[hv1.ResourceName]resource.Quantity{
380380
hv1.ResourceCPU: resource.MustParse("100"),
381381
// No memory capacity
382382
},
@@ -399,9 +399,9 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
399399
{
400400
name: "host filtered out by previous steps",
401401
hypervisors: []*hv1.Hypervisor{
402-
newHypervisorWithCapacity("host1", "100", "64Gi"),
403-
newHypervisorWithCapacity("host2", "100", "128Gi"),
404-
newHypervisorWithCapacity("host3", "100", "256Gi"),
402+
newHypervisorWithEffectiveCapacity("host1", "100", "64Gi"),
403+
newHypervisorWithEffectiveCapacity("host2", "100", "128Gi"),
404+
newHypervisorWithEffectiveCapacity("host3", "100", "256Gi"),
405405
},
406406
// Only host1 and host2 in the request (host3 was filtered out)
407407
request: newPreferSmallerHostsRequest([]string{"host1", "host2"}),
@@ -419,9 +419,9 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
419419
{
420420
name: "varied memory sizes - score calculation",
421421
hypervisors: []*hv1.Hypervisor{
422-
newHypervisorWithCapacity("host1", "100", "100Gi"), // smallest
423-
newHypervisorWithCapacity("host2", "100", "150Gi"), // middle
424-
newHypervisorWithCapacity("host3", "100", "200Gi"), // largest
422+
newHypervisorWithEffectiveCapacity("host1", "100", "100Gi"), // smallest
423+
newHypervisorWithEffectiveCapacity("host2", "100", "150Gi"), // middle
424+
newHypervisorWithEffectiveCapacity("host3", "100", "200Gi"), // largest
425425
},
426426
request: newPreferSmallerHostsRequest([]string{"host1", "host2", "host3"}),
427427
opts: KVMPreferSmallerHostsStepOpts{
@@ -440,10 +440,10 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
440440
{
441441
name: "four hosts with varying sizes",
442442
hypervisors: []*hv1.Hypervisor{
443-
newHypervisorWithCapacity("host1", "100", "64Gi"),
444-
newHypervisorWithCapacity("host2", "100", "96Gi"),
445-
newHypervisorWithCapacity("host3", "100", "128Gi"),
446-
newHypervisorWithCapacity("host4", "100", "192Gi"),
443+
newHypervisorWithEffectiveCapacity("host1", "100", "64Gi"),
444+
newHypervisorWithEffectiveCapacity("host2", "100", "96Gi"),
445+
newHypervisorWithEffectiveCapacity("host3", "100", "128Gi"),
446+
newHypervisorWithEffectiveCapacity("host4", "100", "192Gi"),
447447
},
448448
request: newPreferSmallerHostsRequest([]string{"host1", "host2", "host3", "host4"}),
449449
opts: KVMPreferSmallerHostsStepOpts{
@@ -466,13 +466,13 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
466466
{
467467
ObjectMeta: metav1.ObjectMeta{Name: "host1"},
468468
Status: hv1.HypervisorStatus{
469-
Capacity: map[hv1.ResourceName]resource.Quantity{},
469+
EffectiveCapacity: map[hv1.ResourceName]resource.Quantity{},
470470
},
471471
},
472472
{
473473
ObjectMeta: metav1.ObjectMeta{Name: "host2"},
474474
Status: hv1.HypervisorStatus{
475-
Capacity: map[hv1.ResourceName]resource.Quantity{},
475+
EffectiveCapacity: map[hv1.ResourceName]resource.Quantity{},
476476
},
477477
},
478478
},
@@ -492,8 +492,8 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
492492
{
493493
name: "very small difference in memory",
494494
hypervisors: []*hv1.Hypervisor{
495-
newHypervisorWithCapacity("host1", "100", "128Gi"),
496-
newHypervisorWithCapacity("host2", "100", "129Gi"),
495+
newHypervisorWithEffectiveCapacity("host1", "100", "128Gi"),
496+
newHypervisorWithEffectiveCapacity("host2", "100", "129Gi"),
497497
},
498498
request: newPreferSmallerHostsRequest([]string{"host1", "host2"}),
499499
opts: KVMPreferSmallerHostsStepOpts{
@@ -510,10 +510,10 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
510510
{
511511
name: "extra hypervisors not in request",
512512
hypervisors: []*hv1.Hypervisor{
513-
newHypervisorWithCapacity("host1", "100", "64Gi"),
514-
newHypervisorWithCapacity("host2", "100", "128Gi"),
515-
newHypervisorWithCapacity("host3", "100", "256Gi"), // not in request
516-
newHypervisorWithCapacity("host4", "100", "512Gi"), // not in request
513+
newHypervisorWithEffectiveCapacity("host1", "100", "64Gi"),
514+
newHypervisorWithEffectiveCapacity("host2", "100", "128Gi"),
515+
newHypervisorWithEffectiveCapacity("host3", "100", "256Gi"), // not in request
516+
newHypervisorWithEffectiveCapacity("host4", "100", "512Gi"), // not in request
517517
},
518518
request: newPreferSmallerHostsRequest([]string{"host1", "host2"}),
519519
opts: KVMPreferSmallerHostsStepOpts{
@@ -534,7 +534,7 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
534534
{
535535
ObjectMeta: metav1.ObjectMeta{Name: "host1"},
536536
Status: hv1.HypervisorStatus{
537-
Capacity: map[hv1.ResourceName]resource.Quantity{
537+
EffectiveCapacity: map[hv1.ResourceName]resource.Quantity{
538538
hv1.ResourceMemory: resource.MustParse("64Gi"),
539539
// No CPU
540540
},
@@ -543,7 +543,7 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
543543
{
544544
ObjectMeta: metav1.ObjectMeta{Name: "host2"},
545545
Status: hv1.HypervisorStatus{
546-
Capacity: map[hv1.ResourceName]resource.Quantity{
546+
EffectiveCapacity: map[hv1.ResourceName]resource.Quantity{
547547
hv1.ResourceMemory: resource.MustParse("128Gi"),
548548
// No CPU
549549
},
@@ -567,9 +567,9 @@ func TestKVMPreferSmallerHostsStep_Run(t *testing.T) {
567567
{
568568
name: "zero weight for memory, non-zero for cpu",
569569
hypervisors: []*hv1.Hypervisor{
570-
newHypervisorWithCapacity("host1", "64", "256Gi"), // smallest CPU, largest memory
571-
newHypervisorWithCapacity("host2", "128", "128Gi"), // middle
572-
newHypervisorWithCapacity("host3", "256", "64Gi"), // largest CPU, smallest memory
570+
newHypervisorWithEffectiveCapacity("host1", "64", "256Gi"), // smallest CPU, largest memory
571+
newHypervisorWithEffectiveCapacity("host2", "128", "128Gi"), // middle
572+
newHypervisorWithEffectiveCapacity("host3", "256", "64Gi"), // largest CPU, smallest memory
573573
},
574574
request: newPreferSmallerHostsRequest([]string{"host1", "host2", "host3"}),
575575
opts: KVMPreferSmallerHostsStepOpts{

0 commit comments

Comments
 (0)