11 from __future__
import print_function
13 from LauncherMTTTool
import *
47 LauncherMTTTool.__init__(self)
49 self.
options[
'hostfile'] = (
None,
"The hostfile for SLURM to use")
50 self.
options[
'command'] = (
"srun",
"Command for executing the application")
51 self.
options[
'np'] = (
None,
"Number of processes to run")
52 self.
options[
'timeout'] = (
None,
"Maximum execution time - terminate a test if it exceeds this time")
53 self.
options[
'options'] = (
None,
"Comma-delimited sets of command line options that shall be used on each test")
54 self.
options[
'skipped'] = (
"77",
"Exit status of a test that declares it was skipped")
55 self.
options[
'merge_stdout_stderr'] = (
False,
"Merge stdout and stderr into one output stream")
56 self.
options[
'stdout_save_lines'] = (-1,
"Number of lines of stdout to save")
57 self.
options[
'stderr_save_lines'] = (-1,
"Number of lines of stderr to save")
58 self.
options[
'test_dir'] = (
None,
"Names of directories to be scanned for tests")
59 self.
options[
'fail_tests'] = (
None,
"Names of tests that are expected to fail")
60 self.
options[
'fail_returncodes'] = (
None,
"Expected return code of tests expected to fail")
61 self.
options[
'fail_timeout'] = (
None,
"Maximum execution time for tests expected to fail")
62 self.
options[
'skip_tests'] = (
None,
"Names of tests to be skipped")
63 self.
options[
'max_num_tests'] = (
None,
"Maximum number of tests to run")
64 self.
options[
'job_name'] = (
None,
"User-defined name for job")
65 self.
options[
'modules'] = (
None,
"Modules to load")
66 self.
options[
'modules_unload'] = (
None,
"Modules to unload")
67 self.
options[
'test_list'] = (
None,
"List of tests to run, default is all")
68 self.
options[
'allocate_cmd'] = (
None,
"Command to use for allocating nodes from the resource manager")
69 self.
options[
'deallocate_cmd'] = (
None,
"Command to use for deallocating nodes from the resource manager")
79 IPlugin.activate(self)
84 IPlugin.deactivate(self)
86 deallocate_cmdargs = shlex.split(self.
cmds[
'deallocate_cmd'])
87 _status,_stdout,_stderr,_time = self.testDef.execmd.execute(self.
cmds, deallocate_cmdargs, self.
testDef)
95 lines = testDef.printOptions(self.
options)
106 testDef.logger.verbose_print(
"SLURM Launcher")
110 if log[
'section']
is not None:
111 if "Default" in log[
'section']:
115 testDef.parseOptions(log, self.
options, keyvals, myopts)
117 keys = list(self.options.keys())
118 optkeys = list(myopts.keys())
119 for optkey
in optkeys:
131 log[
'stderr'] =
"Section not specified"
136 parent = keyvals[
'parent']
137 if parent
is not None:
140 bldlog = testDef.logger.getLog(parent)
142 location = bldlog[
'location']
147 log[
'stderr'] =
"Location of built tests was not provided"
150 if bldlog[
'parameters']
is not None:
152 for md
in bldlog[
'parameters']:
153 if "modules_unload" == md[0]:
155 if keyvals[
'modules_unload']
is not None:
157 mods = md[1].split(
',')
158 newmods = keyvals[
'modules_unload'].split(
',')
161 keyvals[
'modules_unload'] =
','.join(mods)
163 keyvals[
'modules_unload'] = md[1]
166 for md
in bldlog[
'parameters']:
167 if "modules" == md[0]:
169 if keyvals[
'modules']
is not None:
171 mods = md[1].split(
',')
172 newmods = keyvals[
'modules'].split(
',')
175 keyvals[
'modules'] =
','.join(mods)
177 keyvals[
'modules'] = md[1]
183 midlog = testDef.logger.getLog(bldlog[
'middleware'])
184 if midlog
is not None:
187 if midlog[
'location']
is not None:
190 oldbinpath = os.environ[
'PATH']
191 pieces = oldbinpath.split(
':')
195 bindir = os.path.join(midlog[
'location'],
"bin")
196 pieces.insert(0, bindir)
197 newpath =
":".join(pieces)
198 os.environ[
'PATH'] = newpath
201 oldldlibpath = os.environ[
'LD_LIBRARY_PATH']
202 pieces = oldldlibpath.split(
':')
206 bindir = os.path.join(midlog[
'location'],
"lib")
207 pieces.insert(0, bindir)
208 newpath =
":".join(pieces)
209 os.environ[
'LD_LIBRARY_PATH'] = newpath
217 if midlog[
'parameters']
is not None:
219 for md
in midlog[
'parameters']:
220 if "modules_unload" == md[0]:
222 if keyvals[
'modules_unload']
is not None:
224 mods = md[1].split(
',')
225 newmods = keyvals[
'modules_unload'].split(
',')
228 keyvals[
'modules_unload'] =
','.join(mods)
230 keyvals[
'modules_unload'] = md[1]
233 for md
in midlog[
'parameters']:
234 if "modules" == md[0]:
236 if keyvals[
'modules']
is not None:
238 mods = md[1].split(
',')
239 newmods = keyvals[
'modules'].split(
',')
242 keyvals[
'modules'] =
','.join(mods)
244 keyvals[
'modules'] = md[1]
252 log[
'stderr'] =
"Parent test build stage was not provided"
256 testDef.parseOptions(log, self.
options, keyvals, cmds)
267 if cmds[
'test_list']
is None:
269 if cmds[
'test_dir']
is not None:
271 dirs = cmds[
'test_dir'].split()
275 dr = dr.replace(
'\"',
'')
276 dr = dr.replace(
',',
'')
277 for dirName, subdirList, fileList
in os.walk(dr):
278 for fname
in fileList:
280 filename = os.path.abspath(os.path.join(dirName,fname))
281 if os.path.isfile(filename)
and os.access(filename, os.X_OK):
283 tests.append(filename)
287 for dirName, subdirList, fileList
in os.walk(
"."):
288 for fname
in fileList:
290 filename = os.path.abspath(os.path.join(dirName,fname))
291 if os.path.isfile(filename)
and os.access(filename, os.X_OK):
293 tests.append(filename)
297 for dirName, subdirList, fileList
in os.walk(
"."):
298 for fname
in fileList:
300 filename = os.path.abspath(os.path.join(dirName,fname))
301 if os.path.isfile(filename)
and os.access(filename, os.X_OK):
303 tests.append(filename)
306 if cmds[
'test_dir']
is not None:
307 dirs = cmds[
'test_dir'].split()
312 dr = dr.replace(
'\"',
'')
313 dr = dr.replace(
',',
'')
314 for dirName, subdirList, fileList
in os.walk(dr):
315 for fname_cmd
in cmds[
'test_list'].split(
"\n"):
316 fname = fname_cmd.strip().split(
" ")[0]
317 fname_args =
" ".join(fname_cmd.strip().split(
" ")[1:])
318 if fname
not in fileList:
320 filename = os.path.abspath(os.path.join(dirName,fname))
321 if os.path.isfile(filename)
and os.access(filename, os.X_OK):
322 tests.append((filename+
" "+fname_args).strip())
326 log[
'stderr'] =
"No tests found"
330 skipStatus = int(cmds[
'skipped'])
332 cmdargs = [cmds[
'command']]
335 if (cmds[
'command'] ==
'mpiexec' or cmds[
'command'] ==
'mpiexec.hydra' or cmds[
'command'] ==
'mpirun')
and cmds[
'job_name']
is not None:
336 if cmds[
'options']
is None or (cmds[
'options']
is not None and '-bootstrap slurm' not in cmds[
'options']):
338 if cmds[
'fail_tests']
is not None and 'ini_check' in cmds[
'fail_tests']:
341 testDef.logger.verbose_print(
'stdout: ' +
"%s used, but \"-bootstrap slurm\" not in options" % cmds[
'command'])
344 log[
'stderr'] =
"%s used, but \"-bootstrap slurm\" not in options" % cmds[
'command']
347 cmdargs.append(
"-bootstrap-exec-args")
348 cmdargs.append(
"--job-name=%s"%cmds[
'job_name'])
349 elif cmds[
'command'] ==
'srun' and cmds[
'job_name']
is not None:
350 cmdargs.append(
"--job-name")
351 cmdargs.append(cmds[
'job_name'])
353 if cmds[
'options']
is not None:
354 for op
in cmds[
'options'].split():
356 if (cmds[
'command'] ==
'mpiexec' or cmds[
'command'] ==
'mpiexec.hydra' or cmds[
'command'] ==
'mpirun')
and cmds[
'np']
is not None:
357 cmdargs.append(
"-np")
358 cmdargs.append(cmds[
'np'])
359 elif cmds[
'command'] ==
'srun' and cmds[
'np']
is not None:
361 cmdargs.append(cmds[
'np'])
362 if cmds[
'hostfile']
is not None:
363 cmdargs.append(
"-hostfile")
364 cmdargs.append(cmds[
'hostfile'])
366 log[
'testresults'] = []
373 if cmds[
'max_num_tests']
is not None:
374 maxTests = int(cmds[
'max_num_tests'])
379 usedModuleUnload =
False
381 if cmds[
'modules_unload']
is not None:
382 status,stdout,stderr = testDef.modcmd.unloadModules(cmds[
'modules_unload'], testDef)
384 log[
'status'] = status
385 log[
'stderr'] = stderr
388 usedModuleUnload =
True
395 if cmds[
'modules']
is not None:
396 status,stdout,stderr = testDef.modcmd.loadModules(cmds[
'modules'], testDef)
398 log[
'status'] = status
399 log[
'stderr'] = stderr
407 fail_tests = cmds[
'fail_tests']
408 if fail_tests
is not None:
409 fail_tests = [t.strip()
for t
in fail_tests.split(
"\n")]
412 for i,t
in enumerate(fail_tests):
414 if (t2.split(
" ")[0].split(
"/")[-1]+
" "+
" ".join(t2.split(
" ")[1:])).strip() == t.strip():
416 fail_returncodes = cmds[
'fail_returncodes']
417 if fail_returncodes
is not None:
418 fail_returncodes = [int(t.strip())
for t
in fail_returncodes.split(
"\n")]
420 if fail_tests
is None:
421 expected_returncodes = {test:0
for test
in tests}
423 if fail_returncodes
is None:
424 expected_returncodes = {test:(
None if test
in fail_tests
else 0)
for test
in tests}
426 fail_returncodes = {test:rtncode
for test,rtncode
in zip(fail_tests,fail_returncodes)}
427 expected_returncodes = {test:(fail_returncodes[test]
if test
in fail_returncodes
else 0)
for test
in tests}
431 if cmds[
'allocate_cmd']
is not None and cmds[
'deallocate_cmd']
is not None:
433 allocate_cmdargs = shlex.split(cmds[
'allocate_cmd'])
434 _status,_stdout,_stderr,_time = testDef.execmd.execute(cmds, allocate_cmdargs, testDef)
436 log[
'status'] = _status
437 log[
'stderr'] = _stderr
444 if cmds[
'skip_tests']
is not None and (test.split(
" ")[0].split(
'/')[-1]+
" "+
" ".join(test.split(
" ")[1:])).strip()
in [st.strip()
for st
in cmds[
'skip_tests'].split()]:
447 if numTests == maxTests:
450 testLog = {
'test':test}
451 cmdargs.extend(shlex.split(test))
452 testLog[
'cmd'] =
" ".join([
"\"%s\"" % cmdarg
if " " in cmdarg
else cmdarg
for cmdarg
in cmdargs])
454 harass_exec_ids = testDef.harasser.start(testDef)
456 harass_check = testDef.harasser.check(harass_exec_ids, testDef)
457 if harass_check
is not None:
458 testLog[
'stderr'] =
'Not all harasser scripts started. These failed to start: ' \
459 +
','.join([h_info[1][
'start_script']
for h_info
in harass_check[0]])
460 testLog[
'time'] = sum([r_info[3]
for r_info
in harass_check[1]])
461 testLog[
'status'] = 1
463 finalError = testLog[
'stderr']
464 numFail = numFail + 1
465 testDef.harasser.stop(harass_exec_ids, testDef)
468 status,stdout,stderr,time = testDef.execmd.execute(cmds, cmdargs, testDef)
470 testDef.harasser.stop(harass_exec_ids, testDef)
472 if ((expected_returncodes[test]
is None and 0 == status)
or (expected_returncodes[test]
is not None and expected_returncodes[test] != status))
and skipStatus != status
and 0 == finalStatus:
473 if expected_returncodes[test] == 0:
478 if (expected_returncodes[test]
is None and 0 != status)
or (expected_returncodes[test] == status):
479 numPass = numPass + 1
480 elif skipStatus == status:
481 numSkip = numSkip + 1
483 numFail = numFail + 1
484 if expected_returncodes[test] == 0:
485 testLog[
'status'] = status
487 if status == expected_returncodes[test]:
488 testLog[
'status'] = 0
490 testLog[
'status'] = 1
491 testLog[
'stdout'] = stdout
492 testLog[
'stderr'] = stderr
493 testLog[
'time'] = time
494 log[
'testresults'].append(testLog)
495 cmdargs = cmdargs[:-1]
496 numTests = numTests + 1
497 if numTests == maxTests:
501 if cmds[
'allocate_cmd']
is not None and cmds[
'deallocate_cmd']
is not None and self.
allocated:
502 deallocate_cmdargs = shlex.split(cmds[
'deallocate_cmd'])
503 _status,_stdout,_stderr,_time = testDef.execmd.execute(cmds, deallocate_cmdargs, testDef)
505 log[
'status'] = _status
506 log[
'stderr'] = _stderr
511 log[
'status'] = finalStatus
512 log[
'stderr'] = finalError
513 log[
'numTests'] = numTests
514 log[
'numPass'] = numPass
515 log[
'numSkip'] = numSkip
516 log[
'numFail'] = numFail
519 if cmds[
'command'] ==
'srun':
522 num_tasks_per_node =
None
524 if '-n ' in cmds[
'options']:
525 num_tasks = str(cmds[
'options'].split(
'-n ')[1].split(
' ')[0])
526 if '--ntasks=' in cmds[
'options']:
527 num_tasks = str(cmds[
'options'].split(
'--ntasks=')[1].split(
' ')[0])
528 if '-N ' in cmds[
'options']:
529 num_nodes = str(cmds[
'options'].split(
'-N ')[1].split(
' ')[0])
530 if '--nodes=' in cmds[
'options']:
531 num_nodes = str(cmds[
'options'].split(
'--nodes=')[1].split(
' ')[0])
532 if '-w ' in cmds[
'options']:
533 num_nodes = str(len(cmds[
'options'].split(
'-w ')[1].split(
' ')[0].split(
',')))
534 if '--nodelist=' in cmds[
'options']:
535 num_nodes = str(len(cmds[
'options'].split(
'--nodelist=')[1].split(
' ')[0].split(
',')))
536 if '--ntasks-per-node=' in cmds[
'options']:
537 num_tasks_per_node = str(cmds[
'options'].split(
'--ntasks-per-node=')[1].split(
' ')[0])
539 if num_tasks
is not None:
540 log[
'np'] = num_tasks
541 elif num_nodes
is not None and num_tasks_per_node
is not None:
543 log[
'np'] = str(int(num_tasks_per_node)*int(num_nodes))
548 elif cmds[
'command'] ==
'mpiexec' or cmds[
'command'] ==
'mpiexec.hydra' or cmds[
'command'] ==
'mpirun':
551 num_tasks_per_node =
None
553 if '-n ' in cmds[
'options']:
554 num_tasks = str(cmds[
'options'].split(
'-n ')[1].split(
' ')[0])
555 if '-np ' in cmds[
'options']:
556 num_tasks = str(cmds[
'options'].split(
'-np ')[1].split(
' ')[0])
557 if '-hosts ' in cmds[
'options']:
558 num_nodes = str(len(cmds[
'options'].split(
'-hosts ')[1].split(
' ')[0]))
559 if '-ppn ' in cmds[
'options']:
560 num_tasks_per_node = str(cmds[
'options'].split(
'-ppn ')[1].split(
' ')[0])
561 if '-grr ' in cmds[
'options']:
562 num_tasks_per_node = str(cmds[
'options'].split(
'-grr ')[1].split(
' ')[0])
563 if '-perhost ' in cmds[
'options']:
564 num_tasks_per_node = str(cmds[
'options'].split(
'-perhost ')[1].split(
' ')[0])
566 if num_tasks
is not None:
567 log[
'np'] = num_tasks
568 elif num_nodes
is not None and num_tasks_per_node
is not None:
570 log[
'np'] = str(int(num_tasks_per_node)*int(num_nodes))
577 log[
'np'] = cmds[
'np']
583 status,stdout,stderr = testDef.modcmd.unloadModules(cmds[
'modules'], testDef)
585 log[
'status'] = status
586 log[
'stderr'] = stderr
590 status,stdout,stderr = testDef.modcmd.loadModules(cmds[
'modules_unload'], testDef)
592 log[
'status'] = status
593 log[
'stderr'] = stderr
598 os.environ[
'PATH'] = oldbinpath
599 os.environ[
'LD_LIBRARY_PATH'] = oldldlibpath