@@ -395,6 +395,225 @@ func TestAddDomainCapabilities_UnsupportedFiltered(t *testing.T) {
395395 }
396396}
397397
398+ func TestAddAllocationCapacity_InstanceSpreadAcrossMultipleNumaCells (t * testing.T ) {
399+ // Test scenario: An instance with 128 GiB memory and 16 CPUs is spread
400+ // across NUMA cells 1 and 2. Each cell should report 64 GiB memory
401+ // allocation and 8 CPU allocation.
402+ caps := capabilities.Capabilities {
403+ Host : capabilities.CapabilitiesHost {
404+ Topology : capabilities.CapabilitiesHostTopology {
405+ CellSpec : capabilities.CapabilitiesHostTopologyCells {
406+ Num : 4 ,
407+ Cells : []capabilities.CapabilitiesHostTopologyCell {
408+ {
409+ ID : 0 ,
410+ Memory : capabilities.CapabilitiesHostTopologyCellMemory {
411+ Unit : "GiB" ,
412+ Value : 256 ,
413+ },
414+ CPUs : capabilities.CapabilitiesHostTopologyCellCPUs {
415+ Num : 64 ,
416+ },
417+ },
418+ {
419+ ID : 1 ,
420+ Memory : capabilities.CapabilitiesHostTopologyCellMemory {
421+ Unit : "GiB" ,
422+ Value : 256 ,
423+ },
424+ CPUs : capabilities.CapabilitiesHostTopologyCellCPUs {
425+ Num : 64 ,
426+ },
427+ },
428+ {
429+ ID : 2 ,
430+ Memory : capabilities.CapabilitiesHostTopologyCellMemory {
431+ Unit : "GiB" ,
432+ Value : 256 ,
433+ },
434+ CPUs : capabilities.CapabilitiesHostTopologyCellCPUs {
435+ Num : 64 ,
436+ },
437+ },
438+ {
439+ ID : 3 ,
440+ Memory : capabilities.CapabilitiesHostTopologyCellMemory {
441+ Unit : "GiB" ,
442+ Value : 256 ,
443+ },
444+ CPUs : capabilities.CapabilitiesHostTopologyCellCPUs {
445+ Num : 64 ,
446+ },
447+ },
448+ },
449+ },
450+ },
451+ },
452+ }
453+
454+ domInfos := []dominfo.DomainInfo {
455+ {
456+ Name : "multi-numa-instance" ,
457+ Memory : & dominfo.DomainMemory {
458+ Unit : "GiB" ,
459+ Value : 128 ,
460+ },
461+ CPUTune : & dominfo.DomainCPUTune {
462+ VCPUPins : []dominfo.DomainVCPUPin {
463+ {VCPU : 0 , CPUSet : "64" },
464+ {VCPU : 1 , CPUSet : "65" },
465+ {VCPU : 2 , CPUSet : "66" },
466+ {VCPU : 3 , CPUSet : "67" },
467+ {VCPU : 4 , CPUSet : "68" },
468+ {VCPU : 5 , CPUSet : "69" },
469+ {VCPU : 6 , CPUSet : "70" },
470+ {VCPU : 7 , CPUSet : "71" },
471+ {VCPU : 8 , CPUSet : "128" },
472+ {VCPU : 9 , CPUSet : "129" },
473+ {VCPU : 10 , CPUSet : "130" },
474+ {VCPU : 11 , CPUSet : "131" },
475+ {VCPU : 12 , CPUSet : "132" },
476+ {VCPU : 13 , CPUSet : "133" },
477+ {VCPU : 14 , CPUSet : "134" },
478+ {VCPU : 15 , CPUSet : "135" },
479+ },
480+ },
481+ // Instance uses NUMA cells 1 and 2 for memory
482+ NumaTune : & dominfo.DomainNumaTune {
483+ MemNodes : []dominfo.DomainNumaMemNode {
484+ {CellID : 1 , Mode : "strict" , Nodeset : "1" },
485+ {CellID : 2 , Mode : "strict" , Nodeset : "2" },
486+ },
487+ },
488+ // Instance uses NUMA cells 1 and 2 for CPUs
489+ CPU : & dominfo.DomainCPU {
490+ Numa : & dominfo.DomainCPUNuma {
491+ Cells : []dominfo.DomainCPUNumaCell {
492+ {ID : 1 , CPUs : "0-7" , Memory : 64 , Unit : "GiB" },
493+ {ID : 2 , CPUs : "8-15" , Memory : 64 , Unit : "GiB" },
494+ },
495+ },
496+ },
497+ },
498+ }
499+
500+ l := & LibVirt {
501+ capabilitiesClient : & mockCapabilitiesClient {caps : caps },
502+ domainInfoClient : & mockDomInfoClient {infos : domInfos },
503+ }
504+
505+ hv := v1.Hypervisor {}
506+ result , err := l .addAllocationCapacity (hv )
507+
508+ if err != nil {
509+ t .Fatalf ("addAllocationCapacity() returned unexpected error: %v" , err )
510+ }
511+
512+ // Check total capacity (4 cells * 256 GiB = 1024 GiB)
513+ expectedTotalMemCapacity := resource .NewQuantity (1024 * 1024 * 1024 * 1024 , resource .BinarySI )
514+ memCap := result .Status .Capacity ["memory" ]
515+ if ! memCap .Equal (* expectedTotalMemCapacity ) {
516+ t .Errorf ("Expected total memory capacity %s, got %s" ,
517+ expectedTotalMemCapacity .String (), memCap .String ())
518+ }
519+
520+ // Check total CPU capacity (4 cells * 64 = 256)
521+ expectedTotalCpuCapacity := resource .NewQuantity (256 , resource .DecimalSI )
522+ cpuCap := result .Status .Capacity ["cpu" ]
523+ if ! cpuCap .Equal (* expectedTotalCpuCapacity ) {
524+ t .Errorf ("Expected total CPU capacity %s, got %s" ,
525+ expectedTotalCpuCapacity .String (), cpuCap .String ())
526+ }
527+
528+ // Check total allocation (128 GiB memory, 16 CPUs)
529+ expectedTotalMemAlloc := resource .NewQuantity (128 * 1024 * 1024 * 1024 , resource .BinarySI )
530+ memAlloc := result .Status .Allocation ["memory" ]
531+ if ! memAlloc .Equal (* expectedTotalMemAlloc ) {
532+ t .Errorf ("Expected total memory allocation %s, got %s" ,
533+ expectedTotalMemAlloc .String (), memAlloc .String ())
534+ }
535+
536+ expectedTotalCpuAlloc := resource .NewQuantity (16 , resource .DecimalSI )
537+ cpuAlloc := result .Status .Allocation ["cpu" ]
538+ if ! cpuAlloc .Equal (* expectedTotalCpuAlloc ) {
539+ t .Errorf ("Expected total CPU allocation %s, got %s" ,
540+ expectedTotalCpuAlloc .String (), cpuAlloc .String ())
541+ }
542+
543+ // Check that we have 4 cells
544+ if len (result .Status .Cells ) != 4 {
545+ t .Fatalf ("Expected 4 cells, got %d" , len (result .Status .Cells ))
546+ }
547+
548+ // Create a map for easier cell lookup
549+ cellsByID := make (map [uint64 ]v1.Cell )
550+ for _ , cell := range result .Status .Cells {
551+ cellsByID [cell .CellID ] = cell
552+ }
553+
554+ // Cell 0 should have zero allocation (not used by the instance)
555+ cell0 := cellsByID [0 ]
556+ expectedCell0MemAlloc := resource .NewQuantity (0 , resource .BinarySI )
557+ cell0MemAlloc := cell0 .Allocation ["memory" ]
558+ if ! cell0MemAlloc .Equal (* expectedCell0MemAlloc ) {
559+ t .Errorf ("Cell 0: Expected memory allocation %s, got %s" ,
560+ expectedCell0MemAlloc .String (), cell0MemAlloc .String ())
561+ }
562+ expectedCell0CpuAlloc := resource .NewQuantity (0 , resource .DecimalSI )
563+ cell0CpuAlloc := cell0 .Allocation ["cpu" ]
564+ if ! cell0CpuAlloc .Equal (* expectedCell0CpuAlloc ) {
565+ t .Errorf ("Cell 0: Expected CPU allocation %s, got %s" ,
566+ expectedCell0CpuAlloc .String (), cell0CpuAlloc .String ())
567+ }
568+
569+ // Cell 1 should have 64 GiB memory and 8 CPUs allocated
570+ // (128 GiB / 2 cells = 64 GiB per cell, 16 CPUs / 2 cells = 8 CPUs per cell)
571+ cell1 := cellsByID [1 ]
572+ expectedCell1MemAlloc := resource .NewQuantity (64 * 1024 * 1024 * 1024 , resource .BinarySI )
573+ cell1MemAlloc := cell1 .Allocation ["memory" ]
574+ if ! cell1MemAlloc .Equal (* expectedCell1MemAlloc ) {
575+ t .Errorf ("Cell 1: Expected memory allocation %s, got %s" ,
576+ expectedCell1MemAlloc .String (), cell1MemAlloc .String ())
577+ }
578+ expectedCell1CpuAlloc := resource .NewQuantity (8 , resource .DecimalSI )
579+ cell1CpuAlloc := cell1 .Allocation ["cpu" ]
580+ if ! cell1CpuAlloc .Equal (* expectedCell1CpuAlloc ) {
581+ t .Errorf ("Cell 1: Expected CPU allocation %s, got %s" ,
582+ expectedCell1CpuAlloc .String (), cell1CpuAlloc .String ())
583+ }
584+
585+ // Cell 2 should have 64 GiB memory and 8 CPUs allocated
586+ // (128 GiB / 2 cells = 64 GiB per cell, 16 CPUs / 2 cells = 8 CPUs per cell)
587+ cell2 := cellsByID [2 ]
588+ expectedCell2MemAlloc := resource .NewQuantity (64 * 1024 * 1024 * 1024 , resource .BinarySI )
589+ cell2MemAlloc := cell2 .Allocation ["memory" ]
590+ if ! cell2MemAlloc .Equal (* expectedCell2MemAlloc ) {
591+ t .Errorf ("Cell 2: Expected memory allocation %s, got %s" ,
592+ expectedCell2MemAlloc .String (), cell2MemAlloc .String ())
593+ }
594+ expectedCell2CpuAlloc := resource .NewQuantity (8 , resource .DecimalSI )
595+ cell2CpuAlloc := cell2 .Allocation ["cpu" ]
596+ if ! cell2CpuAlloc .Equal (* expectedCell2CpuAlloc ) {
597+ t .Errorf ("Cell 2: Expected CPU allocation %s, got %s" ,
598+ expectedCell2CpuAlloc .String (), cell2CpuAlloc .String ())
599+ }
600+
601+ // Cell 3 should have zero allocation (not used by the instance)
602+ cell3 := cellsByID [3 ]
603+ expectedCell3MemAlloc := resource .NewQuantity (0 , resource .BinarySI )
604+ cell3MemAlloc := cell3 .Allocation ["memory" ]
605+ if ! cell3MemAlloc .Equal (* expectedCell3MemAlloc ) {
606+ t .Errorf ("Cell 3: Expected memory allocation %s, got %s" ,
607+ expectedCell3MemAlloc .String (), cell3MemAlloc .String ())
608+ }
609+ expectedCell3CpuAlloc := resource .NewQuantity (0 , resource .DecimalSI )
610+ cell3CpuAlloc := cell3 .Allocation ["cpu" ]
611+ if ! cell3CpuAlloc .Equal (* expectedCell3CpuAlloc ) {
612+ t .Errorf ("Cell 3: Expected CPU allocation %s, got %s" ,
613+ expectedCell3CpuAlloc .String (), cell3CpuAlloc .String ())
614+ }
615+ }
616+
398617func TestAddAllocationCapacity_Success (t * testing.T ) {
399618 caps := capabilities.Capabilities {
400619 Host : capabilities.CapabilitiesHost {
0 commit comments