Exemplo n.º 1
0
def filterDate( selectOutput, start, end ):
  '''
    Selects all the downtimes that meet the constraints of 'start' and 'end' dates
  '''

  downtimes = selectOutput
  downtimesFiltered = []

  if start is not None:
    try:
      start = Time.fromString( start )
    except:
      error( "datetime formt is incorrect, pls try [%Y-%m-%d[ %H:%M:%S]]" )
    start = Time.toEpoch( start )

  if end is not None:
    try:
      end = Time.fromString( end )
    except:
      error( "datetime formt is incorrect, pls try [%Y-%m-%d[ %H:%M:%S]]" )
    end = Time.toEpoch( end )

  if start is not None and end is not None:
    for dt in downtimes:
      dtStart = Time.toEpoch( dt[ 'startDate' ] )
      dtEnd = Time.toEpoch( dt[ 'endDate' ] )
      if ( dtStart >= start ) and ( dtEnd <= end ):
        downtimesFiltered.append( dt )

  elif start is not None and end is None:
    for dt in downtimes:
      dtStart = Time.toEpoch( dt[ 'startDate' ] )
      if dtStart >= start:
        downtimesFiltered.append( dt )

  elif start is None and end is not None:
    for dt in downtimes:
      dtEnd = Time.toEpoch( dt[ 'endDate' ] )
      if dtEnd <= end:
        downtimesFiltered.append( dt )

  else:
    downtimesFiltered = downtimes

  return downtimesFiltered
Exemplo n.º 2
0
  def addLoggingRecord(self,
                       jobID,
                       status='idem',
                       minor='idem',
                       application='idem',
                       date='',
                       source='Unknown'):
    """ Add a new entry to the JobLoggingDB table. One, two or all the three status
        components (major, minor, application) can be specified.
        Optionally the time stamp of the status can
        be provided in a form of a string in a format '%Y-%m-%d %H:%M:%S' or
        as datetime.datetime object. If the time stamp is not provided the current
        UTC time is used.
    """

    event = 'status/minor/app=%s/%s/%s' % (status, minor, application)
    self.gLogger.info("Adding record for job " + str(jobID) + ": '" + event + "' from " + source)

    if not date:
      # Make the UTC datetime string and float
      _date = Time.dateTime()
      epoc = time.mktime(_date.timetuple()) + _date.microsecond / 1000000. - MAGIC_EPOC_NUMBER
      time_order = round(epoc, 3)
    else:
      try:
        if isinstance(date, basestring):
          # The date is provided as a string in UTC
          _date = Time.fromString(date)
          epoc = time.mktime(_date.timetuple()) + _date.microsecond / 1000000. - MAGIC_EPOC_NUMBER
          time_order = round(epoc, 3)
        elif isinstance(date, Time._dateTimeType):
          _date = date
          epoc = time.mktime(_date.timetuple()) + _date.microsecond / 1000000. - \
              MAGIC_EPOC_NUMBER  # pylint: disable=no-member
          time_order = round(epoc, 3)
        else:
          self.gLogger.error('Incorrect date for the logging record')
          _date = Time.dateTime()
          epoc = time.mktime(_date.timetuple()) - MAGIC_EPOC_NUMBER
          time_order = round(epoc, 3)
      except BaseException:
        self.gLogger.exception('Exception while date evaluation')
        _date = Time.dateTime()
        epoc = time.mktime(_date.timetuple()) - MAGIC_EPOC_NUMBER
        time_order = round(epoc, 3)

    cmd = "INSERT INTO LoggingInfo (JobId, Status, MinorStatus, ApplicationStatus, " + \
          "StatusTime, StatusTimeOrder, StatusSource) VALUES (%d,'%s','%s','%s','%s',%f,'%s')" % \
        (int(jobID), status, minor, application[:255],
         str(_date), time_order, source)

    return self._update(cmd)
Exemplo n.º 3
0
  def accountPilots( self, pilotsToAccount, connection ):
    """ account for pilots
    """
    accountingFlag = False
    pae = self.am_getOption( 'PilotAccountingEnabled', 'yes' )
    if pae.lower() == "yes":
      accountingFlag = True

    if not pilotsToAccount:
      self.log.info( 'No pilots to Account' )
      return S_OK()

    accountingSent = False
    if accountingFlag:
      retVal = self.pilotDB.getPilotInfo( pilotsToAccount.keys(), conn = connection )
      if not retVal['OK']:
        self.log.error( 'Fail to retrieve Info for pilots', retVal['Message'] )
        return retVal
      dbData = retVal[ 'Value' ]
      for pref in dbData:
        if pref in pilotsToAccount:
          if dbData[pref][ 'Status' ] not in self.finalStateList:
            dbData[pref][ 'Status' ] = pilotsToAccount[pref][ 'Status' ]
            dbData[pref][ 'DestinationSite' ] = pilotsToAccount[pref][ 'DestinationSite' ]
            dbData[pref][ 'LastUpdateTime' ] = Time.fromString( pilotsToAccount[pref][ 'StatusDate' ] )

      retVal = self.__addPilotsAccountingReport( dbData )
      if not retVal['OK']:
        self.log.error( 'Fail to retrieve Info for pilots', retVal['Message'] )
        return retVal

      self.log.info( "Sending accounting records..." )
      retVal = gDataStoreClient.commit()
      if not retVal[ 'OK' ]:
        self.log.error( "Can't send accounting repots", retVal[ 'Message' ] )
      else:
        self.log.info( "Accounting sent for %s pilots" % len( pilotsToAccount ) )
        accountingSent = True

    if not accountingFlag or accountingSent:
      for pRef in pilotsToAccount:
        pDict = pilotsToAccount[pRef]
        self.log.verbose( 'Setting Status for %s to %s' % ( pRef, pDict['Status'] ) )
        self.pilotDB.setPilotStatus( pRef,
                                     pDict['Status'],
                                     pDict['DestinationSite'],
                                     pDict['StatusDate'],
                                     conn = connection )

    return S_OK()
Exemplo n.º 4
0
 def _checkJobLastUpdateTime( self, joblist , StalledDays ):
   timeLimitToConsider = Time.dateTime() - Time.day * StalledDays 
   ret = False
   for JobID in joblist:
     result = self.jobDB.getJobAttributes(int(JobID))
     if result['OK']:
        if result['Value'].has_key('LastUpdateTime'):
          LastUpdateTime = result['Value']['LastUpdateTime']
          if Time.fromString(LastUpdateTime) > timeLimitToConsider:
            ret = True
            self.log.debug('Since '+str(JobID)+' updates LastUpdateTime on '+str(LastUpdateTime)+', this does not to need to be deleted.')
            break
     else:
       self.log.error("Error taking job info. from DB:%s" % str( result['Message'] ) )
   return ret
Exemplo n.º 5
0
 def _checkJobLastUpdateTime( self, joblist , StalledDays ):
   timeLimitToConsider = Time.dateTime() - Time.day * StalledDays 
   ret = False
   for jobID in joblist:
     result = self.jobDB.getJobAttributes( int( jobID ) )
     if result['OK']:
       if 'LastUpdateTime' in result['Value']:
         lastUpdateTime = result['Value']['LastUpdateTime']
         if Time.fromString( lastUpdateTime ) > timeLimitToConsider:
           ret = True
           self.log.debug( 'Since %s updates LastUpdateTime on %s this does not to need to be deleted.' % ( str( jobID ), str( lastUpdateTime ) ) )
           break
     else:
       self.log.error( "Error taking job info from DB", result['Message'] )
   return ret
Exemplo n.º 6
0
    def addLoggingRecord(self, jobID, status="idem", minor="idem", application="idem", date="", source="Unknown"):

        """ Add a new entry to the JobLoggingDB table. One, two or all the three status
        components can be specified. Optionaly the time stamp of the status can
        be provided in a form of a string in a format '%Y-%m-%d %H:%M:%S' or
        as datetime.datetime object. If the time stamp is not provided the current
        UTC time is used.
    """

        event = "status/minor/app=%s/%s/%s" % (status, minor, application)
        self.gLogger.info("Adding record for job " + str(jobID) + ": '" + event + "' from " + source)

        if not date:
            # Make the UTC datetime string and float
            _date = Time.dateTime()
            epoc = time.mktime(_date.timetuple()) + _date.microsecond / 1000000.0 - MAGIC_EPOC_NUMBER
            time_order = round(epoc, 3)
        else:
            try:
                if type(date) in StringTypes:
                    # The date is provided as a string in UTC
                    _date = Time.fromString(date)
                    epoc = time.mktime(_date.timetuple()) + _date.microsecond / 1000000.0 - MAGIC_EPOC_NUMBER
                    time_order = round(epoc, 3)
                elif type(date) == Time._dateTimeType:
                    _date = date
                    epoc = time.mktime(_date.timetuple()) + _date.microsecond / 1000000.0 - MAGIC_EPOC_NUMBER
                    time_order = round(epoc, 3)
                else:
                    self.gLogger.error("Incorrect date for the logging record")
                    _date = Time.dateTime()
                    epoc = time.mktime(_date.timetuple()) - MAGIC_EPOC_NUMBER
                    time_order = round(epoc, 3)
            except:
                self.gLogger.exception("Exception while date evaluation")
                _date = Time.dateTime()
                epoc = time.mktime(_date.timetuple()) - MAGIC_EPOC_NUMBER
                time_order = round(epoc, 3)

        cmd = (
            "INSERT INTO LoggingInfo (JobId, Status, MinorStatus, ApplicationStatus, "
            + "StatusTime, StatusTimeOrder, StatusSource) VALUES (%d,'%s','%s','%s','%s',%f,'%s')"
            % (int(jobID), status, minor, application, str(_date), time_order, source)
        )

        return self._update(cmd)
Exemplo n.º 7
0
  def addFileRecord( self, lfns, status, minor = "Unknown", date = None, source = "Unknown" ):
    """ Add a new entry to the DataLoggingDB table. 

    :warning: Optionally the time stamp of the status can be provided in a form of a string 
    in a format '%Y-%m-%d %H:%M:%S' or as datetime.datetime object. If the time stamp is not 
    provided the current UTC time is used.

    :param self: self reference
    :param list lfns: list of LFNs
    :param str status: status
    :param str minor: additional information
    :param mixed date: date and time
    :param str source: source setting the new status
    """
    self.gLogger.info( "Entering records for %s lfns: %s/%s from source %s" % ( len( lfns ), status, minor, source ) )
    if not date:
      _date = Time.dateTime()
    else:
      if type( date ) in StringTypes:
        _date = Time.fromString( date )
      else:
        _date = date

    try:
      time_order = Time.to2K( _date ) - NEW_MAGIC_EPOCH_2K
    except AttributeError:
      gLogger.error( 'Wrong date argument given using current time stamp' )
      dateNow = Time.dateTime()
      time_order = Time.to2K( dateNow ) - NEW_MAGIC_EPOCH_2K

    inDict = { 'Status': status,
               'MinorStatus': minor,
               'StatusTime': _date,
               'StatusTimeOrder': time_order,
               'Source': source
              }
    result = S_OK( 0 )
    for lfn in lfns:
      inDict['LFN'] = lfn
      res = self.insertFields( self.tableName, inDict = inDict )
      if not res['OK']:
        return res
      result['Value'] += res['Value']
      result['lastRowId'] = res['lastRowId']
    return result
Exemplo n.º 8
0
def tupleToMessage(varTuple):
    varList = list(varTuple)
    varList[2] = Time.fromString(varList[2])
    return Message(*varList)
Exemplo n.º 9
0
    def __parseFormParams(self):
        params = self.request.arguments
        pD = {}
        extraParams = {}
        pinDates = False

        for name in params:
            if name.find("_") != 0:
                continue
            value = params[name][0]
            name = name[1:]
            pD[name] = str(value)

        print pD
        #Personalized title?
        if 'plotTitle' in pD:
            extraParams['plotTitle'] = pD['plotTitle']
            del (pD['plotTitle'])
        #Pin dates?
        if 'pinDates' in pD:
            pinDates = pD['pinDates']
            del (pD['pinDates'])
            pinDates = pinDates.lower() in ("yes", "y", "true", "1")
        #Get plotname
        if not 'grouping' in pD:
            return S_ERROR("Missing grouping!")
        grouping = pD['grouping']
        #Get plotname
        if not 'typeName' in pD:
            return S_ERROR("Missing type name!")
        typeName = pD['typeName']
        del (pD['typeName'])
        #Get plotname
        if not 'plotName' in pD:
            return S_ERROR("Missing plot name!")
        reportName = pD['plotName']
        del (pD['plotName'])
        #Get times
        if not 'timeSelector' in pD:
            return S_ERROR("Missing time span!")
        #Find the proper time!
        pD['timeSelector'] = int(pD['timeSelector'])
        if pD['timeSelector'] > 0:
            end = Time.dateTime()
            start = end - datetime.timedelta(seconds=pD['timeSelector'])
            if not pinDates:
                extraParams['lastSeconds'] = pD['timeSelector']
        else:
            if 'endTime' not in pD:
                end = False
            else:
                end = Time.fromString(pD['endTime'])
                del (pD['endTime'])
            if 'startTime' not in pD:
                return S_ERROR("Missing starTime!")
            else:
                start = Time.fromString(pD['startTime'])
                del (pD['startTime'])
        del (pD['timeSelector'])

        for k in pD:
            if k.find("ex_") == 0:
                extraParams[k[3:]] = pD[k]
        #Listify the rest
        for selName in pD:
            pD[selName] = List.fromChar(pD[selName], ",")
        return S_OK(
            (typeName, reportName, start, end, pD, grouping, extraParams))
Exemplo n.º 10
0
    def _setJobStatusBulk(cls, jobID, statusDict, force=False):
        """Set various status fields for job specified by its jobId.
        Set only the last status in the JobDB, updating all the status
        logging information in the JobLoggingDB. The statusDict has datetime
        as a key and status information dictionary as values
        """
        jobID = int(jobID)
        log = gLogger.getLocalSubLogger("JobStatusBulk/Job-%d" % jobID)

        result = cls.jobDB.getJobAttributes(
            jobID, ["Status", "StartExecTime", "EndExecTime"])
        if not result["OK"]:
            return result
        if not result["Value"]:
            # if there is no matching Job it returns an empty dictionary
            return S_ERROR("No Matching Job")

        # If the current status is Stalled and we get an update, it should probably be "Running"
        currentStatus = result["Value"]["Status"]
        if currentStatus == JobStatus.STALLED:
            currentStatus = JobStatus.RUNNING
        startTime = result["Value"].get("StartExecTime")
        endTime = result["Value"].get("EndExecTime")
        # getJobAttributes only returns strings :(
        if startTime == "None":
            startTime = None
        if endTime == "None":
            endTime = None
        # Remove useless items in order to make it simpler later, although there should not be any
        for sDict in statusDict.values():
            for item in sorted(sDict):
                if not sDict[item]:
                    sDict.pop(item, None)

        # Get the latest time stamps of major status updates
        result = cls.jobLoggingDB.getWMSTimeStamps(int(jobID))
        if not result["OK"]:
            return result
        if not result["Value"]:
            return S_ERROR("No registered WMS timeStamps")
        # This is more precise than "LastTime". timeStamps is a sorted list of tuples...
        timeStamps = sorted((float(t), s) for s, t in result["Value"].items()
                            if s != "LastTime")
        lastTime = Time.toString(Time.fromEpoch(timeStamps[-1][0]))

        # Get chronological order of new updates
        updateTimes = sorted(statusDict)
        log.debug(
            "*** New call ***", "Last update time %s - Sorted new times %s" %
            (lastTime, updateTimes))
        # Get the status (if any) at the time of the first update
        newStat = ""
        firstUpdate = Time.toEpoch(Time.fromString(updateTimes[0]))
        for ts, st in timeStamps:
            if firstUpdate >= ts:
                newStat = st
        # Pick up start and end times from all updates
        for updTime in updateTimes:
            sDict = statusDict[updTime]
            newStat = sDict.get("Status", newStat)

            if not startTime and newStat == JobStatus.RUNNING:
                # Pick up the start date when the job starts running if not existing
                startTime = updTime
                log.debug("Set job start time", startTime)
            elif not endTime and newStat in JobStatus.JOB_FINAL_STATES:
                # Pick up the end time when the job is in a final status
                endTime = updTime
                log.debug("Set job end time", endTime)

        # We should only update the status to the last one if its time stamp is more recent than the last update
        attrNames = []
        attrValues = []
        if updateTimes[-1] >= lastTime:
            minor = ""
            application = ""
            # Get the last status values looping on the most recent upupdateTimes in chronological order
            for updTime in [dt for dt in updateTimes if dt >= lastTime]:
                sDict = statusDict[updTime]
                log.debug("\t",
                          "Time %s - Statuses %s" % (updTime, str(sDict)))
                status = sDict.get("Status", currentStatus)
                # evaluate the state machine if the status is changing
                if not force and status != currentStatus:
                    res = JobStatus.JobsStateMachine(
                        currentStatus).getNextState(status)
                    if not res["OK"]:
                        return res
                    newStat = res["Value"]
                    # If the JobsStateMachine does not accept the candidate, don't update
                    if newStat != status:
                        # keeping the same status
                        log.error(
                            "Job Status Error",
                            "%s can't move from %s to %s: using %s" %
                            (jobID, currentStatus, status, newStat),
                        )
                        status = newStat
                        sDict["Status"] = newStat
                        # Change the source to indicate this is not what was requested
                        source = sDict.get("Source", "")
                        sDict["Source"] = source + "(SM)"
                    # at this stage status == newStat. Set currentStatus to this new status
                    currentStatus = newStat

                minor = sDict.get("MinorStatus", minor)
                application = sDict.get("ApplicationStatus", application)

            log.debug(
                "Final statuses:",
                "status '%s', minor '%s', application '%s'" %
                (status, minor, application))
            if status:
                attrNames.append("Status")
                attrValues.append(status)
            if minor:
                attrNames.append("MinorStatus")
                attrValues.append(minor)
            if application:
                attrNames.append("ApplicationStatus")
                attrValues.append(application)
            # Here we are forcing the update as it's always updating to the last status
            result = cls.jobDB.setJobAttributes(jobID,
                                                attrNames,
                                                attrValues,
                                                update=True,
                                                force=True)
            if not result["OK"]:
                return result

        # Update start and end time if needed
        if endTime:
            result = cls.jobDB.setEndExecTime(jobID, endTime)
            if not result["OK"]:
                return result
        if startTime:
            result = cls.jobDB.setStartExecTime(jobID, startTime)
            if not result["OK"]:
                return result

        # Update the JobLoggingDB records
        heartBeatTime = None
        for updTime in updateTimes:
            sDict = statusDict[updTime]
            status = sDict.get("Status", "idem")
            minor = sDict.get("MinorStatus", "idem")
            application = sDict.get("ApplicationStatus", "idem")
            source = sDict.get("Source", "Unknown")
            result = cls.jobLoggingDB.addLoggingRecord(
                jobID,
                status=status,
                minorStatus=minor,
                applicationStatus=application,
                date=updTime,
                source=source)
            if not result["OK"]:
                return result
            # If the update comes from a job, update the heart beat time stamp with this item's stamp
            if source.startswith("Job"):
                heartBeatTime = updTime
        if heartBeatTime is not None:
            result = cls.jobDB.setHeartBeatData(
                jobID, {"HeartBeatTime": heartBeatTime})
            if not result["OK"]:
                return result

        return S_OK((attrNames, attrValues))
Exemplo n.º 11
0
  def export_getJobPageSummaryWeb(self, selectDict, sortList, startItem, maxItems, selectJobs=True):
    """ Get the summary of the job information for a given page in the
        job monitor in a generic format
    """
    resultDict = {}
    startDate = selectDict.get('FromDate', None)
    if startDate:
      del selectDict['FromDate']
    # For backward compatibility
    if startDate is None:
      startDate = selectDict.get('LastUpdate', None)
      if startDate:
        del selectDict['LastUpdate']
    endDate = selectDict.get('ToDate', None)
    if endDate:
      del selectDict['ToDate']

    result = self.jobPolicy.getControlledUsers(RIGHT_GET_INFO)
    if not result['OK']:
      return S_ERROR('Failed to evaluate user rights')
    if result['Value'] != 'ALL':
      selectDict[('Owner', 'OwnerGroup')] = result['Value']

    # Sorting instructions. Only one for the moment.
    if sortList:
      orderAttribute = sortList[0][0] + ":" + sortList[0][1]
    else:
      orderAttribute = None

    statusDict = {}
    result = gJobDB.getCounters('Jobs', ['Status'], selectDict,
                                newer=startDate,
                                older=endDate,
                                timeStamp='LastUpdateTime')

    nJobs = 0
    if result['OK']:
      for stDict, count in result['Value']:
        nJobs += count
        statusDict[stDict['Status']] = count

    resultDict['TotalRecords'] = nJobs
    if nJobs == 0:
      return S_OK(resultDict)

    resultDict['Extras'] = statusDict

    if selectJobs:
      iniJob = startItem
      if iniJob >= nJobs:
        return S_ERROR('Item number out of range')

      result = gJobDB.selectJobs(selectDict, orderAttribute=orderAttribute,
                                 newer=startDate, older=endDate, limit=(maxItems, iniJob))
      if not result['OK']:
        return S_ERROR('Failed to select jobs: ' + result['Message'])

      summaryJobList = result['Value']
      if not self.globalJobsInfo:
        validJobs, _invalidJobs, _nonauthJobs, _ownJobs = self.jobPolicy.evaluateJobRights(summaryJobList,
                                                                                           RIGHT_GET_INFO)
        summaryJobList = validJobs

      result = gJobDB.getAttributesForJobList(summaryJobList, SUMMARY)
      if not result['OK']:
        return S_ERROR('Failed to get job summary: ' + result['Message'])

      summaryDict = result['Value']

      # Evaluate last sign of life time
      for jobID, jobDict in summaryDict.items():
        if jobDict['HeartBeatTime'] == 'None':
          jobDict['LastSignOfLife'] = jobDict['LastUpdateTime']
        else:
          lastTime = Time.fromString(jobDict['LastUpdateTime'])
          hbTime = Time.fromString(jobDict['HeartBeatTime'])
          # There is no way to express a timedelta of 0 ;-)
          # Not only Stalled jobs but also Failed jobs because Stalled
          if ((hbTime - lastTime) > (lastTime - lastTime) or
              jobDict['Status'] == "Stalled" or
              jobDict['MinorStatus'].startswith('Job stalled') or
              jobDict['MinorStatus'].startswith('Stalling')):
            jobDict['LastSignOfLife'] = jobDict['HeartBeatTime']
          else:
            jobDict['LastSignOfLife'] = jobDict['LastUpdateTime']

      tqDict = {}
      result = gTaskQueueDB.getTaskQueueForJobs(summaryJobList)
      if result['OK']:
        tqDict = result['Value']

      # If no jobs can be selected after the properties check
      if not summaryDict.keys():
        return S_OK(resultDict)

      # prepare the standard structure now
      key = summaryDict.keys()[0]
      paramNames = summaryDict[key].keys()

      records = []
      for jobID, jobDict in summaryDict.items():
        jParList = []
        for pname in paramNames:
          jParList.append(jobDict[pname])
        jParList.append(tqDict.get(jobID, 0))
        records.append(jParList)

      resultDict['ParameterNames'] = paramNames + ['TaskQueueID']
      resultDict['Records'] = records

    return S_OK(resultDict)
Exemplo n.º 12
0
  def __parseFormParams(self):
    params = self.request.arguments

    pD = {}
    extraParams = {}
    pinDates = False

    for name in params:
      if name.find("_") != 0:
        continue
      value = params[name][0]
      name = name[1:]
      pD[name] = str(value)

    # Personalized title?
    if 'plotTitle' in pD:
      extraParams['plotTitle'] = pD['plotTitle']
      del(pD['plotTitle'])
    # Pin dates?
    if 'pinDates' in pD:
      pinDates = pD['pinDates']
      del(pD['pinDates'])
      pinDates = pinDates.lower() in ("yes", "y", "true", "1")
    # Get plotname
    if 'grouping' not in pD:
      return S_ERROR("Missing grouping!")
    grouping = pD['grouping']
    # Get plotname
    if 'typeName' not in pD:
      return S_ERROR("Missing type name!")
    typeName = pD['typeName']
    del(pD['typeName'])
    # Get plotname
    if 'plotName' not in pD:
      return S_ERROR("Missing plot name!")
    reportName = pD['plotName']
    del(pD['plotName'])
    # Get times
    if 'timeSelector' not in pD:
      return S_ERROR("Missing time span!")
    # Find the proper time!
    pD['timeSelector'] = int(pD['timeSelector'])
    if pD['timeSelector'] > 0:
      end = Time.dateTime()
      start = end - datetime.timedelta(seconds=pD['timeSelector'])
      if not pinDates:
        extraParams['lastSeconds'] = pD['timeSelector']
    else:
      if 'endTime' not in pD:
        end = False
      else:
        end = Time.fromString(pD['endTime'])
        del(pD['endTime'])
      if 'startTime' not in pD:
        return S_ERROR("Missing starTime!")
      else:
        start = Time.fromString(pD['startTime'])
        del(pD['startTime'])
    del(pD['timeSelector'])

    for k in pD:
      if k.find("ex_") == 0:
        extraParams[k[3:]] = pD[k]
    # Listify the rest
    for selName in pD:
      if selName == 'grouping':
        pD[selName] = [pD[selName]]
      else:
        try:
          pD[selName] = json.loads(pD[selName])
        except ValueError:
          pD[selName] = List.fromChar(pD[selName], ",")

    return S_OK((typeName, reportName, start, end, pD, grouping, extraParams))
Exemplo n.º 13
0
  def __parseJobStatus( self, job, gridType ):
    """ Parse output of grid pilot status command
    """

    statusRE = 'Current Status:\s*(\w*)'
    destinationRE = 'Destination:\s*([\w\.-]*)'
    statusDateLCGRE = 'reached on:\s*....(.*)'
    submittedDateRE = 'Submitted:\s*....(.*)'
    statusFailedRE = 'Current Status:.*\(Failed\)'

    status = None
    destination = 'Unknown'
    statusDate = None
    submittedDate = None

    try:
      status = re.search( statusRE, job ).group( 1 )
      if status == 'Done' and re.search( statusFailedRE, job ):
        status = 'Failed'
      if re.search( destinationRE, job ):
        destination = re.search( destinationRE, job ).group( 1 )
      if gridType == 'LCG' and re.search( statusDateLCGRE, job ):
        statusDate = re.search( statusDateLCGRE, job ).group( 1 )
        statusDate = time.strftime( '%Y-%m-%d %H:%M:%S', time.strptime( statusDate, '%b %d %H:%M:%S %Y' ) )
      if gridType == 'gLite' and re.search( submittedDateRE, job ):
        submittedDate = re.search( submittedDateRE, job ).group( 1 )
        submittedDate = time.strftime( '%Y-%m-%d %H:%M:%S', time.strptime( submittedDate, '%b %d %H:%M:%S %Y %Z' ) )
    except:
      self.log.exception( 'Error parsing %s Job Status output:\n' % gridType, job )

    isParent = False
    if re.search( 'Nodes information', job ):
      isParent = True
    isChild = False
    if re.search( 'Parent Job', job ):
      isChild = True

    if status == "Running":
      # Pilots can be in Running state for too long, due to bugs in the WMS
      if statusDate:
        statusTime = Time.fromString( statusDate )
        delta = Time.dateTime() - statusTime
        if delta > 4 * Time.day:
          self.log.info( 'Setting pilot status to Deleted after 4 days in Running' )
          status = "Deleted"
          statusDate = statusTime + 4 * Time.day
      elif submittedDate:
        statusTime = Time.fromString( submittedDate )
        delta = Time.dateTime() - statusTime
        if delta > 7 * Time.day:
          self.log.info( 'Setting pilot status to Deleted more than 7 days after submission still in Running' )
          status = "Deleted"
          statusDate = statusTime + 7 * Time.day

    childRefs = []
    childDicts = {}
    if isParent:
      for subjob in List.fromChar( job, ' Status info for the Job :' )[1:]:
        chRef = List.fromChar( subjob, '\n' )[0].strip()
        childDict = self.__parseJobStatus( subjob, gridType )
        childRefs.append( chRef )
        childDicts[chRef] = childDict

    return { 'Status': status,
             'DestinationSite': destination,
             'StatusDate': statusDate,
             'isChild': isChild,
             'isParent': isParent,
             'ParentRef': False,
             'FinalStatus' : status in self.finalStateList,
             'ChildRefs' : childRefs,
             'ChildDicts' : childDicts }
Exemplo n.º 14
0
def tupleToMessage( varTuple ):
  varList = list( varTuple )
  varList[ 2 ] = Time.fromString( varList[ 2 ] )
  return Message( *varList )
Exemplo n.º 15
0
    def export_getJobPageSummaryWeb(self,
                                    selectDict,
                                    sortList,
                                    startItem,
                                    maxItems,
                                    selectJobs=True):
        """ Get the summary of the job information for a given page in the
        job monitor in a generic format
    """
        resultDict = {}
        startDate = selectDict.get('FromDate', None)
        if startDate:
            del selectDict['FromDate']
        # For backward compatibility
        if startDate is None:
            startDate = selectDict.get('LastUpdate', None)
            if startDate:
                del selectDict['LastUpdate']
        endDate = selectDict.get('ToDate', None)
        if endDate:
            del selectDict['ToDate']

        # Sorting instructions. Only one for the moment.
        if sortList:
            orderAttribute = sortList[0][0] + ":" + sortList[0][1]
        else:
            orderAttribute = None

        if selectJobs:
            result = jobDB.selectJobs(selectDict,
                                      orderAttribute=orderAttribute,
                                      newer=startDate,
                                      older=endDate)
            if not result['OK']:
                return S_ERROR('Failed to select jobs: ' + result['Message'])

            jobList = result['Value']

            # A.T. This needs optimization
            #validJobList, invalidJobList, nonauthJobList, ownerJobList = self.jobPolicy.evaluateJobRights( jobList,
            #                                                                                               RIGHT_GET_INFO )
            #jobList = validJobList

            nJobs = len(jobList)
            resultDict['TotalRecords'] = nJobs
            if nJobs == 0:
                return S_OK(resultDict)

            iniJob = startItem
            lastJob = iniJob + maxItems
            if iniJob >= nJobs:
                return S_ERROR('Item number out of range')

            if lastJob > nJobs:
                lastJob = nJobs

            summaryJobList = jobList[iniJob:lastJob]
            result = jobDB.getAttributesForJobList(summaryJobList, SUMMARY)
            if not result['OK']:
                return S_ERROR('Failed to get job summary: ' +
                               result['Message'])

            summaryDict = result['Value']

            # Evaluate last sign of life time
            for jobID, jobDict in summaryDict.items():
                if jobDict['HeartBeatTime'] == 'None':
                    jobDict['LastSignOfLife'] = jobDict['LastUpdateTime']
                else:
                    lastTime = Time.fromString(jobDict['LastUpdateTime'])
                    hbTime = Time.fromString(jobDict['HeartBeatTime'])
                    if (hbTime - lastTime) > (
                            lastTime -
                            lastTime) or jobDict['Status'] == "Stalled":
                        jobDict['LastSignOfLife'] = jobDict['HeartBeatTime']
                    else:
                        jobDict['LastSignOfLife'] = jobDict['LastUpdateTime']

            tqDict = {}
            result = taskQueueDB.getTaskQueueForJobs(summaryJobList)
            if result['OK']:
                tqDict = result['Value']

            # prepare the standard structure now
            key = summaryDict.keys()[0]
            paramNames = summaryDict[key].keys()

            records = []
            for jobID, jobDict in summaryDict.items():
                jParList = []
                for pname in paramNames:
                    jParList.append(jobDict[pname])
                if tqDict and tqDict.has_key(jobID):
                    jParList.append(tqDict[jobID])
                else:
                    jParList.append(0)
                records.append(jParList)

            resultDict['ParameterNames'] = paramNames + ['TaskQueueID']
            resultDict['Records'] = records

        statusDict = {}
        result = jobDB.getCounters('Jobs', ['Status'],
                                   selectDict,
                                   newer=startDate,
                                   older=endDate,
                                   timeStamp='LastUpdateTime')
        if result['OK']:
            for stDict, count in result['Value']:
                statusDict[stDict['Status']] = count
        resultDict['Extras'] = statusDict

        return S_OK(resultDict)
Exemplo n.º 16
0
    def export_getJobPageSummaryWeb(self,
                                    selectDict,
                                    sortList,
                                    startItem,
                                    maxItems,
                                    selectJobs=True):
        """ Get the summary of the job information for a given page in the
        job monitor in a generic format
    """
        resultDict = {}
        startDate = selectDict.get('FromDate', None)
        if startDate:
            del selectDict['FromDate']
        # For backward compatibility
        if startDate is None:
            startDate = selectDict.get('LastUpdate', None)
            if startDate:
                del selectDict['LastUpdate']
        endDate = selectDict.get('ToDate', None)
        if endDate:
            del selectDict['ToDate']

        # Provide JobID bound to a specific PilotJobReference
        # There is no reason to have both PilotJobReference and JobID in selectDict
        # If that occurs, use the JobID instead of the PilotJobReference
        pilotJobRefs = selectDict.get('PilotJobReference')
        if pilotJobRefs:
            del selectDict['PilotJobReference']
            if 'JobID' not in selectDict or not selectDict['JobID']:
                if not isinstance(pilotJobRefs, list):
                    pilotJobRefs = [pilotJobRefs]
                selectDict['JobID'] = []
                for pilotJobRef in pilotJobRefs:
                    res = PilotManagerClient().getPilotInfo(pilotJobRef)
                    if res['OK'] and 'Jobs' in res['Value'][pilotJobRef]:
                        selectDict['JobID'].extend(
                            res['Value'][pilotJobRef]['Jobs'])

        result = self.jobPolicy.getControlledUsers(RIGHT_GET_INFO)
        if not result['OK']:
            return S_ERROR('Failed to evaluate user rights')
        if result['Value'] != 'ALL':
            selectDict[('Owner', 'OwnerGroup')] = result['Value']

        # Sorting instructions. Only one for the moment.
        if sortList:
            orderAttribute = sortList[0][0] + ":" + sortList[0][1]
        else:
            orderAttribute = None

        statusDict = {}
        result = self.gJobDB.getCounters('Jobs', ['Status'],
                                         selectDict,
                                         newer=startDate,
                                         older=endDate,
                                         timeStamp='LastUpdateTime')

        nJobs = 0
        if result['OK']:
            for stDict, count in result['Value']:
                nJobs += count
                statusDict[stDict['Status']] = count

        resultDict['TotalRecords'] = nJobs
        if nJobs == 0:
            return S_OK(resultDict)

        resultDict['Extras'] = statusDict

        if selectJobs:
            iniJob = startItem
            if iniJob >= nJobs:
                return S_ERROR('Item number out of range')

            result = self.gJobDB.selectJobs(selectDict,
                                            orderAttribute=orderAttribute,
                                            newer=startDate,
                                            older=endDate,
                                            limit=(maxItems, iniJob))
            if not result['OK']:
                return S_ERROR('Failed to select jobs: ' + result['Message'])

            summaryJobList = result['Value']
            if not self.globalJobsInfo:
                validJobs, _invalidJobs, _nonauthJobs, _ownJobs = self.jobPolicy.evaluateJobRights(
                    summaryJobList, RIGHT_GET_INFO)
                summaryJobList = validJobs

            result = self.getAttributesForJobList(summaryJobList, SUMMARY)
            if not result['OK']:
                return S_ERROR('Failed to get job summary: ' +
                               result['Message'])

            summaryDict = result['Value']

            # Evaluate last sign of life time
            for jobID, jobDict in summaryDict.items():
                if jobDict['HeartBeatTime'] == 'None':
                    jobDict['LastSignOfLife'] = jobDict['LastUpdateTime']
                else:
                    lastTime = Time.fromString(jobDict['LastUpdateTime'])
                    hbTime = Time.fromString(jobDict['HeartBeatTime'])
                    # Not only Stalled jobs but also Failed jobs because Stalled
                    if ((hbTime - lastTime) > timedelta(0)
                            or jobDict['Status'] == "Stalled"
                            or jobDict['MinorStatus'].startswith('Job stalled')
                            or jobDict['MinorStatus'].startswith('Stalling')):
                        jobDict['LastSignOfLife'] = jobDict['HeartBeatTime']
                    else:
                        jobDict['LastSignOfLife'] = jobDict['LastUpdateTime']

            tqDict = {}
            result = self.gTaskQueueDB.getTaskQueueForJobs(summaryJobList)
            if result['OK']:
                tqDict = result['Value']

            # If no jobs can be selected after the properties check
            if not summaryDict.keys():
                return S_OK(resultDict)

            # prepare the standard structure now
            key = summaryDict.keys()[0]
            paramNames = summaryDict[key].keys()

            records = []
            for jobID, jobDict in summaryDict.items():
                jParList = []
                for pname in paramNames:
                    jParList.append(jobDict[pname])
                jParList.append(tqDict.get(jobID, 0))
                records.append(jParList)

            resultDict['ParameterNames'] = paramNames + ['TaskQueueID']
            resultDict['Records'] = records

        return S_OK(resultDict)
Exemplo n.º 17
0
  def export_getJobPageSummaryWeb( self, selectDict, sortList, startItem, maxItems, selectJobs = True ):
    """ Get the summary of the job information for a given page in the
        job monitor in a generic format
    """
    resultDict = {}
    startDate = selectDict.get( 'FromDate', None )
    if startDate:
      del selectDict['FromDate']
    # For backward compatibility
    if startDate is None:
      startDate = selectDict.get( 'LastUpdate', None )
      if startDate:
        del selectDict['LastUpdate']
    endDate = selectDict.get( 'ToDate', None )
    if endDate:
      del selectDict['ToDate']

    # Sorting instructions. Only one for the moment.
    if sortList:
      orderAttribute = sortList[0][0] + ":" + sortList[0][1]
    else:
      orderAttribute = None

    if selectJobs:
      result = jobDB.selectJobs( selectDict, orderAttribute = orderAttribute,
                                newer = startDate, older = endDate )
      if not result['OK']:
        return S_ERROR( 'Failed to select jobs: ' + result['Message'] )

      jobList = result['Value']
      
      # A.T. This needs optimization
      #validJobList, invalidJobList, nonauthJobList, ownerJobList = self.jobPolicy.evaluateJobRights( jobList,
      #                                                                                               RIGHT_GET_INFO )
      #jobList = validJobList
      
      nJobs = len( jobList )
      resultDict['TotalRecords'] = nJobs
      if nJobs == 0:
        return S_OK( resultDict )

      iniJob = startItem
      lastJob = iniJob + maxItems
      if iniJob >= nJobs:
        return S_ERROR( 'Item number out of range' )

      if lastJob > nJobs:
        lastJob = nJobs

      summaryJobList = jobList[iniJob:lastJob]
      result = jobDB.getAttributesForJobList( summaryJobList, SUMMARY )
      if not result['OK']:
        return S_ERROR( 'Failed to get job summary: ' + result['Message'] )

      summaryDict = result['Value']

      # Evaluate last sign of life time
      for jobID, jobDict in summaryDict.items():
        if jobDict['HeartBeatTime'] == 'None':
          jobDict['LastSignOfLife'] = jobDict['LastUpdateTime']
        else:
          lastTime = Time.fromString( jobDict['LastUpdateTime'] )
          hbTime = Time.fromString( jobDict['HeartBeatTime'] )
          if ( hbTime - lastTime ) > ( lastTime - lastTime ) or jobDict['Status'] == "Stalled":
            jobDict['LastSignOfLife'] = jobDict['HeartBeatTime']
          else:
            jobDict['LastSignOfLife'] = jobDict['LastUpdateTime']

      tqDict = {}
      result = taskQueueDB.getTaskQueueForJobs( summaryJobList )
      if result['OK']:
        tqDict = result['Value']

      # prepare the standard structure now
      key = summaryDict.keys()[0]
      paramNames = summaryDict[key].keys()

      records = []
      for jobID, jobDict in summaryDict.items():
        jParList = []
        for pname in paramNames:
          jParList.append( jobDict[pname] )
        if tqDict and tqDict.has_key( jobID ):
          jParList.append( tqDict[jobID] )
        else:
          jParList.append( 0 )
        records.append( jParList )

      resultDict['ParameterNames'] = paramNames + ['TaskQueueID']
      resultDict['Records'] = records

    statusDict = {}
    result = jobDB.getCounters( 'Jobs', ['Status'], selectDict,
                               newer = startDate,
                               older = endDate,
                               timeStamp = 'LastUpdateTime' )
    if result['OK']:
      for stDict, count in result['Value']:
        statusDict[stDict['Status']] = count
    resultDict['Extras'] = statusDict

    return S_OK( resultDict )
Exemplo n.º 18
0
    def addLoggingRecord(
        self,
        jobID,
        status=None,
        minorStatus=None,
        applicationStatus=None,
        date=None,
        source=None,
        minor=None,
        application=None,
    ):
        """Add a new entry to the JobLoggingDB table. One, two or all the three status
        components (status, minorStatus, applicationStatus) can be specified.
        Optionally the time stamp of the status can
        be provided in a form of a string in a format '%Y-%m-%d %H:%M:%S' or
        as datetime.datetime object. If the time stamp is not provided the current
        UTC time is used.
        """

        # Backward compatibility
        # FIXME: to remove in next version
        if minor:
            minorStatus = minor
        if application:
            applicationStatus = application

        status = status or "idem"
        minorStatus = minorStatus or "idem"
        applicationStatus = applicationStatus or "idem"
        source = source or "Unknown"

        event = "status/minor/app=%s/%s/%s" % (status, minorStatus,
                                               applicationStatus)
        self.log.info("Adding record for job ",
                      str(jobID) + ": '" + event + "' from " + source)

        try:
            if not date:
                # Make the UTC datetime string and float
                _date = Time.dateTime()
            elif isinstance(date, six.string_types):
                # The date is provided as a string in UTC
                _date = Time.fromString(date)
            elif isinstance(date, Time._dateTimeType):
                _date = date
            else:
                self.log.error("Incorrect date for the logging record")
                _date = Time.dateTime()
        except Exception:
            self.log.exception("Exception while date evaluation")
            _date = Time.dateTime()
        epoc = time.mktime(_date.timetuple(
        )) + _date.microsecond / 1000000.0 - MAGIC_EPOC_NUMBER

        cmd = (
            "INSERT INTO LoggingInfo (JobId, Status, MinorStatus, ApplicationStatus, "
            +
            "StatusTime, StatusTimeOrder, StatusSource) VALUES (%d,'%s','%s','%s','%s',%f,'%s')"
            % (int(jobID), status, minorStatus, applicationStatus[:255],
               str(_date), epoc, source[:32]))

        return self._update(cmd)
Exemplo n.º 19
0
  def export_getJobPageSummaryWeb( self, selectDict, sortList, startItem, maxItems, selectJobs = True ):
    """ Get the summary of the job information for a given page in the
        job monitor in a generic format
    """
    resultDict = {}
    startDate = selectDict.get( 'FromDate', None )
    if startDate:
      del selectDict['FromDate']
    # For backward compatibility
    if startDate is None:
      startDate = selectDict.get( 'LastUpdate', None )
      if startDate:
        del selectDict['LastUpdate']
    endDate = selectDict.get( 'ToDate', None )
    if endDate:
      del selectDict['ToDate']

    result = self.jobPolicy.getControlledUsers( RIGHT_GET_INFO )
    if not result['OK']:
      return S_ERROR( 'Failed to evaluate user rights' )
    if result['Value'] != 'ALL':
      selectDict[ ( 'Owner', 'OwnerGroup' ) ] = result['Value']

    # Sorting instructions. Only one for the moment.
    if sortList:
      orderAttribute = sortList[0][0] + ":" + sortList[0][1]
    else:
      orderAttribute = None

    statusDict = {}
    result = gJobDB.getCounters( 'Jobs', ['Status'], selectDict,
                               newer = startDate,
                               older = endDate,
                               timeStamp = 'LastUpdateTime' )

    nJobs = 0
    if result['OK']:
      for stDict, count in result['Value']:
        nJobs += count
        statusDict[stDict['Status']] = count

    resultDict['TotalRecords'] = nJobs
    if nJobs == 0:
      return S_OK( resultDict )

    resultDict['Extras'] = statusDict

    if selectJobs:
      iniJob = startItem
      if iniJob >= nJobs:
        return S_ERROR( 'Item number out of range' )

      result = gJobDB.selectJobs( selectDict, orderAttribute = orderAttribute,
                                newer = startDate, older = endDate, limit = ( maxItems, iniJob ) )
      if not result['OK']:
        return S_ERROR( 'Failed to select jobs: ' + result['Message'] )

      summaryJobList = result['Value']
      if not self.globalJobsInfo:      
        validJobs, _invalidJobs, _nonauthJobs, _ownJobs = self.jobPolicy.evaluateJobRights( summaryJobList,
                                                                                            RIGHT_GET_INFO )
        summaryJobList = validJobs

      result = gJobDB.getAttributesForJobList( summaryJobList, SUMMARY )
      if not result['OK']:
        return S_ERROR( 'Failed to get job summary: ' + result['Message'] )

      summaryDict = result['Value']

      # Evaluate last sign of life time
      for jobID, jobDict in summaryDict.items():
        if jobDict['HeartBeatTime'] == 'None':
          jobDict['LastSignOfLife'] = jobDict['LastUpdateTime']
        else:
          lastTime = Time.fromString( jobDict['LastUpdateTime'] )
          hbTime = Time.fromString( jobDict['HeartBeatTime'] )
          if ( hbTime - lastTime ) > ( lastTime - lastTime ) or jobDict['Status'] == "Stalled":
            jobDict['LastSignOfLife'] = jobDict['HeartBeatTime']
          else:
            jobDict['LastSignOfLife'] = jobDict['LastUpdateTime']

      tqDict = {}
      result = gTaskQueueDB.getTaskQueueForJobs( summaryJobList )
      if result['OK']:
        tqDict = result['Value']

      # If no jobs can be selected after the properties check
      if not summaryDict.keys():
        return S_OK( resultDict )

      # prepare the standard structure now
      key = summaryDict.keys()[0]
      paramNames = summaryDict[key].keys()

      records = []
      for jobID, jobDict in summaryDict.items():
        jParList = []
        for pname in paramNames:
          jParList.append( jobDict[pname] )
        jParList.append( tqDict.get( jobID, 0 ) )
        records.append( jParList )

      resultDict['ParameterNames'] = paramNames + ['TaskQueueID']
      resultDict['Records'] = records

    return S_OK( resultDict )
Exemplo n.º 20
0
    def __parseJobStatus(self, job, gridType):
        """ Parse output of grid pilot status command
    """

        statusRE = 'Current Status:\s*(\w*)'
        destinationRE = 'Destination:\s*([\w\.-]*)'
        statusDateLCGRE = 'reached on:\s*....(.*)'
        submittedDateRE = 'Submitted:\s*....(.*)'
        statusFailedRE = 'Current Status:.*\(Failed\)'

        status = None
        destination = 'Unknown'
        statusDate = None
        submittedDate = None

        try:
            status = re.search(statusRE, job).group(1)
            if status == 'Done' and re.search(statusFailedRE, job):
                status = 'Failed'
            if re.search(destinationRE, job):
                destination = re.search(destinationRE, job).group(1)
            if gridType == 'LCG' and re.search(statusDateLCGRE, job):
                statusDate = re.search(statusDateLCGRE, job).group(1)
                statusDate = time.strftime(
                    '%Y-%m-%d %H:%M:%S',
                    time.strptime(statusDate, '%b %d %H:%M:%S %Y'))
            if gridType == 'gLite' and re.search(submittedDateRE, job):
                submittedDate = re.search(submittedDateRE, job).group(1)
                submittedDate = time.strftime(
                    '%Y-%m-%d %H:%M:%S',
                    time.strptime(submittedDate, '%b %d %H:%M:%S %Y %Z'))
        except:
            self.log.exception(
                'Error parsing %s Job Status output:\n' % gridType, job)

        isParent = False
        if re.search('Nodes information', job):
            isParent = True
        isChild = False
        if re.search('Parent Job', job):
            isChild = True

        if status == "Running":
            # Pilots can be in Running state for too long, due to bugs in the WMS
            if statusDate:
                statusTime = Time.fromString(statusDate)
                delta = Time.dateTime() - statusTime
                if delta > 4 * Time.day:
                    self.log.info(
                        'Setting pilot status to Deleted after 4 days in Running'
                    )
                    status = "Deleted"
                    statusDate = statusTime + 4 * Time.day
            elif submittedDate:
                statusTime = Time.fromString(submittedDate)
                delta = Time.dateTime() - statusTime
                if delta > 7 * Time.day:
                    self.log.info(
                        'Setting pilot status to Deleted more than 7 days after submission still in Running'
                    )
                    status = "Deleted"
                    statusDate = statusTime + 7 * Time.day

        childRefs = []
        childDicts = {}
        if isParent:
            for subjob in List.fromChar(job, ' Status info for the Job :')[1:]:
                chRef = List.fromChar(subjob, '\n')[0].strip()
                childDict = self.__parseJobStatus(subjob, gridType)
                childRefs.append(chRef)
                childDicts[chRef] = childDict

        return {
            'Status': status,
            'DestinationSite': destination,
            'StatusDate': statusDate,
            'isChild': isChild,
            'isParent': isParent,
            'ParentRef': False,
            'FinalStatus': status in self.finalStateList,
            'ChildRefs': childRefs,
            'ChildDicts': childDicts
        }
Exemplo n.º 21
0
    def __parseJobStatus(self, job, gridType):
        """ Parse output of grid pilot status command
    """

        statusRE = "Current Status:\s*(\w*)"
        destinationRE = "Destination:\s*([\w\.-]*)"
        statusDateLCGRE = "reached on:\s*....(.*)"
        submittedDateRE = "Submitted:\s*....(.*)"
        statusFailedRE = "Current Status:.*\(Failed\)"

        status = None
        destination = "Unknown"
        statusDate = None
        submittedDate = None

        try:
            status = re.search(statusRE, job).group(1)
            if status == "Done" and re.search(statusFailedRE, job):
                status = "Failed"
            if re.search(destinationRE, job):
                destination = re.search(destinationRE, job).group(1)
            if gridType == "LCG" and re.search(statusDateLCGRE, job):
                statusDate = re.search(statusDateLCGRE, job).group(1)
                statusDate = time.strftime("%Y-%m-%d %H:%M:%S", time.strptime(statusDate, "%b %d %H:%M:%S %Y"))
            if gridType == "gLite" and re.search(submittedDateRE, job):
                submittedDate = re.search(submittedDateRE, job).group(1)
                submittedDate = time.strftime("%Y-%m-%d %H:%M:%S", time.strptime(submittedDate, "%b %d %H:%M:%S %Y %Z"))
        except:
            self.log.exception("Error parsing %s Job Status output:\n" % gridType, job)

        isParent = False
        if re.search("Nodes information", job):
            isParent = True
        isChild = False
        if re.search("Parent Job", job):
            isChild = True

        if status == "Running":
            # Pilots can be in Running state for too long, due to bugs in the WMS
            if statusDate:
                statusTime = Time.fromString(statusDate)
                delta = Time.dateTime() - statusTime
                if delta > 4 * Time.day:
                    self.log.info("Setting pilot status to Deleted after 4 days in Running")
                    status = "Deleted"
                    statusDate = statusTime + 4 * Time.day
            elif submittedDate:
                statusTime = Time.fromString(submittedDate)
                delta = Time.dateTime() - statusTime
                if delta > 7 * Time.day:
                    self.log.info("Setting pilot status to Deleted more than 7 days after submission still in Running")
                    status = "Deleted"
                    statusDate = statusTime + 7 * Time.day

        childRefs = []
        childDicts = {}
        if isParent:
            for subjob in List.fromChar(job, " Status info for the Job :")[1:]:
                chRef = List.fromChar(subjob, "\n")[0].strip()
                childDict = self.__parseJobStatus(subjob, gridType)
                childRefs.append(chRef)
                childDicts[chRef] = childDict

        return {
            "Status": status,
            "DestinationSite": destination,
            "StatusDate": statusDate,
            "isChild": isChild,
            "isParent": isParent,
            "ParentRef": False,
            "FinalStatus": status in self.finalStateList,
            "ChildRefs": childRefs,
            "ChildDicts": childDicts,
        }
 def __dateToSecs(self, timeVar):
     dt = Time.fromString(timeVar)
     return int(Time.toEpoch(dt))
Exemplo n.º 23
0
 def __dateToSecs( self, timeVar ):
   dt = Time.fromString( timeVar )
   return int( Time.toEpoch( dt ) )
Exemplo n.º 24
0
    def export_getJobPageSummaryWeb(self,
                                    selectDict,
                                    sortList,
                                    startItem,
                                    maxItems,
                                    selectJobs=True):
        """Get the summary of the job information for a given page in the
        job monitor in a generic format
        """

        resultDict = {}

        startDate, endDate, selectDict = self.parseSelectors(selectDict)

        # initialize jobPolicy
        credDict = self.getRemoteCredentials()
        ownerDN = credDict["DN"]
        ownerGroup = credDict["group"]
        operations = Operations(group=ownerGroup)
        globalJobsInfo = operations.getValue(
            "/Services/JobMonitoring/GlobalJobsInfo", True)
        jobPolicy = JobPolicy(ownerDN, ownerGroup, globalJobsInfo)
        jobPolicy.jobDB = self.jobDB
        result = jobPolicy.getControlledUsers(RIGHT_GET_INFO)
        if not result["OK"]:
            return result
        if not result["Value"]:
            return S_ERROR(
                "User and group combination has no job rights (%r, %r)" %
                (ownerDN, ownerGroup))
        if result["Value"] != "ALL":
            selectDict[("Owner", "OwnerGroup")] = result["Value"]

        # Sorting instructions. Only one for the moment.
        if sortList:
            orderAttribute = sortList[0][0] + ":" + sortList[0][1]
        else:
            orderAttribute = None

        result = self.jobDB.getCounters("Jobs", ["Status"],
                                        selectDict,
                                        newer=startDate,
                                        older=endDate,
                                        timeStamp="LastUpdateTime")
        if not result["OK"]:
            return result

        statusDict = {}
        nJobs = 0
        for stDict, count in result["Value"]:
            nJobs += count
            statusDict[stDict["Status"]] = count

        resultDict["TotalRecords"] = nJobs
        if nJobs == 0:
            return S_OK(resultDict)

        resultDict["Extras"] = statusDict

        if selectJobs:
            iniJob = startItem
            if iniJob >= nJobs:
                return S_ERROR("Item number out of range")

            result = self.jobDB.selectJobs(selectDict,
                                           orderAttribute=orderAttribute,
                                           newer=startDate,
                                           older=endDate,
                                           limit=(maxItems, iniJob))
            if not result["OK"]:
                return result

            summaryJobList = result["Value"]
            if not globalJobsInfo:
                validJobs, _invalidJobs, _nonauthJobs, _ownJobs = jobPolicy.evaluateJobRights(
                    summaryJobList, RIGHT_GET_INFO)
                summaryJobList = validJobs

            result = self.getJobsAttributes(summaryJobList, SUMMARY)
            if not result["OK"]:
                return result

            summaryDict = result["Value"]
            # If no jobs can be selected after the properties check
            if not summaryDict:
                return S_OK(resultDict)

            # Evaluate last sign of life time
            for jobDict in summaryDict.values():
                if not jobDict.get(
                        "HeartBeatTime") or jobDict["HeartBeatTime"] == "None":
                    jobDict["LastSignOfLife"] = jobDict["LastUpdateTime"]
                elif False:
                    # Code kept in case this is not working, but if we update the HeartBeatTime
                    #     at each status change from the jobs it should not be needed
                    # Items are always strings
                    lastTime = Time.fromString(jobDict["LastUpdateTime"])
                    hbTime = Time.fromString(jobDict["HeartBeatTime"])
                    # Try and identify statuses not set by the job itself as too expensive to get logging info
                    # Not only Stalled jobs but also Failed jobs because Stalled
                    if (hbTime > lastTime
                            or jobDict["Status"] == JobStatus.STALLED
                            or jobDict["MinorStatus"] in (
                                JobMinorStatus.REQUESTS_DONE,
                                JobMinorStatus.STALLED_PILOT_NOT_RUNNING,
                            )
                            or jobDict["MinorStatus"].startswith("Stalling")):
                        jobDict["LastSignOfLife"] = jobDict["HeartBeatTime"]
                    else:
                        jobDict["LastSignOfLife"] = jobDict["LastUpdateTime"]
                else:
                    jobDict["LastSignOfLife"] = jobDict["HeartBeatTime"]

            # prepare the standard structure now
            # This should be faster than making a list of values()
            for jobDict in summaryDict.values():
                paramNames = list(jobDict)
                break
            records = [
                list(jobDict.values()) for jobDict in summaryDict.values()
            ]

            resultDict["ParameterNames"] = paramNames
            resultDict["Records"] = records

        return S_OK(resultDict)