| #!/usr/bin/env expect |
| ############################################################################ |
| # Purpose: Test federation functionality |
| # Test scontrol show federations |
| # Test that persistent connections are made |
| # |
| # Reqs: 1. Using slurmdbd accounting storage type and is up |
| # 2. fed_slurm_base is defined in globals.local - set to directory that |
| # has access to each federation configure (fedc1, fedc2, fedc3). |
| # Eg. |
| # federation/slurm/ (src) |
| # federation/fed1/bin |
| # federation/fed1/sbin |
| # federation/fed1/etc |
| # federation/fed1/... |
| # federation/fed2/... |
| # federation/fed3/... |
| # 3. controllers are up and running. |
| ############################################################################ |
| # Copyright (C) SchedMD LLC. |
| # |
| # This file is part of Slurm, a resource management program. |
| # For details, see <https://slurm.schedmd.com/>. |
| # Please also read the included file: DISCLAIMER. |
| # |
| # Slurm is free software; you can redistribute it and/or modify it under |
| # the terms of the GNU General Public License as published by the Free |
| # Software Foundation; either version 2 of the License, or (at your option) |
| # any later version. |
| # |
| # Slurm is distributed in the hope that it will be useful, but WITHOUT ANY |
| # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| # details. |
| # |
| # You should have received a copy of the GNU General Public License along |
| # with Slurm; if not, write to the Free Software Foundation, Inc., |
| # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| ############################################################################ |
| |
| source ./globals |
| source ./globals_accounting |
| source ./globals_federation |
| |
| set fed_name "feda" |
| set timeout 5 |
| |
| # |
| # Check accounting config and bail if not found. |
| # |
| if {[get_config_param "AccountingStorageType"] ne "accounting_storage/slurmdbd"} { |
| skip "This test can't be run without a usable AccountStorageType" |
| } |
| |
| if {[get_admin_level] ne "Administrator"} { |
| skip "This test can't be run without being an Accounting administrator. Use: sacctmgr mod user \$USER set admin=admin" |
| } |
| |
| proc cleanup { } { |
| global fed_name |
| |
| delete_federations $fed_name |
| } |
| |
| proc test_fed_status {cname fed_flags cluster_list} { |
| # Match db info with what cluster has. |
| global fed_slurm_base fed_name eol |
| array set clusters $cluster_list |
| set matches 0 |
| set lines 0 |
| set my_scontrol "${fed_slurm_base}/$cname/bin/scontrol" |
| spawn $my_scontrol show federation |
| set expected_matches [array size clusters] |
| if {$expected_matches} { |
| # Match the fedname line |
| incr expected_matches |
| } |
| expect { |
| -re "$eol" { |
| incr lines |
| set line $expect_out(buffer) |
| log_debug "Line: $line" |
| |
| if {[regexp "Federation: $fed_name" $line match]} { |
| log_debug "Matched: $match" |
| incr matches |
| } elseif {[regexp {Self:\s+(\S+):(\S+):(\d+) ID:(\d+) FedState:(\S*) Features:(\S*)} \ |
| $line match name host port id state features]} { |
| log_debug "Matched: $match" |
| if {$expected_matches && |
| [dict get $clusters($name) host] eq $host && |
| [dict get $clusters($name) state] eq $state && |
| [dict get $clusters($name) features] eq $features && |
| [dict get $clusters($name) conn] eq "Self" && |
| [dict get $clusters($name) port] == $port && |
| [dict get $clusters($name) id] == $id} { |
| log_debug "Matched self: $name" |
| incr matches |
| } |
| } elseif {[regexp {Sibling:\s+(\S+):(\S+):(\d+) ID:(\d+) FedState:(\S*) Features:(\S*) PersistConnSend/Recv:(\S+)} \ |
| $line match name host port id state features conn]} { |
| log_debug "Matched: $match" |
| if {$expected_matches && |
| [dict get $clusters($name) host] eq $host && |
| [dict get $clusters($name) state] eq $state && |
| [dict get $clusters($name) features] eq $features && |
| [dict get $clusters($name) conn] eq $conn && |
| [dict get $clusters($name) port] == $port && |
| [dict get $clusters($name) id] == $id} { |
| log_debug "Matched sibling: $name" |
| incr matches |
| } |
| } |
| exp_continue |
| } |
| timeout { |
| fail "scontrol not responding" |
| } |
| eof { |
| wait |
| } |
| } |
| |
| if {$lines != $expected_matches} { |
| fail "Line count and expected matches don't match ($lines != $expected_matches)" |
| } |
| |
| if {$matches != $expected_matches} { |
| fail "Failed to match ($matches != $expected_matches)" |
| } |
| } |
| |
| if {![check_federation_setup]} { |
| skip "This test can't be run without fed_slurm_base, fedc1, fedc2, fedc3 setup in globals.local" |
| } |
| |
| if {![check_federation_up]} { |
| skip "This test can't be run without all clusters up" |
| } |
| |
| # Remove existing setup |
| cleanup |
| |
| # add clusters to federation |
| if [setup_federation $fed_name] { |
| fail "Failed to setup federation" |
| } |
| |
| # Get cluster/fed info from db |
| array set clusters [get_clusterfed_info $fed_name] |
| |
| set fed_flags "None" |
| |
| log_info "Test from $fedc1" |
| dict set clusters($fedc1) conn Self |
| dict set clusters($fedc2) conn "Yes/Yes" |
| dict set clusters($fedc3) conn "Yes/Yes" |
| test_fed_status $fedc1 $fed_flags [array get clusters] |
| |
| log_info "Test from $fedc2" |
| dict set clusters($fedc1) conn "Yes/Yes" |
| dict set clusters($fedc2) conn Self |
| dict set clusters($fedc3) conn "Yes/Yes" |
| test_fed_status $fedc2 $fed_flags [array get clusters] |
| |
| log_info "Test from $fedc3" |
| dict set clusters($fedc1) conn "Yes/Yes" |
| dict set clusters($fedc2) conn "Yes/Yes" |
| dict set clusters($fedc3) conn Self |
| test_fed_status $fedc3 $fed_flags [array get clusters] |
| |
| log_info "Remove $fedc3 and test from $fedc1 and $fedc2" |
| if [remove_cluster_from_fed $fedc3 $fed_name] { |
| fail "Unable to remove cluster 3 ($fedc3) from federation ($fed_name)" |
| } |
| array unset clusters $fedc3 |
| dict set clusters($fedc1) conn Self |
| dict set clusters($fedc2) conn "Yes/Yes" |
| test_fed_status $fedc1 $fed_flags [array get clusters] |
| |
| dict set clusters($fedc1) conn "Yes/Yes" |
| dict set clusters($fedc2) conn Self |
| test_fed_status $fedc2 $fed_flags [array get clusters] |
| |
| log_info "Remove $fedc1 and test from $fedc2" |
| if [remove_cluster_from_fed $fedc1 $fed_name] { |
| fail "Unable to remove cluster 1 ($fedc1) from federation ($fed_name)" |
| } |
| array unset clusters $fedc1 |
| dict set clusters($fedc2) conn Self |
| test_fed_status $fedc2 $fed_flags [array get clusters] |
| |
| log_info "Remove $fedc2 and test from $fedc2" |
| array unset clusters |
| if [remove_cluster_from_fed $fedc2 $fed_name] { |
| fail "Unable to remove cluster 2 ($fedc2) from federation ($fed_name)" |
| } |
| test_fed_status $fedc2 $fed_flags [array get clusters] |
| |
| log_info "Add $fedc1 and test from $fedc1" |
| if [add_cluster_to_fed $fedc1 $fed_name] { |
| fail "Unable to add cluster 1 ($fedc1) to federation ($fed_name)" |
| } |
| array set clusters [get_clusterfed_info $fed_name] |
| dict set clusters($fedc1) conn Self |
| test_fed_status $fedc1 $fed_flags [array get clusters] |
| |
| log_info "Add $fedc2 and test from $fedc1" |
| if [add_cluster_to_fed $fedc2 $fed_name] { |
| fail "Unable to add cluster 2 ($fedc2) to federation ($fed_name)" |
| } |
| sleep 5 |
| array set clusters [get_clusterfed_info $fed_name] |
| dict set clusters($fedc1) conn Self |
| dict set clusters($fedc2) conn "Yes/Yes" |
| test_fed_status $fedc1 $fed_flags [array get clusters] |
| |
| log_info "Add $fedc3 and test from $fedc1" |
| if [add_cluster_to_fed $fedc3 $fed_name] { |
| fail "Unable to add cluster 3 ($fedc3) to federation ($fed_name)" |
| } |
| sleep 5 |
| array set clusters [get_clusterfed_info $fed_name] |
| dict set clusters($fedc1) conn Self |
| dict set clusters($fedc2) conn "Yes/Yes" |
| dict set clusters($fedc3) conn "Yes/Yes" |
| test_fed_status $fedc1 $fed_flags [array get clusters] |
| |
| |
| #log_info "Test federation flags (LLC)" |
| #set matches 0 |
| #spawn $sacctmgr -i modify federation $fed_name set flags+=LLC |
| #expect { |
| # -re "Setting$eol" { |
| # incr matches |
| # exp_continue |
| # } |
| # -re "^\\s+Flags\\s+\\+=\\s+LLC$eol" { |
| # incr matches |
| # exp_continue |
| # } |
| # -re "^\\s+Modified federation...$eol" { |
| # incr matches |
| # exp_continue |
| # } |
| # -re "^\\s+$fed_name$eol" { |
| # incr matches |
| # exp_continue |
| # } |
| # timeout { |
| # fail "sacctmgr add not responding" |
| # } |
| # eof { |
| # wait |
| # } |
| #} |
| #if {$matches != 4} { |
| # fail "Setting LLC flag" |
| #} |
| # |
| #set fed_flags "LLC" |
| #array set clusters [get_clusterfed_info $fed_name] |
| #dict set clusters($fedc1) conn Self |
| #dict set clusters($fedc2) conn "Yes/Yes" |
| #dict set clusters($fedc3) conn "Yes/Yes" |
| #test_fed_status $fedc1 $fed_flags [array get clusters] |
| # |
| # |
| #log_info "Test removal of federation flags (LLC)" |
| #set matches 0 |
| #spawn $sacctmgr -i modify federation $fed_name set flags-=LLC |
| #expect { |
| # -re "Setting$eol" { |
| # incr matches |
| # exp_continue |
| # } |
| # -re "^\\s+Flags\\s+\\-=\\s+LLC$eol" { |
| # incr matches |
| # exp_continue |
| # } |
| # -re "^\\s+Modified federation...$eol" { |
| # incr matches |
| # exp_continue |
| # } |
| # -re "^\\s+$fed_name$eol" { |
| # incr matches |
| # exp_continue |
| # } |
| # timeout { |
| # fail "sacctmgr add not responding" |
| # } |
| # eof { |
| # wait |
| # } |
| #} |
| #if {$matches != 4} { |
| # fail "Removing federation flags (got $matches)" |
| #} |
| # |
| #set fed_flags "None" |
| #array set clusters [get_clusterfed_info $fed_name] |
| #dict set clusters($fedc1) conn Self |
| #dict set clusters($fedc2) conn "Yes/Yes" |
| #dict set clusters($fedc3) conn "Yes/Yes" |
| #test_fed_status $fedc1 $fed_flags [array get clusters] |
| |
| |
| log_info "Test setting of cluster features" |
| set matches 0 |
| spawn $sacctmgr -i modify cluster $fedc3 set features=fb,fa |
| expect { |
| -re "Setting$eol" { |
| incr matches |
| exp_continue |
| } |
| -re "\\s+Feature\\s+=\\s+fb$eol" { |
| incr matches |
| exp_continue |
| } |
| -re "\\s+Feature\\s+=\\s+fa$eol" { |
| incr matches |
| exp_continue |
| } |
| -re "Modified cluster...$eol" { |
| incr matches |
| exp_continue |
| } |
| -re "^\\s+$fedc3$eol" { |
| incr matches |
| exp_continue |
| } |
| timeout { |
| fail "sacctmgr add not responding" |
| } |
| eof { |
| wait |
| } |
| } |
| if {$matches != 5} { |
| fail "Unexpected error (got $matches)" |
| } |
| |
| array set clusters [get_clusterfed_info $fed_name] |
| dict set clusters($fedc1) conn Self |
| dict set clusters($fedc2) conn "Yes/Yes" |
| dict set clusters($fedc3) conn "Yes/Yes" |
| test_fed_status $fedc1 $fed_flags [array get clusters] |
| |
| log_info "Test modifying/add of cluster features" |
| set matches 0 |
| spawn $sacctmgr -i modify cluster $fedc3 set features+=fc |
| expect { |
| -re "Setting$eol" { |
| incr matches |
| exp_continue |
| } |
| -re "\\s+Feature\\s+\\+=\\s+fc$eol" { |
| incr matches |
| exp_continue |
| } |
| -re "Modified cluster...$eol" { |
| incr matches |
| exp_continue |
| } |
| -re "^\\s+$fedc3$eol" { |
| incr matches |
| exp_continue |
| } |
| timeout { |
| fail "sacctmgr add not responding" |
| } |
| eof { |
| wait |
| } |
| } |
| if {$matches != 4} { |
| fail "Unexpected error (got $matches)" |
| } |
| |
| array set clusters [get_clusterfed_info $fed_name] |
| dict set clusters($fedc1) conn Self |
| dict set clusters($fedc2) conn "Yes/Yes" |
| dict set clusters($fedc3) conn "Yes/Yes" |
| test_fed_status $fedc1 $fed_flags [array get clusters] |
| |
| log_info "Test modifying/remove of cluster features" |
| set matches 0 |
| spawn $sacctmgr -i modify cluster $fedc3 set features-=fb |
| expect { |
| -re "Setting$eol" { |
| incr matches |
| exp_continue |
| } |
| -re "\\s+Feature\\s+-=\\s+fb$eol" { |
| incr matches |
| exp_continue |
| } |
| -re "Modified cluster...$eol" { |
| incr matches |
| exp_continue |
| } |
| -re "^\\s+$fedc3$eol" { |
| incr matches |
| exp_continue |
| } |
| timeout { |
| fail "sacctmgr add not responding" |
| } |
| eof { |
| wait |
| } |
| } |
| if {$matches != 4} { |
| fail "Unexpected error (got $matches)" |
| } |
| |
| array set clusters [get_clusterfed_info $fed_name] |
| dict set clusters($fedc1) conn Self |
| dict set clusters($fedc2) conn "Yes/Yes" |
| dict set clusters($fedc3) conn "Yes/Yes" |
| test_fed_status $fedc1 $fed_flags [array get clusters] |
| |
| |
| log_info "Test clearing of cluster features" |
| set matches 0 |
| spawn $sacctmgr -i modify cluster $fedc3 set features= |
| expect { |
| -re "Setting$eol" { |
| incr matches |
| exp_continue |
| } |
| -re "\\s+Feature\\s+=\\s+$eol" { |
| incr matches |
| exp_continue |
| } |
| -re "Modified cluster...$eol" { |
| incr matches |
| exp_continue |
| } |
| -re "^\\s+$fedc3$eol" { |
| incr matches |
| exp_continue |
| } |
| timeout { |
| fail "sacctmgr add not responding" |
| } |
| eof { |
| wait |
| } |
| } |
| if {$matches != 4} { |
| fail "Unexpected error (got $matches)" |
| } |
| |
| array set clusters [get_clusterfed_info $fed_name] |
| dict set clusters($fedc1) conn Self |
| dict set clusters($fedc2) conn "Yes/Yes" |
| dict set clusters($fedc3) conn "Yes/Yes" |
| test_fed_status $fedc1 $fed_flags [array get clusters] |
| |
| log_info "Delete federation and test from $fedc1" |
| delete_federations $fed_name |
| array unset clusters |
| test_fed_status $fedc2 $fed_flags [array get clusters] |