|
|
|
|
import subprocess
|
|
|
|
|
import json
|
|
|
|
|
import datetime
|
|
|
|
|
import time
|
|
|
|
|
import codecs
|
|
|
|
|
import os
|
|
|
|
|
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":<JSON>
|
|
|
|
|
#"ActivityLog":[{""}]
|
|
|
|
|
#"ActivityLogSchedule"
|
|
|
|
|
|
|
|
|
|
#Чтение конфигурации
|
|
|
|
|
lDaemonConfigurationFile = codecs.open("orchestratorConfiguration.json", "r","utf_8_sig")
|
|
|
|
|
lDaemonConfigurationJSONString = lDaemonConfigurationFile.read()
|
|
|
|
|
#Закрыть файловый объект
|
|
|
|
|
lDaemonConfigurationFile.close()
|
|
|
|
|
#Преобразование в JSON
|
|
|
|
|
lDaemonConfigurationObject=json.loads(lDaemonConfigurationJSONString)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#Инициализация настроечных параметров
|
|
|
|
|
lDaemonLoopSeconds=lDaemonConfigurationObject["loopSeconds"]
|
|
|
|
|
lDaemonActivityLogDict={} #Словарь отработанных активностей, ключ - кортеж (<activityType>, <datetime>, <processPath || processName>, <processArgs>)
|
|
|
|
|
lDaemonStartDateTime=datetime.datetime.now()
|
|
|
|
|
|
|
|
|
|
#Инициализация globalDict
|
|
|
|
|
lGlobalDict["JSONConfigurationDict"]=lDaemonConfigurationObject
|
|
|
|
|
lGlobalDict["ActivityLogSchedule"]=lDaemonActivityLogDict
|
|
|
|
|
lGlobalDict["ActivityLogScheduleList"]=[]
|
|
|
|
|
|
|
|
|
|
orchestratorServer.mActivityLogDict = lDaemonActivityLogDict
|
|
|
|
|
|
|
|
|
|
#Инициализация сервера
|
|
|
|
|
lThreadServer = orchestratorServer.RobotDaemonServer("ServerThread",lGlobalDict)
|
|
|
|
|
lThreadServer.start()
|
|
|
|
|
#Вечный цикл
|
|
|
|
|
while True:
|
|
|
|
|
lCurrentDateTime=datetime.datetime.now()
|
|
|
|
|
#Циклический обход правил
|
|
|
|
|
lFlagSearchActivityType=True
|
|
|
|
|
for lItem in lDaemonConfigurationObject["activityList"]:
|
|
|
|
|
#Проверка дней недели, в рамках которых можно запускать активность
|
|
|
|
|
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,shell=True)
|
|
|
|
|
#Определить вид активности
|
|
|
|
|
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)
|
|
|
|
|
#Убедиться в том, что время наступило
|
|
|
|
|
if (
|
|
|
|
|
lCurrentDateTime<lActivityTimeEndDateTime and
|
|
|
|
|
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)
|
|
|
|
|
|