#!/usr/bin/expect
############################################################################
# Purpose: Test of SLURM functionality
#          Validate scontrol create, delete, and update for reservations.
#
# Output:  "TEST: #.#" followed by "SUCCESS" if test was successful, OR
#          "FAILURE: ..." otherwise with an explanation of the failure, OR
#          anything else indicates a failure mode that must be investigated.
############################################################################
# Copyright (C) 2009 Lawrence Livermore National Security
# Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
# Written by Dave Bremer <dbremer@llnl.gov>
# CODE-OCEC-09-009. All rights reserved.
#
#
# This file is part of SLURM, a resource management program.
# For details, see <http://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 ./inc3.11.1
source ./inc3.11.2
source ./inc3.11.3
source ./inc3.11.4
source ./inc3.11.5
source ./inc3.11.6
source ./inc3.11.7
source ./inc3.11.8
source ./inc3.11.9



set test_id		"3.11"
set file_in		"test$test_id.input"
set exit_code		0
set res_name		""
set res_name_save	""
set res_nodes		""
set res_thread_cnt	0
set user_name		""
set def_partition 	""
set def_node		""
set def_share_force     0
set def_node_name	""
set def_node_inx_min	-1
set def_node_inx_max	-1
set ii			0

print_header $test_id


#
# Procedure to create a new reservation and validate it.
# Modifies the global var res_name in the process
#
proc create_res { res_params failure_expected } {
	#exp_internal 1
	global scontrol
	global alpha_numeric_under number alpha_numeric_nodelist
	global res_name
	global res_nodes
	global res_nodecnt
	global res_corecnt
	global res_thread_cnt

	set ret_code 0
	set res_name ""

	#
	# Create a reservation using the list of params in res_params
	#
	set arglist [linsert $res_params 0 $scontrol create res]
	eval spawn $arglist
	expect {
		-re "Reservation created: ($alpha_numeric_under)" {
			set res_name $expect_out(1,string)
		}
		-re "Error creating the reservation: Invalid user" {
			if {!$failure_expected} {
				send_user "\nFAILURE: user not authorized "
				send_user "to create reservation\n"
			}
			set ret_code 1
			exp_continue
		}
		-nocase "Error" {
			if {!$failure_expected} {
				send_user "\nFAILURE: problem creating "
				send_user "reservation with args: $res_params\n"
			}
			set ret_code 1
			exp_continue
		}
		timeout {
			send_user "\n\033\[31mFAILURE: scontrol not responding\033\[m\n"
			set ret_code 1
		}
		eof {
			wait
		}
	}
	if { $ret_code != 0 } {
		return $ret_code
	}

	spawn $scontrol show res $res_name
	expect {
		-re "ReservationName=($alpha_numeric_under)" {
			set tmp_res_name $expect_out(1,string)
			if {$tmp_res_name != $res_name} {
				if {!$failure_expected} {
					send_user "\nFAILURE: problem showing "
					send_user "reservation created with:  "
					send_user "$res_params\n"
				}
				set ret_code 1
			}
			exp_continue
		}
		-re "No reservations in the system" {
			if {!$failure_expected} {
				send_user "\nFAILURE: no reservations found  "
				send_user "after reservation created with:  "
				send_user "$res_params\n"
			}
			set ret_code 1
			exp_continue
		}
		-re "Reservation ($alpha_numeric_under) not found" {
			if {!$failure_expected} {
				send_user "\nFAILURE: Reservation $res_name not"
				send_user "found after reservation created "
				send_user "with:  $res_params\n"
			}
			set ret_code 1
			exp_continue
		}
		-re "Nodes=($alpha_numeric_nodelist)" {
			set res_nodes $expect_out(1,string)
			exp_continue
		}
		-re "NodeCnt=($alpha_numeric_under)" {
			set res_nodecnt $expect_out(1,string)
			exp_continue
		}
		-re "CoreCnt=($alpha_numeric_under)" {
			set res_corecnt $expect_out(1,string)
			exp_continue
		}
		timeout {
			send_user "\nFAILURE: scontrol not responding\n"
			set ret_code 1
		}
		eof {
			wait
		}
	}

	spawn $scontrol show node $res_nodes
	expect {
		-re "ThreadsPerCore=($number)" {
			set res_thread_cnt $expect_out(1,string)
			exp_continue
		}
		timeout {
			send_user "\nFAILURE: scontrol not responding\n"
			set ret_code 1
		}
		eof {
			wait
		}
	}
	#exp_internal 0

	return $ret_code
}


#
# Procedure to update a reservation
#
proc update_res { res_name res_params failure_expected } {
	global scontrol
	global alpha_numeric_under
	set ret_code 0

	#
	# Update the reservation using the list of arguments in res_params
	#
	set arglist [linsert $res_params 0 $scontrol update ReservationName=$res_name]
	eval spawn $arglist
	expect {
		-re "Reservation updated." {
			exp_continue
		}
		-re "Error creating the reservation: Invalid user" {
			if {!$failure_expected} {
				send_user "\nWARNING: user not authorized "
				send_user "to update reservation\n"
			}
			set ret_code 1
			exp_continue
		}
		-re "Error" {
			if {!$failure_expected} {
				send_user "\nFAILURE: problem updating "
				send_user "reservation $res_name with "
				send_user "$res_params\n"
			}
			set ret_code 1
			exp_continue
		}
		-re "error" {
			if {!$failure_expected} {
				send_user "\nFAILURE: problem updating "
				send_user "reservation $res_name with "
				send_user "$res_params\n"
			}
			set ret_code 1
			exp_continue
		}
		timeout {
			send_user "\nFAILURE: scontrol not responding\n"
			set ret_code 1
		}
		eof {
			wait
		}
	}
	return $ret_code
}


#
# Procedure to delete a reservation
#
proc delete_res { res_name } {
	global scontrol
	set ret_code 0

	spawn $scontrol delete ReservationName=$res_name
	expect {
		-re "invalid" {
			send_user "\nFAILURE: problem deleting reservation $res_name\n"
			set ret_code 1
			exp_continue
		}
		-re "reservation is in use" {
			send_user "\nFAILURE: $res_name is in use\n"
			set ret_code 1
			exp_continue
		}
	}
	return $ret_code
}


#
# Identify usable nodes in default partition
#
set def_partition [default_partition]
if {[string compare $def_partition ""] == 0} {
	send_user "\nFAILURE: failed to find default partition\n"
	exit 1
}

spawn $scontrol show partition $def_partition
expect {
	-re " Shared=FORCE" {
		set def_share_force 1
		exp_continue
	}
	eof {
		wait
	}
}
spawn $sinfo -h -o "=%N=" -p $def_partition
expect {
	-re "=(.+)=" {
		set def_node $expect_out(1,string)
		exp_continue
	}
	eof {
		wait
	}
}
spawn $sinfo -h -o "=%N=" -p $def_partition
expect {
	-re "=($alpha_numeric).($number)-($number).=" {
		set def_node_name $expect_out(1,string)
		set def_node_inx_min $expect_out(2,string)
		set def_node_inx_max $expect_out(3,string)
		exp_continue
	}
	eof {
		wait
	}
}
if {[string compare $def_node ""] == 0} {
	send_user "\nFAILURE:default partition seems to have no nodes\n"
	exit 1
}

#
# Determine system size
#
set core_spec 0
set cores_per_socket 0
set sockets_per_node 0
log_user 0
spawn $scontrol show node -o
expect {
	-re "CoresPerSocket=($number)" {
		if {$cores_per_socket == 0} {
			set cores_per_socket $expect_out(1,string)
		}
		exp_continue
	}
	-re "Sockets=($number)" {
		if {$sockets_per_node == 0} {
			set sockets_per_node $expect_out(1,string)
		}
		exp_continue
	}
	-re "CoreSpecCount=($number)" {
		if {$expect_out(1,string) > 0} {
			set core_spec 1
		}
		exp_continue
	}
	-re "CPUSpecList=($number)" {
		set core_spec 1
		exp_continue
	}
	eof {
		wait
	}
}
log_user 1
set cores_per_node [expr $cores_per_socket * $sockets_per_node]
set node_count [available_nodes $def_partition ""]
set cluster_cpus [expr $cores_per_node * $node_count]

#
# Get the user name
#
spawn $bin_id -un
expect {
	-re "($alpha_numeric_under)" {
		set user_name $expect_out(1,string)
	}
	eof {
		wait
	}
}

set cons_res_actived 0
if {$def_share_force == 0} {
	spawn $scontrol show config
	expect {
		-re "select/cons_res" {
			set cons_res_actived 1
		}
		timeout {
			send_user "\nFAILURE: scontrol not responding\n"
			set exit_code 1
		}
		eof {
			wait
		}
	}
}

inc3_11_1
inc3_11_2
inc3_11_3
inc3_11_4
inc3_11_5
inc3_11_6
if {$cons_res_actived == 1 && $core_spec == 0} {
	inc3_11_7
	inc3_11_8
	inc3_11_9
}

if {$exit_code == 0} {
	exec $bin_rm -f $file_in
	send_user "\nSUCCESS\n"
} else {
	send_user "\nFAILURE\n"
}
exit $exit_code
