def Run(self, force=False): """Do the actual work of the Cron. Will first check if DueToRun is True. CronJob object must be locked (i.e. opened via OpenWithLock) for Run() to be called. Args: force: If True, the job will run no matter what (i.e. even if DueToRun() returns False). Raises: LockError: if the object is not locked. """ if not self.locked: raise aff4.LockError("CronJob must be locked for Run() to be called.") if self.KillOldFlows(): return # If currently running flow has finished, update our state. current_flow_urn = self.Get(self.Schema.CURRENT_FLOW_URN) if current_flow_urn: current_flow = aff4.FACTORY.Open(current_flow_urn, token=self.token) runner = current_flow.GetRunner() if not runner.IsRunning(): if runner.context.state == rdfvalue.Flow.State.ERROR: self.Set(self.Schema.LAST_RUN_STATUS, rdfvalue.CronJobRunStatus( status=rdfvalue.CronJobRunStatus.Status.ERROR)) stats.STATS.IncrementCounter("cron_job_failure", fields=[self.urn.Basename()]) else: self.Set(self.Schema.LAST_RUN_STATUS, rdfvalue.CronJobRunStatus( status=rdfvalue.CronJobRunStatus.Status.OK)) start_time = self.Get(self.Schema.LAST_RUN_TIME) elapsed = time.time() - start_time.AsSecondsFromEpoch() stats.STATS.RecordEvent("cron_job_latency", elapsed, fields=[self.urn.Basename()]) self.DeleteAttribute(self.Schema.CURRENT_FLOW_URN) self.Flush() if not force and not self.DueToRun(): return cron_args = self.Get(self.Schema.CRON_ARGS) flow_urn = flow.GRRFlow.StartFlow( runner_args=cron_args.flow_runner_args, args=cron_args.flow_args, token=self.token, sync=False) self.Set(self.Schema.CURRENT_FLOW_URN, flow_urn) self.Set(self.Schema.LAST_RUN_TIME, rdfvalue.RDFDatetime().Now()) self.Flush() flow_link = aff4.FACTORY.Create(self.urn.Add(flow_urn.Basename()), "AFF4Symlink", token=self.token) flow_link.Set(flow_link.Schema.SYMLINK_TARGET(flow_urn)) flow_link.Close()
def StopCurrentRun(self, reason="Cron lifetime exceeded.", force=True): current_flow_urn = self.Get(self.Schema.CURRENT_FLOW_URN) if current_flow_urn: flow.GRRFlow.TerminateFlow(current_flow_urn, reason=reason, force=force, token=self.token) self.Set(self.Schema.LAST_RUN_STATUS, rdfvalue.CronJobRunStatus( status=rdfvalue.CronJobRunStatus.Status.TIMEOUT)) self.DeleteAttribute(self.Schema.CURRENT_FLOW_URN) self.Flush()