2022-11-10 15:37:44 +01:00
#!/usr/bin/perl
use strict ;
use warnings ;
2022-11-15 11:10:32 +01:00
use Test::More ;
2022-11-10 15:37:44 +01:00
use PVE::RS::ResourceScheduling::Static ;
2023-03-21 13:33:44 +01:00
sub test_basic {
my $ static = PVE::RS::ResourceScheduling::Static - > new ( ) ;
is ( scalar ( $ static - > list_nodes ( ) - > @ * ) , 0 , 'node list empty' ) ;
$ static - > add_node ( "A" , 10 , 100_000_000_000 ) ;
is ( scalar ( $ static - > list_nodes ( ) - > @ * ) , 1 , '1 node added' ) ;
$ static - > add_node ( "B" , 20 , 200_000_000_000 ) ;
is ( scalar ( $ static - > list_nodes ( ) - > @ * ) , 2 , '2nd node' ) ;
$ static - > add_node ( "C" , 30 , 300_000_000_000 ) ;
is ( scalar ( $ static - > list_nodes ( ) - > @ * ) , 3 , '3rd node' ) ;
$ static - > remove_node ( "C" ) ;
is ( scalar ( $ static - > list_nodes ( ) - > @ * ) , 2 , '3rd removed should be 2' ) ;
ok ( $ static - > contains_node ( "A" ) , 'should contain a node A' ) ;
ok ( $ static - > contains_node ( "B" ) , 'should contain a node B' ) ;
ok ( ! $ static - > contains_node ( "C" ) , 'should not contain a node C' ) ;
}
2022-11-10 15:37:44 +01:00
2023-03-21 13:33:44 +01:00
sub test_balance {
my $ static = PVE::RS::ResourceScheduling::Static - > new ( ) ;
$ static - > add_node ( "A" , 10 , 100_000_000_000 ) ;
$ static - > add_node ( "B" , 20 , 200_000_000_000 ) ;
my $ service = {
maxcpu = > 4 ,
maxmem = > 20_000_000_000 ,
} ;
for ( my $ i = 0 ; $ i < 15 ; $ i + + ) {
my $ score_list = $ static - > score_nodes_to_start_service ( $ service ) ;
# imitate HA manager
my $ scores = { map { $ _ - > [ 0 ] = > - $ _ - > [ 1 ] } $ score_list - > @ * } ;
my @ nodes = sort {
$ scores - > { $ a } <=> $ scores - > { $ b } || $ a cmp $ b
} keys $ scores - > % * ;
if ( $ i % 3 == 2 ) {
is ( $ nodes [ 0 ] , "A" , 'first should be A' ) ;
is ( $ nodes [ 1 ] , "B" , 'second should be A' ) ;
} else {
is ( $ nodes [ 0 ] , "B" , 'first should be B' ) ;
is ( $ nodes [ 1 ] , "A" , 'second should be A' ) ;
}
$ static - > add_service_usage_to_node ( $ nodes [ 0 ] , $ service ) ;
}
2022-11-10 15:37:44 +01:00
}
2022-11-15 11:10:32 +01:00
2023-03-21 13:33:45 +01:00
sub test_overcommitted {
my $ static = PVE::RS::ResourceScheduling::Static - > new ( ) ;
$ static - > add_node ( "A" , 4 , 4_102_062_080 ) ;
$ static - > add_node ( "B" , 4 , 4_102_062_080 ) ;
$ static - > add_node ( "C" , 4 , 4_102_053_888 ) ;
$ static - > add_node ( "D" , 4 , 4_102_053_888 ) ;
my $ service = {
maxcpu = > 1 ,
maxmem = > 536_870_912 ,
} ;
$ static - > add_service_usage_to_node ( "A" , $ service ) ;
$ static - > add_service_usage_to_node ( "A" , $ service ) ;
$ static - > add_service_usage_to_node ( "A" , $ service ) ;
$ static - > add_service_usage_to_node ( "B" , $ service ) ;
$ static - > add_service_usage_to_node ( "A" , $ service ) ;
my $ score_list = $ static - > score_nodes_to_start_service ( $ service ) ;
# imitate HA manager
my $ scores = { map { $ _ - > [ 0 ] = > - $ _ - > [ 1 ] } $ score_list - > @ * } ;
my @ nodes = sort {
$ scores - > { $ a } <=> $ scores - > { $ b } || $ a cmp $ b
} keys $ scores - > % * ;
is ( $ nodes [ 0 ] , "C" , 'first should be C' ) ;
is ( $ nodes [ 1 ] , "D" , 'second should be D' ) ;
is ( $ nodes [ 2 ] , "B" , 'third should be B' ) ;
is ( $ nodes [ 3 ] , "A" , 'fourth should be A' ) ;
}
2023-03-21 17:44:52 +01:00
sub test_balance_small_memory_difference {
my ( $ with_start_load ) = @ _ ;
2023-03-21 17:44:51 +01:00
my $ static = PVE::RS::ResourceScheduling::Static - > new ( ) ;
# Memory is different to avoid flaky results with what would otherwise be ties.
$ static - > add_node ( "A" , 8 , 10_000_000_000 ) ;
$ static - > add_node ( "B" , 4 , 9_000_000_000 ) ;
$ static - > add_node ( "C" , 4 , 8_000_000_000 ) ;
2023-03-21 17:44:52 +01:00
if ( $ with_start_load ) {
$ static - > add_service_usage_to_node ( "A" , { maxcpu = > 4 , maxmem = > 1_000_000_000 } ) ;
$ static - > add_service_usage_to_node ( "B" , { maxcpu = > 2 , maxmem = > 1_000_000_000 } ) ;
$ static - > add_service_usage_to_node ( "C" , { maxcpu = > 2 , maxmem = > 1_000_000_000 } ) ;
}
2023-03-21 17:44:51 +01:00
my $ service = {
maxcpu = > 3 ,
maxmem = > 16_000_000 ,
} ;
for ( my $ i = 0 ; $ i < 20 ; $ i + + ) {
my $ score_list = $ static - > score_nodes_to_start_service ( $ service ) ;
# imitate HA manager
my $ scores = { map { $ _ - > [ 0 ] = > - $ _ - > [ 1 ] } $ score_list - > @ * } ;
my @ nodes = sort {
$ scores - > { $ a } <=> $ scores - > { $ b } || $ a cmp $ b
} keys $ scores - > % * ;
if ( $ i % 4 <= 1 ) {
is ( $ nodes [ 0 ] , "A" , 'first should be A' ) ;
is ( $ nodes [ 1 ] , "B" , 'second should be B' ) ;
is ( $ nodes [ 2 ] , "C" , 'third should be C' ) ;
} elsif ( $ i % 4 == 2 ) {
is ( $ nodes [ 0 ] , "B" , 'first should be B' ) ;
is ( $ nodes [ 1 ] , "C" , 'second should be C' ) ;
is ( $ nodes [ 2 ] , "A" , 'third should be A' ) ;
} elsif ( $ i % 4 == 3 ) {
is ( $ nodes [ 0 ] , "C" , 'first should be C' ) ;
is ( $ nodes [ 1 ] , "A" , 'second should be A' ) ;
is ( $ nodes [ 2 ] , "B" , 'third should be B' ) ;
} else {
die "internal error, got $i % 4 == " . ( $ i % 4 ) . "\n" ;
}
$ static - > add_service_usage_to_node ( $ nodes [ 0 ] , $ service ) ;
}
}
2023-03-21 13:33:44 +01:00
test_basic ( ) ;
test_balance ( ) ;
2023-03-21 13:33:45 +01:00
test_overcommitted ( ) ;
2023-03-21 17:44:52 +01:00
test_balance_small_memory_difference ( 1 ) ;
test_balance_small_memory_difference ( 0 ) ;
2023-03-21 13:33:44 +01:00
2022-11-15 11:10:32 +01:00
done_testing ( ) ;