public ActivationFilterResponse FilterActivation(Stream jobXml, int schedulerPass, int jobIndex, bool backfill, int resourceCount) { LogEventMsg("FilterActivation"); ActivationFilterResponse retVal = ActivationFilterResponse.StartJob; _filterActivationCalls++; return(retVal); }
/// <summary> /// Analyse the Job and if all the required licenses are available start the job. /// If there are not enough total licenses to satisfy the request, fail the job. /// If there are not enough licenses currently available, request the scheduler keep /// the allocated resources so that when the licenses become available the job can /// be scheduled. /// </summary> /// <param name="job"></param> /// <param name="schedulerPass"></param> /// <param name="jobIndex"></param> /// <param name="backfill"></param> /// <param name="resourceCount"></param> /// <returns></returns> public ActivationFilterResponse FilterActivation( Stream jobXml, int schedulerPass, int jobIndex, bool backfill, int resourceCount) { ActivationFilterResponse returnDecision = ActivationFilterResponse.StartJob; _schedulerPass = schedulerPass; _jobIndex = jobIndex; _backfill = backfill; _resourceCount = resourceCount; if ((schedulerPass == 1) && (jobIndex == 1)) { // Scheduler restarted. Ensure we never use stale data from FlexLM server by clearing cache Cache.Clear(); } ParseJobXml(jobXml); // If this job does not parse correctly or has no license requests, tell the Scheduler // to proceed and schedule the job as normal. if (_requestedFeatures.Count <= 0) { return(ActivationFilterResponse.StartJob); } // If the job is flagged as backfill then there is a possibility that allowing it to // run might block a higher priority job from running due to the use of shared licenses. if (backfill) { // Some users may wish to disable this feature so that licenses are utilized as much as // possible. // Let another job take the backfill slot if there is one. return(ActivationFilterResponse.DoNotRunKeepResourcesAllowOtherJobsToSchedule); } // Find out what licenses are available Cache.Load(schedulerPass, jobIndex); if (Cache.licenseInfo.PollServerFailed) { // FlexLM server is down. Hold the job and let other non-licensed Jobs // to be scheduled. Administrator can release the held jobs when the issue // is resolved using job modify /holduntil or just wait for the HoldUntil // time to elapse. return(ActivationFilterResponse.HoldJobReleaseResourcesAllowOtherJobsToSchedule); } // Iterate through the requesting features and determine whether // there are enough license tokens. IDictionaryEnumerator iterator = _requestedFeatures.GetEnumerator(); // Run lmutils lmstat to verify the available license tokens. while (iterator.MoveNext()) { string featureName = iterator.Key as string; int numberRequested = (int)iterator.Value; if (Cache.licenseInfo.LicenseDirectory.ContainsKey(featureName)) { int total = Cache.licenseInfo.LicenseDirectory[featureName].Total; int inUse = Cache.licenseInfo.LicenseDirectory[featureName].InUse; if (numberRequested > total) { if (_growing) { // Ignore additional resources returnDecision = ActivationFilterResponse.RejectAdditionOfResources; break; } // Not enough licenses purchased to ever satisfy this job. SetProgressMessage("FlexLM error: Not enough licenses for " + featureName); returnDecision = ActivationFilterResponse.FailJob; break; } else if (numberRequested > total - inUse) { if (_growing) { // Ignore additional resources returnDecision = ActivationFilterResponse.RejectAdditionOfResources; break; } // Not enough resources to run this job on this pass. Reserve the licenses that are // available and wait for more to become available Cache.Reserve(featureName, total - inUse); returnDecision = ActivationFilterResponse.DoNotRunKeepResourcesAllowOtherJobsToSchedule; } else { Cache.Reserve(featureName, numberRequested); } } else { if (_growing) { // Ignore additional resources returnDecision = ActivationFilterResponse.RejectAdditionOfResources; break; } // Requested a license we don't have SetProgressMessage("FlexLM error: License " + featureName + " not found"); returnDecision = ActivationFilterResponse.FailJob; break; } } // If we want the resources for this job, persist the updates if ((returnDecision == ActivationFilterResponse.DoNotRunKeepResourcesAllowOtherJobsToSchedule) || (returnDecision == ActivationFilterResponse.StartJob)) { Cache.Save(); } return(returnDecision); }
/// <summary> /// Entry point for an activation filter. /// </summary> /// <param name="jobXml"></param> /// XML stream containing the job in question. /// <param name="schedulerPass"></param> /// <param name="jobIndex"></param> /// <param name="backfill"></param> /// <param name="resourceCount"></param> /// <returns></returns> public ActivationFilterResponse FilterActivation(Stream jobXml, int schedulerPass, int jobIndex, bool backfill, int resourceCount) { if (setupLogFile() != 0) { return(ActivationFilterResponse.FailJob); } ActivationFilterResponse retval = ActivationFilterResponse.FailJob; try { // If the job is submitted outside peak business hours, no change is necessary if (DuringOffHours()) { logFile.WriteLine("AF: During Off Peak Hours, job starting"); return(ActivationFilterResponse.StartJob); } // Currently during peak business hours // Check if user is authorized to start a job during these hours // If not, delay the start of the job until off peak hours are in play // Load the job file as an XmlDocument. XmlDocument doc = new XmlDocument(); doc.Load(jobXml); XmlNamespaceManager nsMgr = new XmlNamespaceManager(doc.NameTable); nsMgr.AddNamespace("hpc", xmlNameSpace); // Find the job node in the XML document. XmlNode jobXML = doc.SelectSingleNode("/hpc:Job", nsMgr); if (jobXML == null) { throw new Exception("No job in the xml file"); } // Find the User attribute for the job. XmlAttributeCollection attrCol = jobXML.Attributes; XmlAttribute userAttr = attrCol["User"]; string user = userAttr.Value; // If user does not have permission to run jobs during peak hours, adjust HoldUntil if needed if (!PeakHoursUser(user)) { string jobIdString = attrCol["Id"].Value; int jobId; Int32.TryParse(jobIdString, out jobId); if (jobId != 0) { using (IScheduler scheduler = new Scheduler()) { scheduler.Connect("localhost"); ISchedulerJob job = scheduler.OpenJob(jobId); DateTime peakEnd = DateTime.Today.AddHours((double)endhours); // If the job is not already set to delay until off peak hours, set it // This property should be null, but could be non-null if some other // thread has set it after scheduling called the activation filter if ((job.HoldUntil == null) || (job.HoldUntil < peakEnd)) { job.SetHoldUntil(peakEnd); job.Commit(); logFile.WriteLine("Delay job {0} until off peak hours", jobId); } else { logFile.WriteLine("Job {0} already set to {1}", jobId, job.HoldUntil); } scheduler.Close(); } // using scheduler } else { logFile.WriteLine("jobId == 0, delaying job by default duration"); } retval = ActivationFilterResponse.HoldJobReleaseResourcesAllowOtherJobsToSchedule; } else { logFile.WriteLine("Job to run during peak hours"); retval = ActivationFilterResponse.StartJob; } } catch (IOException e) { logFile.WriteLine("Error Loading the XmlFile"); logFile.WriteLine(e.ToString()); retval = ActivationFilterResponse.FailJob; } catch (Exception e) { logFile.WriteLine(e.ToString()); retval = ActivationFilterResponse.FailJob; } finally { logFile.Close(); } return(retval); }