def getSite4Region(self, regions): regs = None if utils.isValid(regions): rgs = utils.parseArray(regions) regs = [] for r in rgs: regs += self._site4regions[r] return regs
def __init__(self,name=None,parent=None,obj=None): pmModule.__init__(self,name,parent,obj) self._jobstates = utils.jobStates self._lstates = len(self._jobstates) actIndex = utils.name2Index(self._jobstates,'activated')+1 canIndex = utils.name2Index(self._jobstates,'cancelled')+1 self._jobsFactoryStates = utils.parseArray(self._jobstates[:actIndex]) self._jobsWNStates = utils.parseArray(self._jobstates[actIndex:canIndex-1]) self._jobsCaneledStates = utils.parseArray(self._jobstates[canIndex:]) shift = 1 self._shift = shift self._ifailed = utils.name2Index(self._jobstates,'failed')+shift self._itotal = self._lstates+shift self._ifail = 0 self._description,params = utils.normalizeDbSchema(pmt,'jobsarchived4') self.publishUI(self.doQuery,params = params)
def doJson(self, pandaid, message=None, host=None, timestamp=None, errorcode=None, test=None): """ Contact Us Panda Monitor Modules """ usr = self.server().user() pandaid = utils.parseArray(pandaid) plid = len(pandaid) main = {} if plid >= 1: main['pandaid'] = pandaid[0] if plid >= 2: main['taskid'] = pandaid[1] if plid == 2 and usr != None: pandaid.append(usr) plid = len(pandaid) if plid >= 3: pandaid[2] = pmt.cleanUserID(pandaid[2]).replace(' ', '+') main['user'] = pandaid[2] if usr != None: mail = self.server().email() if mail == None and test != None: mail = '*****@*****.**' main['username'] = usr if mail != None: main['mail'] = mail msg = self.message(pandaid, message, host, timestamp, errorcode) msg += self.signature() subject = self.subject(pandaid) toaddrs = '' if test == None: toaddrs = '[email protected] [email protected] ' # toaddrs+='%s %s %s' % ('*****@*****.**', '*****@*****.**', mail) toaddrs += '%s %s' % ('*****@*****.**', mail) main['message'] = msg main[ 'subject'] = subject if test == None else 'Test: %s ' % subject main['toaddrs'] = toaddrs response = pmt.sendmail(msg, subject, toaddrs, fromaddr=mail) main['response'] = response self.publishTitle("User %s sent support mail from %s" % (usr, mail)) else: self.publishTitle("User %s wanted to send the support mail " % usr) self.publish(main) else: self.publishTitle( "Unknown user, please use the Web https protocol.") self.publish(main) self.publish({'s-maxage': 0, 'max-age': 0}, role=pmRoles.cache())
def isValid(self, params, exceptions=None): """ Check whether the extra parameters are valid """ if params != None: p = utils.parseArray(params) ex = self.extraParams() for nxp in p: if exceptions != None and nxp in exceptions: continue if ex == None or not nxp in ex: raise ValueError( "Unexpected module parameter : '%s' from : \n\t '%s' \n" % (nxp, "'\n\t'".join(sorted(ex.keys())))) return True
def isValid(self, params, exceptions=None): """ Check whether the extra parameters are valid """ if params != None: p = utils.parseArray(params) ex = self.extraParams() for nxp in p: if exceptions != None and nxp in exceptions: continue if ex == None or not nxp in ex: raise ValueError( "Unexpected module parameter : '%s' from : \n\t '%s' \n" % (nxp, "'\n\t'".join(sorted(ex.keys()))) ) return True
def doJson(self, pandaid, message=None,host=None,timestamp=None,errorcode=None,test=None): """ Contact Us Panda Monitor Modules """ usr = self.server().user() pandaid = utils.parseArray(pandaid) plid = len(pandaid) main = {} if plid >= 1: main['pandaid'] = pandaid[0] if plid >= 2: main['taskid'] = pandaid[1] if plid == 2 and usr != None: pandaid.append(usr) plid = len(pandaid) if plid >= 3: pandaid[2] = pmt.cleanUserID(pandaid[2]).replace(' ','+') main['user'] = pandaid[2] if usr != None: mail = self.server().email() if mail == None and test != None: mail = '*****@*****.**' main['username']= usr if mail != None: main['mail']= mail msg = self.message(pandaid, message, host,timestamp,errorcode); msg += self.signature() subject = self.subject(pandaid) toaddrs = '' if test == None: toaddrs = '[email protected] [email protected] ' # toaddrs+='%s %s %s' % ('*****@*****.**', '*****@*****.**', mail) toaddrs+='%s %s' % ( '*****@*****.**', mail) main['message'] = msg; main['subject'] = subject if test==None else 'Test: %s ' % subject main['toaddrs'] = toaddrs response = pmt.sendmail(msg,subject,toaddrs,fromaddr=mail) main['response'] = response self.publishTitle("User %s sent support mail from %s" % (usr,mail) ) else: self.publishTitle("User %s wanted to send the support mail " % usr ) self.publish(main) else: self.publishTitle("Unknown user, please use the Web https protocol.") self.publish(main) self.publish( {'s-maxage':0,'max-age': 0}, role=pmRoles.cache())
def doJson(self,lfn=None, jobs=None,type='input',ds=None,table='new',limit=1000,jobstatus=None,site=None,jobtype='production',days=1,user=None,select=None): """ Show the list of Panda id with LFN or versa verse LFNs by Panda IDs <ul> <li><code>lfn</code> - the list of the comma separated files <li><code>ds</code> - the list of the comma separated datasets <li><code>jobs</code> - the list of the comma separated Panda's job IDs <li><code>table</code> = "new" (default) look up the records for last 3 days <br> ="old" - look up the records those more than 3 days old (slow) <br> ="deep" - look up the "old" and "new" tables (slow) <li><code>type</code> - the type selector. <br> = 'input - the default value<br> = '*' | 'all' - list all types available. <li><code>jobstatus</code> = the comma separated list of the job status to filter <br>For example: 'defined, waiting,assigned,activated,sent,starting,running' <li><code>site</code> = the comma separated list of the sizte to list the jobs from <br> For example 'UTA_SWT2' <li><code>jobtype</code> = the comma separated list of the job type to filter <br> For example, "analysis, production" <li><code>days</code> = the number of the days to look up the list of the jobs if either 'jobstatus' or 'site' parameter is defined <li><code>user</code> = the comma separated list of the usernames . <br>NB. The names may contain the the wildcard symbol '*'. Be aware the wildcard slows the search down </ul> """ title = 'The list of files for the ' if jobstatus and jobstatus.strip() =='': jobstatus = None if site and site.strip() =='': site = None if lfn and lfn.strip() =='': lfn = None if jobs and isinstance(jobs,str) and jobs.strip() =='': jobs = None if ds and ds.strip() =='': ds=None if type and type.strip() =='': type='all' if lfn==None and jobs==None and ds==None and jobstatus==None and site==None: self.publishTitle("Ambigios query: lfn=%(lfn)s; pandaid=%(pandaid)s either lfn or padaid can be defined. One can not define lfn and pandaid at once" % { 'lfn': lfn, 'pandaid' : jobs} ) self.publish('<h2>Check the input parameters. Click the "?" to see the API documentaion<h2>', role=pmRoles.html()) else: nav = '' if limit: nav += "Limit %s rows." % limit if type=='*' or type==None: type = 'all' if lfn != None: self.publishTitle("The list of the PANDA jobs with the LFN of the '%s' type provided" % type) if not '*' in lfn: # disregard the jobtype parameter if utils.isFilled(jobtype): nav += " Disregarding the jobtype='%s' default parameter" % jobtype jobtype = None if ds != None: self.publishTitle("The list of the PANDA jobs with the DATASETs of the '%s' type provided" % type) if jobs!=None: self.publishTitle("The list of the '%s' LFN with the PANDA Job IDs provided" % type) if utils.isFilled(nav): self.publishNav(nav) main = {} main["buffer"] = {} main["buffer"]["method"] = "joblfn" main["buffer"]["params"] = (lfn if lfn!=None else '',jobs if jobs!= None else '' ) if jobs != None: main["buffer"]["jobs"] = jobs main["buffer"]["type"] = False if (utils.isFilled(jobstatus) or utils.isFilled(site) or utils.isFilled(user)) and not utils.isFilled(jobs): tables = ['atlas_panda.jobsArchived4','atlas_panda.jobsActive4','atlas_panda.jobsWaiting4','atlas_panda.jobsDefined4'] r = pmt.getJobIds(site, jobtype,jobstatus,table=tables,days=days,username=user) jobs = [i[0] for i in r['rows']] if not utils.isFilled(select): select = [] if jobs == None or ( not isinstance(jobs,int) and len(jobs) > 1): select.append('pandaid'); select += ['type', 'lfn', 'fsize', 'dataset', 'guid', 'scope', 'destinationse'] else: select = utils.parseArray(select); main["buffer"]["data"] = pmt.getJobLFN(select=','.join(select),table=table,lfn=lfn,pandaid=jobs,type=type,ds=ds,limit=limit) self.publish(main) self.publish( "%s/%s" % (self.server().fileScriptURL(),"taskBuffer/%s.js" % "getJobLFN"),role=pmRoles.script())
def doJobs( self, pandaid=None, params=None, jobparam=None, table=None, hours=None, tstart=None, tend=None, field="modificationTime", days=None, format=None, jobtype=None, testsite=None, limit=1500, summary=None, minjob=1, dump=None, region=None, lfn=None, showcpu=None, ): ## Perform the query main = {} errorcolcheck = False selection = "*" vals = self.extraValuesFilled(self._alias) title = "PanDA Job(s)" if utils.isFilled(pandaid): hours = None days = None title += " %s " % pandaid if days != None: title += " for %.2f Day" % float(days) if days > 1: title += "s" if hours != None: if days == None: title += " for " title += " %d Hour" % int(hours) if hours > 1: title += "s" if vals != None: for k in vals.keys(): if vals[k] == "undefined": vals[k] = None elif ( vals[k] != None and k.lower() == "jobstatus" and ( vals[k].lower().find("prerun") >= 0 or vals[k].lower().find("finishing") >= 0 or vals[k].lower().find("unassigned") >= 0 or vals[k].lower().find("retried") >= 0 ) ): stvals = utils.parseArray(vals[k]) statvals = [] for v in stvals: if v.lower() == "prerun": statvals += ["defined", "assigned", "waiting", "activated", "pending", "sent", "starting"] elif v.lower() == "finishing": statvals += ["holding", "transferring"] elif v.lower() == "unassigned": vals["computingSite"] = "NULL" statvals += ["cancelled"] elif v.lower() == "retried": # See the slide 3 from Tadashi: https://indico.cern.ch/getFile.py/access?contribId=13&sessionId=11&resId=0&materialId=slides&confId=119171 vals["taskBufferErrorCode"] = [106, 107] statvals += ["failed"] else: statvals += [v] vals[k] = ",".join(statvals) cleanVal = dict((k, v) for k, v in vals.iteritems() if v is not None) vals = cleanVal if vals == None: vals = {} nav = "" certificate = None certusr = None try: cert = self.server().certificate() if cert != None: certusr = pmt.cleanUserID(cert) main["ceruser"] = certusr except: pass if vals.get("prodUserName") == "auto" and certusr != None: if cert != None: vals["prodUserName"] = certusr for v in vals: nav += "<b>%s</b>=%s " % (v, vals[v]) # nav += "<span id=linkjobid stule='display:inline'></span>" # nav +="<script>$(document).ready(function(){$('#linkjobid').html(utils().linkJobs(s.cloud,jobtype" # nav += jobtype if jobtype!=None else "undefined" # nav += ", s.jobStatus, " # nav += "%d" % hours if hours!=None else "undefined" # nav += ", s.computingSite,'Classic Page' ))});</script>"; if not utils.isFilled(summary): nav += "<b>%s</b>=%s " % ("limit", limit) self.publishNav(nav) if len(vals) == 0: vals = None if vals == None and jobparam == None: main["Description"] = self.description() else: if lfn != None and lfn != "undefined": lfnselect = "pandaid,lfn" lfnjobs = pmt.getJobLFN(select=lfnselect, table="new", lfn=lfn, pandaid=pandaid, type="*", limit=limit) if lfnjobs["rows"] > 0: pandaid = [ljobs[0] for ljobs in lfnjobs["rows"]] selection = {} if vals != None: selection.update(vals) if pandaid != None: selection.update({nmap.get("pandaid"): pandaid}) if region != None: selection.update({"region": region}) main["Selection"] = selection conditions = vals if conditions == None: conditions = {} cs = conditions.get("computingSite") if cs == None: site4region = self.getSite4Region(region) if site4region != None and len(site4region) > 0: conditions["computingSite"] = site4region else: pass # ignore the region parameter if utils.isValid(summary): jobtype = ( "production" if jobtype == None and jobparam.lower().find("taskid") >= 0 and jobparam.lower().find("jeditaskid") < 0 else jobtype ) jobs = pmt.getJobsAtt( pandaid, jobparam, conditions, None, hours, tstart, tend, field, days, format, jobtype, testsite, None, True, ) rows = jobs["rows"] indx = [] if len(rows) > 30: for i, r in enumerate(rows): try: if r[1] > minjob: indx.append(i) continue except: pass cleanrows = [rows[i] for i in indx] jobs["rows"] = cleanrows istatus = utils.name2Index(jobs["header"], "jobstatus") if istatus != None: statOrder = utils.name2Index(utils.jobStates) def byStatus(a, b): return statOrder[a[istatus]] - statOrder[b[istatus]] jobs["rows"] = sorted(jobs["rows"], cmp=byStatus) else: if jobparam == self._allparams and conditions.get(self._jobParametersName) == None: conditions[self._jobParametersName] = "any" jobs = pmt.getJobsAtt( pandaid, "PandaID," + jobparam, conditions, None, hours, tstart, tend, field, days, format, jobtype, testsite, limit, ) errorcolcheck = True if len(jobs) > 0: header = [nmap.get(h) for h in jobs["header"]] info = jobs["rows"] main["header"] = header # + self._extraFields timecols = [] errdict = None errorcol = not errorcolcheck for i, h in enumerate(header): if "time" in h.lower() and "cpuconsumptiontime" != h.lower(): timecols.append(i) if not errorcol and "error" in h.lower(): errorcol = True ## # add an artificial retryID ## header += ['retryID'] headindx = utils.name2Index(header) creationtDict = {} histograms = {} prodSourceLabel = headindx.get("prodSourceLabel") jobStatus = headindx.get("jobStatus") status4title = conditions.get("jobStatus") if not utils.isFilled(status4title): if len(info) == 1 and jobStatus != None: status4title = info[0][jobStatus] if utils.isFilled(status4title): title = status4title[0].upper() + status4title[1:] + " " + title prodtype = "production" in jobtype.lower() if jobtype != None else True taskidsum = prodtype if not utils.isValid(summary) and dump != "yes": jsets = setutils.factory(header, info, self._errorCodes, self._siteId, self._siteNicks) main["jobset"] = jsets.jobsets() for r in info: if not taskidsum and ((prodSourceLabel and r[prodSourceLabel] == "managed") and prodtype): taskidsum = True if errorcol and errorcolcheck: errdict = self.getErrors(r, headindx, errdict) for t in timecols: r[t] = utils.epochTime(r[t]) ## r += [None] # retryID # row = self.jobsetTime(utils.zip(header(info[r])),creationtDict,histograms) # info[r] = self.addFields(utils.zip(header(info[r])),creationtDict,histograms) # Action cleanUserID SSL_CLIENT_S_DN main["info"] = info if errorcolcheck: main["errorCodes"] = errdict main["colNames"] = sorted(header) main["jobsummary"] = copy.copy(self._jobSum) if taskidsum: main["jobsummary"] += [["Task ID", "taskID"]] # print utils.lineInfo(), "===============", self._description.get("JEDITASKID"), self._description.get("JediTaskID") # if self._description.get("JEDITASKID") or self._description.get("JediTaskID"): # main['jobsummary'] += [['Jedi ID','JediTaskID']] elif jobtype != "jedi": main["jobsummary"] += [["Jobsets", "jobsetID"]] # need constrain elif jobtype == "analysis": main["jobsummary"] += [["Analysis Tasks", "destinationDBlock"]] if showcpu == "yes": main["jobsummary"] += [["CPU Type", "cpuConsumptionUnit"]] self.publishTitle(title) return main
def doQuery(self,site='all',jobtype='all',days=1,hostonly='yes',plot='finished,failed',style='SB', details=None,deep='no'): """ Get the list of the jobs' status per worker node for selected site for upto 3 last days <ol> <li><code>site</code> - site to get the information about or "all" <li><code>jobtype</code> = 'production" or " analysis" or "all" <li><code>days</code> - number of days we want to fetch the information for. This parameter must be less or equal 3. <li><code>hostonly</code> - "yes" . "no" - means provide the information 'per CPU' rather 'per host' <li><code>plot</code> - the comma separated list of the <a href='https://twiki.cern.ch/twiki/bin/viewauth/Atlas/PandaShiftGuide#Job_state_definitions_in_Panda'>job status names</a> to generate the plot for <li><code>style</code> the combination of the symbols: 'H' - histogram, 'B' - bar , 'L' - line, 'P' - points, 'S' - stacked<br> = 'BS' - 'by default' <li><code>details</code> - 'yes' - provide the status per host<br> <br> = 'summary' - provide the summary only <br> default = 'yes' if not site == 'all' else 'no' <li><code>deep</code> - do not look up the "long job table" . It can be very slow. default = 'no' <li> <b><a title='Click to see the full list of the parameters available' href='http://pandamon.cern.ch/describe?table=^JOBSARCHIVED4&doc=*'>PARAM</a>=value</b> - comma-separated list of the value <a href ='https://twiki.cern.ch/twiki/bin/view/PanDA/PandaPlatform#API_parameter_value_format'> patterns</a> to filter the job records. <li><code>jobStatus</code> - it can be any comma-separated list of the Panda Jobs states patterns or / and <br> two 'meta' states: "factory" to list the "factory" nodes and "wn" to list the the Worker Nodes </ol> """ vals = self.extraValuesFilled() if site == None: site='all' factory = None wn = None titletype = "PanDA" jobStatus = None if vals != None: jstat = vals.get('jobStatus') jobStatus = jstat if jstat != None: jstat = [x.lower() for x in utils.parseArray(jstat)] print utils.lineInfo(), jstat, 'factory' in jstat if 'factory' in jstat: factory = self.factory() jstat += factory titletype = "Factory" if 'wn' in jstat: wn = self.wn() jstat += wn titletype = "Worker" jstat = list(set(jstat)) vals['jobStatus'] = ','.join(jstat) if deep == None or deep == False: deep = 'no' deep = not deep.lower() == 'no' title = '' hours = (float(days))*24 Deep = 'Deep' if deep else '' if float(days) > 3 and False and not deep: days = 3.0 hours = 24*days title = 'The List of the %s Nodes Activity for the Last %s Hours Only.' % (titletype, int(hours)) else: title = 'The %s List of the %s Nodes Activity for the %s Hours' % (Deep, titletype,int(hours) ) days = float(days) try: if jobtype.lower() == 'all': jobtype=None except: pass self.publishTitle(title) modes = ( 'Defined', 'Waiting', 'Active', 'Archived' ) tables = [] for mode in modes: tables += ['ATLAS_PANDA.jobs%s4' % mode] if days>3 and deep: tables += ['ATLAS_PANDAARCH.JOBSARCHIVED'] q = pmt.wnList(site, jobtype, table=tables, days=days,conditions = vals) try: if details == None: details = not (site == None or site == 'None' or site.lower() == 'all' or site == '*' ) # else: # details = isinstance(details,str) and details.lower() == 'yes' except: details = False ## Publish the result main = {} main['data'] = self.do(q['header'],q['rows'],site,hostonly,details,factory,wn) main['params'] = { 'jobtype': jobtype,'days': days,'site': site,'hostonly':hostonly,'jobStatus':jobStatus} plotpars = [] if plot: for p in plot.split(","): if p.lower() == 'prerun' or factory != None: if wn == None: plotpars += self.factory() if factory == None: plotpars += ['pending','sent','starting'] elif p.lower() == 'finishing' and factory == None: plotpars += ['holding','transferring'] else: plotpars += [p] main['params']['plot'] = list(set(plotpars)) # remove duplicates if style: main['params']['style'] = style self.publish(main) self.publishNav(' type=%s days= last %s ' % (jobtype, days ) ) self.publish( "%s/%s" % ( self.server().fileScriptURL(),"monitor/%s.js" % "wnlist" ),role=pmRoles.script()) self.publish( {'s-maxage':600,'max-age': 600}, role=pmRoles.cache())
def doJobs(self, pandaid=None, params=None, jobparam=None, table=None, hours=None, tstart=None, tend=None, field='modificationTime', days=None, format=None, jobtype=None, testsite=None, limit=1500, summary=None, minjob=1, dump=None, region=None, lfn=None, showcpu=None): ## Perform the query main = {} errorcolcheck = False selection = '*' vals = self.extraValuesFilled(self._alias) title = 'PanDA Job(s)' if utils.isFilled(pandaid): hours = None days = None title += " %s " % pandaid if days != None: title += ' for %.2f Day' % float(days) if days > 1: title += "s" if hours != None: if days == None: title += " for " title += ' %d Hour' % int(hours) if hours > 1: title += "s" if vals != None: for k in vals.keys(): if vals[k] == 'undefined': vals[k] = None elif vals[k] != None and k.lower() == 'jobstatus' and ( vals[k].lower().find('prerun') >= 0 or vals[k].lower().find('finishing') >= 0 or vals[k].lower().find('unassigned') >= 0 or vals[k].lower().find('retried') >= 0): stvals = utils.parseArray(vals[k]) statvals = [] for v in stvals: if v.lower() == 'prerun': statvals += [ 'defined', 'assigned', 'waiting', 'activated', 'pending', 'sent', 'starting' ] elif v.lower() == 'finishing': statvals += ['holding', 'transferring'] elif v.lower() == 'unassigned': vals['computingSite'] = 'NULL' statvals += ['cancelled'] elif v.lower() == 'retried': # See the slide 3 from Tadashi: https://indico.cern.ch/getFile.py/access?contribId=13&sessionId=11&resId=0&materialId=slides&confId=119171 vals['taskBufferErrorCode'] = [106, 107] statvals += ['failed'] else: statvals += [v] vals[k] = ','.join(statvals) cleanVal = dict( (k, v) for k, v in vals.iteritems() if v is not None) vals = cleanVal if vals == None: vals = {} nav = '' certificate = None certusr = None try: cert = self.server().certificate() if cert != None: certusr = pmt.cleanUserID(cert) main['ceruser'] = certusr except: pass if vals.get('prodUserName') == 'auto' and certusr != None: if cert != None: vals['prodUserName'] = certusr for v in vals: nav += "<b>%s</b>=%s " % (v, vals[v]) # nav += "<span id=linkjobid stule='display:inline'></span>" # nav +="<script>$(document).ready(function(){$('#linkjobid').html(utils().linkJobs(s.cloud,jobtype" # nav += jobtype if jobtype!=None else "undefined" # nav += ", s.jobStatus, " # nav += "%d" % hours if hours!=None else "undefined" # nav += ", s.computingSite,'Classic Page' ))});</script>"; if not utils.isFilled(summary): nav += "<b>%s</b>=%s " % ('limit', limit) self.publishNav(nav) if len(vals) == 0: vals = None if vals == None and jobparam == None: main['Description'] = self.description() else: if lfn != None and lfn != "undefined": lfnselect = 'pandaid,lfn' lfnjobs = pmt.getJobLFN(select=lfnselect, table='new', lfn=lfn, pandaid=pandaid, type='*', limit=limit) if lfnjobs['rows'] > 0: pandaid = [ljobs[0] for ljobs in lfnjobs['rows']] selection = {} if vals != None: selection.update(vals) if pandaid != None: selection.update({nmap.get('pandaid'): pandaid}) if region != None: selection.update({'region': region}) main['Selection'] = selection conditions = vals if conditions == None: conditions = {} cs = conditions.get('computingSite') if cs == None: site4region = self.getSite4Region(region) if site4region != None and len(site4region) > 0: conditions['computingSite'] = site4region else: pass # ignore the region parameter if utils.isValid(summary): jobtype = 'production' if jobtype == None and jobparam.lower( ).find('taskid') >= 0 and jobparam.lower().find( 'jeditaskid') < 0 else jobtype jobs = pmt.getJobsAtt(pandaid, jobparam, conditions, None, hours, tstart, tend, field, days, format, jobtype, testsite, None, True) rows = jobs['rows'] indx = [] if len(rows) > 30: for i, r in enumerate(rows): try: if r[1] > minjob: indx.append(i) continue except: pass cleanrows = [rows[i] for i in indx] jobs['rows'] = cleanrows istatus = utils.name2Index(jobs['header'], 'jobstatus') if istatus != None: statOrder = utils.name2Index(utils.jobStates) def byStatus(a, b): return statOrder[a[istatus]] - statOrder[b[istatus]] jobs['rows'] = sorted(jobs['rows'], cmp=byStatus) else: if jobparam == self._allparams and conditions.get( self._jobParametersName) == None: conditions[self._jobParametersName] = 'any' jobs = pmt.getJobsAtt(pandaid, 'PandaID,' + jobparam, conditions, None, hours, tstart, tend, field, days, format, jobtype, testsite, limit) errorcolcheck = True if len(jobs) > 0: header = [nmap.get(h) for h in jobs['header']] info = jobs['rows'] main['header'] = header # + self._extraFields timecols = [] errdict = None errorcol = not errorcolcheck for i, h in enumerate(header): if 'time' in h.lower( ) and 'cpuconsumptiontime' != h.lower(): timecols.append(i) if not errorcol and 'error' in h.lower(): errorcol = True ## # add an artificial retryID ## header += ['retryID'] headindx = utils.name2Index(header) creationtDict = {} histograms = {} prodSourceLabel = headindx.get('prodSourceLabel') jobStatus = headindx.get('jobStatus') status4title = conditions.get('jobStatus') if not utils.isFilled(status4title): if len(info) == 1 and jobStatus != None: status4title = info[0][jobStatus] if utils.isFilled(status4title): title = status4title[0].upper( ) + status4title[1:] + " " + title prodtype = 'production' in jobtype.lower( ) if jobtype != None else True taskidsum = prodtype if not utils.isValid(summary) and dump != 'yes': jsets = setutils.factory(header, info, self._errorCodes, self._siteId, self._siteNicks) main['jobset'] = jsets.jobsets() for r in info: if not taskidsum and ( (prodSourceLabel and r[prodSourceLabel] == 'managed') and prodtype): taskidsum = True if errorcol and errorcolcheck: errdict = self.getErrors(r, headindx, errdict) for t in timecols: r[t] = utils.epochTime(r[t]) ## r += [None] # retryID # row = self.jobsetTime(utils.zip(header(info[r])),creationtDict,histograms) # info[r] = self.addFields(utils.zip(header(info[r])),creationtDict,histograms) # Action cleanUserID SSL_CLIENT_S_DN main['info'] = info if errorcolcheck: main['errorCodes'] = errdict main['colNames'] = sorted(header) main['jobsummary'] = copy.copy(self._jobSum) if taskidsum: main['jobsummary'] += [['Task ID', 'taskID']] # print utils.lineInfo(), "===============", self._description.get("JEDITASKID"), self._description.get("JediTaskID") # if self._description.get("JEDITASKID") or self._description.get("JediTaskID"): # main['jobsummary'] += [['Jedi ID','JediTaskID']] elif jobtype != 'jedi': main['jobsummary'] += [['Jobsets', 'jobsetID']] # need constrain elif jobtype == 'analysis': main['jobsummary'] += [[ 'Analysis Tasks', 'destinationDBlock' ]] if showcpu == 'yes': main['jobsummary'] += [['CPU Type', 'cpuConsumptionUnit']] self.publishTitle(title) return main