def getIDs(): """ Get IDs from current request context. IDs are taken from 'id' url parameter. Exceptions for getJobsFromList are handled by callers so they can generate appropriate responses. """ ids = request.args.get('id', default=[]) if ids: return jobmgr.getIDsFromList(ids) else: return []
def main(): # parse arguments parser = argparse.ArgumentParser(description='Get jobs from aCT') parser.add_argument('-a', '--all', action='store_true', help='all jobs that match other criteria') parser.add_argument('-j', '--jobs', default='', help='comma separated list of job IDs or ranges') parser.add_argument( '-f', '--find', default='', help='get only jobs with matching (sub)string in their name') parser.add_argument('-s', '--state', default='', help='get only jobs with certain state') parser.add_argument('-v', '--verbose', action='store_true', help='show more information') parser.add_argument('-p', '--proxy', default=None, help='custom path to proxy certificate') parser.add_argument('-n', '--no-clean', action='store_true', help='do not clean jobs') clicommon.showHelpOnCommandOnly(parser) args = parser.parse_args() # logging logFormat = "[%(asctime)s] [%(filename)s:%(lineno)d] [%(levelname)s] - %(message)s" if args.verbose: logging.basicConfig(format=logFormat, level=logging.DEBUG, stream=sys.stdout) else: logging.basicConfig(format=logFormat, level=logging.DEBUG, filename=os.devnull) # create a list of jobs to work on if args.all: jobs = [] # empty means all jobs elif args.jobs: try: jobs = jobmgr.getIDsFromList(args.jobs) except InvalidJobRangeError as e: print("error: range '{}' is not a valid range".format(e.jobRange)) sys.exit(2) except InvalidJobIDError as e: print("error: ID '{}' is not a valid ID".format(e.jobid)) sys.exit(3) else: print("error: no jobs specified (use -a or -j)") sys.exit(10) # get proxy ID given proxy proxyid = clicommon.getProxyIdFromProxy(args.proxy) # get job info manager = jobmgr.JobManager() try: results = manager.getJobs(proxyid, jobs, args.state, args.find) except TmpConfigurationError: print('error: tmp directory not configured') sys.exit(5) if not results.jobdicts: print('no jobs to get') sys.exit(0) # copy job results dontRemove = [] for result in results.jobdicts: try: if result['dir']: # if there are job results in tmp dst_dirname = os.path.basename(os.path.normpath( result['name'])) dstdir = getLocalDir(dst_dirname) shutil.copytree(result['dir'], dstdir) print('Results stored at: {}'.format(dstdir)) else: raise NoJobDirectoryError(result['dir']) except NoJobDirectoryError as e: print('error: tmp results directory {} does not exist'.format( e.jobdir)) except TargetDirExistsError as e: print('error: job destination {} already exists'.format(e.dstdir)) # don't clean job that could not be removed dontRemove.append(result['id']) # delete jobs that should not be removed from results for jobid in dontRemove: for result in results.jobdicts: if result['id'] == jobid: jobix = results.clientIDs.index(result['id']) del results.clientIDs[jobix] del results.arcIDs[jobix] del results.jobdicts[jobix] # clean jobs if not args.no_clean: manager.forceCleanJobs(results)
def main(): # parse arguments parser = argparse.ArgumentParser(description='Kill jobs') parser.add_argument('-a', '--all', action='store_true', help='all jobs that match other criteria') parser.add_argument('-j', '--jobs', default='', help='comma separated list of job IDs or ranges') parser.add_argument( '-f', '--find', default='', help='get only jobs with matching (sub)string in their name') parser.add_argument('-s', '--state', default='', help='get only jobs with certain state') parser.add_argument('-v', '--verbose', action='store_true', help='show more information') parser.add_argument('-p', '--proxy', default=None, help='custom path to proxy certificate') clicommon.showHelpOnCommandOnly(parser) args = parser.parse_args() # logging logFormat = "[%(asctime)s] [%(filename)s:%(lineno)d] [%(levelname)s] - %(message)s" if args.verbose: logging.basicConfig(format=logFormat, level=logging.DEBUG, stream=sys.stdout) else: logging.basicConfig(format=logFormat, level=logging.DEBUG, filename=os.devnull) # create a list of jobs to work on if args.all: jobs = [] # empty means all jobs elif args.jobs: try: jobs = jobmgr.getIDsFromList(args.jobs) except InvalidJobRangeError as e: print("error: range '{}' is not a valid range".format(e.jobRange)) sys.exit(2) except InvalidJobIDError as e: print("error: ID '{}' is not a valid ID".format(e.jobid)) sys.exit(3) else: print("error: no jobs specified (use -a or -j)") sys.exit(10) # get proxy ID given proxy proxyid = clicommon.getProxyIdFromProxy(args.proxy) # kill jobs manager = jobmgr.JobManager() numKilled = manager.killJobs(proxyid, jobs, args.state, args.find) print('Jobs killed: {}'.format(numKilled))
def main(): # parse arguments parser = argparse.ArgumentParser(description='Get job info from aCT') parser.add_argument('-a', '--all', action='store_true', help='all jobs that match other criteria') parser.add_argument( '-j', '--jobs', default='', help='ID/range(id1-id2;id1<id2)/comma separated list of IDs/ranges') parser.add_argument( '-f', '--find', default='', help='get only jobs with matching (sub)string in their name') parser.add_argument('-s', '--state', default='', help='get only jobs with certain state') parser.add_argument('-n', '--name', default='', help='get only jobs with given name') parser.add_argument('-v', '--verbose', action='store_true', help='show more information') parser.add_argument('-p', '--proxy', default=None, help='custom path to proxy certificate') # arguments passed directly to arccat parser.add_argument('-o', '--stdout', action='store_true', help='show the stdout of the job (default)', default=True) parser.add_argument('-e', '--stderr', action='store_true', help='show the stderr of the job') #parser.add_argument('-l', '--joblog', action='store_true', # help='show A-REX\'s error log of the job') #parser.add_argument('-P', '--listplugins', action='store_true', # help='list the available plugins') #parser.add_argument('-t', '--timeout', type=int, nargs=1, # help='timeout in seconds (default 20)', default=20) clicommon.showHelpOnCommandOnly(parser) args = parser.parse_args() # logging logFormat = "[%(asctime)s] [%(filename)s:%(lineno)d] [%(levelname)s] - %(message)s" if args.verbose: logging.basicConfig(format=logFormat, level=logging.DEBUG, stream=sys.stdout) else: logging.basicConfig(format=logFormat, level=logging.DEBUG, filename=os.devnull) # get column names from database manager = jobmgr.JobManager() # create a list of jobs to work on if args.all: jobs = [] # empty means all jobs elif args.jobs: try: jobs = jobmgr.getIDsFromList(args.jobs) except InvalidJobRangeError as e: print("error: range '{}' is not a valid range".format(e.jobRange)) sys.exit(2) except InvalidJobIDError as e: print("error: ID '{}' is not a valid ID".format(e.jobid)) sys.exit(3) else: print("error: no jobs specified (use -a or -j)") sys.exit(10) proxyid = clicommon.getProxyIdFromProxy(args.proxy) # get ARC job IDs of jobs that match filters try: jobdicts = manager.getJobStats(proxyid, jobs, args.state, args.find, clicols=[], arccols=["JobID", "StdOut", "StdErr"], jobname=args.name) except Exception as e: print('error: {}'.format(str(e))) sys.exit(9) if not jobdicts: # no jobs so just exit print('no jobs found that fit given filters') sys.exit(0) for job in jobdicts: url = job["a_JobID"] + "/" if args.stderr: url += job["a_StdErr"] elif args.stdout: url += job["a_StdOut"] subprocess.run(["arccp", url, "-"])
def main(): # parse arguments parser = argparse.ArgumentParser(description='Get job info from aCT') parser.add_argument('-a', '--all', action='store_true', help='all jobs that match other criteria') parser.add_argument( '-j', '--jobs', default='', help='ID/range(id1-id2;id1<id2)/comma separated list of IDs/ranges') parser.add_argument( '-f', '--find', default='', help='get only jobs with matching (sub)string in their name') parser.add_argument('-s', '--state', default='', help='get only jobs with certain state') parser.add_argument('-v', '--verbose', action='store_true', help='show more information') parser.add_argument('-p', '--proxy', default=None, help='custom path to proxy certificate') parser.add_argument('--arc-cols', default='JobID,State,arcstate', help='columns from ARC table that should be fetched') parser.add_argument( '--client-cols', default='id,jobname', help='columns from client table that should be fetched') parser.add_argument('--get-cols', action='store_true', help='print all available column names') clicommon.showHelpOnCommandOnly(parser) args = parser.parse_args() # logging logFormat = "[%(asctime)s] [%(filename)s:%(lineno)d] [%(levelname)s] - %(message)s" if args.verbose: logging.basicConfig(format=logFormat, level=logging.DEBUG, stream=sys.stdout) else: logging.basicConfig(format=logFormat, level=logging.DEBUG, filename=os.devnull) # get column names from database manager = jobmgr.JobManager() if args.get_cols: clientCols = manager.getClientColumns() arcCols = manager.getArcColumns() print('client cols:', end=' ') for col in clientCols: print(col, end=' ') print() print('arc cols:', end=' ') for col in arcCols: print(col, end=' ') print() sys.exit(0) # create a list of jobs to work on if args.all: jobs = [] # empty means all jobs elif args.jobs: try: jobs = jobmgr.getIDsFromList(args.jobs) except InvalidJobRangeError as e: print("error: range '{}' is not a valid range".format(e.jobRange)) sys.exit(2) except InvalidJobIDError as e: print("error: ID '{}' is not a valid ID".format(e.jobid)) sys.exit(3) else: print("error: no jobs specified (use -a or -j)") sys.exit(10) # create column lists if not args.client_cols: clicols = [] else: clicols = args.client_cols.split(',') if not args.arc_cols: arccols = [] else: arccols = args.arc_cols.split(',') # get proxy ID given proxy proxyid = clicommon.getProxyIdFromProxy(args.proxy) # get information try: jobdicts = manager.getJobStats(proxyid, jobs, args.state, args.find, clicols=clicols, arccols=arccols) except Exception as e: print('error: {}'.format(str(e))) sys.exit(9) if not jobdicts: # no jobs so just exit sys.exit(0) # For each column, determine biggest sized value so that output can # be nicely formatted. colsizes = {} for job in jobdicts: for key, value in job.items(): # All keys have a letter and underscore prepended, which is not # used when printing colsize = max(len(str(key[2:])), len(str(value))) try: if colsize > colsizes[key]: colsizes[key] = colsize except KeyError: colsizes[key] = colsize # Print table header for col in clicols: print('{:<{width}}'.format(col, width=colsizes['c_' + col]), end=' ') for col in arccols: print('{:<{width}}'.format(col, width=colsizes['a_' + col]), end=' ') print() line = '' for value in colsizes.values(): line += '-' * value line += '-' * (len(colsizes) - 1) print(line) # Print jobs for job in jobdicts: for col in clicols: fullKey = 'c_' + col txt = job.get(fullKey) # just in case the value is a bunch of whitespace # TODO: This (str(txt)) might not be a general fix; it is a direct # fix for the problem encountered with # datetime.datetime object for 'created' field that # has to be converted to a string. # The same fix is used for arccols below. # TODO: This fix assumes that all job fields are properly # convertible to string. Is that really so? if not txt or str(txt).strip() == '': # short circuit important! txt = "''" print('{:<{width}}'.format(txt, width=colsizes[fullKey]), end=' ') for col in arccols: fullKey = 'a_' + col txt = job.get(fullKey) # just in case the value is a bunch of whitespace if not txt or str(txt).strip() == '': # short circuit important! txt = "''" print('{:<{width}}'.format(str(txt), width=colsizes[fullKey]), end=' ') print()