def _qstat(jobid=None, username=getlogin(), full=False): """Return the stdout of ``qstat`` minus the header lines. By default, 'username' is set to the current user. 'full' is the '-f' option 'jobid' is a string or list of strings of job ids Returns: str: the text of qstat, minus the header lines """ # -u and -f contradict in earlier versions of Torque if full and username is not None and int( torque_version.split(".")[0]) < 5 and jobid is None: # First get all jobs by the user qopt = ["qselect"] qopt += ["-u", username] # Call 'qselect' using subprocess stdout = run(qopt)[0] # Get the jobids jobid = [] for line in StringIO(stdout): jobid += [line.rstrip("\n")] opt = ["qstat"] # If there are jobid(s), you don't need a username if username is not None and jobid is None: opt += ["-u", username] # But if there are jobid(s) and a username, you need -a to get full output elif username is not None and jobid is not None and not full: opt += ["-a"] # By this point we're guaranteed torque ver >= 5.0, so -u and -f are safe together if full: opt += ["-f"] if jobid is not None: if isinstance(jobid, string_types): jobid = [jobid] elif isinstance(jobid, list): pass else: print( "Error in prisms_jobs.interface.torque.qstat(). type(jobid):", type(jobid)) sys.exit() opt += jobid # call 'qstat' using subprocess stdout, stderr, returncode = run(opt) #pylint: disable=unused-variable sout = StringIO(stdout) # strip the header lines if full is False: for line in sout: if line[0] == "-": break # return the remaining text return sout.read()
def submit(substr, write_submit_script=None): """Submit a job using ``sbatch``. Args: substr (str): The submit script string write_submit_script (bool, optional): If true, submit via file skipping lines containing '#SBATCH -J'; otherwise, submit via commandline. If not specified, uses ``prisms_jobs.config['write_submit_script']``. Returns: str: ID of submitted job Raises: JobsError: If a submission error occurs """ m = re.search(r"#SBATCH\s+-J\s+(.*)\s", substr) #pylint: disable=invalid-name if m: jobname = m.group(1) #pylint: disable=unused-variable else: raise JobsError( None, r"""Error in pbs.misc.submit(). Jobname ("#SBATCH\s+-J\s+(.*)\s") not found in submit string.""" ) # if write_submit_script is None: # write_submit_script = prisms_jobs.config(['write_submit_script']) if write_submit_script: if os.path.exists(jobname): index = 0 while os.path.exists(jobname + ".bak." + str(index)): index += 1 print("Backing up existing submit script:", jobname, "->", jobname + ".bak." + str(index)) os.rename(jobname, jobname + ".bak." + str(index)) # write submit script, without -N line with open(jobname, 'w') as f: for line in substr.splitlines(): if not re.search(r"SBATCH\s+-J\s+(.*)", line): f.write(line + '\n') stdout, stderr, returncode = run(["sbatch", jobname]) #pylint: disable=unused-variable else: stdout, stderr, returncode = run(["sbatch"], input=substr, stdin=subprocess.PIPE) #pylint: disable=unused-variable print(stdout[:-1]) if re.search("error", stdout): print(stdout) raise JobsError(0, "Submission error.\n") else: jobid = stdout.rstrip().split()[-1] return jobid
def alter(jobid, arg): """``scontrol`` update job. Args: jobid (str): ID of job to alter arg (str): 'arg' is a scontrol command option string. For instance, "-a 201403152300.19" Returns: int: ``scontrol`` returncode """ return run(["scontrol", "update", "JobId=", jobid] + arg.split())[2]
def release(jobid): """``scontrol`` un-delay a job. Args: jobid (str): ID of job to release Returns: int: ``scontrol`` returncode """ return run(["scontrol", "update", "JobId=", jobid, "StartTime=", "now"])[2]
def delete(jobid): """``scancel`` a job. Args: jobid (str): ID of job to cancel Returns: int: ``scancel`` returncode """ return run(["scancel", jobid])[2]
def _getversion(): """Returns the torque version as string or None if no ``qstat`` """ if find_executable("qstat") is None: return None opt = ["qstat", "--version"] # call 'qstat' using subprocess stdout = run(opt)[0] # return the version number return stdout.rstrip("\n").lower().lstrip("version: ")
def hold(jobid): """``scontrol`` delay a job. Args: jobid (str): ID of job to delay (for 30days) Returns: int: ``scontrol`` returncode """ return run( ["scontrol", "update", "JobId=", jobid, "StartTime=", "now+30days"])[2]
def alter(jobid, arg): """``qalter`` a job. Args: jobid (str): ID of job to alter arg (str): 'arg' is a scontrol command option string. For instance, "-a 201403152300.19" Returns: int: ``qalter`` returncode """ stdout, stderr, returncode = run(["qalter"] + arg.split() + [jobid]) #pylint: disable=unused-variable return returncode
def release(jobid): """``qrls`` a job. Args: jobid (str): ID of job to release Returns: int: ``qrls`` returncode """ stdout, stderr, returncode = run(["qrls", jobid]) #pylint: disable=unused-variable return returncode
def hold(jobid): """``qhold`` a job. Args: jobid (str): ID of job to hold Returns: int: ``qhold`` returncode """ stdout, stderr, returncode = run(["qhold", jobid]) #pylint: disable=unused-variable return returncode
def delete(jobid): """``qdel`` a PBS job. Args: jobid (str): ID of job to delete Returns: int: ``qdel`` returncode """ stdout, stderr, returncode = run(["qdel", jobid]) #pylint: disable=unused-variable return returncode
def _squeue(jobid=None, username=getlogin(), full=False, sformat=None): #pylint: disable=unused-argument """Return the stdout of squeue minus the header lines. By default, 'username' is set to the current user. 'full' is the '-f' option 'jobid' is a string or list of strings of job ids 'sformat' is a squeue format string (e.g., "%A %i %j %c") Returns: str: the text of squeue, minus the header lines """ # If Full is true, we need to use scontrol: if full is True: if jobid is None: if username is None: # Clearly we want ALL THE JOBS sopt = ["scontrol", "show", "job"] # Submit the command # Nothing to strip, as scontrol provides no headers return run(sopt)[0] else: # First, get jobids that belong to that username using # squeue (-h strips the header) sopt = ["squeue", "-h", "-u", username] qsout = run(sopt)[0] # Get the jobids jobid = [] for line in StringIO(qsout): jobid += [line.rstrip("\n")] # Great, now we have some jobids to pass along # Ensure the jobids are a list, even if they're a list of 1... if not isinstance(jobid, list) and jobid is not None: jobid = [jobid] if isinstance(jobid, list): opt = ["scontrol", "show", "job"] sreturn = "" for my_id in jobid: sopt = opt + [str(my_id)] sreturn = sreturn + run(sopt)[0] + "\n" return sreturn else: sopt = ["squeue", "-h"] if username is not None: sopt += ["-u", username] if jobid is not None: sopt += ["--job="] if isinstance(jobid, list): sopt += ["'" + ",".join([str(i) for i in jobid]) + "'"] else: sopt += [str(jobid)] if sformat is not None: sopt += ["-o", "'" + sformat + "'"] else: if jobid is None and username is None: sopt += ["-o", "'%i %u %P %j %U %D %C %m %l %t %M'"] else: sopt += ["-o", "'%i %j %u %M %t %P'"] return run(sopt)[0]