#!/usr/bin/expect
############################################################################
# Purpose: Test of Slurm functionality
#          Test user_resv_delete parameter.
############################################################################
# Copyright (C) 2021 SchedMD LLC
# Written by Chad Vizino <chad@schedmd.com>
#
# 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_accounting

set job_id               0
set user_name            [get_my_user_name]
set default_partition    [default_partition]
set resv_name            "resv_$test_name"
set config_file          [get_conf_path]/slurm.conf
set slurm_user           [get_config_param "SlurmUser"]
set test_acct            "$test_name\_acct"
regsub {\(.*} $slurm_user {} slurm_user

proc testproc_cleanup {} {
	global job_id resv_name

	log_info "testproc_cleanup called"
	cancel_job $job_id
	delete_res $resv_name
}

proc cleanup {} {
	global config_file do_useracct_cleanup sacctmgr test_acct testsuite_user

	log_info "cleanup called"
	testproc_cleanup

	run_command "$sacctmgr -vi delete user name=$testsuite_user"
	run_command "$sacctmgr -vi delete account name=$test_acct"

	restore_conf $config_file
	reconfigure
}

proc set_user_resv_delete {} {
	global bin_echo bin_sed config_file

	set params [get_config_param "SlurmctldParameters"]
	if {![param_value $params "user_resv_delete"]} {
		if { $params eq "" || $params eq "(null)" } {
			# no SlurmctldParameters so add to end of file
			run_command -fail -nolog "$bin_echo SlurmctldParameters=user_resv_delete >> $config_file"
		} else {
			# SlurmctldParameters present so add it to end of the list
			run_command -fail -nolog "$bin_sed -i s/$params.*$/&,user_resv_delete/ $config_file"
		}
		reconfigure -fail

		if {![param_contains [get_config_param "SlurmctldParameters"] "user_resv_delete"]} {
			fail "could not set user_resv_delete as a SlurmctldParameter"
		}
	}
	log_info "user_resv_delete set in SlurmctldParameters"
}

proc unset_user_resv_delete {} {
	global bin_sed config_file

	set params [get_config_param "SlurmctldParameters"]
	if {[param_value $params "user_resv_delete"]} {
		run_command -fail -nolog "$bin_sed -i -e s/user_resv_delete// -e /SlurmctldParameters=$/d $config_file"
		reconfigure -fail

		if {[param_contains [get_config_param "SlurmctldParameters"] "user_resv_delete"]} {
			fail "could not unset user_resv_delete as a SlurmctldParameter"
		}
	}
	log_info "user_resv_delete unset in SlurmctldParameters"
}

#
# Preconditions
#
if {![is_super_user]} {
	skip "Must be super user to run test"
}

# save config
save_conf $config_file

if {![check_run_as_user $testsuite_user]} {
	skip "testsuite_user must be defined in globals.local (now is \"$testsuite_user\") and sudo must be configured for the current user ([get_my_user_name]) without passwd"
}

if {$testsuite_user == $slurm_user} {
	skip "Test needs testsuite_user ($testsuite_user) different than SlurmUser ($slurm_user)"
}

# Provide the right permissions to $testsuite_user
run_command -fail "$sacctmgr -vi add account name=$test_acct"
run_command -fail "$sacctmgr -vi add user name=$testsuite_user account=$test_acct"
run_command -fail "$sacctmgr -vi update user $testsuite_user set adminlevel=None"

#
# Main testproc
#
proc test_user_resv_delete {AccountingStorageEnforce test_user resv_user expected_submit_permissions expected_delete_permissions} {
	global scontrol resv_name job_id
	global default_partition

	# Setup the test reservation
	if {[create_res $resv_name "StartTime=now Duration=1 NodeCnt=1 partition=$default_partition user=$resv_user"]} {
		fail "Unable to create a reservation"
	}
	wait_for {[get_reservation_param $resv_name State] eq "ACTIVE"} {}

	if {$expected_submit_permissions} {
		log_info "Confirm that reservation member user CAN submit job"
		set job_id [submit_job -user $test_user -subtest         "-o /dev/null -e /dev/null --reservation=$resv_name --wrap=\"sleep 10\""]
	} else {
		log_info "Confirm that reservation non-member user CANNOT submit job"
		set job_id [submit_job -user $test_user -subtest -xfail  "-o /dev/null -e /dev/null --reservation=$resv_name --wrap=\"sleep 10\""]

	}
	cancel_job $job_id

	if {$expected_delete_permissions} {
		log_info "Confirm that reservation member user CAN delete a reservation"
		run_command -subtest -user $test_user "$scontrol delete reservationname=$resv_name"
		run_command -subtest -xfail "$scontrol show reservationname=$resv_name"
	} else {
		log_info "Confirm that reservation non-member user CANNOT delete reservation"
		# TODO: Add -subtest -xfail once bug 10676 is fixed (>=21.08)
		set output [run_command_output -user $test_user "$scontrol delete reservationname=$resv_name"]
		set rc [regexp -all -nocase {invalid user id} $output]
		subtest {$rc == 1} "Message \"invalid user id\" should be shown when $test_user attempt to delete reservation $resv_name"
		run_command -subtest "$scontrol show reservationname=$resv_name"
	}

	testproc_cleanup
}

#
# Test with current AccountingStorageEnforce
#
set params [get_config_param "AccountingStorageEnforce"]

log_info "run tests with user_resv_delete set"
set_user_resv_delete
testproc test_user_resv_delete $params $testsuite_user $testsuite_user true true
testproc test_user_resv_delete $params $testsuite_user $slurm_user false false

log_info "run tests with user_resv_delete NOT set"
unset_user_resv_delete
testproc test_user_resv_delete $params $testsuite_user $testsuite_user true false
testproc test_user_resv_delete $params $testsuite_user $slurm_user false false

#
# Reconfigure to add/remove AccountingStorageEnforce=associations
# TODO: Cannot be done because it won't be removed (Bug 8606 and 10597), so skip
# set params [get_config_param "AccountingStorageEnforce"]
# testproc test_user_resv_delete $params $testsuite_user $testsuite_user true
# testproc test_user_resv_delete $params $testsuite_user $slurm_user false
skip "We need to be able to add/remove AccountingStorageEnforce=associations (Bug 8606 and 10597)"
