示例#1
0
int MTraceLoadWorkload(

  char     *Buffer,   /* I */
  int      *TraceLen, /* I (optional,modified) */
  mjob_t   *J,        /* O */
  int       Mode,     /* I */
  int      *Version)  /* O */

  {
  char *tail;
  char *head;

  char *ptr;
  char *ptr2;

  char *tok;
  char *TokPtr;

  char Line[MAX_MLINE << 4];
  char tmpLine[MAX_MLINE];

  char MHostName[MAX_MNAME];
  char MReqHList[MAX_MLINE << 2];
  char Reservation[MAX_MNAME];

  char tmpTaskRequest[MAX_MLINE];
  char tmpSpecWCLimit[MAX_MLINE];
  char tmpState[MAX_WORD];
  char tmpOpsys[MAX_WORD];
  char tmpArch[MAX_WORD];
  char tmpNetwork[MAX_WORD];
  char tmpMemCmp[MAX_WORD];
  char tmpDiskCmp[MAX_WORD];
  char tmpReqNFList[MAX_MLINE];
  char tmpClass[MAX_MLINE];
  char tmpRMName[MAX_MLINE];
  char tmpCmd[MAX_MLINE];
  char tmpRMXString[MAX_MLINE >> 2];
  char tmpParName[MAX_MNAME];
  char tmpJFlags[MAX_MLINE];
  char tmpQReq[MAX_WORD];
  char tmpASString[MAX_MLINE];
  char tmpRMemBuf[MAX_MNAME];
  char tmpRDiskBuf[MAX_MNAME];
  char tmpDSwapBuf[MAX_MNAME];
  char tmpDMemBuf[MAX_MNAME];
  char tmpDDiskBuf[MAX_MNAME];
  char UName[MAX_MNAME];
  char GName[MAX_MNAME];
  char AName[MAX_MNAME];

  char SetString[MAX_MLINE];

  unsigned long tmpQTime;
  unsigned long tmpDTime;
  unsigned long tmpSTime;
  unsigned long tmpCTime;

  unsigned long tmpSQTime;


  unsigned long tmpSDate;
  unsigned long tmpEDate;

  int      TPN;
  int      TasksAllocated;
  int      index;
  int      rc;

  int      tindex;
  int      nindex;

  mqos_t  *QDef;

  mreq_t  *RQ[MAX_MREQ_PER_JOB];

  mnode_t *N;

  long     ReqProcSpeed;

  const char *FName = "MTraceLoadWorkload";

  DBG(5,fSIM) DPrint("%s(Buffer,TraceLen,J,%d,%d)\n",
    FName,
    Mode,
    (Version != NULL) ? *Version : -1);

  if (J == NULL)
    {
    DBG(5,fSIM) DPrint("ALERT:    NULL job pointer passed in %s()\n",
      FName);

    return(FAILURE);
    }

  if (Buffer == NULL)
    {
    return(FAILURE);
    }

  if ((tail = strchr(Buffer,'\n')) == NULL)
    {
    /* assume line is '\0' terminated */

    if (TraceLen != NULL)
      tail = Buffer + *TraceLen;
    else
      tail = Buffer + strlen(Buffer);
    }

  head = Buffer;

  MUStrCpy(Line,head,MIN(tail - head + 1,sizeof(Line)));

  DBG(6,fSIM) DPrint("INFO:     parsing trace line '%s'\n",
    Line);

  if (TraceLen != NULL)
    *TraceLen = (tail - head) + 1;

  /* eliminate comments */

  if ((ptr = strchr(Line,'#')) != NULL)
    {
    DBG(5,fSIM) DPrint("INFO:     detected trace comment line, '%s'\n",
      Line);

    *ptr = '\0';
    }

  if (Line[0] == '\0')
    {
    return(FAILURE);
    }

  /* look for VERSION settings */

  if (!strncmp(Line,TRACE_WORKLOAD_VERSION_MARKER,strlen(TRACE_WORKLOAD_VERSION_MARKER)))
    {
    if (MTraceGetWorkloadVersion(Line,Version) == FAILURE)
      {
      DBG(0,fSIM) DPrint("ALERT:    cannot determine workload trace version\n");

      /* assume default version */

      if (Version != NULL)
        *Version = DEFAULT_WORKLOAD_TRACE_VERSION;
      }
    else
      {
      DBG(3,fSIM) DPrint("INFO:     workload trace version %d detected\n",
        (Version != NULL) ? *Version : -1);
      }

    return(FAILURE);
    }  /* END if (!strncmp(Line,TRACE_WORKLOAD_VERSION_MARKER)) */

  /* set default workload attributes */

  memset(J,0,sizeof(mjob_t));

  if (MReqCreate(J,NULL,&J->Req[0],FALSE) == FAILURE)
    {
    DBG(0,fSIM) DPrint("ALERT:    cannot create job req\n");

    return(FAILURE);
    }

  MRMJobPreLoad(J,NULL,0);

  RQ[0]         = J->Req[0];

  RQ[0]->Index  = 0;

  J->StartCount = 0;
  J->R          = NULL;

  switch(*Version)
    {
    case 230:

      /*                Name NR TReq User Grop WClk Stat Clss QUT DST STT CMT netw Arch Opsy MemC RMem DskC RDsk Feat SQT TA TPN QO MO AC CM CC BP PU Part DPrc DMem DDisk DSwap STARTDATE ENDDATE MNODE RM HL RES RES1 RES2 RES3 OVERFLOW */

      rc = sscanf(Line,"%64s %d %64s %64s %64s %64s %64s %64s %lu %lu %lu %lu %64s %64s %64s %64s %64s %64s %64s %64s %lu %d %d %64s %1024s %64s %1024s %1024s %d %lf %64s %d %64s %64s %64s %lu %lu %1024s %64s %1024s %64s %64s %1024s %s %s",
           J->Name,
           &J->Request.NC,
           tmpTaskRequest,
           UName,
           GName,
           tmpSpecWCLimit,
           tmpState,
           tmpClass,
           &tmpQTime,
           &tmpDTime,
           &tmpSTime,
           &tmpCTime,
           tmpNetwork,
           tmpArch,
           tmpOpsys,
           tmpMemCmp,
           tmpRMemBuf,
           tmpDiskCmp,
           tmpRDiskBuf,
           tmpReqNFList,
           &tmpSQTime,             /* SystemQueueTime */
           &TasksAllocated,        /* allocated task count */
           &TPN,
           tmpQReq,
           tmpJFlags,
           AName,
           tmpCmd,
           tmpRMXString,           /* RM extension string */
           &J->Bypass,             /* Bypass          */
           &J->PSUtilized,         /* PSUtilized      */
           tmpParName,             /* partition used  */
           &RQ[0]->DRes.Procs,
           tmpDMemBuf,
           tmpDDiskBuf,
           tmpDSwapBuf,
           &tmpSDate,
           &tmpEDate,
           MHostName,
           tmpRMName,
           MReqHList,
           Reservation,
           SetString,              /* resource sets required by job */
           tmpASString,            /* application simulator name */
           tmpLine,                /* RES1 */
           tmpLine                 /* check for too many fields */
           );

      /* fail if all fields not read in */

      switch (rc)
        {
        case 43:

          strcpy(MHostName,NONE);

          J->RM = &MRM[0];

          break;

        case 44:

          /* canonical 230 trace */

          if (isdigit(tmpRMName[0]))
            J->RM = &MRM[(int)strtol(tmpRMName,NULL,0)];
          else
            J->RM = &MRM[0];

          break;

        default:

          DBG(1,fSIM) DPrint("ALERT:    version %d workload trace is corrupt '%s' (%d of %d fields read) ignoring line\n",
            *Version,
            Line,
            rc,
            44);

          MJobDestroy(&J);

          return(FAILURE);

          /*NOTREACHED*/

          break;
        }  /* END switch(rc) */

      RQ[0]->RequiredMemory = MURSpecToL(tmpRMemBuf,mvmMega,mvmMega);
      RQ[0]->RequiredDisk   = MURSpecToL(tmpRDiskBuf,mvmMega,mvmMega);

      RQ[0]->DRes.Mem       = MURSpecToL(tmpDMemBuf,mvmMega,mvmMega);
      RQ[0]->DRes.Swap      = MURSpecToL(tmpDSwapBuf,mvmMega,mvmMega);
      RQ[0]->DRes.Disk      = MURSpecToL(tmpDDiskBuf,mvmMega,mvmMega);

      if (Mode != msmProfile)
        {
        ptr  = NULL;
        ptr2 = NULL;

        if (strcmp(tmpASString,NONE))
          {
          if ((ptr = MUStrTok(tmpASString,":",&TokPtr)) != NULL)
            {
            ptr2 = MUStrTok(NULL,"|",&TokPtr);
            }
          }

        if (MASGetDriver((void **)&J->ASFunc,ptr,msdApplication) == SUCCESS)
          {
          (*J->ASFunc)(J,mascCreate,ptr2,NULL);
          }
        }    /* END if (Mode != msmProfile) */

      /* obtain job step number from LL based job name */

      /* FORMAT:  <FROM_HOST>.<CLUSTER>.<PROC> */

      MUStrCpy(tmpLine,J->Name,sizeof(tmpLine));

      if ((ptr = MUStrTok(tmpLine,".",&TokPtr)) != NULL)
        {
        MUStrCpy(J->SubmitHost,ptr,sizeof(J->SubmitHost));

        if ((ptr = MUStrTok(NULL,".",&TokPtr)) != NULL)
          {
          J->Cluster = (int)strtol(ptr,NULL,0);

          if ((ptr = MUStrTok(NULL,".",&TokPtr)) != NULL)
            {
            J->Proc = (int)strtol(ptr,NULL,0);
            }
          }
        }

      /* adjust job flags */

      if (Mode == msmProfile)
        {
        MUStrDup(&J->MasterHostName,MHostName);

        /* NOTE:  flags may be specified as string or number */

        if ((J->SpecFlags = strtol(tmpJFlags,NULL,0)) == 0)
          {
          MUBMFromString(tmpJFlags,MJobFlags,&J->SpecFlags);
          }
        }
      else
        {
        /* simulation mode */

        if ((MSim.Flags & (1 << msimfIgnMode)) ||
            (MSim.Flags & (1 << msimfIgnAll)))
          {
          J->SpecFlags = 0;
          }
        else
          {
          /* NOTE:  flags may be specified as string or number */

          if ((J->SpecFlags = strtol(tmpJFlags,NULL,0)) == 0)
            {
            MUBMFromString(tmpJFlags,MJobFlags,&J->SpecFlags);
            }

          if (J->SysFlags & (1 << mjfBackfill))
            J->SysFlags ^= (1 << mjfBackfill);

          if ((J->SpecFlags & (1 << mjfHostList)) &&
              (MSim.Flags & (1 << msimfIgnHostList)))
            {
            J->SpecFlags ^= (1 << mjfHostList);
            }
          }
        }    /* END else (Mode == msmProfile) */

      /* extract arbitrary job attributes */

      /* FORMAT:  JATTR:<ATTR>[=<VALUE>] */

      {
      char *ptr;
      char *TokPtr;

      ptr = MUStrTok(tmpJFlags,"[]",&TokPtr);

      while (ptr != NULL)
        {
        if (!strncmp(ptr,"JATTR:",strlen("JATTR:")))
          {
          MJobSetAttr(J,mjaGAttr,(void **)(ptr + strlen("JATTR:")),0,mSet);
          }

        ptr = MUStrTok(NULL,"[]",&TokPtr);
        }  /* END while (ptr != NULL) */
      }    /* END BLOCK */

      /* set default flags, remove set 'ignore' flags */

      J->SpecFlags |= MSim.TraceDefaultJobFlags;

      for (index = 0;index < M64.INTBITS;index++)
        {
        if (!(MSim.TraceIgnoreJobFlags & (1 << index)))
          continue;

        if (!(J->SpecFlags & (1 << index)))
          continue;

        J->SpecFlags ^= (1 << index);
        }  /* END for (index) */

      /* load task info */

      if (!strncmp(tmpTaskRequest,"PBS=",strlen("PBS=")))
        {
        char tmpLine[MAX_MLINE];

        tpbsa_t tmpA;
        short   TaskList[MAX_MTASK];

        memset(&tmpA,0,sizeof(tmpA));

        sprintf(tmpLine,"Resource_List,nodes,%s",
          &tmpTaskRequest[strlen("PBS=")]);

        MPBSJobSetAttr(J,NULL,tmpLine,&tmpA,TaskList,0);

        MPBSJobAdjustResources(J,&tmpA,J->RM);
        }
      else
        {
        ptr = MUStrTok(tmpTaskRequest,",",&TokPtr);
        tindex = 1;

        while (ptr != NULL)
          {
          if (strchr(ptr,'-') != NULL)
            {
            /* NOTE:  not handled */
            }
          else
            {
            RQ[0]->TaskRequestList[tindex] = atoi(ptr);
            tindex++;
            }

          ptr = MUStrTok(NULL,",",&TokPtr);
          }

        RQ[0]->TaskRequestList[tindex] = 0;
        RQ[0]->TaskRequestList[0]      = RQ[0]->TaskRequestList[1];

        RQ[0]->TaskCount    = RQ[0]->TaskRequestList[0];

        J->Request.TC   = RQ[0]->TaskRequestList[0];

        RQ[0]->TasksPerNode = MAX(0,TPN);

        if (MPar[0].JobNodeMatch & (1 << nmExactNodeMatch))
          {
          RQ[0]->NodeCount  = RQ[0]->TaskCount;
          J->Request.NC = RQ[0]->TaskCount;
          }

        if (MPar[0].JobNodeMatch & (1 << nmExactProcMatch))
          {
          if (RQ[0]->TasksPerNode >= 1)
            {
            RQ[0]->RequiredProcs = RQ[0]->TasksPerNode;
            RQ[0]->ProcCmp       = mcmpEQ;
            }

          if (RQ[0]->TasksPerNode > J->Request.TC)
            {
            RQ[0]->TasksPerNode = 0;
            }
          }
        }    /* END BLOCK */

      /* process WCLimit constraints */

      ptr = MUStrTok(tmpSpecWCLimit,",:",&TokPtr);
      tindex = 1;

      while (ptr != NULL)
        {
        if (strchr(ptr,'-') != NULL)
          {
          /* NOTE:  not handled */
          }
        else
          {
          J->SpecWCLimit[tindex] = strtol(ptr,NULL,0);

          tindex++;
          }

        ptr = MUStrTok(NULL,",:",&TokPtr);
        }  /* END while (ptr != NULL) */

      J->SpecWCLimit[tindex] = 0;
      J->SpecWCLimit[0]      = J->SpecWCLimit[1];

      J->SubmitTime     = tmpQTime;
      J->DispatchTime   = MAX(tmpDTime,tmpSTime);
      J->StartTime      = MAX(tmpDTime,tmpSTime);
      J->CompletionTime = tmpCTime;

      J->SystemQueueTime = tmpSQTime;

      J->SpecSMinTime   = tmpSDate;
      J->CMaxTime       = tmpEDate;

      /* determine required reservation */

      if (strcmp(Reservation,NONE) &&
          strcmp(Reservation,J->Name))
        {
        J->SpecFlags |= (1 << mjfAdvReservation);

        if (strcmp(Reservation,ALL) != 0)
          {
          strcpy(J->ResName,Reservation);
          }
        }

      /* determine job class */

      if ((MSim.Flags & (1 << msimfIgnClass)) ||
          (MSim.Flags & (1 << msimfIgnAll)))
        {
        mclass_t *C;

        MClassAdd("DEFAULT",&C);

        /* ignore specified classes */

        RQ[0]->DRes.PSlot[0].count = 1;
        RQ[0]->DRes.PSlot[C->Index].count = 1;
        }
      else
        {
        int cindex;

        MUNumListFromString(RQ[0]->DRes.PSlot,tmpClass,eClass);

        for (cindex = 1;cindex < MAX_MCLASS;cindex++)
          {
          if (RQ[0]->DRes.PSlot[cindex].count > 0)
            {
            MClassAdd(MAList[eClass][cindex],NULL);
            }
          }  /* END for (cindex) */
        }

      if (Mode != msmProfile)
        {
        if ((strcmp(MReqHList,NONE) != 0) &&
           !(MSim.Flags & (1 << msimfIgnHostList)) &&
           !(MSim.Flags & (1 << msimfIgnAll)))
          {
          J->SpecFlags |= (1 << mjfHostList);

          ptr = MUStrTok(MReqHList,":",&TokPtr);

          nindex = 0;

          if (J->ReqHList == NULL)
            J->ReqHList = (mnalloc_t *)calloc(1,sizeof(mnalloc_t) * (MAX_MNODE_PER_JOB + 1));

          J->ReqHList[0].N = NULL;

          while (ptr != NULL)
            {
            if (MNodeFind(ptr,&N) == FAILURE)
              {
              if (MSched.DefaultDomain[0] != '\0')
                {
                if ((tail = strchr(ptr,'.')) != NULL)
                  {
                  /* try short name */

                  MUStrCpy(MReqHList,ptr,MIN(sizeof(MReqHList),(tail - ptr + 1)));
                  }
                else
                  {
                  /* append default domain */

                  if (MSched.DefaultDomain[0] == '.')
                    {
                    sprintf(MReqHList,"%s%s",
                      ptr,
                      MSched.DefaultDomain);
                    }
                  else
                    {
                    sprintf(MReqHList,"%s.%s",
                      ptr,
                      MSched.DefaultDomain);
                    }
                  }

                if (MNodeFind(MReqHList,&N) != SUCCESS)
                  {
                  DBG(1,fUI) DPrint("ALERT:    cannot locate node '%s' for job '%s' hostlist\n",
                    ptr,
                    J->Name);

                  N = NULL;
                  }
                }
              else
                {
                DBG(1,fUI) DPrint("ALERT:    cannot locate node '%s' for job '%s' hostlist\n",
                  ptr,
                  J->Name);

                N = NULL;
                }
              }  /* END if (MNodeFind() == FAILURE) */

            if (N != NULL)
              {
              if (J->ReqHList[nindex].N == N)
                {
                J->ReqHList[nindex].TC++;
                }
              else
                {
                if (J->ReqHList[nindex].N != NULL)
                  nindex++;

                J->ReqHList[nindex].N = N;

                J->ReqHList[nindex].TC = 1;
                }
              }

            ptr = MUStrTok(NULL,":",&TokPtr);
            }    /* END while (ptr != NULL) */

          J->ReqHList[nindex + 1].N = NULL;
          }      /* END if (strcmp(MReqHList,NONE)) */
        else if ((J->SpecFlags & (1 << mjfHostList)) &&
                 (J->ReqHList == NULL))
          {
          DBG(1,fSIM) DPrint("ALERT:    job %s requests hostlist but has no hostlist specified\n",
            J->Name);

          J->SpecFlags ^= (1 << mjfHostList);
          }
        }    /* END if (MODE != msmProfile) */

      break;

    default:

      DBG(4,fSIM) DPrint("ALERT:    cannot load version %d workload trace record\n",
        *Version);

      MJobDestroy(&J);

      return(FAILURE);

      /*NOTREACHED*/

      break;
    }    /* END switch(*Version) */

  if (!strcmp(AName,NONE) ||
      !strcmp(AName,"0"))
    {
    AName[0] = '\0';
    }

  if ((strcmp(tmpRMXString,NONE) != 0) && (strcmp(tmpRMXString,"0") != 0))
    {
    MJobSetAttr(J,mjaRMXString,(void **)tmpRMXString,mdfString,0);
    }

  if (RQ[0]->DRes.Procs == 0)
    RQ[0]->DRes.Procs = 1;

  if (J->SpecWCLimit[0] == (unsigned long)-1)
    J->SpecWCLimit[0] = MAX_MTIME;

  MUStrDup(&J->E.Cmd,tmpCmd);

  if (Mode == msmSim)
    {
    J->State           = mjsIdle;
    J->EState          = mjsIdle;
    J->Bypass          = 0;
    J->PSUtilized      = 0.0;

    J->SystemQueueTime = J->SubmitTime;
    J->SimWCTime       = MAX(1,J->CompletionTime - J->StartTime);

    J->StartTime       = 0;
    J->DispatchTime    = 0;
    J->CompletionTime  = 0;

    J->WCLimit         = J->SpecWCLimit[0];
    }
  else
    {
    /* profile mode */

    int tmpI;

    tmpI = (int)strtol(tmpParName,NULL,0);

    if (tmpI > 0) 
      {
      RQ[0]->PtIndex = tmpI;
      }
    else
      {
      mpar_t *P;

      MParFind(tmpParName,&P);

      RQ[0]->PtIndex = P->Index;
      }

    J->TaskCount = TasksAllocated;

    J->PSDedicated = MJobGetProcCount(J) * (J->CompletionTime - J->StartTime);

    J->WCLimit = J->SpecWCLimit[0];

    for (index = 0;MJobState[index] != NULL;index++)
      {
      if (!strcmp(tmpState,MJobState[index]))
        {
        J->State  = index;
        J->EState = index;

        break;
        }
      }    /* END for (index) */
    }

  if (J->State == mjsNotRun)
    {
    DBG(3,fSIM) DPrint("ALERT:    ignoring job '%s' (job never ran, state '%s')\n",
      J->Name,
      MJobState[J->State]);

    MJobDestroy(&J);

    return(FAILURE);
    }

  /* check for timestamp corruption */

  if (Mode == msmProfile)
    {
    /* profiler mode */

    if (MSched.TraceFlags & (1 << tfFixCorruption))
      {
      if (J->StartTime < J->DispatchTime)
        {
        DBG(2,fSIM) DPrint("WARNING:  fixing job '%s' with corrupt dispatch/start times (%ld < %ld)\n",
          J->Name,
          J->DispatchTime,
          J->StartTime);

        J->DispatchTime = J->StartTime;
        }

      if (J->SubmitTime > J->StartTime)
        {
        DBG(2,fSIM) DPrint("WARNING:  fixing job '%s' with corrupt queue/start times (%ld > %ld)\n",
          J->Name,
          J->SubmitTime,
          J->StartTime);

        if (J->SystemQueueTime > 0)
          J->SubmitTime = MIN(J->StartTime,J->SystemQueueTime);
        else
          J->SubmitTime = J->StartTime;
        }

      if (J->SystemQueueTime > J->DispatchTime)
        {
        DBG(2,fSIM) DPrint("WARNING:  fixing job '%s' with corrupt system queue/dispatch times (%ld > %ld)\n",
          J->Name,
          J->SystemQueueTime,
          J->DispatchTime);

        J->SystemQueueTime = J->DispatchTime;
        }

      if (J->SystemQueueTime < J->SubmitTime)
        {
        DBG(2,fSIM) DPrint("WARNING:  fixing job '%s' with corrupt system queue/queue time (%ld < %ld)\n",
          J->Name,
          J->SystemQueueTime,
          J->SubmitTime);

        J->SystemQueueTime = J->SubmitTime;
        }
      }    /* END if (MSched.TraceFlags & (1 << tfFixCorruption)) */

    if ((J->SubmitTime > J->DispatchTime) ||
        (J->DispatchTime > J->CompletionTime))
      {
      DBG(1,fSIM) DPrint("ALERT:    ignoring job '%s' with corrupt queue/start/completion times (%ld > %ld > %ld)\n",
        J->Name,
        J->SubmitTime,
        J->DispatchTime,
        J->CompletionTime);

      MJobDestroy(&J);

      return(FAILURE);
      }
    }    /* END if (Mode != msmSim) */

  if (MJobSetCreds(J,UName,GName,AName) == FAILURE)
    {
    DBG(1,fSTRUCT) DPrint("ALERT:    ignoring job '%s' with invalid authentication info (%s:%s:%s)\n",
      J->Name,
      UName,
      GName,
      AName);

    MJobDestroy(&J);

    return(FAILURE);
    }

  /* determine network */

  if (strstr(tmpNetwork,MAList[eNetwork][0]) == NULL)
    {
    RQ[0]->Network = MUMAGetIndex(eNetwork,tmpNetwork,mAdd);
    }

  if (strstr(tmpOpsys,MAList[eOpsys][0]) == NULL)
    {
    if ((RQ[0]->Opsys = MUMAGetIndex(eOpsys,tmpOpsys,mAdd)) == FAILURE)
      {
      DBG(0,fSIM) DPrint("WARNING:  cannot add opsys '%s' for job '%s'\n",
        tmpOpsys,
        J->Name);
      }
    }

  if (strstr(tmpArch,MAList[eArch][0]) == NULL)
    {
    if ((RQ[0]->Arch = MUMAGetIndex(eArch,tmpArch,mAdd)) == FAILURE)
      {
      DBG(0,fSIM) DPrint("WARNING:  cannot add arch '%s' for job '%s'\n",
        tmpArch,
        J->Name);
      }
    }

  /* load feature values */

  if ((MSched.ProcSpeedFeatureHeader[0] != '\0') &&
      (MSched.ReferenceProcSpeed > 0))
    {
    sprintf(tmpLine,"[%s",
      MSched.ProcSpeedFeatureHeader);

    if ((ptr = strstr(tmpReqNFList,tmpLine)) != NULL)
      {
      ReqProcSpeed = strtol(ptr + strlen(tmpLine),NULL,0);

      J->SimWCTime *= (long)((double)ReqProcSpeed / MSched.ReferenceProcSpeed);
      }
    }

  if ((MSched.Mode != msmSim) || !(MSim.Flags & (1 << msimfIgnFeatures)))
    {
    if (!strstr(tmpReqNFList,MAList[eFeature][0]))
      {
      tok = MUStrTok(tmpReqNFList,"[]",&TokPtr);

      do
        {
        MUGetMAttr(eFeature,tok,mAdd,RQ[0]->ReqFBM,sizeof(RQ[0]->ReqFBM));
        }
      while ((tok = MUStrTok(NULL,"[]",&TokPtr)) != NULL);
      }
    }

  RQ[0]->MemCmp    = MUCmpFromString(tmpMemCmp,NULL);
  RQ[0]->DiskCmp   = MUCmpFromString(tmpDiskCmp,NULL);

  RQ[0]->NAccessPolicy = MSched.DefaultNAccessPolicy;

  RQ[0]->TaskCount = J->Request.TC;
  RQ[0]->NodeCount = J->Request.NC;

  MJobProcessExtensionString(J,J->RMXString);

  if ((MSim.Flags & (1 << msimfIgnQOS)))
    {
    tmpQReq[0] = '\0';
    }

  {
  char *ptr;
  char *TokPtr;

  ptr = MUStrTok(tmpQReq,":",&TokPtr);

  if ((ptr != NULL) &&
      (ptr[0] != '\0') &&
       strcmp(ptr,"-1") &&
       strcmp(ptr,"0") &&
       strcmp(ptr,NONE) &&
       strcmp(ptr,DEFAULT))
    {
    if (MQOSAdd(ptr,&J->QReq) == FAILURE)
      {
      /* cannot locate requested QOS */

      MQOSFind(DEFAULT,&J->QReq);
      }

    if (Mode == msmProfile)
      {
      if ((ptr = MUStrTok(NULL,":",&TokPtr)) != NULL)
        {
        MQOSAdd(ptr,&J->Cred.Q);
        }
      }
    }    /* END if ((ptr != NULL) && ...) */
  }      /* END BLOCK */

  if (Mode == msmSim)
    {
    if ((MQOSGetAccess(J,J->QReq,NULL,&QDef) == FAILURE) ||
        (J->QReq == NULL) ||
        (J->QReq == &MQOS[0]))
      {
      MJobSetQOS(J,QDef,0);
      }
    else
      {
      MJobSetQOS(J,J->QReq,0);
      }
    }    /* END if (Mode == msmSim) */

  if ((SetString[0] != '0') && (strcmp(SetString,NONE)))
    {
    /* FORMAT:  ONEOF,FEATURE[,X:Y:Z] */

    if ((ptr = MUStrTok(SetString,",: \t",&TokPtr)) != NULL)
      {
      /* determine selection type */

      RQ[0]->SetSelection = MUGetIndex(ptr,(const char **)MResSetSelectionType,0,mrssNONE);

      if ((ptr = MUStrTok(NULL,",: \t",&TokPtr)) != NULL)
        {
        /* determine set attribute */

        RQ[0]->SetType = MUGetIndex(ptr,(const char **)MResSetAttrType,0,mrstNONE);

        index = 0;

        if ((ptr = MUStrTok(NULL,", \t",&TokPtr)) != NULL)
          {
          /* determine set list */

          while (ptr != NULL)
            {
            MUStrDup(&RQ[0]->SetList[index],ptr);

            index++;

            ptr = MUStrTok(NULL,", \t",&TokPtr);
            }
          }

        RQ[0]->SetList[index] = NULL;
        }  /* END if ((ptr = MUStrTok(NULL)) != NULL) */
      }    /* END if ((ptr = MUStrTok(SetString)) != NULL) */
    }      /* END if ((SetString[0] != '0') && (strcmp(SetString,NONE))) */

  if (MJobEval(J) == FAILURE)
    {
    /* job not properly formed */

    DBG(1,fSTRUCT) DPrint("ALERT:    ignoring job '%s' with corrupt configuration\n",
      J->Name);

    MJobDestroy(&J);

    return(FAILURE);
    }

  DBG(6,fSIM) DPrint("INFO:     job '%s' loaded.  class: %s  opsys: %s  arch: %s\n",
    J->Name,
    MUCAListToString(RQ[0]->DRes.PSlot,NULL,NULL),
    MAList[eOpsys][RQ[0]->Opsys],
    MAList[eArch][RQ[0]->Arch]);

  return(SUCCESS);
  }  /* END MTraceLoadWorkload() */
示例#2
0
int MRMJobValidate(

  mjob_t              *J,              /* I */
  mrm_t               *R,              /* I */
  char                *EMsg,           /* O (optional,minsize=MMAX_LINE) */
  enum MJobCtlCmdEnum *FailureAction,  /* I (optional) */
  int                 *SC)             /* O (optional) */

  {
  enum MWJobAttrEnum aindex;
  enum MRMSubTypeEnum SType;

  int     index;

  char    SPath[MMAX_BUFFER];

  char   *BPtr;
  int     BSpace;

  char   *ptr;
  char   *TokPtr;

  char   *ptr2;
  char   *TokPtr2;

  char    tEMsg[MMAX_LINE];

  enum MStatusCodeEnum tmpSC;

  mbool_t GRes = FALSE;

  const char *FName = "MRMJobValidate";

  MDB(2,fRM) MLog("%s(%s,%s,EMsg,FailureAction,SC)\n",
    FName,
    (J != NULL) ? J->Name : "NULL",
    (R != NULL) ? R->Name : "NULL");

  if (EMsg != NULL)
    EMsg[0] = '\0';

  if (SC != NULL)
    *SC = 0;

  if (J == NULL)
    {
    return(FAILURE);
    }

  if (R->ND.URL[mrmXJobValidate] == NULL)
    {
    /* no job validate script specified */

    return(SUCCESS);
    }

  MUSNInit(&BPtr,&BSpace,SPath,sizeof(SPath));

  MUSNPrintF(&BPtr,&BSpace,"%s=%s ",
    MWikiJobAttr[mwjaUName],
    J->Credential.U->Name);

  if (J->EUser != NULL)
    {
    /* report execution user */

    MUSNPrintF(&BPtr,&BSpace,"%s=%s ",
      "EUSER",
      J->EUser);
    }

  if (J->Credential.G != NULL)
    {
    MUSNPrintF(&BPtr,&BSpace,"%s=%s ",
      MWikiJobAttr[mwjaGName],
      J->Credential.G->Name);
    }

  if (J->SpecWCLimit[0] > 0)
    {
    MUSNPrintF(&BPtr,&BSpace,"%s=%ld ",
      MWikiJobAttr[mwjaWCLimit],
      J->SpecWCLimit[0]);
    }

/* 
  if (J->Request.TC > 0)
    {
    MUSNPrintF(&BPtr,&BSpace,"%s=%d ",
      MWikiJobAttr[mwjaTasks],
      J->Request.TC);
    }
*/

  if (J->Credential.C != NULL)
    {
    MUSNPrintF(&BPtr,&BSpace,"%s=%s ",
      MWikiJobAttr[mwjaRClass],
      J->Credential.C->Name);
    }

  if (J->QOSRequested != NULL)
    {
    MUSNPrintF(&BPtr,&BSpace,"%s=%s ",
      MWikiJobAttr[mwjaQOS],
      J->QOSRequested->Name);
    }

  if (J->Env.Cmd != NULL)
    {
    char *ptr;
    char *TokPtr;

    char tmpLine[MMAX_LINE];

    MUStrCpy(tmpLine,J->Env.Cmd,sizeof(tmpLine));

    ptr = MUStrTok(tmpLine," ",&TokPtr);

    MUStringChop(ptr);

    MUSNPrintF(&BPtr,&BSpace,"%s=%s ",
      MWikiJobAttr[mwjaExec],
      ptr);
    }    /* END if (J->E.Cmd != NULL) */

  if (!bmisclear(&J->Req[0]->ReqFBM))
    {
    char tmpLine[MMAX_LINE];

    MUSNPrintF(&BPtr,&BSpace,"%s=%s ",
      MWikiJobAttr[mwjaRFeatures],
      MUNodeFeaturesToString(',',&J->Req[0]->ReqFBM,tmpLine));
    }

  if (J->Variables.Table != NULL)
    {
    mstring_t tmp(MMAX_LINE);

    MJobAToMString(J,mjaVariables,&tmp);

    MUSNPrintF(&BPtr,&BSpace,"%s=%s ",
      MWikiJobAttr[mwjaVariables],
      tmp.c_str());
    }

  /* display generic resources */

  for (index = 1;index < MSched.M[mxoxGRes];index++)
    { 
    if (MGRes.Name[index][0] == '\0')
      break;
 
    if (MSNLGetIndexCount(&J->Req[0]->DRes.GenericRes,index) == 0)
      continue;

    if (GRes == FALSE)
      {
      MUSNPrintF(&BPtr,&BSpace,"GRES=%s:%d",
        MGRes.Name[index],
        MSNLGetIndexCount(&J->Req[0]->DRes.GenericRes,index));

      GRes = TRUE;
      }
    else
      {
      MUSNPrintF(&BPtr,&BSpace,",%s:%d",
        MGRes.Name[index],
        MSNLGetIndexCount(&J->Req[0]->DRes.GenericRes,index));
      }
    }  /* END for (index) */

  /* send this off to JOBVALIDATEURL */
  
  SType = R->ND.NatType;

  R->ND.NatType = mrmstX1E;

  mstring_t Response(MMAX_LINE);

  /* NOTE: should we pass-in Job Validate specific timeout, ie 2 seconds? (NYI) */

  if (MNatDoCommand(
        &R->ND,
        SPath,
        mrmXJobValidate,
        R->ND.Protocol[mrmXJobValidate],
        FALSE,
        NULL,
        NULL,
        &Response,
        tEMsg,               /* O */
        &tmpSC) == FAILURE)
    {
    R->ND.NatType = SType;

    /* make failure action configurable */

    if ((ptr = strstr(tEMsg,"ACTION=")) != NULL)
      {
      ptr += strlen("ACTION=");

      ptr2 = MUStrTok(ptr," \n\t",&TokPtr);

      if (FailureAction != NULL)
        *FailureAction = (enum MJobCtlCmdEnum)MUGetIndexCI(ptr2,MJobCtlCmds,FALSE,mjcmNONE);
      }

    if (EMsg != NULL)
      MUStrCpy(EMsg,tEMsg,MMAX_LINE);

    if (SC != NULL)
      *SC = (int)tmpSC;

    return(FAILURE);
    }

  if (SC != NULL)
    *SC = (int)tmpSC;

  R->ND.NatType = SType;

  for (index = 0;Response[index] != '\0';index++)
    {
    if (Response[index] == '\n')
      Response[index] = ' ';
    }

  mstring_t tmpString(MMAX_LINE);

  MWikiFromAVP(NULL,Response.c_str(),&tmpString);

  /* Need a char array that can be modified, not the immutable tmpString  */
  char *mutableResponse = NULL;
  MUStrDup(&mutableResponse,tmpString.c_str());

  ptr = MUStrTok(mutableResponse,";",&TokPtr);

  int rc = SUCCESS;

  /* NYI:  change other job attributes such as NodeCount RMXString User/Group */

  while (ptr != NULL)
    {
    ptr2 = MUStrTok(ptr,"=",&TokPtr2);

    aindex = (enum MWJobAttrEnum)MUGetIndexCI(ptr2,MWikiJobAttr,FALSE,mwjaNONE);

    switch (aindex)
      {
      case mwjaAccount:

        if ((J->Credential.A == NULL) || (strcmp(TokPtr2,J->Credential.A->Name)))
          {
          if (MRMJobModify(
                J,
                "Account_Name",
                NULL,
                TokPtr2,
                mSet,
                "account modified by jobvalidate interface",
                tEMsg,              /* O */
                NULL) != SUCCESS)
            {
            MDB(2,fSCHED) MLog("INFO:     cannot set account on job %s to '%s' - invalid account - %s\n",
              J->Name,
              TokPtr2,
              tEMsg);

            if (EMsg != NULL)
              strcpy(EMsg,"cannot set account");

            rc = FAILURE;
            goto cleanupExit;
            }

          MAcctAdd(TokPtr2,&J->Credential.A);

          bmset(&J->IFlags,mjifAccountLocked);
          }

        break;

      case mwjaRClass:

        if ((J->Credential.C == NULL) || (strcmp(TokPtr2,J->Credential.C->Name)))
          {
          mclass_t *C;

          if (MClassFind(TokPtr2,&C) == FAILURE)
            {
            MDB(2,fSCHED) MLog("INFO:     cannot set class on job %s to '%s' - invalid class\n",
              J->Name,
              TokPtr2);

            if (EMsg != NULL)
              strcpy(EMsg,"cannot locate class");

            rc = FAILURE;
            goto cleanupExit;
            }
          
          if (MJobSetClass(J,C,TRUE,tEMsg) == FAILURE)
            {
            MDB(2,fSCHED) MLog("INFO:     cannot set class on job %s to '%s' - %s\n",
              J->Name,
              C->Name,
              tEMsg);

            if (EMsg != NULL)
              strcpy(EMsg,"cannot set class");

            rc = FAILURE;
            goto cleanupExit;
            }

          bmset(&J->IFlags,mjifClassLocked);
          }  /* END if ((J->Cred.C == NULL) || ...) */

        break;

      case mwjaQOS:

        /* bypass qos checks and put qos directly onto job */

        J->QOSRequested = NULL;

        if (MQOSFind(TokPtr2,&J->Credential.Q) != SUCCESS)
          {
          MDB(2,fSCHED) MLog("INFO:     cannot set qos on job %s to '%s' - invalid QoS\n",
            J->Name,
            TokPtr2);

          if (EMsg != NULL)
            strcpy(EMsg,"cannot locate qos");

          rc = FAILURE;
          goto cleanupExit;
          }

        bmset(&J->IFlags,mjifQOSLocked);

        break;

      case mwjaRFeatures:

        MReqSetAttr(J,J->Req[0],mrqaReqNodeFeature,(void **)TokPtr2,mdfString,mSet);

        break;

      case mwjaWCLimit:

        if (MRMJobModify(
             J,
             "Resource_List",
             "walltime",
             TokPtr2,
             mSet,
             "walltime modified by jobvalidate interface",
             tEMsg,
             NULL) == FAILURE)
          {
          MDB(2,fSCHED) MLog("INFO:     cannot modify walltime for rm job %s - '%s'\n",
            J->Name,
            tEMsg);

          if (EMsg != NULL)
            strcpy(EMsg,"cannot modify walltime");

          rc = FAILURE;
          goto cleanupExit;
          }

        break;

      case mwjaVariables:

        MJobSetAttr(J,mjaVariables,(void **)TokPtr2,mdfString,mAdd);

        break;

      default:

        /* NO-OP */
 
        break;
      }  /* END switch (aindex) */

    ptr = MUStrTok(NULL,";",&TokPtr);
    }    /* END while (ptr != NULL) */

cleanupExit:
  MUFree(&mutableResponse);

  return(rc);
  }  /* END MRMJobValidate() */
示例#3
0
文件: MTrig.c 项目: dhh1128/cbase
int MTrigRegisterEvent(

  mtrig_t *T)  /* I (modified) */

  {
  if ((T->State == mtsFailure) && (T->RetryCount < T->MaxRetryCount))
    {
    mulong ETime = T->ETime;

    MTrigReset(T);

    /* FIXME: should ETime be the original? what about T->Offset and T->RearmTime? */

    T->ETime = ETime;

    T->RetryCount++;

    return(SUCCESS);
    }

  if (T->O != NULL)
    {
    switch (T->OType)
      {
      case mxoRsv:
      case mxoJob:
      case mxoNode:
      case mxoRM:
      case mxoQOS:
      case mxoUser:
      case mxoClass:
      case mxoGroup:
      case mxoAcct:

        {
        if (T->State == mtsSuccessful)
          {
          MTrigSetVars(T,FALSE,NULL);
          MTrigProbe(T);
          MTrigUnsetVars(T,FALSE,NULL);

          /* record state in journal to mark that this trigger is completely done */

          MTrigSetState(T,T->State);  /* use same state so that we record it in journal */

#ifdef MYAHOO3
          /* notify dependents of successful completion */
          /* MTrigNotifyDependents(T); */

          if (T->Dependents != NULL)
            {
            mln_t *LLPtr;
            mtrig_t *tmpTrig;

            LLPtr = T->Dependents;

            while (LLPtr != NULL)
              {
              if (MTrigFind(LLPtr->Name,&tmpTrig) == SUCCESS)
                {
                MULLRemove(&tmpTrig->TrigDeps,T->Name,NULL);

                if ((tmpTrig->TrigDeps == NULL) ||
                    (tmpTrig->TrigDeps->ListSize == 0))
                  {
                  tmpTrig->OutstandingTrigDeps = FALSE;
                  }
                }

              LLPtr = LLPtr->Next;
              }
            }
#endif /* MYAHOO3 */

          MOWriteEvent((void *)T,mxoTrig,mrelTrigEnd,NULL,NULL,NULL);

          CreateAndSendEventLog(meltTrigEnd,T->TName,mxoTrig,(void *)T);
          }   /* END if (T->State == mtsSuccessful) */
        else if (MTRIGISRUNNING(T))
          {
          if (T->OBuf != NULL)
            MTrigProbe(T);
          }
        else
          {
          /* trigger failed */

          MOWriteEvent((void *)T,mxoTrig,mrelTrigFailure,NULL,NULL,NULL);

          MTrigSetVars(T,TRUE,NULL);
          MTrigUnsetVars(T,TRUE,NULL);

          if (bmisset(&T->SFlags,mtfAttachError))
            {
            char *EBuf;
            
            /* read in stderr and attach as message to object */

            switch (T->OType)
              {
              case mxoJob:

                {
                mjob_t *tmpCJ = NULL;

                mjob_t *J = (mjob_t *)T->O;

                if ((EBuf = MFULoadNoCache(T->EBuf,1,NULL,NULL,NULL,NULL)) == NULL)
                  {
                  MDB(3,fSCHED) MLog("INFO:     cannot load error data for trigger %s (File: %s)\n",
                    T->TName,
                    (T->EBuf == NULL) ? "NULL" : T->EBuf);
                  }

                if (EBuf != NULL)
                  {
                  if (MJOBISCOMPLETE(J) &&
                      (MJobCFind(J->Name,&tmpCJ,mjsmBasic) == SUCCESS))
                    {
                    /* In the case of a jobepilogue, this is being called after
                     * the job has already been added to the completed job
                     * table and is being destroyed from MJobDestroy. */

                    MJobSetAttr(tmpCJ,mjaMessages,(void **)EBuf,mdfString,mAdd);

                    J = tmpCJ; /* so T->Msg will be set on the completed job */
                    }
                  else
                    {
                    MJobSetAttr(J,mjaMessages,(void **)EBuf,mdfString,mAdd);
                    }
                  }

                if (T->Msg != NULL)
                  MJobSetAttr(J,mjaMessages,(void **)T->Msg,mdfString,mAdd);

                MUFree(&EBuf);
                }  /* END case mxoJob */

                break;

              case mxoNode:

                {
                mnode_t *N = (mnode_t *)T->O;

                if ((EBuf = MFULoadNoCache(T->EBuf,1,NULL,NULL,NULL,NULL)) == NULL)
                  {
                  MDB(3,fSCHED) MLog("INFO:     cannot load error data for trigger %s (File: %s)\n",
                    T->TName,
                    (T->EBuf == NULL) ? "NULL" : T->EBuf);
                  }

                if (EBuf != NULL)
                  MNodeSetAttr(N,mnaMessages,(void **)EBuf,mdfString,mAdd);

                if (T->Msg != NULL)
                  MNodeSetAttr(N,mnaMessages,(void **)T->Msg,mdfString,mAdd);

                MUFree(&EBuf);
                }  /* END case mxoNode */

                break;

              default:

                /* NO-OP */

                break;
              }
            }
          }  /* END else (T->State == mtsSuccessful) */
        }    /* END case mxoRSV */

        break;

      default:

        if (T->State == mtsSuccessful)
          {
          MOWriteEvent((void *)T,mxoTrig,mrelTrigEnd,NULL,NULL,NULL);
          CreateAndSendEventLog(meltTrigEnd,T->TName,mxoTrig,(void *)T);
          }
        else if (T->State == mtsFailure)
          {
          MOWriteEvent((void *)T,mxoTrig,mrelTrigFailure,NULL,NULL,NULL);

          if (MSched.PushEventsToWebService == TRUE)
            {
            MEventLog *Log = new MEventLog(meltTrigEnd);
            Log->SetPrimaryObject(T->TName,mxoTrig,(void *)T);
            Log->SetStatus("failure");

            MEventLogExportToWebServices(Log);

            delete Log;
            }
          }

        break;
      }  /* END switch (T->OType) */
    }    /* END if (T->O != NULL) */

  return(SUCCESS);
  }  /* END MTrigRegisterEvent() */
示例#4
0
int MTrigLaunchInternalAction(

  mtrig_t *T,             /* I (optional) */
  char    *ActionString,  /* I */
  mbool_t *Complete,      /* O */
  char    *Msg)           /* O (optional,minsize=MMAX_LINE) */

  {
  /* FORMAT:  <OTYPE>:<OID>:<ACTION>:<context information> */

  char *ptr = NULL;
  char *TokPtr = NULL;
  char *tmpAString = NULL;

  char ArgLine[MMAX_LINE*10];
  char OID[MMAX_BUFFER];
  char Action[MMAX_LINE*10];

  enum MXMLOTypeEnum OType;

  const char *FName = "MTrigLaunchInternalAction";

  MDB(4,fSCHED) MLog("%s(%s,%s,Msg)\n",
    FName,
    ((T != NULL) && (T->TName != NULL)) ? T->TName : "NULL",
    (ActionString != NULL) ? ActionString : "NULL");

  if (Msg != NULL)
    Msg[0] = '\0';

  if (Complete != NULL)
    *Complete = TRUE;

  if (ActionString == NULL)
    {
    if (Msg != NULL)
      strcpy(Msg,"internal error");

    return(FAILURE);
    }

  MUStrDup(&tmpAString,ActionString);

  /* NOTE: this format and parsing is duplicated in MTrigCheckInternalAction()
           any update here must be copied to that routine */

  ptr = MUStrTok(tmpAString,":",&TokPtr);

  if (ptr == NULL)
    {
    MDB(4,fSCHED) MLog("ERROR:    invalid action");

    if (Msg != NULL)
      strcpy(Msg,"invalid action");

    MUFree(&tmpAString);

    return(FAILURE);
    }

  OType = (enum MXMLOTypeEnum)MUGetIndexCI(ptr,MXO,FALSE,mxoNONE);

  if (OType == mxoNONE)
    {
    MDB(4,fSCHED) MLog("ERROR:    invalid object type '%s' in %s\n",
      ptr,
      FName);

    if (Msg != NULL)
      strcpy(Msg,"invalid object type");

    MUFree(&tmpAString);

    return(FAILURE);
    }

  ptr = MUStrTok(NULL,":",&TokPtr);

  if (ptr == NULL)
    {
    MDB(4,fSCHED) MLog("ERROR:    cannot extract object ID in %s\n",
      FName);

    if (Msg != NULL)
      strcpy(Msg,"invalid object id");

    MUFree(&tmpAString);

    return(FAILURE);
    }

  MUStrCpy(OID,ptr,sizeof(OID));

  ptr = MUStrTok(NULL,":",&TokPtr);

  if (ptr == NULL)
    {
    MDB(4,fSCHED) MLog("ERROR:    cannot parse action in %s\n",
      FName);

    if (Msg != NULL)
      strcpy(Msg,"cannot locate action");

    MUFree(&tmpAString);

    return(FAILURE);
    }

  MUStrCpy(Action,ptr,sizeof(Action));

  if ((TokPtr != NULL) && (TokPtr[0] != '\0'))
    MUStrCpy(ArgLine,TokPtr,sizeof(ArgLine));
  else
    ArgLine[0] = '\0';

  MUFree(&tmpAString);

  switch (OType)
    {
    case mxoJob:

      {
      mjob_t *J;

      char *JID;
      char *TokPtr;
 
      /* OID FORMAT:  <JID>[+<JID>]... */

      mbool_t FailureDetected;

      enum MJobCtlCmdEnum atype;

      atype = (enum MJobCtlCmdEnum)MUGetIndexCI(Action,MJobCtlCmds,FALSE,mjcmNONE);

      if (atype == mjcmNONE)
        {
        MDB(4,fSCHED) MLog("ERROR:    cannot parse job action '%s' in %s\n",
          Action,
          FName);

        return(FAILURE);
        }

      FailureDetected = FALSE;

      JID = MUStrTok(OID,"+",&TokPtr);

      while (JID != NULL)
        {
        if (!strcmp(JID,"-"))
          {
          if (T == NULL)
            return(FAILURE);

          J = (mjob_t *)T->O;
          }
        else if (MJobFind(JID,&J,mjsmExtended) == FAILURE)
          {
          MDB(4,fSCHED) MLog("ERROR:    cannot locate job '%s' in %s\n",
            JID,
            FName);

          JID = MUStrTok(NULL,"+",&TokPtr);

          FailureDetected = TRUE;

          continue;
          }

        switch (atype)
          {
          case mjcmCancel:

            {
            char *CCodeCheck;
            char UpperArgLine[MMAX_LINE];

            MDB(7,fSCHED) MLog("  INFO:  Job flaged for cancel by trigger action. '%s' in %s\n",
                JID,
                FName);

            bmset(&J->IFlags, mjifCancel);

            MUStrToUpper(ArgLine,UpperArgLine,MMAX_LINE);

            /* If specified, allow trigger to set the completion code of the job */

            if ((CCodeCheck = strstr(UpperArgLine,"CCODE=")) != NULL)
              {
              CCodeCheck += strlen("CCODE="); /* Skip the "CCODE:" part */

              if (CCodeCheck[0] != '\0')
                {
                J->CompletionCode = strtol(CCodeCheck,NULL,10);
                }
              }
            else
              {
              J->CompletionCode = 273; /* Completion code for a canceled job in TORQUE */
              }
            }  /* END case mjcmCancel */

            break;

          case mjcmComplete:
 
            {
            char *CCodeCheck;
            char UpperArgLine[MMAX_LINE];

            if ((!bmisset(&J->Flags,mjfSystemJob) &&
                 !bmisset(&J->Flags,mjfNoRMStart)))
              {
              MDB(4,fSCHED) MLog("ERROR:    job %s in bad state for complete in %s\n",
                J->Name,
                FName);

              JID = MUStrTok(NULL,"+",&TokPtr);

              FailureDetected = TRUE;

              continue;
              }

            /* the next three lines set the WCLimit to the exact runtime
             * this also causes MS3WorkloadQuery to remove the job */

            J->SpecWCLimit[0] = MSched.Time - J->StartTime;
            J->SpecWCLimit[1] = MSched.Time - J->StartTime;

            J->WCLimit = MSched.Time - J->StartTime;

            if (MJOBISACTIVE(J) == TRUE)
              {
              MRsvJCreate(J,NULL,J->StartTime,mjrActiveJob,NULL,FALSE);  /* just removes active rsv? */
              }

            MUStrToUpper(ArgLine,UpperArgLine,MMAX_LINE);

            if ((CCodeCheck = strstr(UpperArgLine,"CCODE=")) != NULL)
              {
              CCodeCheck += strlen("CCODE="); /* Skip the "CCODE:" part */

              if (CCodeCheck[0] != '0')
                {
                J->CompletionCode = strtol(CCodeCheck,NULL,10);
                }
              }

            /* MSched.TrigCompletedJob = TRUE; -- not sure why we wanted to skip the UI phase here... */
            }  /* END BLOCK (case mjcmComplete) */

            break;

          case mjcmModify:

            {
            char *TokPtr;

            char *Attr = NULL;
            char *Value = NULL;
            char *Msg = NULL;

            enum MJobAttrEnum aindex;
            enum MObjectSetModeEnum Op;

            if (strstr(ArgLine,"+="))
              Op = mAdd;
            else if (strstr(ArgLine,"-="))
              Op = mDecr;
            else
              Op = mSet;

            Attr  = MUStrTok(ArgLine,"+-=",&TokPtr);
            Value = MUStrTok(NULL,"=: \t\n",&TokPtr);
            Msg = MUStrTok(NULL,":\t\n",&TokPtr);  /* extract message */

            aindex = (enum MJobAttrEnum)MUGetIndexCI(Attr,MJobAttr,FALSE,mnaNONE);

            switch (aindex)
              {
              case mjaHold:

                if (MJobSetAttr(J,mjaHold,(Value != NULL) ? (void **)Value : (void **)"batch",mdfString,mSet) == FAILURE)
                  {
                  MDB(4,fSCHED) MLog("ERROR:    cannot hold job '%s' in %s\n",
                    JID,
                    FName);

                  JID = MUStrTok(NULL,"+",&TokPtr);

                  FailureDetected = TRUE;

                  continue;
                  }

                if (Msg != NULL)
                  {
                  /* attach provided message */

                  MMBAdd(
                    &J->MessageBuffer,
                    Msg,
                    NULL,
                    mmbtHold,
                    0,
                    0,
                    NULL);
                  }

                if (MJOBISACTIVE(J))
                  {
                  /* Set to idle but don't clear DRM and DRMJID */
                  MJobToIdle(J,FALSE,FALSE);

                  J->SubState = mjsstNONE;
                  }

                /* checkpoint change (make this configurable at this point?) */

                MOCheckpoint(mxoJob,(void *)J,FALSE,NULL);
          
                break;

              case mjaVariables:

                {
                char tmpLine[MMAX_LINE*2];

                snprintf(tmpLine,sizeof(tmpLine),"%s=%s",
                  Value,
                  Msg);

                if (MJobSetAttr(J,mjaVariables,(void **)tmpLine,mdfString,Op) == FAILURE)
                  {
                  MDB(4,fSCHED) MLog("ERROR:    cannot set trigvar job '%s' in %s\n",
                    JID,
                    FName);

                  JID = MUStrTok(NULL,"+",&TokPtr);

                  FailureDetected = TRUE;

                  continue;
                  }
                }  /* END BLOCK */

                break;

              default:

                if (!strcasecmp(Attr,"gres"))
                  {
                  if ((Op == mAdd) && 
                      (MJobAddRequiredGRes(
                         J,
                         Value,
                         1,
                         mxaGRes,
                         FALSE,
                         FALSE) == SUCCESS))
                    {
                    /* SUCCESS - NO-OP */
                    }
                  else if ((Op == mDecr) &&
                           (MJobRemoveGRes(J,Value,TRUE) == SUCCESS))
                    {
                    /* SUCCESS -- Do Nothing */
                    }
                  else
                    {
                    MDB(4,fSCHED) MLog("ERROR:    cannot adjust gres for job '%s' in %s\n",
                      JID,
                      FName);

                    JID = MUStrTok(NULL,"+",&TokPtr);

                    FailureDetected = TRUE;

                    continue;
                    }
                  }
                else
                  {
                  MDB(4,fSCHED) MLog("ERROR:    cannot modify attribute '%s' for job '%s' in %s\n",
                    Attr,
                    JID,
                    FName);

                  JID = MUStrTok(NULL,"+",&TokPtr);

                  FailureDetected = TRUE;

                  continue;
                  }

                break;
              }
            }   /* END BLOCK (case mjcmModify) */

            break;

          case mjcmSignal:

            {
            char  EMsg[MMAX_LINE];
            int   SC;

            if (MRMJobSignal(J,-1,ArgLine,EMsg,&SC) == FAILURE)
              {
              MDB(4,fSCHED) MLog("ERROR:    cannot send signal '%s' to job '%s' in %s\n",
                ArgLine,
                JID,
                FName);

              JID = MUStrTok(NULL,"+",&TokPtr);

              FailureDetected = TRUE;

              continue;
              }
            }    /* END BLOCK (case mjcmSignal) */

            break;

          case mjcmStart:

            /* FIXME:  check reservation, check allocation */

            {
            J->SubState = mjsstNONE;

            /* set "copy-tasklist" flag */

            bmset(&J->IFlags,mjifCopyTaskList);

            if (MRMJobStart(J,NULL,NULL) == FAILURE)
              {
              MDB(4,fSCHED) MLog("ERROR:    cannot start job '%s' in %s\n",
                JID,
                FName);

              JID = MUStrTok(NULL,"+",&TokPtr);

              FailureDetected = TRUE;

              continue;
              }

            J->State = mjsRunning;
            }   /* END BLOCK (case mjcmStart) */

            break;

         case mjcmRequeue:

            /* FIXME:  check reservation, check allocation */

            {
            char EMsg[MMAX_LINE];

            J->SubState = mjsstNONE;

            /* set "copy-tasklist" flag */

            if (MJobRequeue(J,NULL,"workflow failure",EMsg,NULL) == FAILURE)
              {
              MDB(4,fSCHED) MLog("ERROR:    cannot requeue job '%s' in %s\n",
                JID,
                FName);

              JID = MUStrTok(NULL,"+",&TokPtr);

              FailureDetected = TRUE;

              continue;
              }

            J->State = mjsIdle;
            }   /* END BLOCK (case mjcmStart) */

          default:

            MDB(4,fSCHED) MLog("ERROR:    action '%s' not handled in %s\n",
              Action,
              FName);

            return(FAILURE);

            /*NOTREACHED*/

            break;
          }  /* END switch (atype) */
   
        JID = MUStrTok(NULL,"+",&TokPtr);
        }    /* END while (JID != NULL) */

      if (FailureDetected == TRUE)
        {
        return(FAILURE);
        }
      }  /* END BLOCK (case mxoJob) */

      break;

    case mxoNode:

      {
      enum MNodeCtlCmdEnum atype;
      char *rsvProfile = NULL;

      atype = (enum MNodeCtlCmdEnum)MUGetIndexCI(Action,MNodeCtlCmds,FALSE,mncmNONE);

      if (!strcasecmp(Action,"reserve"))
        {
        char tmpLine[MMAX_LINE];

        snprintf(tmpLine,sizeof(tmpLine),"auto-trigger-rsv.%s",
          T->TName);

        if (ArgLine[0] != '\0')
          {
          char *Attr  = MUStrTok(ArgLine,"=",&TokPtr);
          char *Value = MUStrTok(NULL,"= \t\n",&TokPtr);

          if ((Attr != NULL) && 
              (strncasecmp(Attr,"rsvprofile",strlen("rsvprofile")) == 0))
            rsvProfile = Value;
          }

        if (T->OType != mxoRsv)
          {
          MNodeReserve(
            (mnode_t *)T->O,
            MCONST_EFFINF,
            tmpLine,
            rsvProfile,
            "Reservation created by trigger");

          return(SUCCESS);
          }
        else
          {
          return(FAILURE);
          }
        }
      else if ((!strcasecmp(Action,"evacvms")) && (MSched.AllowVMMigration == TRUE))
        {
        /* Evacuate all vms on nodes held by this reservation */

        char tmpMsg[MMAX_LINE];
        int rc = SUCCESS;

        mnl_t NL;

        MNLInit(&NL);

        MNLFromString(OID,&NL,1,FALSE);

        rc = MNodeEvacVMsMultiple(&NL);

        MNLFree(&NL);

        /* Write out events */

        snprintf(tmpMsg,sizeof(tmpMsg),"attempting to migrate vms from node '%s' for evacvms reservation '%s' (TID: %s)",
          OID,
          ((mrsv_t *)T->O)->Name,
          (T->TName != NULL) ? T->TName : "NULL");

        MDB(5,fSTRUCT) MLog("INFO:     %s\n",
          tmpMsg);

        return(rc);
        } /* END if (!strcasecmp(Action,"evacvms")) */

      if (atype == mncmNONE)
        {
        return(FAILURE);
        }

      switch (atype)
        {
        case mncmModify:
 
          if (MSched.AggregateNodeActions == FALSE)
            {
            char *ptr;
            char *TokPtr;
   
            mnode_t *N;
   
            char *Attr;
            char *Value;
   
            enum MNodeAttrEnum aindex;

            /* always look on the bright side of life */
            mbool_t NodeModifySuccessDetected;
   
            /* FORMAT:  <ARG>=<VALUE> */
   
            Attr  = MUStrTok(ArgLine,"=",&TokPtr);
            Value = MUStrTok(NULL,"= \t\n",&TokPtr);
   
            aindex = (enum MNodeAttrEnum)MUGetIndexCI(Attr,MNodeAttr,FALSE,mnaNONE);

            NodeModifySuccessDetected = FALSE;
   
            /* FORMAT: OID = node[,node]... */
   
            ptr = MUStrTok(OID,",",&TokPtr);
   
            if ((ptr == NULL) || (aindex == mnaNONE))
              {
              MDB(4,fSCHED) MLog("ERROR:    unknown attribute to modify on node '%s'\n",
                Attr);

              return(FAILURE);
              }
   
            while (ptr != NULL)
              {
              if (MNodeFind(ptr,&N) == FAILURE)
                {
                ptr = MUStrTok(NULL,",",&TokPtr);
   
                continue;
                }
   
              switch (aindex)
                {
                case mnaOS:
   
                  {
                  char EMsg[MMAX_LINE];
   
                  if (!strcmp(Value,MAList[meOpsys][0]))
                    {
                    if ((N->PowerSelectState == mpowOff) &&
                      (MNodeSetAttr(N,mnaPowerIsEnabled,(void **)"true",mdfString,mVerify) == FAILURE))
                      {
                      if (Msg != NULL)
                        MUStrCpy(Msg,EMsg,MMAX_LINE);

                      /* do not return failure just because one provisioning job fails */
                      }
                    }
                  else if (MNodeProvision(N,NULL,NULL,Value,TRUE,EMsg,NULL) == FAILURE)
                    {
                    if (Msg != NULL)
                      MUStrCpy(Msg,EMsg,MMAX_LINE);

                    /* do not return failure just because one provisioning job fails */
                    }
                  else 
                    {
                    NodeModifySuccessDetected = TRUE;
                    }
                  }
   
                  break;
   
                case mnaPowerIsEnabled:

                  /* NOTE: do not return failure just because node modify fails
                   * the routine will fail if all node modifies fail */

                  if (!strcmp(Value,"on"))
                    {
                    /* power node on */
   
                    if (MNodeSetAttr(N,mnaPowerIsEnabled,(void **)"true",mdfString,mVerify) == SUCCESS)
                      {
                      NodeModifySuccessDetected = TRUE;
                      }
                    }
                  else if (!strcasecmp(Value,"off"))
                    {
                    /* power node off */
   
                    if (MNodeSetAttr(N,mnaPowerIsEnabled,(void **)"false",mdfString,mVerify) == SUCCESS)
                      {
                      NodeModifySuccessDetected = TRUE;
                      }
                    }
                  else if (!strcasecmp(Value,"reset"))
                    {
                    char EMsg[MMAX_LINE];
   
                    /* reset node */
   
                    if (MNodeReboot(N,NULL,EMsg,NULL) == FAILURE)
                      {
                      if (Msg != NULL)
                        MUStrCpy(Msg,EMsg,MMAX_LINE);
                      }
                    else 
                      {
                      NodeModifySuccessDetected = TRUE;
                      }
                    }
                  else if (!strcasecmp(Value,"on+"))
                    {
                    /* power node on, but trigger isn't finished until action is complete */
                  
                    if (Complete != NULL)
                      *Complete = FALSE;
   
                    if (T != NULL)
                      MUStrDup(&T->CompleteAction,ActionString);
   
                    MNodeSetAttr(N,mnaPowerIsEnabled,(void **)"true",mdfString,mVerify);

                    T->PID = 1;
                    }
                  else if (!strcasecmp(Value,"off+"))
                    {
                    /* power node off, but trigger isn't finished until action is complete */
   
                    if (T != NULL)
                      MUStrDup(&T->CompleteAction,ActionString);
   
                    if (Complete != NULL)
                      *Complete = FALSE;
   
                    MNodeSetAttr(N,mnaPowerIsEnabled,(void **)"false",mdfString,mVerify);

                    T->PID = 1;
                    }
   
                  break;
      
                default:
   
                  return(FAILURE);
   
                  /*NOTREACHED*/
   
                  break;
                }   /* END switch (aindex) */
   
              ptr = MUStrTok(NULL,",",&TokPtr);
              }  /* END while (ptr != NULL) */

            /* if none of the node modify requests (non-aggregating) succeeded, 
               then return failure.  (success just means it was submitted
               at this stage) */

            if ((aindex == mnaOS) && 
                (NodeModifySuccessDetected == FALSE))
              {
              return (FAILURE);
              }
            }  /* END if (MSched.AggregateNodeActions == FALSE) */
          else
            {
            mnl_t NL;

            char *Attr;
            char *Value;
   
            enum MNodeAttrEnum aindex;

            int nindex;
   
            /* FORMAT:  <ARG>=<VALUE> */
   
            Attr  = MUStrTok(ArgLine,"=",&TokPtr);
            Value = MUStrTok(NULL,"= \t\n",&TokPtr);
   
            aindex = (enum MNodeAttrEnum)MUGetIndexCI(Attr,MNodeAttr,FALSE,mnaNONE);
   
            /* FORMAT: OID = node[,node]... */
   
            if (aindex == mnaNONE)
              {
              return(FAILURE);
              }

            MNLInit(&NL);

            MNLFromString(OID,&NL,-1,FALSE);

            /* NOTE: in the node aggregating case, return failure when there is an error 
             * performing node modify operations (e.g. communicating with the RM) */
   
            switch (aindex)
              {
              case mnaNodeState:

                {
                enum MStatusCodeEnum SC;
                char EMsg[MMAX_LINE];

                if (MNodeModify(NULL,OID,mnaNodeState,Value,EMsg,&SC) == FAILURE)
                  {
                  MDB(2,fRM) MLog("WARNING:  cannot modify state of '%s' = %s\n",
                    OID,
                    EMsg);
           
                  return(FAILURE);
                  }
                }  /* END case mnaNodeState */

                break;

              case mnaOS:
 
                {
                char EMsg[MMAX_LINE];
 
                if (MNLGetemReady(&NL,Value,EMsg) == FAILURE)
                  {
                  /* NYI: append EMsg to Msg */
 
                  if (Msg != NULL)
                    MUStrCpy(Msg,EMsg,MMAX_LINE);

                  MNLFree(&NL);

                  return (FAILURE);
                  }
                }  /* END BLOCK case mnaOS */
 
                break;
 
              case mnaPowerIsEnabled:

                {
                mnode_t *N;

                for (nindex = 0;MNLGetNodeAtIndex(&NL,nindex,&N) == SUCCESS;nindex++)
                  {
                  if (N == MSched.GN)
                    continue;

                  if ((!strcasecmp(Value,"on")) ||
                      (!strcasecmp(Value,"on+")))
                    {
                    /* power node on */
           
                    if ((N->PowerSelectState == mpowOn) ||
                        (MNodeGetSysJob(N,msjtPowerOn,MBNOTSET,NULL) == SUCCESS))
                      {
                      /* skip this node */

                      MDB(5,fSCHED) MLog("INFO:   not powering node '%s' on--power select state is already 'ON'\n",
                        N->Name);

                      MNLRemove(&NL,N);

                      continue;
                      }
                    }
                  else if ((!strcasecmp(Value,"off")) ||
                           (!strcasecmp(Value,"off+")))
                    {
                    /* power node off */
           
                    if ((N->PowerSelectState == mpowOff) ||
                        (MNodeGetSysJob(N,msjtPowerOff,TRUE,NULL) == SUCCESS))
                      {
                      /* skip this node */

                      MDB(5,fSCHED) MLog("INFO:   not powering node '%s' off--power select state is already 'OFF'\n",
                        N->Name);

                      MNLRemove(&NL,N);

                      continue;
                      }
                    }
                  }  /* END for (nindex) */
                }    /* END BLOCK */

                if (!strcmp(Value,"on"))
                  {
                  /* power node on */
 
                  if (MNLSetAttr(&NL,mnaPowerIsEnabled,(void **)"true",mdfString,mVerify) == FAILURE)
                    {
                    MNLFree(&NL);

                    return (FAILURE);
                    }
                  }
                else if (!strcasecmp(Value,"off"))
                  {
                  /* power node off */
 
                  if (MNLSetAttr(&NL,mnaPowerIsEnabled,(void **)"false",mdfString,mVerify) == FAILURE)
                    {
                    MNLFree(&NL);

                    return (FAILURE);
                    }
                  }
                else if (!strcasecmp(Value,"reset"))
                  {
                  char EMsg[MMAX_LINE];
 
                  /* reset node */
 
                  if (MNodeReboot(NULL,&NL,EMsg,NULL) == FAILURE)
                    {
                    MNLFree(&NL);

                    /* NYI: append EMsg to Msg */
 
                    if (Msg != NULL)
                      MUStrCpy(Msg,EMsg,MMAX_LINE);

                    return (FAILURE);
                    }
                  }
                else if (!strcasecmp(Value,"on+"))
                  {
                  /* power node on, but trigger isn't finished until action is complete */

                  if (MNLSetAttr(&NL,mnaPowerIsEnabled,(void **)"true",mdfString,mVerify) == FAILURE)
                    {
                    MNLFree(&NL);

                    if (Complete != NULL)
                      *Complete = TRUE;

                    return(FAILURE);                   
                    }

                    if (Complete != NULL)
                      *Complete = FALSE;
 
                  if (T != NULL)
                    MUStrDup(&T->CompleteAction,ActionString);

                  T->PID = 1;
                  }
                else if (!strcasecmp(Value,"off+"))
                  {
                  /* power node off, but trigger isn't finished until action is complete */
 
                  if (MNLSetAttr(&NL,mnaPowerIsEnabled,(void **)"false",mdfString,mVerify) == FAILURE)
                    {
                    MNLFree(&NL);

                    if (Complete != NULL)
                      *Complete = TRUE;

                    return(FAILURE);                   
                    }

                    if (Complete != NULL)
                      *Complete = FALSE;
 
                  if (T != NULL)
                    MUStrDup(&T->CompleteAction,ActionString);

                  T->PID = 1;
                  }
 
                break;
    
              default:
 
                MNLFree(&NL);

                return (FAILURE);
 
                /*NOTREACHED*/
 
                break;
              }   /* END switch (aindex) */
            }     /* END else */

          break;

        case mncmCreate:

          {
          int rc;

          mnode_t *N;


          char EMsg[MMAX_LINE];
          char tmpLine[MMAX_LINE*10];

          /* FORMAT:  COUNT:OS */

          if (MNodeFind(OID,&N) == FAILURE)
            {
            if (Msg != NULL)
              snprintf(Msg,MMAX_LINE,"cannot locate hostlist '%s'",OID);

            return(FAILURE);
            }

          /* FORMAT:  COUNT:OS */

          snprintf(tmpLine,sizeof(tmpLine),"%s:%s%s%s",
            N->Name,
            ArgLine,
            ((T->OType == mxoJob) && ((mjob_t *)T->O != NULL)) ? ":operationid=" : "",
            ((T->OType == mxoJob) && ((mjob_t *)T->O != NULL)) ? ((mjob_t *)T->O)->Name : "");

          mstring_t Output(MMAX_LINE);

          rc = MRMVMCreate(tmpLine,&Output,EMsg,NULL);

          if (rc == FAILURE)
            {
            if (Msg != NULL)
              MUStrCpy(Msg,EMsg,MMAX_LINE);

            MUStrCpy(Msg,Output.c_str(),MMAX_LINE);
            }

          return(rc);
          }  /* END BLOCK (case mncmCreate) */

          break;

        case mncmMigrate:

          {
          int rc;

          char *TokPtr = ArgLine;

          char      *VMName;
          char      *SrcNodeName;
          char      *DestNodeName;
          mnode_t   *SrcNode;
          mnode_t   *DestNode;
          mln_t     *VMLink;
          char      *VMList[2];
          mnl_t      DestNL;

          /* FORMAT:  <VM>:<DestNode>,... */

          TokPtr = ArgLine;

          VMName  = MUStrTok(NULL,":=",&TokPtr);
          DestNodeName = MUStrTok(NULL,":=",&TokPtr);

          SrcNodeName  = OID;

          if ((DestNodeName == NULL) || (VMName == NULL) ||(SrcNodeName) == NULL)
            {
            return(FAILURE);
            }

          if (MNodeFind(SrcNodeName,&SrcNode) == FAILURE)
            {
            return(FAILURE);
            }

          if (MNodeFind(DestNodeName,&DestNode) == FAILURE)
            {
            return(FAILURE);
            }

          if (MULLCheck(SrcNode->VMList,VMName,&VMLink) == FAILURE)
            {
            /* Should we be checking this here? */

            /* return(FAILURE); */
            }

          MNLInit(&DestNL);

          VMList[0] = VMName;

          MNLSetNodeAtIndex(&DestNL,0,DestNode);
          MNLSetTCAtIndex(&DestNL,0,1);
          MNLTerminateAtIndex(&DestNL,1);

          VMList[1] = NULL;

          rc = MRMJobMigrate((mjob_t *)T->O,VMList,&DestNL,Msg,NULL);

          MNLFree(&DestNL);

          return(rc);
          }  /* END BLOCK (case mncmMigrateVM) */

          break;

        default:

          return(FAILURE);

          /*NOTREACHED*/

          break;
        }
      }   /* END BLOCK (case mxoNode) */

      break;

    case mxoxJobGroup:

      {
      job_iter JTI;

      marray_t JArray;

      int jindex;

      mjob_t *J;

      char *JID;
      char *ptr;
      char *TokPtr;
 
      /* OID FORMAT:  <JID>[+<JID>]... */

      mbool_t FailureDetected;

      enum MJobCtlCmdEnum atype;

      char *Attr = NULL;
      char *Value = NULL;
      char *Msg = NULL;

      enum MJobAttrEnum aindex = mjaNONE;

      atype = (enum MJobCtlCmdEnum)MUGetIndexCI(Action,MJobCtlCmds,FALSE,mjcmNONE);

      if (atype == mjcmNONE)
        {
        MDB(4,fSCHED) MLog("ERROR:    cannot parse job action '%s' in %s\n",
          Action,
          FName);

        return(FAILURE);
        }

      if (atype == mjcmModify)
        {
        char *TokPtr;

        Attr  = MUStrTok(ArgLine,"+-=",&TokPtr);
        Value = MUStrTok(NULL,"=: \t\n",&TokPtr);
        Msg = MUStrTok(NULL,":\t\n",&TokPtr);  /* extract message */

        aindex = (enum MJobAttrEnum)MUGetIndexCI(Attr,MJobAttr,FALSE,mnaNONE);
        }

      FailureDetected = FALSE;

      JID = MUStrTok(OID,"+",&TokPtr);

      while (JID != NULL)
        {
        MUArrayListCreate(&JArray,sizeof(mjob_t *),1);

        if (!strcmp(JID,"-"))
          {
          if (T == NULL)
            return(FAILURE);

          ptr = T->OID;
          }
        else
          {
          ptr = JID;
          }

        MJobIterInit(&JTI);

        while (MJobTableIterate(&JTI,&J) == SUCCESS)
          {
          if ((J->JGroup != NULL) && (J->JGroup->Name != NULL) && (!strcmp(ptr,J->JGroup->Name)))
            {
            MUArrayListAppend(&JArray,&J);
            }
          }

        if (MUArrayListGet(&JArray,0) == NULL)
          {
          MDB(4,fSCHED) MLog("ERROR:    cannot locate job '%s' in %s\n",
            JID,
            FName);

          JID = MUStrTok(NULL,"+",&TokPtr);

          FailureDetected = TRUE;

          continue;
          }

        for (jindex = 0;jindex < JArray.NumItems;jindex++)
          {
          J = *(mjob_t **)MUArrayListGet(&JArray,jindex);
       
          if (J == NULL)
            continue;

          switch (atype)
            {
            case mjcmCancel:
   
              {
              char *CCodeCheck;
              char UpperArgLine[MMAX_LINE];
   
              if (MJobCancel(J,NULL,FALSE,Msg,NULL) == FAILURE)
                {
                MDB(4,fSCHED) MLog("ERROR:    cannot cancel job '%s' in %s\n",
                  JID,
                  FName);
   
                JID = MUStrTok(NULL,"+",&TokPtr);
   
                FailureDetected = TRUE;
   
                continue;
                }
   
              MUStrToUpper(ArgLine,UpperArgLine,MMAX_LINE);
   
              /* If specified, allow trigger to set the completion code of the job */
   
              if ((CCodeCheck = strstr(UpperArgLine,"CCODE=")) != NULL)
                {
                CCodeCheck += strlen("CCODE="); /* Skip the "CCODE:" part */
   
                if (CCodeCheck[0] != '\0')
                  {
                  J->CompletionCode = strtol(CCodeCheck,NULL,10);
                  }
                }
              else
                {
                J->CompletionCode = 273; /* Completion code for a canceled job in TORQUE */
                }
              }  /* END case mjcmCancel */
   
              break;
   
            case mjcmModify:

              switch (aindex)
                {
                case mjaHold:

                  if (MJobSetAttr(
                        J,
                        mjaHold,
                        (Value != NULL) ? (void **)Value : (void **)"batch",
                        mdfString,
                        mSet) == FAILURE)
                    {
                    MDB(4,fSCHED) MLog("ERROR:    cannot hold job '%s' in %s\n",
                      JID,
                      FName);

                    JID = MUStrTok(NULL,"+",&TokPtr);

                    FailureDetected = TRUE;

                    continue;
                    }

                  if (Msg != NULL)
                    {
                    /* attach provided message */

                    MMBAdd(
                      &J->MessageBuffer,
                      Msg,
                      NULL,
                      mmbtHold,
                      0,
                      0,
                      NULL);
                    }

                  if (J->SubState == mjsstProlog)
                    {
                    J->SubState = mjsstNONE;
                    }

                  /* checkpoint change (make this configurable at this point?) */

                  MOCheckpoint(mxoJob,(void *)J,FALSE,NULL);
          
                  break;

                default:

                  MDB(4,fSCHED) MLog("ERROR:    cannot modify attribute '%s' for job '%s' in %s\n",
                    Attr,
                    JID,
                    FName);

                  JID = MUStrTok(NULL,"+",&TokPtr);

                  FailureDetected = TRUE;

                  break;
                }  /* END switch (aindex) */

                break;

              default:
   
                MDB(4,fSCHED) MLog("ERROR:    action '%s' not handled in %s\n",
                  Action,
                  FName);
   
                return(FAILURE);
   
                /*NOTREACHED*/
   
                break;
            }  /* END switch (atype) */
          }    /* END for (jindex) */

        JID = MUStrTok(NULL,"+",&TokPtr);

        MUArrayListFree(&JArray);
        }    /* END while (JID != NULL) */

      if (FailureDetected == TRUE)
        {
        return(FAILURE);
        }
      }  /* END BLOCK (case mxoxJobGroup) */

      break;

    case mxoSched:

      {
      enum MSchedCtlCmdEnum atype;

      atype = (enum MSchedCtlCmdEnum)MUGetIndexCI(Action,MSchedCtlCmds,FALSE,msctlNONE);

      switch (atype)
        {
        case msctlVMMigrate:

          {
          enum MVMMigrationPolicyEnum aindex;
          aindex = (enum MVMMigrationPolicyEnum)MUGetIndexCI(ArgLine,MVMMigrationPolicy,FALSE,mvmmmNONE);

          return(MUIVMCtlPlanMigrations(aindex,FALSE,FALSE,NULL));
          }
  
        default:

          return(FAILURE);

        } /* END switch (atype) */
      }   /* END case mxoSched */

      break;

    case mxoTrig:

      {
      enum MSchedCtlCmdEnum atype;

      atype = (enum MSchedCtlCmdEnum)MUGetIndexCI(Action,MSchedCtlCmds,FALSE,msctlNONE);

      if (atype == msctlNONE)
        {
        return(FAILURE);
        }

      switch (atype)
        {
        case msctlModify:

          {
          char *TokPtr;

          mtrig_t *T;

          char *Attr;
          char *Value;

          enum MTrigAttrEnum aindex;

          Attr  = MUStrTok(ArgLine,"=",&TokPtr);
          Value = MUStrTok(NULL,"\"",&TokPtr);

          /* FORMAT: OID = trigid */

          aindex = (enum MTrigAttrEnum)MUGetIndexCI(Attr,MTrigAttr,FALSE,mtaNONE);

          if ((OID == NULL) || (OID[0] == '\0') || (aindex == mtaNONE))
            {
            return(FAILURE);
            }

          if (MTrigFind(OID,&T) == FAILURE)
            {
            return(FAILURE);
            }

          switch (aindex)
            {
            case mtaActionData:

              if (MTrigSetAttr(T,aindex,Value,mdfString,mSet) == FAILURE)
                {
                return(FAILURE);
                }

              break;

            default:

              return(FAILURE);

              /*NOTREACHED*/

              break;
            }  /* END switch (aindex) */

          break;
          }     /* END case msctlModify */

        default:

          return(FAILURE);

          /*NOTREACHED*/

          break;
        }       /* END switch (atype) */
      }         /* END BLOCK (case mxoTrig) */

      break;

    case mxoRM:

      {
      mrm_t  *R = NULL;
      char *RMID;
      char *TokPtr;
      mbool_t FailureDetected;

      enum MRMCtlCmdEnum atype;

      atype = (enum MRMCtlCmdEnum)MUGetIndexCI(Action,MRMCtlCmds,FALSE,mrmctlNONE);

      if (atype == mrmctlNONE)
        {
        MDB(4,fSCHED) MLog("ERROR:    cannot parse rm action '%s' in %s\n",
        Action,
        FName);

        return(FAILURE);
        }

      FailureDetected = FALSE;

      RMID = MUStrTok(OID,"+",&TokPtr);

      while (RMID != NULL)
        {
        if (!strcmp(RMID, "-"))
          {
          if (T == NULL)
            return(FAILURE);

          R = (mrm_t *)T->O;
          }
        else if (MRMFind(RMID,&R) == FAILURE) 
          {
          if (Msg != NULL)
            strcpy(Msg,"cannot locate specified RM");

          RMID = MUStrTok(NULL,"+",&TokPtr);

          FailureDetected = TRUE;

          continue;
          }

        switch (atype)
          {
          case mrmctlModify:

            {
            char   *TokPtr;

            enum MRMAttrEnum aindex;

            char *Attr;
            char *Value;

            /* FORMAT: <attr>=<value> */

            Attr  = MUStrTok(ArgLine,"=",&TokPtr);
            Value = MUStrTok(NULL,"\"",&TokPtr);

            aindex = (enum MRMAttrEnum)MUGetIndexCI(Attr,MRMAttr,FALSE,mrmaNONE);

            switch (aindex)
              {
              case mrmaState:
  
                return(MRMSetAttr(R,aindex,(void **)Value,mdfString,mSet));

                break;

              default:

                if (Msg != NULL)
                  strcpy(Msg,"cannot modify specified attribute");
   
                return(FAILURE);

                /* NOTREACHED */

                break;
              } /* END switch (aindex) */
            }     /* END BLOCK (case mrmctlModify) */

            break;

          case mrmctlDestroy:

            MDB(3,fUI) MLog("WARNING:  cannot destroy static RM\n");
                                                                                      
            if (Msg != NULL)
              strcpy(Msg,"WARNING:  cannot destroy static RM\n");
                                                                                      
            return(FAILURE);
 
            /* NOTREACHED */
  
            break;

          case mrmctlPurge:

            return(MRMPurge(R));

            break;

          default:

            if (Msg != NULL)
              strcpy(Msg,"action not supported for RM object");

            return(FAILURE);

            /*NOTREACHED*/

            break;
          } /* END switch (atype) */

        RMID = MUStrTok(NULL,"+",&TokPtr);
        } /* END while (RMID != NULL */  

      if (FailureDetected == TRUE)
        {
        return(FAILURE);
        }
      } /* END BLOCK (case mxoRM) */

      break;

    case mxoRsv:
 
      {
      enum MRsvCtlCmdEnum atype;

      atype = (enum MRsvCtlCmdEnum)MUGetIndexCI(Action,MRsvCtlCmds,FALSE,mrcmNONE);

      if (atype == mrcmNONE)
        {
        return(FAILURE);
        }

      switch (atype)
        {
        case mrcmModify:

          {
          char *ptr;
          char *TokPtr;

          enum MRsvAttrEnum attr;

          mrsv_t *R;

          if (!strcmp(OID,"-"))
            {
            if (T == NULL)
              return(FAILURE);

            R = (mrsv_t *)T->O;
            }
          else if (MRsvFind(OID,&R,mraNONE) == FAILURE)
            {
            return(FAILURE);
            }

          ptr = MUStrTok(ArgLine,":",&TokPtr);

          attr = (enum MRsvAttrEnum)MUGetIndexCI(ptr,MRsvAttr,FALSE,mraNONE);

          switch (attr)
            {
            case mraACL:

              {
              enum MObjectSetModeEnum Mode;

              if (MUStrIsEmpty(TokPtr))
                Mode = mSet;
              else if (strstr(TokPtr,"-=") != NULL)
                Mode = mDecr;
              else if (strstr(TokPtr,"+=") != NULL)
                Mode = mAdd;
              else
                Mode = mSet;
                
              MRsvSetAttr(R,mraACL,(void *)TokPtr,mdfString,Mode);
              }

              break;

            default:

              return(FAILURE);

              /*NOTREACHED*/

              break;
            }
          }  /* END case mrcmModify */

          break;

        case mrcmDestroy:

          {
          mrsv_t *R;

          if (!strcmp(OID,"-"))
            {
            if (T == NULL)
              return(FAILURE);

            R = (mrsv_t *)T->O;
            }
          else if (MRsvFind(OID,&R,mraNONE) == FAILURE)
            {
            return(FAILURE);
            }

          R->CancelIsPending = TRUE;

          R->EndTime = MSched.Time - 1;
          R->ExpireTime = 0;
   
          /* remove reservation */
   
          MRsvCheckStatus(NULL);
   
          if ((long)R->StartTime <= MUIDeadLine)
            {
            /* adjust UI phase wake up time */
   
            if (MSched.AdminEventAggregationTime >= 0)
              MUIDeadLine = MIN(MUIDeadLine,(long)MSched.Time + MSched.AdminEventAggregationTime);
            }
          }  /* END case mrcmDestroy */

          break;

        case mrcmOther:
 
          {
          mrsv_t *R;

          if (!strcmp(OID,"-"))
            {
            if (T == NULL)
              {
              return(FAILURE);
              }

            R = (mrsv_t *)T->O;
            }
          else if (MRsvFind(OID,&R,mraNONE) == FAILURE)
            {
            return(FAILURE);
            }

          /* parse argline */

          if (strstr(ArgLine,"submit") != NULL)
            {
            MJobSubmitFromJSpec(R->SpecJ,NULL,Msg);
            }  /* END if (strstr(ArgLine,"submit") != NULL) */
          }    /* END BLOCK (case mrcmOther) */

          break;

        default:

          return(FAILURE);

          /*NOTREACHED*/

          break;
        }  /* END switch (atype) */
      }    /* END BLOCK (case mxoRsv) */

      break;

    case mxoxVPC:

      {
      mpar_t *VPC;

      MVPCFind(OID,&VPC,TRUE);

      if (!strcasecmp(Action,"destroy"))
        {
        MVPCDestroy(&VPC,ArgLine);
        }
      else
        {
        return(FAILURE);
        }
      }  /* END case mxoxVPC */

      break;

    default:

      if (Msg != NULL)
        strcpy(Msg,"unsupported trigger object type");

      return(FAILURE);

      /* NOTREACHED */

      break;
    }  /* END switch (OType) */

  /*NOTE: return may (and does) return in above switch statement */
  return(SUCCESS);
  }  /* END MTrigLaunchInternalAction() */
示例#5
0
int MJobProcessRestrictedAttrs(

  mjob_t *J,    /* I */
  char   *EMsg) /* O */

  {
  const char *FName = "MJobProcessRestrictedAttrs";

  MDB(5,fSCHED) MLog("%s(%s)\n",
    FName,
    (J != NULL) ? J->Name : NULL);

  if ((J->Triggers != NULL) && (J->TemplateExtensions == NULL))
    {
    /* triggers can come from other places (ie. CLASSCFG[] JOBTRIGGERS) */

    MOReportEvent((void *)J,J->Name,mxoJob,mttCreate,J->CTime,TRUE);

    return(SUCCESS);
    }
  else if ((J->Triggers != NULL) && (J->TemplateExtensions != NULL))
    {
    MOReportEvent((void *)J,J->Name,mxoJob,mttCreate,J->CTime,TRUE);
    }

  if (J->TemplateExtensions == NULL)
    {
    return(SUCCESS);
    }

  if (J->TemplateExtensions->SpecTrig[0] != NULL)
    {
    char tmpBuf[MMAX_BUFFER];

    int   VarValBufSize;
    int   index;

    mln_t *VarList = NULL;

    for (index = 0;index < MDEF_VARVALBUFCOUNT;index++)
      {
      tmpVarValBuf2[index][0] = '\0';
      }

    if ((J->Credential.Q == NULL) || (!bmisset(&J->Credential.Q->Flags,mqfTrigger)))
      {
      MMBAdd(
        &J->MessageBuffer,
        "trigger specified but not allowed by QOS",
        NULL,
        mmbtOther,
        MSched.Time + MCONST_DAYLEN,
        0,
        NULL);
      }
    else
      {
      int tindex;
      marray_t HashList;

      /* NOTE:  loop through all elements in linked list (NYI) */

      VarValBufSize = MDEF_VARVALBUFCOUNT - 1;

      MJobGetVarList(
        J,
        &VarList,
        tmpVarValBuf2,
        &VarValBufSize);

      MUArrayListCreate(&HashList,sizeof(mhash_t *),4);

      if (J->Variables.Table != NULL)
        {
        MUArrayListAppendPtr(&HashList,&J->Variables);
        }

      if (J->JGroup != NULL)
        {
        mjob_t *tmpJ = NULL;

        if (MJobFind(J->JGroup->Name,&tmpJ,mjsmExtended) == SUCCESS)
          {
          if (tmpJ->Variables.Table != NULL)
            {
            MUArrayListAppendPtr(&HashList,&tmpJ->Variables);
            }
          }
        }

      for (tindex = 0;tindex < MMAX_SPECTRIG;tindex++)
        {
        if (J->TemplateExtensions->SpecTrig[tindex] == NULL)
          break;

        MUInsertVarList(
          J->TemplateExtensions->SpecTrig[tindex],
          VarList,  /* var name array */
          (mhash_t **)HashList.Array, /* variables in hashtables */
          NULL,
          tmpBuf,   /* O */
          sizeof(tmpBuf),
          TRUE);
    
        MUArrayListFree(&HashList);

        if (MTrigLoadString(&J->Triggers,tmpBuf,TRUE,FALSE,mxoJob,J->Name,NULL,EMsg) == FAILURE)
          {
          return(FAILURE);
          }

        MUFree(&J->TemplateExtensions->SpecTrig[tindex]);
        }  /* END for (tindex) */

#ifdef MYAHOO
      /* make sure that holds continue to disable triggers, even after new ones are loaded */

      if (J->Hold != 0)
        {
        MTrigDisable(J->Triggers);
        }
#endif /* MYAHOO */

      if (J->Triggers != NULL)
        {
        mtrig_t *T;

        int tindex;

        for (tindex = 0; tindex < J->Triggers->NumItems;tindex++)
          {
          T = (mtrig_t *)MUArrayListGetPtr(J->Triggers,tindex);

          if (MTrigIsValid(T) == FALSE)
            continue;

          MTrigInitialize(T);

          if (MSched.ForceTrigJobsIdle == TRUE)
            bmset(&J->IFlags,mjifWaitForTrigLaunch);
          }    /* END for (tindex) */

        /* report events for admin reservations */

        MOReportEvent((void *)J,J->Name,mxoJob,mttCreate,J->CTime,TRUE);
        }
      }    /* END else ((J->Cred.Q == NULL) || (!bmisset(&J->Cred.Q->Flags,mqfTrigger))) */

    MULLFree(&VarList,MUFREE);
    }      /* END if (J->TX->SpecTrig != NULL) */

  if (J->TemplateExtensions->SpecMinPreemptTime != NULL)
    {
    if ((J->Credential.Q == NULL) || (!bmisset(&J->Credential.Q->Flags,mqfPreemptCfg)))
      {
      MMBAdd(
        &J->MessageBuffer,
        "minpreempttime specified but not allowed by QOS",
        NULL,
        mmbtOther,
        MSched.Time + MCONST_DAYLEN,
        0,
        NULL);
      }
    else
      {
      MJobSetAttr(J,mjaMinPreemptTime,(void **)J->TemplateExtensions->SpecMinPreemptTime,mdfString,mSet);
      }

    MUFree((char **)&J->TemplateExtensions->SpecMinPreemptTime);
    }  /* if (J->TX->SpecMinPreemptTime != NULL) */

  if ((J->TemplateExtensions->SpecTemplates != NULL) && (J->TemplateExtensions->SpecTemplates[0] != '\0'))
    {
    /* Apply templates */

    mjob_t *SJ;
    char Templates[MMAX_LINE << 2];
    char *Value;
    char *ptr;
    char tmpLine[MMAX_LINE << 2];
    char *TokPtr2;

    MUStrCpy(Templates,J->TemplateExtensions->SpecTemplates,sizeof(Templates));
    Value = Templates;

    if (!bmisset(&J->Flags,mjfTemplatesApplied))
      {
      if (Value[0] == '^')
        {
        bmset(&J->IFlags,mjifNoTemplates);
        Value++;
        }

      TokPtr2 = Value;
      strncpy(tmpLine,Value,sizeof(tmpLine));

      while ((ptr = MUStrTok(TokPtr2,":,",&TokPtr2)) != NULL)
        {
        if ((MTJobFind(ptr,&SJ) == SUCCESS) && 
            (SJ->TemplateExtensions != NULL) && 
            (bmisset(&SJ->TemplateExtensions->TemplateFlags,mtjfTemplateIsSelectable)))
          {
          if (MJobApplySetTemplate(J,SJ,EMsg) == FAILURE)
            {
            return(FAILURE);
            }
          }
        else
          {
          char errMsg[MMAX_LINE];

          snprintf(errMsg,sizeof(errMsg),"WARNING:  cannot apply template '%s'",
            ptr);

          MMBAdd(&J->MessageBuffer,errMsg,NULL,mmbtNONE,0,0,NULL);
          }

        if (!J->TemplateExtensions->ReqSetTemplates.empty())
          MStringAppend(&J->TemplateExtensions->ReqSetTemplates,",");

        MStringAppend(&J->TemplateExtensions->ReqSetTemplates,ptr);
        }
      }

    bmset(&J->Flags,mjfTemplatesApplied);
    bmset(&J->SysFlags,mjfTemplatesApplied);

    /* Free the memory, we don't need it anymore */

    MUFree(&J->TemplateExtensions->SpecTemplates);
    }  /* END if ((J->TX->SpecTemplates != NULL) && ...) */

  if ((J->WCLimit == MMAX_TIME) && (!bmisset(&MSched.Flags,mschedfAllowInfWallTimeJobs)))
    {
    if (EMsg != NULL)
      {
      sprintf(EMsg,"infinite walltime jobs not allowed\n");

      return(FAILURE);
      }
    }

  if ((J->TemplateExtensions->SpecArray != NULL) && 
      (J->TemplateExtensions->SpecArray[0] != '\0') &&
      (J->Array == NULL) &&
      (!bmisset(&J->IFlags,mjifWasLoadedFromCP)))
    {
    char *ptr;
    char *TokPtr = NULL;

    char *arrayStr = NULL;

    mulong BM;

    MUStrDup(&arrayStr,J->TemplateExtensions->SpecArray);

    /* Alloc the Array control container */
    if (MJobArrayAlloc(J) == FAILURE)
      {
      /* NO MEMORY ERROR */
      return(FAILURE);
      }

    ptr = MUStrTok(arrayStr,"[]",&TokPtr);

    MUStrCpy(J->Array->Name,ptr,MMAX_NAME);

    ptr = MUStrTok(NULL,"[]",&TokPtr);

    MUParseRangeString(
      ptr,
      &BM,
      J->Array->Members,
      MMAX_JOBARRAYSIZE,
      &J->Array->Count,
      NULL);

    ptr = MUStrTok(NULL,"%\n\t",&TokPtr);

    if ((ptr != NULL) && (ptr[0] != '\0'))
      {
      J->Array->Limit = strtol(ptr,NULL,10);
      }

    /* NO ERROR CHECKING ON 'NO MEMORY' CONDITION ??? */
    J->Array->JPtrs  = (mjob_t **)MUCalloc(1,sizeof(mjob_t *) * J->Array->Count + 1);
    J->Array->JName  = (char **)MUCalloc(1,sizeof(char *) * J->Array->Count + 1);
    J->Array->JState = (enum MJobStateEnum *)MUCalloc(1,sizeof(enum MJobStateEnum) * J->Array->Count + 1);

    MUFree(&arrayStr);
    }

  return(SUCCESS);
  } /* END MJobProcessRestrictedAttrs() */