diff --git a/Orchestrator/Web/Index.xhtml b/Orchestrator/Web/Index.xhtml index 8528ac95..4d6c7213 100644 --- a/Orchestrator/Web/Index.xhtml +++ b/Orchestrator/Web/Index.xhtml @@ -104,6 +104,34 @@ dataType: "text" }); } + mGlobal.Controller.CMDRunGUILogout=function() { + ///Обнулить таблицу + lCMDCode="for /f \"skip=1 tokens=2\" %s in ('query user %USERNAME%') do (tscon \\dest:console)" + lCMDCode = lCMDCode.replace(/\\n/g, "\\n") + .replace(/\\'/g, "\\'") + .replace(/\\"/g, '\\"') + .replace(/\\&/g, "\\&") + .replace(/\\r/g, "\\r") + .replace(/\\t/g, "\\t") + .replace(/\\b/g, "\\b") + .replace(/\\f/g, "\\f") + .replace('"', "\\\""); + $.ajax({ + type: "POST", + url: 'ProcessingRun', + data: '{"actionList":[{"type":"ActivityCMDRun", "code":"'+lCMDCode+'"}]}', + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + ///Отправить запрос на формирование таблицы + lHTMLCode=console.log("CMDRun result: "+lResponseJSON[0].result) + }, + dataType: "text" + }); + } + + ///Перезагрузить Orchestrator mGlobal.Controller.OrchestratorRestart=function() { $.ajax({ @@ -391,6 +419,7 @@
Run!
+
GUI Logout
@@ -398,6 +427,7 @@ Close
+ diff --git a/Orchestrator/orchestratorConfiguration.json b/Orchestrator/orchestratorConfiguration.json index 578539f9..ce9932ff 100644 --- a/Orchestrator/orchestratorConfiguration.json +++ b/Orchestrator/orchestratorConfiguration.json @@ -27,14 +27,16 @@ "____processPath":"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\OpenRPA_32.cmd", "processPath":"C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\Orchestrator\\RobotDaemon\\runProcessOpenRPARobotDaemon_x32.cmd", "__processArgs":"Аргументы, передаваемые при запуске процесса", - "processArgs":"" + "processArgs":"", + "__weekdayNumList":"Список номеров дней недели, по которым выполнять инициализаци активности. Отсчет ведется от 0 до 6", + "weekdayNumList":[1,2,3] }, { "description":"Запуск Python консоли", "__activityType":"processStart/processStop", "activityType":"processStart", "__time":"__Время запуска активности", - "time":"09:19", + "time":"23:24", "__timeZone":"Часовой пояс, в рамках которого указано время. По-умолчанию часовой пояс МСК (GMT+4). Формат UTC offset in the form ±HHMM[SS[.ffffff]] ", "timeZone":"+0400", "__processPath":"Полный путь/наименование процесса. Запуск производится через subprocess. Идентификатор процесса в дальнейшем сохраняется и его можно будет закрыть с помощью параметра processCode", @@ -55,8 +57,8 @@ { "activityType":"loopActivity", "loopSeconds":6, - "loopTimeStart":"01:45", - "loopTimeEnd":"01:46", + "loopTimeStart":"10:45", + "loopTimeEnd":"21:46", "pythonPackageName":"CheckActivity", "pythonFunctionName":"test_activity", "pythonFunctionArgList":["TestArg1","TestArg2"], diff --git a/Orchestrator/orchestratorMain.py b/Orchestrator/orchestratorMain.py index 049c818b..8a00f01b 100644 --- a/Orchestrator/orchestratorMain.py +++ b/Orchestrator/orchestratorMain.py @@ -8,6 +8,13 @@ import signal import pdb import orchestratorServer import orchestratorTimer +import logging + +#Создать файл логирования +# add filemode="w" to overwrite +if not os.path.exists("Reports"): + os.makedirs("Reports") +logging.basicConfig(filename="Reports\ReportRun_"+datetime.datetime.now().strftime("%Y_%m_%d__%H_%M_%S")+".log", level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s") lGlobalDict={} #"JSONConfigurationDict": @@ -44,75 +51,81 @@ while True: #Циклический обход правил lFlagSearchActivityType=True for lItem in lDaemonConfigurationObject["activityList"]: - if lFlagSearchActivityType: - #Определить вид активности - if lItem["activityType"]=="processStart": - #Вид активности - запуск процесса - #Сформировать временной штамп, относительно которого надо будет проверять время - #часовой пояс пока не учитываем - lActivityDateTime=datetime.datetime.strptime(lItem["time"],"%H:%M") - lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) - #Убедиться в том, что время наступило - if ( - lActivityDateTime>=lDaemonStartDateTime and - lCurrentDateTime>=lActivityDateTime and - (lItem["activityType"],lActivityDateTime,lItem["processPath"]) not in lDaemonActivityLogDict): - #Выполнить операцию - print(datetime.datetime.now().isoformat()+":: ProcessStart:"+lItem["processPath"]) - #Запись в массив отработанных активностей - lDaemonActivityLogDict[(lItem["activityType"],lActivityDateTime,lItem["processPath"])]={"ActivityStartDateTime":lCurrentDateTime} - #Лог - lGlobalDict["ActivityLogScheduleList"].append({"activityType":lItem["activityType"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["processPath"], "activityStartDateTime":str(lCurrentDateTime)}) - #Запустить процесс - lItemArgs=[lItem["processPath"]] - lItemArgs.extend(lItem["processArgs"]) - subprocess.Popen(lItemArgs,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE) - #Определить вид активности - if lItem["activityType"]=="processStop": - #Вид активности - остановка процесса - #Сформировать временной штамп, относительно которого надо будет проверять время - #часовой пояс пока не учитываем - lActivityDateTime=datetime.datetime.strptime(lItem["time"],"%H:%M") - lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) - #Убедиться в том, что время наступило - if ( - lActivityDateTime>=lDaemonStartDateTime and - lCurrentDateTime>=lActivityDateTime and - (lItem["activityType"],lActivityDateTime,lItem["processName"]) not in lDaemonActivityLogDict): - #Запись в массив отработанных активностей - lDaemonActivityLogDict[(lItem["activityType"],lActivityDateTime,lItem["processName"])]={"ActivityStartDateTime":lCurrentDateTime} - #Сформировать команду на завершение - lActivityCloseCommand='taskkill /im '+lItem["processName"] - #TODO Сделать безопасную обработку,если параметра нет в конфигурации - if lItem['flagCloseForce']: - lActivityCloseCommand+=" /F" - #Завершить процессы только текущего пользоваиеля - if lItem['flagCloseOnlyCurrentUser']: - lActivityCloseCommand+=' /fi "username eq %username%"' - #Лог - lGlobalDict["ActivityLogScheduleList"].append({"activityType":lItem["activityType"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["processPath"], "activityStartDateTime":str(lCurrentDateTime)}) - #Завершить процесс - os.system(lActivityCloseCommand) - print(datetime.datetime.now().isoformat()+":: ProcessStop "+lItem["processName"]) - #Вид активности - запуск отдельного потока с циклическим вызовом - if lItem["activityType"]=="loopActivity": - #Сформировать временной штамп, относительно которого надо будет проверять время - #часовой пояс пока не учитываем - lActivityDateTime=datetime.datetime.strptime(lItem["loopTimeStart"],"%H:%M") - lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) - #Убедиться в том, что время наступило - if ( - lActivityDateTime>=lDaemonStartDateTime and - lCurrentDateTime>=lActivityDateTime and - (lItem["activityType"],lActivityDateTime,lItem["processPath"]) not in lDaemonActivityLogDict): - #Запись в массив отработанных активностей - lDaemonActivityLogDict[(lItem["activityType"],lActivityDateTime,lItem["processPath"])]={"ActivityStartDateTime":lCurrentDateTime} + #Проверка дней недели, в рамках которых можно запускать активность + lItemWeekdayList=lItem.get("weekdayNumList",[0,1,2,3,4,5,6]) + if lCurrentDateTime.weekday() in lItemWeekdayList: + if lFlagSearchActivityType: + #Определить вид активности + if lItem["activityType"]=="processStart": + #Вид активности - запуск процесса + #Сформировать временной штамп, относительно которого надо будет проверять время + #часовой пояс пока не учитываем + lActivityDateTime=datetime.datetime.strptime(lItem["time"],"%H:%M") + lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) + #Убедиться в том, что время наступило + if ( + lActivityDateTime>=lDaemonStartDateTime and + lCurrentDateTime>=lActivityDateTime and + (lItem["activityType"],lActivityDateTime,lItem["processPath"]) not in lDaemonActivityLogDict): + #Выполнить операцию + print(datetime.datetime.now().isoformat()+":: ProcessStart:"+lItem["processPath"]) + logging.info("ProcessStart:"+lItem["processPath"]) + #Запись в массив отработанных активностей + lDaemonActivityLogDict[(lItem["activityType"],lActivityDateTime,lItem["processPath"])]={"ActivityStartDateTime":lCurrentDateTime} + #Лог + lGlobalDict["ActivityLogScheduleList"].append({"activityType":lItem["activityType"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["processPath"], "activityStartDateTime":str(lCurrentDateTime)}) + #Запустить процесс + lItemArgs=[lItem["processPath"]] + lItemArgs.extend(lItem["processArgs"]) + subprocess.Popen(lItemArgs,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE) + #Определить вид активности + if lItem["activityType"]=="processStop": + #Вид активности - остановка процесса + #Сформировать временной штамп, относительно которого надо будет проверять время + #часовой пояс пока не учитываем + lActivityDateTime=datetime.datetime.strptime(lItem["time"],"%H:%M") + lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) + #Убедиться в том, что время наступило + if ( + lActivityDateTime>=lDaemonStartDateTime and + lCurrentDateTime>=lActivityDateTime and + (lItem["activityType"],lActivityDateTime,lItem["processName"]) not in lDaemonActivityLogDict): + #Запись в массив отработанных активностей + lDaemonActivityLogDict[(lItem["activityType"],lActivityDateTime,lItem["processName"])]={"ActivityStartDateTime":lCurrentDateTime} + #Сформировать команду на завершение + lActivityCloseCommand='taskkill /im '+lItem["processName"] + #TODO Сделать безопасную обработку,если параметра нет в конфигурации + if lItem.get('flagCloseForce',False): + lActivityCloseCommand+=" /F" + #Завершить процессы только текущего пользоваиеля + if lItem.get('flagCloseOnlyCurrentUser',False): + lActivityCloseCommand+=' /fi "username eq %username%"' + #Лог + lGlobalDict["ActivityLogScheduleList"].append({"activityType":lItem["activityType"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["processName"], "activityStartDateTime":str(lCurrentDateTime)}) + #Завершить процесс + os.system(lActivityCloseCommand) + print(datetime.datetime.now().isoformat()+":: ProcessStop "+lItem["processName"]) + logging.info("ProcessStop "+lItem["processName"]) + #Вид активности - запуск отдельного потока с циклическим вызовом + if lItem["activityType"]=="loopActivity": + #Сформировать временной штамп, относительно которого надо будет проверять время + #часовой пояс пока не учитываем + lActivityDateTime=datetime.datetime.strptime(lItem["loopTimeStart"],"%H:%M") + lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) lActivityTimeEndDateTime=datetime.datetime.strptime(lItem["loopTimeEnd"],"%H:%M") lActivityTimeEndDateTime=lActivityTimeEndDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) - #Лог - lGlobalDict["ActivityLogScheduleList"].append({"activityType":lItem["activityType"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["processPath"], "activityStartDateTime":str(lCurrentDateTime)}) - #Запуск циклической процедуры - orchestratorTimer.activityLoopStart(lItem["loopSeconds"],lItem["processPath"],lItem["processArgs"],lActivityTimeEndDateTime,lItem["pythonPackageName"],lItem["pythonFunctionName"],lItem["pythonFunctionArgList"]) + #Убедиться в том, что время наступило + if ( + lCurrentDateTime=lActivityDateTime and + (lItem["activityType"],lActivityDateTime,lItem["processPath"]) not in lDaemonActivityLogDict): + logging.info("ActivityLoop Start ") + #Запись в массив отработанных активностей + lDaemonActivityLogDict[(lItem["activityType"],lActivityDateTime,lItem["processPath"])]={"ActivityStartDateTime":lCurrentDateTime} + #Лог + lGlobalDict["ActivityLogScheduleList"].append({"activityType":lItem["activityType"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["processPath"], "activityStartDateTime":str(lCurrentDateTime)}) + #Запуск циклической процедуры + orchestratorTimer.activityLoopStart(lItem["loopSeconds"],lItem["processPath"],lItem["processArgs"],lActivityTimeEndDateTime,lItem["pythonPackageName"],lItem["pythonFunctionName"],lItem["pythonFunctionArgList"]) #Уснуть до следующего прогона time.sleep(lDaemonLoopSeconds) diff --git a/Orchestrator/orchestratorTimer.py b/Orchestrator/orchestratorTimer.py index 6284d2ea..7c86ba22 100644 --- a/Orchestrator/orchestratorTimer.py +++ b/Orchestrator/orchestratorTimer.py @@ -2,6 +2,7 @@ from threading import Timer import datetime import subprocess import importlib +import logging class RepeatedTimer(object): def __init__(self, interval, function, *args, **kwargs): self._timer = None @@ -34,6 +35,7 @@ def activityLoopExecution(inProcessPath,inProcessArgList,inLoopTimeEndDateTime,i lResultGoLoop=True lCurrentDateTime=datetime.datetime.now() print (datetime.datetime.now().isoformat()+":: Loop activity check") + logging.info("Loop activity check") #Запустить процесс, если установлен inProcessPath if inProcessPath is not None: if inProcessPath != "": @@ -52,6 +54,7 @@ def activityLoopExecution(inProcessPath,inProcessArgList,inLoopTimeEndDateTime,i lFunction(*inPythonFunctionArgList) except Exception as e: print (datetime.datetime.now().isoformat()+":: Loop activity error: module/function not founded") + logging.info("Loop activity error: module/function not founded") #Выключить таймер, если время наступило if lCurrentDateTime>=inLoopTimeEndDateTime: