1#!/usr/local/bin/python3.8 2# -*- coding: utf-8 -*- 3 4#------------------------------------------------------------------------------- 5 6# This file is part of Code_Saturne, a general-purpose CFD tool. 7# 8# Copyright (C) 1998-2021 EDF S.A. 9# 10# This program is free software; you can redistribute it and/or modify it under 11# the terms of the GNU General Public License as published by the Free Software 12# Foundation; either version 2 of the License, or (at your option) any later 13# version. 14# 15# This program is distributed in the hope that it will be useful, but WITHOUT 16# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 18# details. 19# 20# You should have received a copy of the GNU General Public License along with 21# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin 22# Street, Fifth Floor, Boston, MA 02110-1301, USA. 23 24#------------------------------------------------------------------------------- 25 26import configparser 27 28import sys 29import os, os.path, shutil, sys, string, types, re, subprocess 30 31#=============================================================================== 32# Utility functions 33#=============================================================================== 34 35def parse_wall_time_slurm(s): 36 """ 37 Parse SLURM wall time 38 """ 39 t = None 40 41 wt0 = s.split('-') 42 if len(wt0) == 2: 43 th = int(wt0[0])*3600*24 44 wt = wt0[1].split(':') 45 else: 46 th = 0 47 wt = wt0[0].split(':') 48 if len(wt) == 3: 49 t = th + int(wt[0])*3600 + int(wt[1])*60 + int(wt[2]) 50 elif len(wt) == 2: 51 if len(wt0) == 2: 52 t = th + int(wt[0])*3600 + int(wt[1])*60 53 else: 54 t = th + int(wt[0])*60 + int(wt[1]) 55 elif len(wt) == 1: 56 if len(wt0) == 2: 57 t = th + int(wt[0])*3600 58 else: 59 try: 60 t = th + int(wt[0])*60 61 except Exception: 62 pass 63 64 return t 65 66#------------------------------------------------------------------------------- 67 68def generate_header(batch_template=None, job_name=None, package=None): 69 """ 70 Generate batch header lines based on batch template configuration 71 """ 72 73 lines = [] 74 75 if not package: 76 from code_saturne import cs_package 77 package = cs_package.package() 78 79 if not batch_template: 80 config = configparser.ConfigParser() 81 config.read(package.get_configfiles()) 82 if config.has_option('install', 'batch'): 83 batch_template = config.get('install', 'batch') 84 85 if not batch_template: 86 return lines 87 88 if not job_name: 89 job_name = package.name + ':' + os.path.basename(os.getcwd()) 90 91 # For some systems, name lengths may be limited. 92 # With SLURM 18.08, the max. length seems to be 37 characters. 93 job_name = job_name[:38] 94 95 if not os.path.isabs(batch_template): 96 batch_template = os.path.join(package.get_batchdir(), 97 'batch.' + batch_template) 98 99 fdt = open(batch_template, 'r') 100 101 import re, string 102 kwd1 = re.compile('nameandcase') 103 104 # Determine or build default names if required 105 106 for line in fdt: 107 line = line.rstrip() 108 line = re.sub(kwd1, job_name, line) 109 lines.append(line) 110 111 fdt.close() 112 113 return lines 114 115#=============================================================================== 116# Class used to manage batch directives 117#=============================================================================== 118 119#------------------------------------------------------------------------------- 120 121class batch: 122 """ 123 Parse and modify special batch options in text file lines 124 """ 125 126 #--------------------------------------------------------------------------- 127 128 def __init__(self, package, install_config=None): 129 """ 130 Constructor. 131 """ 132 133 self.rm_type = None 134 135 self.submit_cmd = '' 136 137 self.params = {} 138 139 self.params['job_name'] = None 140 self.params['job_nodes'] = None 141 self.params['job_ppn'] = None 142 self.params['job_procs'] = None 143 self.params['job_threads'] = None 144 self.params['job_walltime'] = None 145 self.params['job_class'] = None 146 self.params['job_account'] = None 147 self.params['job_wckey'] = None 148 149 # Are we using a resource manager ? 150 151 self.rm_type = None 152 self.rm_template = None 153 self.submit_command = '' 154 155 submit_command = None 156 157 if install_config: 158 self.rm_template = install_config['batch'] 159 160 elif package: 161 config = configparser.ConfigParser() 162 config.read(package.get_configfiles()) 163 164 if config.has_option('install', 'batch'): 165 self.rm_template = config.get('install', 'batch') 166 if os.path.isabs(self.rm_template): 167 i = self.rm_template.rfind(".") 168 if i > -1: 169 self.rm_template = self.rm_template[i+1:] 170 171 if config.has_option('install', 'submit_command'): 172 submit_command = config.get('install', 'submit_command') 173 174 if self.rm_template: 175 if self.rm_template[0:5] == 'SLURM': 176 self.rm_type = 'SLURM' 177 self.submit_command = 'sbatch' 178 for k in ('SBATCH_WCKEY', 'SLURM_WCKEY'): 179 if k in os.environ: 180 v = os.environ[k] 181 if v: 182 self.params['job_wckey'] = v 183 elif self.rm_template[0:3] == 'CCC': 184 self.rm_type = 'CCC' 185 self.submit_command = 'ccc_msub' 186 elif self.rm_template[0:3] == 'LSF': 187 self.rm_type = 'LSF' 188 self.submit_command = 'bsub' 189 elif self.rm_template[0:3] == 'OAR': 190 self.rm_type = 'OAR' 191 self.submit_command = 'oarsub' 192 elif self.rm_template[0:3] == 'PBS': 193 self.rm_type = 'PBS' 194 self.submit_command = 'qsub' 195 elif self.rm_template[0:3] == 'SGE': 196 self.rm_type = 'SGE' 197 self.submit_command = 'qsub' 198 else: 199 self.rm_type = os.path.basename(rm_template) 200 201 if submit_command: 202 self.submit_command = submit_command 203 204 #--------------------------------------------------------------------------- 205 206 def __get_command_output__(self, cmd): 207 """ 208 Run a command and return it's standard output. 209 """ 210 p = subprocess.Popen(cmd, 211 shell=True, 212 stdout=subprocess.PIPE, 213 stderr=subprocess.PIPE, 214 universal_newlines=True) 215 lines = [] 216 while True: 217 l = p.stdout.readline() 218 lines.append(l.strip()) 219 if len(l) == 0 and p.poll() != None: 220 break 221 output = p.communicate() 222 223 if p.returncode == 0: 224 return lines 225 else: 226 print(output[1]) 227 return [] 228 229 #--------------------------------------------------------------------------- 230 231 def __pre_parse__(self, s): 232 """ 233 Pre-parse batch line 234 """ 235 r = ' ' 236 i = s.find('#') 237 if i > -1: 238 s = s[:i] 239 s = r.join(s.split()) 240 241 return s 242 243 #--------------------------------------------------------------------------- 244 245 def __parse_lines_env_vars__(self, lines): 246 """ 247 Parse environment variables in batch file lines 248 """ 249 batch_lines = lines 250 251 for i in range(len(batch_lines)): 252 j = batch_lines[i].find('#') 253 if j > -1: 254 toks = batch_lines[i][:j].split() 255 else: 256 toks = batch_lines[i].split() 257 if len(toks) > 1: 258 var = None 259 val = None 260 if toks[0] in ('set', 'export'): 261 k = toks[1].find('=') 262 if k > 1: 263 var = toks[1][0:k] 264 val = toks[1][k+1:] 265 elif toks[0] in ('setenv'): 266 if len(toks) > 2: 267 var = toks[1] 268 val = toks[2] 269 if var == 'OMP_NUM_THREADS': 270 try: 271 self.params['job_threads'] = int(val) 272 except Exception: 273 pass 274 275 #--------------------------------------------------------------------------- 276 277 def __update_lines_env_vars__(self, lines): 278 """ 279 Update environment variables in batch file lines 280 """ 281 if lines: 282 batch_lines = lines 283 284 for i in range(len(batch_lines)): 285 j = batch_lines[i].find('#') 286 if j > -1: 287 toks = batch_lines[i][:j].split() 288 else: 289 toks = batch_lines[i].split() 290 if len(toks) > 1: 291 var = None 292 val = None 293 if toks[0] in ('set', 'export'): 294 k = toks[1].find('=') 295 if k > 1: 296 var = toks[1][0:k] 297 val = toks[1][k+1:] 298 elif toks[0] in ('setenv'): 299 if len(toks) > 2: 300 var = toks[1] 301 val = toks[2] 302 if var == 'OMP_NUM_THREADS' and self.params['job_threads']: 303 s_threads = str(self.params['job_threads']) 304 if toks[0] in ('set', 'export'): 305 s = toks[0] + ' ' + var + '=' + s_threads 306 elif toks[0] in ('setenv'): 307 s = toks[0] + ' ' + var + ' ' + s_threads 308 if j > 1: 309 s += ' ' + batch_lines[i][j:] 310 batch_lines[i] = s 311 312 #--------------------------------------------------------------------------- 313 314 def __parse_lines_slurm__(self, lines): 315 """ 316 Parse SLURM batch file lines 317 """ 318 batch_lines = lines 319 320 for i in range(len(batch_lines)): 321 if batch_lines[i][0:7] == '#SBATCH': 322 batch_args = self.__pre_parse__(batch_lines[i][7:]) 323 if batch_args[0:2] == '--': 324 tok = batch_args.split('=') 325 if len(tok) < 2: 326 continue 327 kw = tok[0] + '=' 328 val = tok[1].split(',')[0].strip() 329 elif batch_args[0] == '-': 330 kw = batch_args[0:2] 331 val = batch_args[2:].split(',')[0].strip() 332 else: 333 continue 334 if kw == '--job-name=' or kw == '-J': 335 self.params['job_name'] = val 336 elif kw == '--ntasks=' or kw == '-n': 337 self.params['job_procs'] = val 338 elif kw == '--nodes=' or kw == '-N': 339 self.params['job_nodes'] = val 340 elif kw == '--ntasks-per-node=': 341 self.params['job_ppn'] = val 342 elif kw == '--cpus-per-task=': 343 self.params['job_threads'] = val 344 elif kw == '--time=' or kw == '-t': 345 self.params['job_walltime'] = parse_wall_time_slurm(val) 346 elif kw == '--partition=' or kw == '-p': 347 self.params['job_class'] = val 348 elif kw == '--account=' or kw == '-A': 349 self.params['job_account'] = val 350 elif kw == '--wckey=': 351 self.params['job_wckey'] = val 352 353 #--------------------------------------------------------------------------- 354 355 def __update_lines_slurm__(self, lines): 356 """ 357 Update the SLURM batch file from dictionary self.params. 358 """ 359 batch_lines = lines 360 361 for i in range(len(batch_lines)): 362 if batch_lines[i][0:7] == '#SBATCH': 363 batch_args = self.__pre_parse__(batch_lines[i][7:]) 364 if batch_args[0:2] == '--': 365 tok = batch_args.split('=') 366 if len(tok) < 2: 367 continue 368 kw = tok[0] + '=' 369 val = tok[1].split(',')[0].strip() 370 elif batch_args[0] == '-': 371 kw = batch_args[0:2] 372 val = batch_args[2:].split(',')[0].strip() 373 if kw == '--job-name=' or kw == '-J': 374 val = str(self.params['job_name']) 375 elif kw == '--ntasks=' or kw == '-n': 376 val = str(self.params['job_procs']) 377 elif kw == '--nodes=' or kw == '-N': 378 val = str(self.params['job_nodes']) 379 elif kw == '--ntasks-per-node=': 380 val = self.params['job_ppn'] 381 elif kw == '--cpus-per-task=': 382 val = self.params['job_threads'] 383 elif kw == '--time=' or kw == '-t': 384 wt = self.params['job_walltime'] 385 if wt > 86400: # 3600*24 386 val = '%d-%d:%02d:%02d' % (wt//86400, 387 (wt%86400)//3600, 388 (wt%3600)//60, 389 wt%60) 390 else: 391 val = '%d:%02d:%02d' % (wt//3600, 392 (wt%3600)//60, 393 wt%60) 394 elif kw == '--partition=' or kw == '-p': 395 val = self.params['job_class'] 396 elif kw == '--account=' or kw == '-A': 397 val = self.params['job_account'] 398 elif kw == '--wckey=': 399 val = self.params['job_wckey'] 400 else: 401 continue 402 batch_lines[i] = '#SBATCH ' + kw + str(val) 403 404 #--------------------------------------------------------------------------- 405 406 def __parse_lines_ccc__(self, lines): 407 """ 408 Parse CCC (CCRT) batch file lines 409 """ 410 batch_lines = lines 411 412 for i in range(len(batch_lines)): 413 if batch_lines[i][0:5] == '#MSUB': 414 batch_args = self.__pre_parse__(batch_lines[i][5:]) 415 tok = batch_args.split() 416 if len(tok) < 2: 417 continue 418 kw = tok[0] 419 val = tok[1].split(',')[0].strip() 420 if kw == '-r': 421 self.params['job_name'] = val 422 elif kw == '-n': 423 self.params['job_procs'] = int(val) 424 elif kw == '-N': 425 self.params['job_nodes'] = int(val) 426 elif kw == '-T': 427 self.params['job_walltime'] = int(val) 428 elif kw == '-q': 429 self.params['job_class'] = val 430 431 #--------------------------------------------------------------------------- 432 433 def __update_lines_ccc__(self, lines): 434 """ 435 Update the Platform LSF batch file lines 436 """ 437 batch_lines = lines 438 439 for i in range(len(batch_lines)): 440 if batch_lines[i][0:5] == '#MSUB': 441 batch_args = self.__pre_parse__(batch_lines[i][5:]) 442 tok = batch_args.split() 443 if len(tok) < 2: 444 continue 445 kw = tok[0] 446 if kw == '-r': 447 val = str(self.params['job_name']) 448 elif kw == '-n': 449 val = str(self.params['job_procs']) 450 elif kw == '-N': 451 val = str(self.params['job_nodes']) 452 elif kw == '-T': 453 val = str(self.params['job_walltime']) 454 elif kw == '-q': 455 val = self.params['job_class'] 456 else: 457 continue 458 batch_lines[i] = '#MSUB ' + kw + ' ' + str(val) 459 460 #--------------------------------------------------------------------------- 461 462 def __parse_lines_lsf__(self, lines): 463 """ 464 Parse Platform LSF batch file lines 465 """ 466 batch_lines = lines 467 468 for i in range(len(batch_lines)): 469 if batch_lines[i][0:5] == '#BSUB': 470 batch_args = self.__pre_parse__(batch_lines[i][5:]) 471 tok = batch_args.split() 472 kw = tok[0] 473 val = tok[1].split(',')[0].strip() 474 if kw == '-J': 475 self.params['job_name'] = val 476 elif kw == '-n': 477 self.params['job_procs'] = int(val) 478 elif kw == '-W' or kw == '-wt' or kw == '-We': 479 wt = val.split(':') 480 if len(wt) == 1: 481 self.params['job_walltime'] = int(wt[0])*60 482 elif len(wt) == 2: 483 self.params['job_walltime'] \ 484 = int(wt[0])*3600 + int(wt[1])*60 485 elif kw == '-q': 486 self.params['job_class'] = val 487 488 #--------------------------------------------------------------------------- 489 490 def __update_lines_lsf__(self, lines): 491 """ 492 Update the Platform LSF batch file lines 493 """ 494 batch_lines = lines 495 496 for i in range(len(batch_lines)): 497 if batch_lines[i][0:5] == '#BSUB': 498 batch_args = self.__pre_parse__(batch_lines[i][5:]) 499 tok = batch_args.split() 500 kw = tok[0] 501 if kw == '-J': 502 val = str(self.params['job_name']) 503 elif kw == '-n': 504 val = str(self.params['job_procs']) 505 elif kw == '-W' or kw == '-wt' or kw == '-We': 506 wt = self.params['job_walltime'] 507 val = '%d:%02d' % (wt//3600, (wt%3600)//60) 508 elif kw == '-q': 509 val = self.params['job_class'] 510 else: 511 continue 512 batch_lines[i] = '#BSUB ' + kw + ' ' + str(val) 513 514 #--------------------------------------------------------------------------- 515 516 def __parse_lines_pbs__(self, lines): 517 """ 518 Parse PBS batch file lines 519 """ 520 batch_lines = lines 521 522 # TODO: specialize for PBS Professional and TORQUE (OpenPBS has not been 523 # maintained since 2004, so we do not support it). 524 # The "-l nodes=N:ppn=P" syntax is common to all PBS variants, 525 # but PBS Pro considers the syntax depecated, and prefers its 526 # own "-l select=N:ncpus=P:mpiprocs=P" syntax. 527 # We do not have access to a PBS Professional system, but according to 528 # its documentation, it has commands such as "pbs-report" or "pbs_probe" 529 # which are not part of TORQUE, while the latter has "pbsnodelist" or 530 # #pbs-config". The presence of either could help determine which 531 # system is available. 532 533 for i in range(len(batch_lines)): 534 if batch_lines[i][0:4] == '#PBS': 535 batch_args = ' ' + self.__pre_parse__(batch_lines[i][4:]) 536 index = batch_args.rfind(' -') 537 while index > -1: 538 arg = batch_args[index+1:] 539 batch_args = batch_args[0:index] 540 if arg[0:2] == '-N': 541 self.params['job_name'] = arg.split()[1] 542 elif arg[0:9] == '-l nodes=': 543 arg_tmp = arg[9:].split(':') 544 self.params['job_nodes'] = arg_tmp[0] 545 for s in arg_tmp[1:]: 546 j = s.find('ppn=') 547 if j > -1: 548 self.params['job_ppn'] \ 549 = s[j:].split('=')[1] 550 elif arg[0:10] == '-l select=': 551 arg_tmp = arg[10:].split(':') 552 self.params['job_nodes'] = arg_tmp[0] 553 for s in arg_tmp[1:]: 554 j = s.find('ncpus=') 555 if j > -1: 556 self.params['job_ppn'] \ 557 = s[j:].split('=')[1] 558 elif arg[0:12] == '-l walltime=': 559 wt = (arg.split('=')[1]).split(':') 560 if len(wt) == 3: 561 self.params['job_walltime'] \ 562 = int(wt[0])*3600 + int(wt[1])*60 + int(wt[2]) 563 elif len(wt) == 2: 564 self.params['job_walltime'] \ 565 = int(wt[0])*60 + int(wt[1]) 566 elif len(wt) == 1: 567 self.params['job_walltime'] \ 568 = int(wt[0]) 569 elif arg[0:2] == '-q': 570 self.params['job_class'] = arg.split()[1] 571 index = batch_args.rfind(' -') 572 573 #--------------------------------------------------------------------------- 574 575 def __update_lines_pbs__(self, lines): 576 """ 577 Update the PBS batch file from dictionary self.params. 578 """ 579 batch_lines = lines 580 581 for i in range(len(batch_lines)): 582 if batch_lines[i][0:4] == '#PBS': 583 ch = '' 584 batch_args = ' ' + self.__pre_parse__(batch_lines[i][4:]) 585 index = batch_args.rfind(' -') 586 while index > -1: 587 arg = batch_args[index+1:] 588 batch_args = batch_args[0:index] 589 if arg[0:2] == '-N': 590 ch = ' -N ' + self.params['job_name'] + ch 591 elif arg[0:9] == '-l nodes=': 592 arg_tmp = arg[9:].split(':') 593 ch1 = ' -l nodes=' + self.params['job_nodes'] 594 for s in arg_tmp[1:]: 595 j = s.find('ppn=') 596 if j > -1: 597 ch1 += ':' + s[0:j] \ 598 + 'ppn=' + self.params['job_ppn'] 599 else: 600 ch1 += ':' + s 601 ch = ch1 + ch 602 elif arg[0:10] == '-l select=': 603 arg_tmp = arg[10:].split(':') 604 ch1 = ' -l select=' + self.params['job_nodes'] 605 for s in arg_tmp[1:]: 606 j = s.find('ncpus=') 607 if j > -1: 608 ch1 += ':' + s[0:j] \ 609 + 'ncpus=' + self.params['job_ppn'] 610 else: 611 ch1 += ':' + s 612 ch = ch1 + ch 613 elif arg[0:12] == '-l walltime=': 614 wt = self.params['job_walltime'] 615 s_wt = '%d:%02d:%02d' % (wt//3600, 616 (wt%3600)//60, 617 wt%60) 618 ch = ' -l walltime=' + s_wt + ch 619 elif arg[0:2] == '-q': 620 ch = ' -q ' + self.params['job_class'] + ch 621 else: 622 ch = ' ' + arg + ch 623 index = batch_args.rfind(' -') 624 ch = '#PBS' + ch 625 batch_lines[i] = ch 626 627 #--------------------------------------------------------------------------- 628 629 def __parse_lines_sge__(self, lines): 630 """ 631 Parse Sun Grid Engine batch file lines 632 """ 633 batch_lines = lines 634 635 for i in range(len(batch_lines)): 636 if batch_lines[i][0:2] == '#$': 637 batch_args = ' ' + self.__pre_parse__(batch_lines[i][2:]) 638 index = batch_args.rfind(' -') 639 while index > -1: 640 arg = batch_args[index+1:] 641 batch_args = batch_args[0:index] 642 if arg[0:2] == '-N': 643 self.params['job_name'] = arg.split()[1] 644 elif arg[0:3] == '-pe': 645 try: 646 arg_tmp = arg[3:].split(' ') 647 self.params['job_procs'] = arg_tmp[2] 648 except Exception: 649 pass 650 elif arg[0:8] == '-l h_rt=': 651 wt = (arg.split('=')[1]).split(':') 652 if len(wt) == 3: 653 self.params['job_walltime'] \ 654 = int(wt[0])*3600 + int(wt[1])*60 + int(wt[2]) 655 elif len(wt) == 2: 656 self.params['job_walltime'] \ 657 = int(wt[0])*60 + int(wt[1]) 658 elif len(wt) == 1: 659 self.params['job_walltime'] = int(wt[0]) 660 elif arg[0:2] == '-q': 661 self.params['job_class'] = arg.split()[1] 662 index = batch_args.rfind(' -') 663 664 #--------------------------------------------------------------------------- 665 666 def __update_lines_sge__(self, lines): 667 """ 668 Update the Sun Grid Engine batch file lines 669 """ 670 batch_lines = lines 671 672 for i in range(len(batch_lines)): 673 if batch_lines[i][0:2] == '#$': 674 ch = '' 675 batch_args = ' ' + self.__pre_parse__(batch_lines[i][2:]) 676 index = batch_args.rfind(' -') 677 while index > -1: 678 arg = batch_args[index+1:] 679 batch_args = batch_args[0:index] 680 if arg[0:2] == '-N': 681 ch = ' -N ' + self.params['job_name'] + ch 682 elif arg[0:3] == '-pe': 683 try: 684 arg_tmp = arg[3:].split(' ') 685 ch = ' -pe ' + arg_tmp[1] + ' ' \ 686 + str(self.params['job_procs']) + ch 687 except Exception: 688 pass 689 elif arg[0:8] == '-l h_rt=': 690 wt = self.params['job_walltime'] 691 s_wt = '%d:%02d:%02d' % (wt//3600, 692 (wt%3600)//60, 693 wt%60) 694 ch = ' -l h_rt=' + s_wt + ch 695 elif arg[0:2] == '-q': 696 ch = ' -q ' + self.params['job_class'] + ch 697 else: 698 ch = ' ' + arg + ch 699 index = batch_args.rfind(' -') 700 ch = '#$' + ch 701 batch_lines[i] = ch 702 703 #--------------------------------------------------------------------------- 704 705 def parse_lines(self, lines): 706 """ 707 Fill self.params reading the job file. 708 """ 709 710 if self.rm_type: 711 if self.rm_type == 'SLURM': 712 self.__parse_lines_slurm__(lines) 713 elif self.rm_type == 'CCC': 714 self.__parse_lines_ccc__(lines) 715 elif self.rm_type == 'LSF': 716 self.__parse_lines_lsf__(lines) 717 elif self.rm_type == 'PBS': 718 self.__parse_lines_pbs__(lines) 719 elif self.rm_type == 'SGE': 720 self.__parse_lines_sge__(lines) 721 722 self.__parse_lines_env_vars__(lines) 723 724 #--------------------------------------------------------------------------- 725 726 def update_lines(self, lines, keyword=None): 727 """ 728 Update the batch file from reading dictionary self.params. 729 If a keyword is given, its presence is checked. 730 """ 731 732 if keyword != None: 733 if keyword not in self.params: 734 msg = str(keyword) + " is not in list " \ 735 + str(list(self.params.keys())) + os.linesep 736 raise ValueError(msg) 737 738 if self.rm_type: 739 if self.rm_type == 'SLURM': 740 self.__update_lines_slurm__(lines) 741 elif self.rm_type == 'CCC': 742 self.__update_lines_ccc__(lines) 743 elif self.rm_type == 'LSF': 744 self.__update_lines_lsf__(lines) 745 elif self.rm_type == 'PBS': 746 self.__update_lines_pbs__(lines) 747 elif self.rm_type == 'SGE': 748 self.__update_lines_sge__(lines) 749 750 self.__update_lines_env_vars__(lines) 751 752 #--------------------------------------------------------------------------- 753 754 def submit_command_prefix(self): 755 """ 756 Return the command prefix used to submit a job. 757 """ 758 759 return self.submit_command + ' ' 760 761 #--------------------------------------------------------------------------- 762 763 def get_class_list(self): 764 """ 765 Return the list of available classes 766 """ 767 768 class_list = [] 769 770 try: 771 772 rm_type = self.rm_type 773 774 if rm_type == 'SLURM': 775 output = self.__get_command_output__('sinfo -s') 776 for l in output[1:]: 777 if len(l) == 0: 778 break 779 else: 780 name = l.split(' ')[0] 781 if name[-1:] == '*': 782 name = name[:-1] 783 class_list.append(name) 784 785 elif rm_type == 'CCC': 786 output = self.__get_command_output__('class') 787 for l in output[1:]: 788 if len(l) == 0: 789 break 790 else: 791 class_list.append(l.split(' ')[0]) 792 793 elif rm_type == 'LSF': 794 output = self.__get_command_output__('bqueues') 795 ignore = True 796 for l in output[1:]: 797 if len(l) == 0: 798 break 799 else: 800 class_list.append(l.split(' ')[0]) 801 802 elif rm_type == 'PBS': 803 output = self.__get_command_output__('qstat -q') 804 ignore = True 805 for l in output: 806 if l[0:3] == '---': 807 ignore = not ignore 808 elif ignore == False: 809 class_list.append(l.split(' ')[0]) 810 811 elif self.case['batch_type'][0:3] == 'SGE': 812 output = self.__get_command_output__('qconf -sc') 813 for l in output: 814 if l[0:1] != '#': 815 class_list.append(l.split(' ')[0]) 816 817 except Exception: 818 import traceback 819 exc_info = sys.exc_info() 820 bt = traceback.format_exception(*exc_info) 821 print(bt) 822 pass 823 824 return class_list 825 826#------------------------------------------------------------------------------- 827# End 828#------------------------------------------------------------------------------- 829 830