#from pyOpenRPA.Orchestrator import Managers from .. import __Orchestrator__ import os import time class Process(): """ Manager process, which is need to be started / stopped / restarted With Process instance you can automate your process activity. Use schedule package to set interval when process should be active and when not. Process instance has the following statuses: - 0_STOPPED - 1_STOPPED_MANUAL - 2_STOP_SAFE - 3_STOP_SAFE_MANUAL - 4_STARTED - 5_STARTED_MANUAL .. code-block:: python lProcess = Orchestrator.Managers.Process(inAgentHostNameStr="PCNAME",inAgentUserNameStr="USER", inProcessNameWOExeStr="notepad",inStartCMDStr="notepad",inStopSafeTimeoutSecFloat=3) # Async way to run job lProcess.ScheduleStatusCheckEverySeconds(inIntervalSecondsInt=5) Orchestrator.OrchestratorScheduleGet().every(5).seconds.do(Orchestrator.OrchestratorThreadStart, lProcess.StartCheck) # OR (sync mode) Orchestrator.OrchestratorScheduleGet().every(5).seconds.do(lProcess.StartCheck) """ mAgentHostNameStr = None mAgentUserNameStr = None mStartPathStr = None mStartCMDStr = None mProcessNameWOExeStr = None mStopSafeTimeoutSecFloat = None mStatusStr = None # 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL def __init__(self, inAgentHostNameStr, inAgentUserNameStr, inProcessNameWOExeStr, inStartPathStr=None, inStartCMDStr = None, inStopSafeTimeoutSecFloat=120): self.mAgentHostNameStr = inAgentHostNameStr self.mAgentUserNameStr = inAgentUserNameStr self.mStartPathStr = inStartPathStr self.mStartCMDStr = inStartCMDStr self.mProcessNameWOExeStr = inProcessNameWOExeStr self.mStopSafeTimeoutSecFloat = inStopSafeTimeoutSecFloat __Orchestrator__.GSettingsGet()["ManagersProcessDict"][(inAgentHostNameStr.upper(), inAgentUserNameStr.upper(), inProcessNameWOExeStr.upper())]=self lActivityDict = __Orchestrator__.ProcessorActivityItemCreate(inDef=self.StatusCheck,inArgList=[]) __Orchestrator__.ProcessorActivityItemAppend(inActivityItemDict=lActivityDict) def Manual2Auto(self) -> str: """ Remove Manual flag from process (if exists) - it will allow the schedule operations via def StatusCheckStart(self): def StatusCheckStorForce(self): def StatusCheckStopSafe(self): :return: Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL """ lLogBool = False if self.mStatusStr=="1_STOPPED_MANUAL": self.mStatusStr = "0_STOPPED"; lLogBool=True if self.mStatusStr=="3_STOP_SAFE_MANUAL": self.mStatusStr = "2_STOP_SAFE"; lLogBool=True if self.mStatusStr=="5_STARTED_MANUAL": self.mStatusStr = "4_STARTED"; lLogBool=True # Log info about process if lLogBool == True: self.StatusChangeLog() return self.mStatusStr def Start(self, inIsManualBool = True) -> str: """ Manual/Auto start. Manual start will block scheduling execution. To return schedule execution use def Manual2Auto :param inIsManualBool: Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation :return: Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL """ # Send activity item to agent - wait result if self.mStartPathStr is not None: lCMDStr = f"start {os.path.abspath(self.mStartPathStr)}" elif self.mStartCMDStr is not None: lCMDStr = f"start {self.mStartCMDStr}" #import pdb #pdb.set_trace() lActivityItemStart = __Orchestrator__.ProcessorActivityItemCreate(inDef="OSCMD", inArgDict={"inCMDStr":lCMDStr,"inSendOutputToOrchestratorLogsBool":False}, inArgGSettingsStr="inGSettings") lGUIDStr = __Orchestrator__.AgentActivityItemAdd(inHostNameStr=self.mAgentHostNameStr, inUserStr=self.mAgentUserNameStr, inActivityItemDict=lActivityItemStart) lStartResult = __Orchestrator__.AgentActivityItemReturnGet(inGUIDStr=lGUIDStr) if inIsManualBool==True: self.mStatusStr = "5_STARTED_MANUAL" else: self.mStatusStr = "4_STARTED" # Log info about process self.StatusChangeLog() return self.mStatusStr def StartCheck(self) -> str: """ Start program if auto stopped (0_STOPPED). :return: Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL """ if self.mStatusStr == "0_STOPPED": self.Start(inIsManualBool=False) return self.mStatusStr def StopSafe(self, inIsManualBool = True) -> str: """ Manual/Auto stop safe. Stop safe is the operation which send signal to process to terminate own work (send term signal to process). Managers.Process wait for the mStopSafeTimeoutSecFloat seconds. After that, if process is not terminated - self will StopForce it. Manual stop safe will block scheduling execution. To return schedule execution use def Manual2Auto :param inIsManualBool: Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation :return: Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL """ # Send activity item to agent - wait result lCMDStr = f'taskkill /im "{self.mProcessNameWOExeStr}.exe" /fi "username eq %USERNAME%"' lActivityItemStart = __Orchestrator__.ProcessorActivityItemCreate( inDef="OSCMD",inArgDict={"inCMDStr": lCMDStr,"inSendOutputToOrchestratorLogsBool":False},inArgGSettingsStr="inGSettings") lGUIDStr = __Orchestrator__.AgentActivityItemAdd(inHostNameStr=self.mAgentHostNameStr, inUserStr=self.mAgentUserNameStr, inActivityItemDict=lActivityItemStart) lStartResult = __Orchestrator__.AgentActivityItemReturnGet(inGUIDStr=lGUIDStr) if inIsManualBool==True: self.mStatusStr = "3_STOP_SAFE_MANUAL" else: self.mStatusStr = "2_STOP_SAFE" # Log info about process self.StatusChangeLog() # Interval check is stopped lTimeStartFloat = time.time() lIntervalCheckSafeStatusFLoat = 15.0 while "SAFE" in self.mStatusStr and (time.time() - lTimeStartFloat) < self.mStopSafeTimeoutSecFloat: self.StatusCheck() time.sleep(lIntervalCheckSafeStatusFLoat) if "SAFE" in self.mStatusStr: # Log info about process lL = __Orchestrator__.OrchestratorLoggerGet() lL.info(f"Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Safe stop has been wait for {self.mStopSafeTimeoutSecFloat} sec. Now do the force stop.") self.StopForce(inIsManualBool=inIsManualBool) # Log info about process self.StatusChangeLog() return self.mStatusStr def StopSafeCheck(self) -> str: """ Stop safe program if auto started (4_STARTED). :return: Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL """ if self.mStatusStr == "4_STARTED": self.StopSafe(inIsManualBool=False) return self.mStatusStr def StopForce(self, inIsManualBool = True) -> str: """ Manual/Auto stop force. Force stop don't wait process termination - it just terminate process now. Manual stop safe will block scheduling execution. To return schedule execution use def Manual2Auto :param inIsManualBool: Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation :return: Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL """ # Send activity item to agent - wait result lCMDStr = f'taskkill /F /im "{self.mProcessNameWOExeStr}.exe" /fi "username eq %USERNAME%"' lActivityItemStart = __Orchestrator__.ProcessorActivityItemCreate( inDef="OSCMD",inArgDict={"inCMDStr": lCMDStr,"inSendOutputToOrchestratorLogsBool":False},inArgGSettingsStr="inGSettings") lGUIDStr = __Orchestrator__.AgentActivityItemAdd(inHostNameStr=self.mAgentHostNameStr, inUserStr=self.mAgentUserNameStr, inActivityItemDict=lActivityItemStart) lStartResult = __Orchestrator__.AgentActivityItemReturnGet(inGUIDStr=lGUIDStr) if inIsManualBool==True: self.mStatusStr = "1_STOPPED_MANUAL" else: self.mStatusStr = "0_STOPPED" # Log info about process self.StatusChangeLog() return self.mStatusStr def StopForceCheck(self) -> str: """ Stop force program if auto started (4_STARTED). :return: Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL """ if self.mStatusStr == "4_STARTED": self.StopForce(inIsManualBool=False) return self.mStatusStr def RestartSafe(self, inIsManualBool = True): """ Manual/Auto restart safe. Restart safe is the operation which send signal to process to terminate own work (send term signal to process). Then it run process. Managers.Process wait for the mStopSafeTimeoutSecFloat seconds. After that, if process is not terminated - self will StopForce it. Manual stop safe will block scheduling execution. To return schedule execution use def Manual2Auto :param inIsManualBool: Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation :return: Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL """ self.StopSafe(inIsManualBool=inIsManualBool) return self.Start(inIsManualBool=inIsManualBool) def RestartForce(self, inIsManualBool = True): """ Manual/Auto restart force. Force restart dont wait process termination - it just terminate process now ant then start it. Manual restart will block scheduling execution. To return schedule execution use def Manual2Auto :param inIsManualBool: Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation :return: Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL """ self.StopForce(inIsManualBool=inIsManualBool) return self.Start(inIsManualBool=inIsManualBool) def StatusChangeLog(self): """ Lof information about status change :return: """ # Log info about process lL = __Orchestrator__.OrchestratorLoggerGet() lL.info(f"Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Status has been changed to {self.mStatusStr})") def StatusCheck(self): """ Check if process is alive. The def will save the manual flag is exists. :return: Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL """ # Send activity item to agent - wait result lLogBool = False lActivityItemUserProcessList = __Orchestrator__.ProcessorActivityItemCreate(inDef="ProcessWOExeUpperUserListGet") lGUIDStr = __Orchestrator__.AgentActivityItemAdd(inHostNameStr=self.mAgentHostNameStr,inUserStr=self.mAgentUserNameStr,inActivityItemDict=lActivityItemUserProcessList) lUserProcessList = __Orchestrator__.AgentActivityItemReturnGet(inGUIDStr=lGUIDStr) if self.mProcessNameWOExeStr.upper() in lUserProcessList: if self.mStatusStr == "1_STOPPED_MANUAL": self.mStatusStr = "5_STARTED_MANUAL"; lLogBool=True if self.mStatusStr == "0_STOPPED": self.mStatusStr = "4_STARTED"; lLogBool=True if self.mStatusStr is None: self.mStatusStr = "4_STARTED"; lLogBool=True else: if self.mStatusStr == "2_STOP_SAFE": self.mStatusStr = "0_STOPPED"; lLogBool = True if self.mStatusStr == "3_STOP_SAFE_MANUAL": self.mStatusStr = "1_STOPPED_MANUAL"; lLogBool = True if self.mStatusStr == "5_STARTED_MANUAL": self.mStatusStr = "1_STOPPED_MANUAL"; lLogBool=True if self.mStatusStr == "4_STARTED": self.mStatusStr = "0_STOPPED"; lLogBool=True if self.mStatusStr is None: self.mStatusStr = "0_STOPPED"; lLogBool=True # Log info about process if lLogBool == True: self.StatusChangeLog() return self.mStatusStr def StatusCheckStart(self): """ Check process status and run it if auto stopped self.mStatusStr is "0_STOPPED" :return: Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL """ lStatusStr = self.StatusCheck() if lStatusStr == "0_STOPPED": self.Start(inIsManualBool=False) return self.mStatusStr def StatusCheckStopForce(self): """ Check process status and auto stop force it if self.mStatusStr is 4_STARTED :return: Process status. See self.mStatusStr. 0_STOPPED 1_STOPPED_MANUAL 2_STOP_SAFE 3_STOP_SAFE_MANUAL 4_STARTED 5_STARTED_MANUAL """ lStatusStr = self.StatusCheck() if lStatusStr == "4_STARTED": self.StopForce(inIsManualBool=False) return self.mStatusStr def StatusCheckStopSafe(self): """ Check process status and auto stop safe it if self.mStatusStr is 4_STARTED :return: """ lStatusStr = self.StatusCheck() if lStatusStr == "4_STARTED": self.StopSafe(inIsManualBool=False) return self.mStatusStr def ScheduleStatusCheckEverySeconds(self,inIntervalSecondsInt=120): """ Run status check every interval in second you specify. :param inIntervalSecondsInt: Interval in seconds. Default is 120 :return: None """ # Check job in threaded way __Orchestrator__.OrchestratorScheduleGet().every(inIntervalSecondsInt).seconds.do(__Orchestrator__.OrchestratorThreadStart,self.StatusCheck) def ProcessGet(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str) -> Process: """ Return the process instance by the inProcessNameWOExeStr :param inAgentHostNameStr: Agent hostname in any case. Required to identify Process :param inAgentUserNameStr: Agent user name in any case. Required to identify Process :param inProcessNameWOExeStr: The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case :return: Process instance (if exists) Else None """ return __Orchestrator__.GSettingsGet()["ManagersProcessDict"].get((inAgentHostNameStr.upper(), inAgentUserNameStr.upper(), inProcessNameWOExeStr.upper()),None) def ProcessStatusStrGet(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str) -> str: """ Get the status of the Process instance. :param inAgentHostNameStr: Agent hostname in any case. Required to identify Process :param inAgentUserNameStr: Agent user name in any case. Required to identify Process :param inProcessNameWOExeStr: The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case :return: Process status. See self.mStatusStr. Process instance has the following statuses: - 0_STOPPED - 1_STOPPED_MANUAL - 2_STOP_SAFE - 3_STOP_SAFE_MANUAL - 4_STARTED - 5_STARTED_MANUAL - None (if Process instance not exists) """ lProcess = ProcessGet(inAgentHostNameStr = inAgentHostNameStr, inAgentUserNameStr = inAgentUserNameStr, inProcessNameWOExeStr=inProcessNameWOExeStr) if lProcess is not None: return lProcess.mStatusStr def ProcessStart(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str, inIsManualBool: bool = True) -> str: """ Manual/Auto start. Manual start will block scheduling execution. To return schedule execution use def Manual2Auto :param inAgentHostNameStr: Agent hostname in any case. Required to identify Process :param inAgentUserNameStr: Agent user name in any case. Required to identify Process :param inProcessNameWOExeStr: The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case :param inIsManualBool: Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation :return: Process status. See self.mStatusStr. Process instance has the following statuses: - 0_STOPPED - 1_STOPPED_MANUAL - 2_STOP_SAFE - 3_STOP_SAFE_MANUAL - 4_STARTED - 5_STARTED_MANUAL - None (if Process instance not exists) """ lProcess = ProcessGet(inAgentHostNameStr = inAgentHostNameStr, inAgentUserNameStr = inAgentUserNameStr, inProcessNameWOExeStr=inProcessNameWOExeStr) if lProcess is not None: return lProcess.Start(inIsManualBool=inIsManualBool) def ProcessStopSafe(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str, inIsManualBool: bool = True) -> str: """ Manual/Auto stop safe. Stop safe is the operation which send signal to process to terminate own work (send term signal to process). Managers.Process wait for the mStopSafeTimeoutSecFloat seconds. After that, if process is not terminated - self will StopForce it. Manual stop safe will block scheduling execution. To return schedule execution use def Manual2Auto :param inAgentHostNameStr: Agent hostname in any case. Required to identify Process :param inAgentUserNameStr: Agent user name in any case. Required to identify Process :param inProcessNameWOExeStr: The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case :param inIsManualBool: Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation :return: Process status. See self.mStatusStr. Process instance has the following statuses: - 0_STOPPED - 1_STOPPED_MANUAL - 2_STOP_SAFE - 3_STOP_SAFE_MANUAL - 4_STARTED - 5_STARTED_MANUAL - None (if Process instance not exists) """ lProcess = ProcessGet(inAgentHostNameStr = inAgentHostNameStr, inAgentUserNameStr = inAgentUserNameStr, inProcessNameWOExeStr=inProcessNameWOExeStr) if lProcess is not None: return lProcess.StopSafe(inIsManualBool=inIsManualBool) def ProcessStopForce(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str, inIsManualBool: bool = True) -> str: """ Manual/Auto stop force. Force stop dont wait process termination - it just terminate process now. Manual stop safe will block scheduling execution. To return schedule execution use def Manual2Auto :param inAgentHostNameStr: Agent hostname in any case. Required to identify Process :param inAgentUserNameStr: Agent user name in any case. Required to identify Process :param inProcessNameWOExeStr: The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case :param inIsManualBool: Default is True - Mark this operation as manual - StatusCheckStart/Stop will be blocked - only StatusCheck will be working. False - Auto operation :return: Process status. See self.mStatusStr. Process instance has the following statuses: - 0_STOPPED - 1_STOPPED_MANUAL - 2_STOP_SAFE - 3_STOP_SAFE_MANUAL - 4_STARTED - 5_STARTED_MANUAL - None (if Process instance not exists) """ lProcess = ProcessGet(inAgentHostNameStr = inAgentHostNameStr, inAgentUserNameStr = inAgentUserNameStr, inProcessNameWOExeStr=inProcessNameWOExeStr) if lProcess is not None: return lProcess.StopForce(inIsManualBool=inIsManualBool) def ProcessStatusCheck(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str) -> str: """ Check if process is alive. The def will save the manual flag is exists. :param inAgentHostNameStr: Agent hostname in any case. Required to identify Process :param inAgentUserNameStr: Agent user name in any case. Required to identify Process :param inProcessNameWOExeStr: The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case :return: Process status. See self.mStatusStr. Process instance has the following statuses: - 0_STOPPED - 1_STOPPED_MANUAL - 2_STOP_SAFE - 3_STOP_SAFE_MANUAL - 4_STARTED - 5_STARTED_MANUAL - None (if Process instance not exists) """ lProcess = ProcessGet(inAgentHostNameStr=inAgentHostNameStr, inAgentUserNameStr=inAgentUserNameStr, inProcessNameWOExeStr=inProcessNameWOExeStr) if lProcess is not None: lProcess.StatusCheck() return lProcess.mStatusStr def ProcessManual2Auto(inAgentHostNameStr: str, inAgentUserNameStr: str, inProcessNameWOExeStr: str) -> str: """ Remove Manual flag from process (if exists) - it will allow the schedule operations via def StatusCheckStart(self): def StatusCheckStorForce(self): def StatusCheckStopSafe(self): :param inAgentHostNameStr: Agent hostname in any case. Required to identify Process :param inAgentUserNameStr: Agent user name in any case. Required to identify Process :param inProcessNameWOExeStr: The process name without extension .exe (the key of the Process instance). Any case - will be processed to the upper case :return: Process status. See self.mStatusStr. Process instance has the following statuses: - 0_STOPPED - 1_STOPPED_MANUAL - 2_STOP_SAFE - 3_STOP_SAFE_MANUAL - 4_STARTED - 5_STARTED_MANUAL - None (if Process instance not exists) """ lProcess = ProcessGet(inAgentHostNameStr=inAgentHostNameStr, inAgentUserNameStr=inAgentUserNameStr, inProcessNameWOExeStr=inProcessNameWOExeStr) if lProcess is not None: return lProcess.Manual2Auto()