orc + agent: L+,W+ support, translate

dev-linux
robo-bo 2 years ago
parent 9efbcd78a5
commit b68d1afe2d

@ -1,3 +1,4 @@
from curses.ascii import CR
import threading, socket, getpass, sys, uuid, subprocess, base64, psutil, getpass, time
from . import O2A, A2O # Data flow Orchestrator To Agent
from . import Processor # Processor Queue
@ -13,10 +14,10 @@ gSettings = None
# Create binary file by the base64 string (safe for JSON transmition)
def OSFileBinaryDataBase64StrCreate(inFilePathStr, inFileDataBase64Str,inGSettings = None):
"""
Create binary file by the base64 string (safe for JSON transmition)
"""L+,W+: Создать бинарный файл на стороне Агента по полученной строке в формате base64 (формат безопасен для передачи по JSON протоколу)
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFile = open(inFilePathStr, "wb")
lFile.write(base64.b64decode(inFileDataBase64Str))
lFile.close()
@ -27,10 +28,10 @@ def OSFileBinaryDataBase64StrCreate(inFilePathStr, inFileDataBase64Str,inGSettin
# Append binary file by the base64 string (safe for JSON transmition)
def OSFileBinaryDataBase64StrAppend(inFilePathStr, inFileDataBase64Str,inGSettings = None):
"""
Create binary file by the base64 string (safe for JSON transmition)
"""L+,W+: Create binary file by the base64 string (safe for JSON transmition)
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFile = open(inFilePathStr, "ab")
lFile.write(base64.b64decode(inFileDataBase64Str))
lFile.close()
@ -41,15 +42,15 @@ def OSFileBinaryDataBase64StrAppend(inFilePathStr, inFileDataBase64Str,inGSettin
# Create text file by the string
def OSFileTextDataStrCreate(inFilePathStr, inFileDataStr, inEncodingStr = "utf-8",inGSettings = None):
"""
Create text file in the agent GUI session
"""L+,W+:Создать текстовый файл на стороне Агента
:param inFilePathStr: File abs path
:param inFileDataStr: File data text content
:param inEncodingStr: Write file encoding
:param inGSettings: global settings of the Agent (singleton)
:param inFilePathStr: Абсолютный путь к создаваемому файлу
:param inFileDataStr: Текст, отправляемый в создаваемый файл
:param inEncodingStr: Кодировка создаваемого файла. По-умолчанию 'utf-8'
:param inGSettings: Глобальный файл настроек
:return:
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFile = open(inFilePathStr, "w", encoding=inEncodingStr)
lFile.write(inFileDataStr)
lFile.close()
@ -59,13 +60,13 @@ def OSFileTextDataStrCreate(inFilePathStr, inFileDataStr, inEncodingStr = "utf-8
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
def OSFileBinaryDataBase64StrReceive(inFilePathStr, inGSettings=None):
"""
Read binary file and encode in base64 to transmit (safe for JSON transmition)
"""L+,W+: Прочитать бинарный файл на стороне агента и отправить на сторону оркестратора в формате base64 (формат безопасный для передачи в формате JSON)
:param inFilePathStr: File path to read
:param inGSettings: global settings of the Agent (singleton)
:return: File content in string base64 format (use base64.b64decode to decode data). Return None if file is not exist
:param inFilePathStr: Абсолютный путь к читаемому файлу
:param inGSettings: Глобальный словарь настроек Агента (необязательный)
:return: Содержимое бинарного файле, преобразованное в формат base64 (используй base64.b64decode для декодирования в байты). Вернет None запрашиваемый файл не существует
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None
lFileDataBase64Str = None
if os.path.exists(inFilePathStr):
@ -73,39 +74,39 @@ def OSFileBinaryDataBase64StrReceive(inFilePathStr, inGSettings=None):
lFileDataBytes = lFile.read()
lFile.close()
lFileDataBase64Str = base64.b64encode(lFileDataBytes).decode("utf-8")
lMessageStr = f"OSFileBinaryDataBase64StrReceive: file {inFilePathStr} has been read"
lMessageStr = f"Функция OSFileBinaryDataBase64StrReceive: файл {inFilePathStr} прочитан успешно"
if lL: lL.debug(lMessageStr)
#A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
else:
if lL: lL.debug(f"OSFileBinaryDataBase64StrReceive: file {inFilePathStr} is not exists - return None")
if lL: lL.debug(f"Функция OSFileBinaryDataBase64StrReceive: файл {inFilePathStr} не существует - отправить None")
return lFileDataBase64Str
def OSFileMTimeGet(inFilePathStr: str) -> float or None:
"""
Read file modification time timestamp format (float)
"""L+,W+: Read file modification time timestamp format (float)
:param inFilePathStr: File path to read
:return: timestamp (float) Return None if file is not exist
:param inFilePathStr: Абсолютный путь к файлу, дату которого требуется получить
:return: Временной слепок (timestamp) в формате float. Вернет None, если запрашиваемый файл не существует
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
global gSettings
lL = gSettings.get("Logger", None) if type(gSettings) is dict else None
lFileMTimeFloat = None
if os.path.exists(inFilePathStr):
lFileMTimeFloat = os.path.getmtime(inFilePathStr)
if lL: lL.debug(f"OSFileMTimeGet: file {inFilePathStr} has been read")
if lL: lL.debug(f"Функция OSFileMTimeGet: файл {inFilePathStr} прочитан успешно")
else:
if lL: lL.debug(f"OSFileMTimeGet: file {inFilePathStr} is not exists - return None")
if lL: lL.debug(f"Функция OSFileMTimeGet: file {inFilePathStr} не существует - вернуть None")
return lFileMTimeFloat
def OSFileTextDataStrReceive(inFilePathStr, inEncodingStr="utf-8", inGSettings=None):
"""
Read text file in the agent GUI session
"""L+,W+: Прочитать текстовый файл на стороне агента и отправить на сторону оркестратора
:param inFilePathStr: File abs path
:param inEncodingStr: Read file encoding. Default utf-8
:param inGSettings: global settings of the Agent (singleton)
:return: File text content in string format (use base64.b64decode to decode data). Return None if file is not exist
:param inFilePathStr: Абсолютный путь к читаемому файлу
:param inEncodingStr: Кодировка создаваемого файла. По-умолчанию 'utf-8'
:param inGSettings: Глобальный словарь настроек
:return: Строка - содержимое текстового файла. Возвращает None, если файл не существует
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFileDataStr = None
lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None
if os.path.exists(inFilePathStr):
@ -121,8 +122,7 @@ def OSFileTextDataStrReceive(inFilePathStr, inEncodingStr="utf-8", inGSettings=N
# Send CMD to OS. Result return to log + Orchestrator by the A2O connection
def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrchestratorLogsBool = True, inCMDEncodingStr = "cp1251", inCaptureBool = True):
"""
Execute CMD on the Agent daemonic process
"""L-,W+: Execute CMD on the Agent daemonic process
:param inCMDStr: command to execute on the Agent session
:param inRunAsyncBool: True - Agent processor don't wait execution; False - Agent processor wait cmd execution
@ -197,11 +197,9 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrche
def ProcessWOExeUpperUserListGet():
"""
Return the process list only for the current user (where Agent is running) without .EXE in upper case. Can use in ActivityItem from Orchestrator to Agent
"""L-,W+: Вернуть список процессов, запущенных под пользователем на стороне агента
:param inProcessNameWOExeList:
:return: list of the agent user process in upper case without .EXE. Example ["NOTEPAD","..."],
:return: Список процессов в формате: ["NOTEPAD","..."] (без постфикса .exe и в верхнем регистре)
"""
lUserNameStr = getpass.getuser()
@ -253,4 +251,4 @@ def Agent(inGSettings):
# Send log that Agent has been started
A2O.LogListSend(inGSettings=inGSettings, inLogList=[f'Host: {inGSettings["AgentDict"]["HostNameUpperStr"]}, User: {inGSettings["AgentDict"]["UserUpperStr"]}, Agent has been started.'])
A2O.LogListSend(inGSettings=inGSettings, inLogList=[f'Хост: {inGSettings["AgentDict"]["HostNameUpperStr"]}, Логин: {inGSettings["AgentDict"]["UserUpperStr"]}, Агент инициализирован успешно'])

@ -1,3 +1,4 @@
from re import I
import subprocess, json, psutil, time, os
from pyOpenRPA.Tools import CrossOS
if CrossOS.IS_WINDOWS_BOOL: import win32security #CrossOS
@ -46,8 +47,7 @@ gSettingsDict = None
# AGENT DEFS
def AgentActivityItemAdd(inHostNameStr, inUserStr, inActivityItemDict, inGSettings=None):
"""
Добавить активность в словарь активностей выбранного Агента
"""L+,W+: Добавить активность в словарь активностей выбранного Агента
:param inGSettings: Глобальный словарь настроек Оркестратора (синглтон)
:param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления
@ -77,8 +77,7 @@ def AgentActivityItemAdd(inHostNameStr, inUserStr, inActivityItemDict, inGSettin
def AgentActivityItemExists(inHostNameStr, inUserStr, inGUIDStr, inGSettings = None):
"""
Выполнить проверку, что активность (ActivityItem) была отправлена на сторону Агента.
"""L+,W+: Выполнить проверку, что активность (ActivityItem) была отправлена на сторону Агента.
:param inGSettings: Глобальный словарь настроек Оркестратора (синглтон)
:param inGUIDStr: ГУИД (GUID) активности (ActivityItem)
@ -97,8 +96,7 @@ def AgentActivityItemExists(inHostNameStr, inUserStr, inGUIDStr, inGSettings = N
return lResultBool
def AgentActivityItemReturnExists(inGUIDStr, inGSettings = None):
"""
Выполнить проверку, что активность (ActivityItem) была выполнена на стороне Агента и результат был получен на стороне Оркестратора.
"""L+,W+: Выполнить проверку, что активность (ActivityItem) была выполнена на стороне Агента и результат был получен на стороне Оркестратора.
:param inGSettings: Глобальный словарь настроек Оркестратора (синглтон)
:param inGUIDStr: ГУИД (GUID) активности (ActivityItem)
@ -111,8 +109,7 @@ def AgentActivityItemReturnExists(inGUIDStr, inGSettings = None):
def AgentActivityItemReturnGet(inGUIDStr, inCheckIntervalSecFloat = 0.5, inGSettings=None):
"""
Ожидает появления результата по активности (ActivityItem). Возвращает результат выполнения активности.
"""L+,W+: Ожидает появления результата по активности (ActivityItem). Возвращает результат выполнения активности.
!ВНИМАНИЕ! Замораживает поток, пока не будет получен результат.
!ВНИМАНИЕ! Запускать следует после того как будет инициализировано ядро Оркестратора (см. функцию OrchestratorInitWait), иначе будет инициирована ошибка.
@ -134,8 +131,7 @@ def AgentActivityItemReturnGet(inGUIDStr, inCheckIntervalSecFloat = 0.5, inGSett
raise Exception(f"__Orchestrator__.AgentActivityItemReturnGet !ATTENTION! Use this function only after Orchestrator initialization! Before orchestrator init exception will be raised.")
def AgentOSCMD(inHostNameStr, inUserStr, inCMDStr, inRunAsyncBool=True, inSendOutputToOrchestratorLogsBool=True, inCMDEncodingStr="cp1251", inGSettings=None, inCaptureBool=True):
"""
Отправка команды командной строки на сессию, где работает pyOpenRPA.Agent. Результат выполнения команды можно выводить в лог оркестратора.
"""L+,W+: Отправка команды командной строки на сессию, где работает pyOpenRPA.Agent. Результат выполнения команды можно выводить в лог оркестратора.
:param inGSettings: Глобальный словарь настроек Оркестратора (синглтон)
:param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления
@ -159,8 +155,7 @@ def AgentOSCMD(inHostNameStr, inUserStr, inCMDStr, inRunAsyncBool=True, inSendOu
return AgentActivityItemAdd(inGSettings=inGSettings, inHostNameStr=inHostNameStr, inUserStr=inUserStr, inActivityItemDict=lActivityItemDict)
def AgentOSLogoff(inHostNameStr, inUserStr):
"""
Выполнить операцию logoff на стороне пользователя.
"""L+,W+: Выполнить операцию logoff на стороне пользователя.
:param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления
:param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления
@ -168,6 +163,7 @@ def AgentOSLogoff(inHostNameStr, inUserStr):
"""
inGSettings = GSettingsGet() # Set the global settings
lCMDStr = "shutdown /l"
if CrossOS.IS_LINUX_BOOL: lCMDStr="logout"
lActivityItemDict = {
"Def":"OSCMD", # def alias (look pyOpeRPA.Agent gSettings["ProcessorDict"]["AliasDefDict"])
"ArgList":[], # Args list
@ -179,8 +175,7 @@ def AgentOSLogoff(inHostNameStr, inUserStr):
return AgentActivityItemAdd(inGSettings=inGSettings, inHostNameStr=inHostNameStr, inUserStr=inUserStr, inActivityItemDict=lActivityItemDict)
def AgentOSFileSend(inHostNameStr, inUserStr, inOrchestratorFilePathStr, inAgentFilePathStr, inGSettings = None):
"""
Отправить файл по адресу inOrchestratorFilePathStr со стороны Оркестратора и сохранить по адресу inAgentFilePathStr на стороне Агента.
"""L+,W+: Отправить файл по адресу inOrchestratorFilePathStr со стороны Оркестратора и сохранить по адресу inAgentFilePathStr на стороне Агента.
Поддерживает передачу крупных файлов (более 2-х Гб.). Функция является синхронной - не закончит свое выполнение, пока файл не будет передан полностью.
!ВНИМАНИЕ - ПОТОКОБЕЗОПАСНАЯ! Вы можете вызвать эту функцию до инициализации ядра Оркестратора. Оркестратор добавит эту функцию в процессорную очередь на исполение. Если вам нужен результат функции, то необходимо сначала убедиться в том, что ядро Оркестратора было инициализированно (см. функцию OrchestratorInitWait).
@ -246,8 +241,7 @@ def AgentOSFileSend(inHostNameStr, inUserStr, inOrchestratorFilePathStr, inAgent
lFile.close()
def AgentOSFileBinaryDataBytesCreate(inHostNameStr, inUserStr, inFilePathStr, inFileDataBytes, inGSettings=None):
"""
Создать бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым inFileDataBytes
"""L+,W+: Создать бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым inFileDataBytes
:param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления
:param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления
@ -270,8 +264,7 @@ def AgentOSFileBinaryDataBytesCreate(inHostNameStr, inUserStr, inFilePathStr, in
def AgentOSFileBinaryDataBase64StrCreate(inHostNameStr, inUserStr, inFilePathStr, inFileDataBase64Str, inGSettings=None):
"""
Создать бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым, декодированным с формата base64: inFileDataBase64Str
"""L+,W+: Создать бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым, декодированным с формата base64: inFileDataBase64Str
:param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления
:param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления
@ -293,8 +286,7 @@ def AgentOSFileBinaryDataBase64StrCreate(inHostNameStr, inUserStr, inFilePathStr
def AgentOSFileBinaryDataBase64StrAppend(inHostNameStr, inUserStr, inFilePathStr, inFileDataBase64Str, inGSettings = None):
"""
Добавить бинарную информацию в существующий бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым, декодированным с формата base64: inFileDataBase64Str
"""L+,W+: Добавить бинарную информацию в существующий бинарный файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым, декодированным с формата base64: inFileDataBase64Str
:param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления
:param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления
@ -317,8 +309,7 @@ def AgentOSFileBinaryDataBase64StrAppend(inHostNameStr, inUserStr, inFilePathStr
# Send text file to Agent (string)
def AgentOSFileTextDataStrCreate(inHostNameStr, inUserStr, inFilePathStr, inFileDataStr, inEncodingStr = "utf-8",inGSettings=None):
"""
Создать текстовый файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым inFileDataStr в кодировке inEncodingStr
"""L+,W+: Создать текстовый файл, который будет расположен по адресу inFilePathStr на стороне Агента с содержимым inFileDataStr в кодировке inEncodingStr
:param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления
:param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления
@ -340,8 +331,7 @@ def AgentOSFileTextDataStrCreate(inHostNameStr, inUserStr, inFilePathStr, inFile
return AgentActivityItemAdd(inGSettings=inGSettings, inHostNameStr=inHostNameStr, inUserStr=inUserStr, inActivityItemDict=lActivityItemDict)
def AgentOSFileBinaryDataBase64StrReceive(inHostNameStr, inUserStr, inFilePathStr, inGSettings = None):
"""
Выполнить чтение бинарного файла и получить содержимое в формате base64 (строка)
"""L+,W+: Выполнить чтение бинарного файла и получить содержимое в формате base64 (строка)
:param inHostNameStr: Наименование хоста, на котором запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления
:param inUserStr: Наименование пользователя, на графической сессии которого запущен Агент. Наименования подключенных агентов доступно для просмотра в панели управления
@ -362,8 +352,7 @@ def AgentOSFileBinaryDataBase64StrReceive(inHostNameStr, inUserStr, inFilePathSt
def AgentOSFileBinaryDataReceive(inHostNameStr, inUserStr, inFilePathStr):
"""
Чтение бинарного файла на стороне Агента по адресу inFilePathStr.
"""L+,W+: Чтение бинарного файла на стороне Агента по адресу inFilePathStr.
!ВНИМАНИЕ - СИНХРОННАЯ! Функция не завершится, пока не будет получен результат чтения на стороне Агента.
@ -401,8 +390,7 @@ def AgentOSFileBinaryDataReceive(inHostNameStr, inUserStr, inFilePathStr):
return lFileDataBytes
def AgentOSFileTextDataStrReceive(inHostNameStr, inUserStr, inFilePathStr, inEncodingStr="utf-8", inGSettings = None):
"""
Чтение текстового файла на стороне Агента по адресу inFilePathStr. По ГИУД с помощью функции AgentActivityItemReturnGet можно будет получить текстовую строку данных, которые были расположены в файле.
"""L+,W+: Чтение текстового файла на стороне Агента по адресу inFilePathStr. По ГИУД с помощью функции AgentActivityItemReturnGet можно будет получить текстовую строку данных, которые были расположены в файле.
!ВНИМАНИЕ - АСИНХРОННАЯ! Функция завершится сразу, не дожидаясь окончания выполнения операции на стороне Агента.
@ -425,8 +413,7 @@ def AgentOSFileTextDataStrReceive(inHostNameStr, inUserStr, inFilePathStr, inEnc
return AgentActivityItemAdd(inGSettings=inGSettings, inHostNameStr=inHostNameStr, inUserStr=inUserStr, inActivityItemDict=lActivityItemDict)
def AgentProcessWOExeUpperUserListGet(inHostNameStr, inUserStr, inGSettings = None):
"""
Получить список процессов, которые выполняется на сессии Агента. Все процессы фиксируются без постфикса .exe, а также в верхнем регистре.
"""L-,W+: Получить список процессов, которые выполняется на сессии Агента. Все процессы фиксируются без постфикса .exe, а также в верхнем регистре.
ПРИМЕР РЕЗУЛЬТАТА, КОТОРЫЙ МОЖНО ПОЛУЧИТЬ ПО ГУИД ЧЕРЕЗ ФУНКЦИЮ AgentActivityItemReturnGet: ["ORCHESTRATOR", "AGENT", "CHROME", "EXPLORER", ...]
@ -448,16 +435,15 @@ def AgentProcessWOExeUpperUserListGet(inHostNameStr, inUserStr, inGSettings = No
# OS DEFS
def OSLogoff():
"""
Выполнить отключение сессии, на которой выполняется Оркестратор.
"""L+,W+: Выполнить отключение сессии, на которой выполняется Оркестратор.
:return:
"""
os.system("shutdown /l")
if CrossOS.IS_WINDOWS_BOOL: os.system("shutdown /l")
elif CrossOS.IS_LINUX_BOOL: os.system("logout")
def OSCredentialsVerify(inUserStr, inPasswordStr, inDomainStr=""): ##
"""
Выполнить верификацию доменного (локального) пользователя по паре логин/пароль
"""L+,W+: Выполнить верификацию доменного (локального) пользователя по паре логин/пароль
:param inUserStr: Наименование пользователя
:param inPasswordStr: Пароль
@ -478,8 +464,7 @@ def OSCredentialsVerify(inUserStr, inPasswordStr, inDomainStr=""): ##
return authenticate(inUserStr, inPasswordStr, service='login', encoding='utf-8', resetcred=True)
def OSRemotePCRestart(inHostStr, inForceBool=True, inLogger = None):
"""
Отправить сигнал на удаленную перезагрузку операционной системы.
"""L-,W+: Отправить сигнал на удаленную перезагрузку операционной системы.
!ВНИМАНИЕ! Перезапуск будет принят, если учетная запись имеет полномочия на перезапуск на соответсвующей машине.
@ -512,10 +497,7 @@ def OSRestart(inForceBool=True, inLogger = None):
OSCMD(inCMDStr=lCMDStr,inLogger=inLogger)
def OSCMD(inCMDStr, inRunAsyncBool=True, inLogger = None):
"""
Отправить команду на выполнение на сессию, где выполняется Оркестратор.
Поддерживается: Windows: +, Linux: +
"""L-,W+: Отправить команду на выполнение на сессию, где выполняется Оркестратор.
:param inCMDStr: Команда на отправку
:param inRunAsyncBool: True - выполнить команду в асинхронном режиме (не дожидаться окончания выполнения программы и не захватывать результат выполнения); False - Ждать окончания выполнения и захватывать результат
@ -561,8 +543,7 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inLogger = None):
return lResultStr
def OrchestratorRestart(inGSettings=None):
"""
Перезапуск Оркестратора с сохранением информации о запущенных RDP сессиях.
"""L+,W+: Перезапуск Оркестратора с сохранением информации о запущенных RDP сессиях.
:param inGSettings: Глобальный словарь настроек Оркестратора (синглтон)
"""
@ -577,8 +558,7 @@ def OrchestratorRestart(inGSettings=None):
sys.exit(0)
def OrchestratorLoggerGet() -> logging.Logger:
"""
Получить логгер Оркестратора
"""L+,W+: Получить логгер Оркестратора
:return: Логгер
"""
@ -586,8 +566,7 @@ def OrchestratorLoggerGet() -> logging.Logger:
def OrchestratorScheduleGet() -> schedule:
"""
Базовый объект расписания, который можно использовать для запуска / остановки роботов.
"""L+,W+: Базовый объект расписания, который можно использовать для запуска / остановки роботов.
Подробнее про объект schedule и его примеры использования см. по адресу: schedule.readthedocs.io
.. code-block:: python
@ -605,8 +584,7 @@ def OrchestratorScheduleGet() -> schedule:
return GSettingsGet().get("SchedulerDict",{}).get("Schedule",None)
def OrchestratorThreadStart(inDef, *inArgList, **inArgDict):
"""
Запустить функцию в отдельном потоке. В таком случае получить результат выполнения функции можно только через общие переменные. (Например через GSettings)
"""L+,W+: Запустить функцию в отдельном потоке. В таком случае получить результат выполнения функции можно только через общие переменные. (Например через GSettings)
:param inDef: Python функция
:param inArgList: Список неименованных аргументов функции inDef
@ -618,8 +596,7 @@ def OrchestratorThreadStart(inDef, *inArgList, **inArgDict):
return lDefThread
def OrchestratorIsAdmin():
"""
Проверить, запущен ли Оркестратор с правами администратора. Права администратора нужны Оркестратору только для контроля графической сессии, на которой он запущен. Если эти права выделить индивидуально, то права администратора будут необязательны.
"""L+,W+: Проверить, запущен ли Оркестратор с правами администратора. Права администратора нужны Оркестратору только для контроля графической сессии, на которой он запущен. Если эти права выделить индивидуально, то права администратора будут необязательны.
:return: True - Запущен с правами администратора; False - Не запущен с правами администратора
"""
@ -628,11 +605,11 @@ def OrchestratorIsAdmin():
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
elif CrossOS.IS_LINUX_BOOL: return os.getuid()==0
else: return True
def OrchestratorIsInited() -> bool:
"""
Проверить, было ли проинициализировано ядро Оркестратора
"""L+,W+: Проверить, было ли проинициализировано ядро Оркестратора
:return: True - Ядро Оркестратора было проинициализировано; False - Требуется время на инициализацию
:rtype: bool
@ -641,8 +618,7 @@ def OrchestratorIsInited() -> bool:
return Core.IsOrchestratorInitialized(inGSettings=GSettingsGet())
def OrchestratorInitWait() -> None:
"""
Ожидать инициализацию ядра Оркестратора
"""L+,W+: Ожидать инициализацию ядра Оркестратора
!ВНИМАНИЕ!: НИ В КОЕМ СЛУЧАЕ НЕ ЗАПУСКАТЬ ЭТУ ФУНКЦИЮ В ОСНОВНОМ ПОТОКЕ, ГДЕ ПРОИСХОДИТ ИНИЦИАЛИЗАЦИЯ ЯДРА ОРКЕСТРАТОРА - ВОЗНИКНЕТ ВЕЧНЫЙ ЦИКЛ
"""
@ -652,8 +628,7 @@ def OrchestratorInitWait() -> None:
def OrchestratorRerunAsAdmin():
"""
Перезапустить Оркестратор с правами локального администратора. Права администратора нужны Оркестратору только для контроля графической сессии, на которой он запущен. Если эти права выделить индивидуально, то права администратора будут необязательны.
"""L-,W+: Перезапустить Оркестратор с правами локального администратора. Права администратора нужны Оркестратору только для контроля графической сессии, на которой он запущен. Если эти права выделить индивидуально, то права администратора будут необязательны.
:return: True - Запущен с правами администратора; False - Не запущен с правами администратора
"""
@ -661,11 +636,10 @@ def OrchestratorRerunAsAdmin():
# Re-run the program with admin rights
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)
else:
print(f"!SKIPPED! Already run as administrator!")
print(f"Уже запущено с правами администратора!")
def OrchestratorPySearchInit(inGlobPatternStr, inDefStr = None, inDefArgNameGSettingsStr = None, inAsyncInitBool = False):
"""
Выполнить поиск и инициализацию пользовательских .py файлов в Оркестраторе (например панелей управления роботов)
"""L+,W+: Выполнить поиск и инициализацию пользовательских .py файлов в Оркестраторе (например панелей управления роботов)
Добавляет инициализированный модуль в пространство sys.modules как imported (имя модуля = имя файла без расширения).
@ -721,7 +695,7 @@ def OrchestratorPySearchInit(inGlobPatternStr, inDefStr = None, inDefArgNameGSet
# # # # # # # #
lResultDict = {}
inGlobPatternStr = CrossOS.PathStr(inPathStr=inGlobPatternStr)
lPyPathStrList = glob.glob(inGlobPatternStr) # get the file list
lL = OrchestratorLoggerGet() # get the logger
for lPyPathItemStr in lPyPathStrList:
@ -737,8 +711,7 @@ def OrchestratorPySearchInit(inGlobPatternStr, inDefStr = None, inDefArgNameGSet
return lResultDict
def OrchestratorSessionSave(inGSettings=None):
"""
Сохранить состояние Оркестратора (для дальнейшего восстановления в случае перезапуска):
"""L+,W+: Сохранить состояние Оркестратора (для дальнейшего восстановления в случае перезапуска):
- RDP сессий, которые контролирует Оркестратор
- Хранилища DataStorage в глобальном словаре настроек GSettings. DataStorage поддерживает хранение объектов Python
@ -782,8 +755,7 @@ def OrchestratorSessionSave(inGSettings=None):
return True
def OrchestratorSessionRestore(inGSettings=None):
"""
Восстановить состояние Оркестратора, если ранее состояние Оркестратора было сохранено с помощью функции OrchestratorSessionSave:
"""L+,W+: Восстановить состояние Оркестратора, если ранее состояние Оркестратора было сохранено с помощью функции OrchestratorSessionSave:
- RDP сессий, которые контролирует Оркестратор
- Хранилища DataStorage в глобальном словаре настроек GSettings. DataStorage поддерживает хранение объектов Python
@ -806,7 +778,7 @@ def OrchestratorSessionRestore(inGSettings=None):
lFile.close() # Close the file
os.remove("_SessionLast_RDPList.json") # remove the temp file
inGSettings["RobotRDPActive"]["RDPList"] = lSessionLastRDPList # Set the last session dict
if lL: lL.warning(f"RDP Session List was restored from previous Orchestrator session")
if lL: lL.warning(f"Список РДП был восстановлен из прошлой сессии оркестратора")
# _SessionLast_StorageDict.pickle (binary)
if os.path.exists("_SessionLast_StorageDict.pickle"):
if "StorageDict" not in inGSettings:
@ -815,7 +787,7 @@ def OrchestratorSessionRestore(inGSettings=None):
lStorageDictDumpDict = pickle.load(lFile)
Server.__ComplexDictMerge2to1Overwrite__(in1Dict=inGSettings["StorageDict"],
in2Dict=lStorageDictDumpDict) # Merge dict 2 into dict 1
if lL: lL.warning(f"StorageDict was restored from previous Orchestrator session")
if lL: lL.warning(f"Словарь StorageDict был восстановлен из прошлой сессии оркестратора")
os.remove("_SessionLast_StorageDict.pickle") # remove the temp file
# _SessionLast_Gsettings.pickle (binary)
if os.path.exists("_SessionLast_GSettings.pickle"):
@ -827,12 +799,11 @@ def OrchestratorSessionRestore(inGSettings=None):
lStorageDictDumpDict = pickle.load(lFile)
Server.__ComplexDictMerge2to1Overwrite__(in1Dict=inGSettings,
in2Dict=lStorageDictDumpDict) # Merge dict 2 into dict 1
if lL: lL.warning(f"GSettings was restored from previous Orchestrator session")
if lL: lL.warning(f"Словарь GSettings был восстановлен из прошлой сессии оркестратора")
os.remove("_SessionLast_GSettings.pickle") # remove the temp file
def UACKeyListCheck(inRequest, inRoleKeyList) -> bool:
"""
Проверить права доступа для пользователя запроса по списку ключей до права.
"""L+,W+: Проверить права доступа для пользователя запроса по списку ключей до права.
.. code-block:: python
@ -847,8 +818,7 @@ def UACKeyListCheck(inRequest, inRoleKeyList) -> bool:
return inRequest.UACClientCheck(inRoleKeyList=inRoleKeyList)
def UACUserDictGet(inRequest) -> dict:
"""
Вернуть UAC (User Access Control) словарб доступов для пользователя, который отправил запрос. Пустой словарь - супердоступ (доступ ко всему)
"""L+,W+: Вернуть UAC (User Access Control) словарь доступов для пользователя, который отправил запрос. Пустой словарь - супердоступ (доступ ко всему)
:param inRequest: Экземпляр request (from http.server import BaseHTTPRequestHandler)
:return: Словарь доступов пользователя. Пустой словарь - супердоступ (доступ ко всему)
@ -856,8 +826,7 @@ def UACUserDictGet(inRequest) -> dict:
return inRequest.UserRoleHierarchyGet() # get the Hierarchy
def UACUpdate(inADLoginStr, inADStr="", inADIsDefaultBool=True, inURLList=None, inRoleHierarchyAllowedDict=None, inGSettings = None):
"""
Дообогащение словаря доступа UAC пользователя inADStr\\inADLoginStr. Если ранее словарь не устанавливался, то по умолчанию он {}. Далее идет дообогащение теми ключами, которые присутствуют в inRoleHierarchyAllowedDict
"""L+,W+: Дообогащение словаря доступа UAC пользователя inADStr\\inADLoginStr. Если ранее словарь не устанавливался, то по умолчанию он {}. Далее идет дообогащение теми ключами, которые присутствуют в inRoleHierarchyAllowedDict
:param inGSettings: Глобальный словарь настроек Оркестратора (синглтон)
:param inADLoginStr: Логин пользователя
@ -900,8 +869,7 @@ def UACUpdate(inADLoginStr, inADStr="", inADIsDefaultBool=True, inURLList=None,
inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"].update({("",inADLoginStr.upper()):lRuleDomainUserDict})
def UACSuperTokenUpdate(inSuperTokenStr, inGSettings=None):
"""
Добавить супертокен (полный доступ). Супертокены используются для подключения к Оркестратору по API
"""L+,W+: Добавить супертокен (полный доступ). Супертокены используются для подключения к Оркестратору по API
:param inGSettings: Глобальный словарь настроек Оркестратора (синглтон)
:param inSuperTokenStr: Кодовая строковая комбинация, которая будет предоставлять доступ роботу / агенту для взаимодействия с Оркестратором по API
@ -917,8 +885,7 @@ def UACSuperTokenUpdate(inSuperTokenStr, inGSettings=None):
# OrchestratorWeb defs
# # # # # # # # # # # # # # # # # # # # # # #
def WebURLIndexChange(inURLIndexStr:str ="/"):
"""
Изменить адрес главной страницы Оркестратора. По умолчанию '/'
"""L+,W+: Изменить адрес главной страницы Оркестратора. По умолчанию '/'
:param inURLIndexStr: Новый адрес главной страницы Оркестратора.
:type inURLIndexStr: str, опционально
@ -926,8 +893,7 @@ def WebURLIndexChange(inURLIndexStr:str ="/"):
GSettingsGet()["ServerDict"]["URLIndexStr"] = inURLIndexStr
def WebURLConnectDef(inMethodStr, inURLStr, inMatchTypeStr, inDef, inContentTypeStr="application/octet-stream", inGSettings = None, inUACBool = None):
"""
Подключить функцию Python к URL.
"""L+,W+: Подключить функцию Python к URL.
:param inMethodStr: Метод доступа по URL "GET" || "POST"
:param inURLStr: URL адрес. Пример "/index"
@ -953,8 +919,7 @@ def WebURLConnectDef(inMethodStr, inURLStr, inMatchTypeStr, inDef, inContentType
def WebURLConnectFolder(inMethodStr, inURLStr, inMatchTypeStr, inFolderPathStr, inGSettings = None, inUACBool = None, inUseCacheBool= False):
"""
Подключить папку к URL.
"""L+,W+: Подключить папку к URL.
:param inMethodStr: Метод доступа по URL "GET" || "POST"
:param inURLStr: URL адрес. Пример "/index"
@ -984,9 +949,7 @@ def WebURLConnectFolder(inMethodStr, inURLStr, inMatchTypeStr, inFolderPathStr,
def WebURLConnectFile(inMethodStr, inURLStr, inMatchTypeStr, inFilePathStr, inContentTypeStr=None, inGSettings = None, inUACBool = None, inUseCacheBool = False):
"""
Подключить файл к URL.
"""L+,W+: Подключить файл к URL.
:param inMethodStr: Метод доступа по URL "GET" || "POST"
:param inURLStr: URL адрес. Пример "/index"
@ -1013,8 +976,7 @@ def WebURLConnectFile(inMethodStr, inURLStr, inMatchTypeStr, inFilePathStr, inCo
inGSettings["ServerDict"]["URLList"].append(lURLItemDict)
def WebListenCreate(inServerKeyStr="Default", inAddressStr="", inPortInt=80, inCertFilePEMPathStr=None, inKeyFilePathStr=None, inGSettings = None):
"""
Настроить веб-сервер Оркестратора.
"""L+,W+: Настроить веб-сервер Оркестратора.
:param inAddressStr: IP адрес для прослушивания. Если "", то прослушивать запросы со всех сетевых карт. Если "127.0.0.1", то слушать запросы только с той ОС, на которой работает Оркестратор
:param inPortInt: Номер порта для прослушивания. Если HTTP - 80; Если HTTPS - 443. По умолчанию 80. Допускается установка других портов
@ -1023,6 +985,8 @@ def WebListenCreate(inServerKeyStr="Default", inAddressStr="", inPortInt=80, inC
:param inGSettings: Глобальный словарь настроек Оркестратора (синглтон)
:return:
"""
inCertFilePEMPathStr=CrossOS.PathStr(inPathStr=inCertFilePEMPathStr)
inKeyFilePathStr=CrossOS.PathStr(inPathStr=inKeyFilePathStr)
inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings
inGSettings["ServerDict"]["ListenDict"][inServerKeyStr]={
"AddressStr":inAddressStr,
@ -1034,8 +998,7 @@ def WebListenCreate(inServerKeyStr="Default", inAddressStr="", inPortInt=80, inC
def WebCPUpdate(inCPKeyStr, inHTMLRenderDef=None, inJSONGeneratorDef=None, inJSInitGeneratorDef=None, inGSettings = None):
"""
Добавить панель управления робота в Оркестратор. Для панели управления открыт доступ для использования функции-генератора HTML, генератора JSON данных, генератора JS кода.
"""L+,W+: Добавить панель управления робота в Оркестратор. Для панели управления открыт доступ для использования функции-генератора HTML, генератора JSON данных, генератора JS кода.
:param inGSettings: Глобальный словарь настроек Оркестратора (синглтон)
:param inCPKeyStr: Текстовый ключ панели управления. Ключ для каждой панели управления должен быть уникальным!
@ -1053,8 +1016,7 @@ def WebCPUpdate(inCPKeyStr, inHTMLRenderDef=None, inJSONGeneratorDef=None, inJSI
def WebAuditMessageCreate(inRequest=None, inOperationCodeStr="-", inMessageStr="-"):
"""
Создание сообщения ИТ аудита с такими сведениями как (Домен, IP, логин и тд.). Данная функция особенно актуальна в том случае, если требуется реализовать дополнительные меры контроля ИТ системы.
"""L+,W+: Создание сообщения ИТ аудита с такими сведениями как (Домен, IP, логин и тд.). Данная функция особенно актуальна в том случае, если требуется реализовать дополнительные меры контроля ИТ системы.
.. code-block:: python
@ -1087,8 +1049,7 @@ def WebAuditMessageCreate(inRequest=None, inOperationCodeStr="-", inMessageStr="
return lResultStr
def WebRequestParseBodyBytes(inRequest=None):
"""
Извлечь данные в байт виде из тела (body) HTTP запроса.
"""L+,W+: Извлечь данные в байт виде из тела (body) HTTP запроса.
:param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя
:return: Строка байт b'' или None (если тело запроса было пустым)
@ -1101,8 +1062,7 @@ def WebRequestParseBodyBytes(inRequest=None):
return lBodyBytes
def WebRequestParseBodyStr(inRequest=None):
"""
Извлечь данные в виде строки из тела (body) HTTP запроса.
"""L+,W+: Извлечь данные в виде строки из тела (body) HTTP запроса.
:param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя
:return: Текстовая строка '' или None (если тело запроса было пустым)
@ -1111,8 +1071,7 @@ def WebRequestParseBodyStr(inRequest=None):
return WebRequestParseBodyBytes(inRequest=inRequest).decode('utf-8')
def WebRequestParseBodyJSON(inRequest=None):
"""
Извлечь из тела (body) запроса HTTP JSON данные и преобразовать в Dict / List структуры языка Python.
"""L+,W+: Извлечь из тела (body) запроса HTTP JSON данные и преобразовать в Dict / List структуры языка Python.
:param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя
:return: Словарь (dict), список (list) или None (если тело запроса было пустым)
@ -1121,8 +1080,7 @@ def WebRequestParseBodyJSON(inRequest=None):
return json.loads(WebRequestParseBodyStr(inRequest=inRequest))
def WebRequestParsePath(inRequest=None):
"""
Извлечь декодированный URL путь из HTTP запроса пользователя в формате строки.
"""L+,W+: Извлечь декодированный URL путь из HTTP запроса пользователя в формате строки.
:param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя
:return: str, пример: /pyOpenRPA/Debugging/DefHelper
@ -1131,8 +1089,7 @@ def WebRequestParsePath(inRequest=None):
return urllib.parse.unquote(inRequest.path)
def WebRequestParseFile(inRequest=None):
"""
Извлечь файл (наименование + содержимое в виде строки байт b'') из HTTP запроса пользователя.
"""L+,W+: Извлечь файл (наименование + содержимое в виде строки байт b'') из HTTP запроса пользователя.
:param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя
:return: Кортеж формата (FileNameStr, FileBodyBytes) or (None, None), если файл не был обнаружен
@ -1158,8 +1115,7 @@ def WebRequestParseFile(inRequest=None):
return lResultTurple
def WebRequestResponseSend(inResponeStr, inRequest=None, inContentTypeStr: str = None, inHeadersDict: dict = None):
"""
Установить ответ на HTTP запрос пользователя.
"""L+,W+: Установить ответ на HTTP запрос пользователя.
:param inResponeStr: Тело ответа (строка)
:param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя
@ -1175,16 +1131,14 @@ def WebRequestResponseSend(inResponeStr, inRequest=None, inContentTypeStr: str =
def WebRequestGet():
"""
Вернуть экземпляр HTTP запроса, если функция вызвана в потоке, который был порожден для отработки HTTP запроса пользователя.
"""L+,W+: Вернуть экземпляр HTTP запроса, если функция вызвана в потоке, который был порожден для отработки HTTP запроса пользователя.
"""
lCurrentThread = threading.current_thread()
if hasattr(lCurrentThread, "request"):
return lCurrentThread.request
def WebUserInfoGet(inRequest=None):
"""
Информация о пользователе, который отправил HTTP запрос.
"""L+,W+: Информация о пользователе, который отправил HTTP запрос.
:param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя
:return: Сведения в формате {"DomainUpperStr": "PYOPENRPA", "UserNameUpperStr": "IVAN.MASLOV"}
@ -1195,8 +1149,7 @@ def WebUserInfoGet(inRequest=None):
return {"DomainUpperStr": lDomainUpperStr, "UserNameUpperStr": lUserUpperStr}
def WebUserIsSuperToken(inRequest = None, inGSettings = None):
"""
Проверить, авторизован ли HTTP запрос с помощью супер токена (токен, который не истекает).
"""L+,W+: Проверить, авторизован ли HTTP запрос с помощью супер токена (токен, который не истекает).
:param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя
:param inGSettings: Глобальный словарь настроек Оркестратора (синглтон)
@ -1210,8 +1163,7 @@ def WebUserIsSuperToken(inRequest = None, inGSettings = None):
return lIsSuperTokenBool
def WebUserUACHierarchyGet(inRequest = None):
"""
Вернуть словарь доступа UAC в отношении пользователя, который выполнил HTTP запрос inRequest
"""L+,W+: Вернуть словарь доступа UAC в отношении пользователя, который выполнил HTTP запрос inRequest
:param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя
:return: UAC словарь доступа или {}, что означает полный доступ
@ -1233,8 +1185,7 @@ if __name__ == "pyOpenRPA.Orchestrator.__Orchestrator__" and "pyOpenRPA.Orchestr
sys.modules["pyOpenRPA.Orchestrator"] = lCurrentModule
def GSettingsGet(inGSettings=None):
"""
Вернуть глобальный словарь настроек Оркестратора. Во время выполнения программы глобальный словарь настроек существует в единственном экземпляре (синглтон)
"""L+,W+: Вернуть глобальный словарь настроек Оркестратора. Во время выполнения программы глобальный словарь настроек существует в единственном экземпляре (синглтон)
:param inGSettings: Дополнительный словарь настроек, который необходимо добавить в основной глобальный словарь настроек Оркестратора (синглтон)
:return: Глобальный словарь настроек GSettings
@ -1246,8 +1197,7 @@ def GSettingsGet(inGSettings=None):
return GSettings # Return the result
def GSettingsKeyListValueSet(inValue, inKeyList=None, inGSettings = None):
"""
Установить значение из глобального словаря настроек Оркестратора GSettings по списку ключей.
"""L+,W+: Установить значение из глобального словаря настроек Оркестратора GSettings по списку ключей.
Пример: Для того, чтобы установить значение для ключа car в словаре {"complex":{"car":"green"}, "simple":"HELLO"}, необходимо передать список ключей: ["complex", "car"]
@ -1269,8 +1219,7 @@ def GSettingsKeyListValueSet(inValue, inKeyList=None, inGSettings = None):
return True
def GSettingsKeyListValueGet(inKeyList=None, inGSettings = None):
"""
Получить значение из глобального словаря настроек Оркестратора GSettings по списку ключей.
"""L+,W+: Получить значение из глобального словаря настроек Оркестратора GSettings по списку ключей.
:param inGSettings: Глобальный словарь настроек Оркестратора (синглтон)
:param inKeyList: Список ключей, по адресу которого получить значение из GSettings
@ -1289,8 +1238,7 @@ def GSettingsKeyListValueGet(inKeyList=None, inGSettings = None):
return lDict.get(inKeyList[-1],None)
def GSettingsKeyListValueAppend(inValue, inKeyList=None, inGSettings = None):
"""
Применить операцию .append к обьекту, расположенному по адресу списка ключей inKeyList в глобальном словаре настроек Оркестратора GSettings. Пример: Добавить значение в конец списка (list).
"""L+,W+: Применить операцию .append к обьекту, расположенному по адресу списка ключей inKeyList в глобальном словаре настроек Оркестратора GSettings. Пример: Добавить значение в конец списка (list).
.. code-block:: python
@ -1328,8 +1276,7 @@ def GSettingsKeyListValueAppend(inValue, inKeyList=None, inGSettings = None):
return True
def GSettingsKeyListValueOperatorPlus(inValue, inKeyList=None, inGSettings = None):
"""
Применить оператор сложения (+) к обьекту, расположенному по адресу списка ключей inKeyList в глобальном словаре настроек Оркестратора GSettings. Пример: соединить 2 списка (list).
"""L+,W+: Применить оператор сложения (+) к обьекту, расположенному по адресу списка ключей inKeyList в глобальном словаре настроек Оркестратора GSettings. Пример: соединить 2 списка (list).
.. code-block:: python
@ -1370,8 +1317,7 @@ def GSettingsKeyListValueOperatorPlus(inValue, inKeyList=None, inGSettings = Non
return True
def StorageRobotExists(inRobotNameStr):
"""
Проверить, существует ли ключ inRobotNameStr в хранилище пользовательской информации StorageDict (GSettings > StarageDict)
"""L+,W+: Проверить, существует ли ключ inRobotNameStr в хранилище пользовательской информации StorageDict (GSettings > StarageDict)
:param inRobotNameStr: Наименование (ключ) робота. !ВНИМАНИЕ! Наименование чувствительно к регистру
:return: True - ключ робота присутствует в хранилище; False - отсутствует
@ -1379,8 +1325,7 @@ def StorageRobotExists(inRobotNameStr):
return inRobotNameStr in GSettingsGet()["StorageDict"]
def StorageRobotGet(inRobotNameStr):
"""
Получить содержимое по ключу робота inRobotNameStr в хранилище пользовательской информации StorageDict (GSettings > StarageDict)
"""L+,W+: Получить содержимое по ключу робота inRobotNameStr в хранилище пользовательской информации StorageDict (GSettings > StarageDict)
:param inRobotNameStr: Наименование (ключ) робота. !ВНИМАНИЕ! Наименование чувствительно к регистру
:return: Значение или структура, которая расположена по адресу (GSettings > StarageDict > inRobotNameStr)
@ -1390,8 +1335,7 @@ def StorageRobotGet(inRobotNameStr):
return GSettingsGet()["StorageDict"][inRobotNameStr]
def ProcessorAliasDefCreate(inDef, inAliasStr=None, inGSettings = None):
"""
Создать синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна).
"""L+,W+: Создать синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна).
Старая версия. Новую версию см. ActivityItemDefAliasCreate
@ -1417,8 +1361,7 @@ def ProcessorAliasDefCreate(inDef, inAliasStr=None, inGSettings = None):
return ActivityItemDefAliasCreate(inDef=inDef, inAliasStr=inAliasStr, inGSettings = inGSettings)
def ProcessorAliasDefUpdate(inDef, inAliasStr, inGSettings = None):
"""
Обновить синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна).
"""L+,W+: Обновить синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна).
Старая версия. Новую версию см. ActivityItemDefAliasUpdate
@ -1444,8 +1387,7 @@ def ProcessorAliasDefUpdate(inDef, inAliasStr, inGSettings = None):
# ActivityItem defs
def ActivityItemHelperDefList(inDefQueryStr=None):
"""
Получить список синонимов (текстовых ключей), доступных для использования в Активностях (ActivityItem).
"""L+,W+: Получить список синонимов (текстовых ключей), доступных для использования в Активностях (ActivityItem).
:param inDefStr: Часть текстового ключ (начало / середина / конец)
:return: Список доступных ключей в формате: ["ActivityItemDefAliasUpdate", "ActivityItemDefAliasCreate", etc...]
@ -1461,8 +1403,7 @@ def ActivityItemHelperDefList(inDefQueryStr=None):
return lResultList
def ActivityItemHelperDefAutofill(inDef):
"""
Анализ аргументов функции по синониму (текстовому ключу).
"""L+,W+: Анализ аргументов функции по синониму (текстовому ключу).
:param inDef: Часть текстового ключ (начало / середина / конец)
:return: Преднастроенная структура активности (ActivityItem)
@ -1500,8 +1441,7 @@ def ActivityItemHelperDefAutofill(inDef):
return lResultDict
def ActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr=None, inArgLoggerStr=None, inGUIDStr = None, inThreadBool = False):
"""
Создать Активность (ActivityItem). Активность можно использовать в ProcessorActivityItemAppend или в Processor.ActivityListExecute или в функциях работы с Агентами.
"""L+,W+: Создать Активность (ActivityItem). Активность можно использовать в ProcessorActivityItemAppend или в Processor.ActivityListExecute или в функциях работы с Агентами.
.. code-block:: python
@ -1584,8 +1524,7 @@ def ActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr=
def ActivityItemDefAliasCreate(inDef, inAliasStr=None, inGSettings = None):
"""
Создать синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна).
"""L+,W+: Создать синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна).
.. code-block:: python
@ -1617,8 +1556,7 @@ def ActivityItemDefAliasCreate(inDef, inAliasStr=None, inGSettings = None):
return inAliasStr
def ActivityItemDefAliasModulesLoad():
"""
Загрузить все функции из импортированных модулей sys.modules в ActivityItem синонимы - полезно для отладки со стороны панели управления.
"""L+,W+: Загрузить все функции из импортированных модулей sys.modules в ActivityItem синонимы - полезно для отладки со стороны панели управления.
"""
lL = OrchestratorLoggerGet()
lL.info(f"Синонимы функций: старт инициализации sys.modules")
@ -1635,8 +1573,7 @@ def ActivityItemDefAliasModulesLoad():
lL.info(f"Синонимы функций: окончание инициализации sys.modules")
def ActivityItemDefAliasUpdate(inDef, inAliasStr, inGSettings = None):
"""
Обновить синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна).
"""L+,W+: Обновить синоним (текстовый ключ) для инициации выполнения функции в том случае, если запрос на выполнения пришел из вне (передача функций невозможна).
.. code-block:: python
@ -1664,8 +1601,7 @@ def ActivityItemDefAliasUpdate(inDef, inAliasStr, inGSettings = None):
def ProcessorActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSettingsStr=None, inArgLoggerStr=None, inGUIDStr = None, inThreadBool = False):
"""
Создать Активность (ActivityItem). Активность можно использовать в ProcessorActivityItemAppend или в Processor.ActivityListExecute или в функциях работы с Агентами.
"""L+,W+: Создать Активность (ActivityItem). Активность можно использовать в ProcessorActivityItemAppend или в Processor.ActivityListExecute или в функциях работы с Агентами.
Старая версия. Новую версию см. в ActivityItemCreate
@ -1736,8 +1672,7 @@ def ProcessorActivityItemCreate(inDef, inArgList=None, inArgDict=None, inArgGSet
inGUIDStr=inGUIDStr, inThreadBool=inThreadBool)
def ProcessorActivityItemAppend(inGSettings = None, inDef=None, inArgList=None, inArgDict=None, inArgGSettingsStr=None, inArgLoggerStr=None, inActivityItemDict=None):
"""
Добавить активность (ActivityItem) в процессорную очередь.
"""L+,W+: Добавить активность (ActivityItem) в процессорную очередь.
.. code-block:: python
@ -1814,8 +1749,7 @@ def ProcessorActivityItemAppend(inGSettings = None, inDef=None, inArgList=None,
## Process defs
def ProcessIsStarted(inProcessNameWOExeStr): # Check if process is started
"""
Проверить, запущен ли процесс, который в наименовании содержит inProcessNameWOExeStr.
"""L-,W+: Проверить, запущен ли процесс, который в наименовании содержит inProcessNameWOExeStr.
!ВНИМАНИЕ! ПРОВЕРЯЕТ ВСЕ ПРОЦЕССЫ ОПЕРАЦИОННОЙ СИСТЕМЫ. И ДРУГИХ ПОЛЬЗОВАТЕЛЬСКИХ СЕССИЙ, ЕСЛИ ОНИ ЗАПУЩЕНЫ НА ЭТОЙ МАШИНЕ.
@ -1841,8 +1775,7 @@ def ProcessIsStarted(inProcessNameWOExeStr): # Check if process is started
return False
def ProcessStart(inPathStr, inArgList, inStopProcessNameWOExeStr=None):
"""
Запуск процесса на сессии Оркестратора, если на ОС не запущен процесс inStopProcessNameWOExeStr.
"""L-,W+: Запуск процесса на сессии Оркестратора, если на ОС не запущен процесс inStopProcessNameWOExeStr.
!ВНИМАНИЕ! ПРИ ПРОВЕРКЕ РАНЕЕ ЗАПУЩЕННЫХ ПРОЦЕССОВ ПРОВЕРЯЕТ ВСЕ ПРОЦЕССЫ ОПЕРАЦИОННОЙ СИСТЕМЫ. И ДРУГИХ ПОЛЬЗОВАТЕЛЬСКИХ СЕССИЙ, ЕСЛИ ОНИ ЗАПУЩЕНЫ НА ЭТОЙ МАШИНЕ.
@ -1879,8 +1812,7 @@ def ProcessStart(inPathStr, inArgList, inStopProcessNameWOExeStr=None):
subprocess.Popen(lItemArgs,shell=True)
def ProcessStop(inProcessNameWOExeStr, inCloseForceBool, inUserNameStr = "%username%"):
"""
Остановить процесс на ОС, где работает Оркестратор, под учетной записью inUserNameStr.
"""L-,W+: Остановить процесс на ОС, где работает Оркестратор, под учетной записью inUserNameStr.
.. code-block:: python
@ -1915,8 +1847,7 @@ def ProcessStop(inProcessNameWOExeStr, inCloseForceBool, inUserNameStr = "%usern
os.system(lActivityCloseCommand)
def ProcessListGet(inProcessNameWOExeList=None):
"""
Вернуть список процессов, запущенных на ОС, где работает Оркестратор. В списке отсортировать процессы по количеству используемой оперативной памяти. Также можно указать перечень процессов, которые интересуют - функция будет показывать активные из них.
"""L-,W+: Вернуть список процессов, запущенных на ОС, где работает Оркестратор. В списке отсортировать процессы по количеству используемой оперативной памяти. Также можно указать перечень процессов, которые интересуют - функция будет показывать активные из них.
!ВНИМАНИЕ! ДЛЯ ПОЛУЧЕНИЯ СПИСКА ВСЕХ ПРОЦЕССОВ ОС НЕОБХОДИМО ЗАПУСКАТЬ ОРКЕСТРАТОР С ПРАВАМИ АДМИНИСТРАТОРА.
@ -1975,8 +1906,7 @@ def ProcessListGet(inProcessNameWOExeList=None):
def ProcessDefIntervalCall(inDef, inIntervalSecFloat, inIntervalAsyncBool=False, inDefArgList=None, inDefArgDict=None, inDefArgGSettingsNameStr=None, inDefArgLoggerNameStr=None, inExecuteInNewThreadBool=True, inLogger=None, inGSettings = None):
"""
Периодический вызов функции Python.
"""L+,W+: Периодический вызов функции Python.
:param inDef: Функция Python, которую потребуется периодически вызывать
:param inIntervalSecFloat: Интервал между вызовами функции в сек.
@ -1998,11 +1928,11 @@ def ProcessDefIntervalCall(inDef, inIntervalSecFloat, inIntervalAsyncBool=False,
if inDefArgLoggerNameStr=="": inDefArgLoggerNameStr=None
if inDefArgGSettingsNameStr=="": inDefArgGSettingsNameStr=None
if inDefArgLoggerNameStr is not None and not inLogger:
raise Exception(f"!ERROR! ProcessDefIntervalCall - You need to send logger in def because your def is require logger. Raise error!")
raise Exception(f"__Orchestrator__.ProcessDefIntervalCall: Вызываемая функция требует передачи логгера, а он не указан")
# Check thread
if not Core.IsProcessorThread(inGSettings=inGSettings):
if inGSettings["Logger"]: inGSettings["Logger"].warning(f"__Orchestrator__.ProcessDefIntervalCall def was called not from processor queue - activity will be append in the processor queue.")
if inGSettings["Logger"]: inGSettings["Logger"].warning(f"__Orchestrator__.ProcessDefIntervalCall: функция вызвана не из процессорной очереди - активность будет перемещена в процессорную очередь")
lProcessorActivityDict = {
"Def": ProcessDefIntervalCall, # def link or def alias (look gSettings["Processor"]["AliasDefDict"])
"ArgList": [], # Args list
@ -2055,8 +1985,7 @@ def ProcessDefIntervalCall(inDef, inIntervalSecFloat, inIntervalAsyncBool=False,
# Python def - start module function
def PythonStart(inModulePathStr, inDefNameStr, inArgList=None, inArgDict=None, inLogger = None):
"""
Импорт модуля и выполнение функции в процессе Оркестратора.
"""L+,W+: Импорт модуля и выполнение функции в процессе Оркестратора.
.. note::
@ -2078,6 +2007,7 @@ def PythonStart(inModulePathStr, inDefNameStr, inArgList=None, inArgDict=None, i
:param inArgDict: Словарь (dict) именованных аргументов для передачи в функцию. По умолчанию None
:param inLogger: Логгер для фиксации сообщений выполнения функции (опционально)
"""
inModulePathStr=CrossOS.PathStr(inPathStr=inModulePathStr)
if inLogger is None: inLogger = OrchestratorLoggerGet()
if inArgList is None: inArgList=[]
if inArgDict is None: inArgDict={}
@ -2092,8 +2022,7 @@ def PythonStart(inModulePathStr, inDefNameStr, inArgList=None, inArgDict=None, i
# Scheduler
# # # # # # # # # # # # # # # # # # # # # # #
def SchedulerActivityTimeAddWeekly(inTimeHHMMStr="23:55:", inWeekdayList=None, inActivityList=None, inGSettings = None):
"""
Добавить активность по расписанию. Допускается указание времени и дней недели, в которые производить запуск.
"""L+,W+: Добавить активность по расписанию. Допускается указание времени и дней недели, в которые производить запуск.
.. code-block:: python
@ -2139,8 +2068,7 @@ def SchedulerActivityTimeAddWeekly(inTimeHHMMStr="23:55:", inWeekdayList=None, i
def RDPTemplateCreate(inLoginStr, inPasswordStr, inHostStr="127.0.0.1", inPortInt = 3389, inWidthPXInt = 1680, inHeightPXInt = 1050,
inUseBothMonitorBool = False, inDepthBitInt = 32, inSharedDriveList=None, inRedirectClipboardBool=True):
"""
Создать шаблон подключения RDP (dict). Данный шаблон далее можно использовать в Orchestrator.RDPSessionConnect
"""L-,W+: Создать шаблон подключения RDP (dict). Данный шаблон далее можно использовать в Orchestrator.RDPSessionConnect
.. code-block:: python
@ -2226,8 +2154,7 @@ def RDPSessionDublicatesResolve(inGSettings):
# lItemDict = inGSettings["RobotRDPActive"]["RDPList"][lItemKeyStr]
def RDPSessionConnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inHostStr=None, inPortStr=None, inLoginStr=None, inPasswordStr=None, inGSettings = None, inRedirectClipboardBool=True):
"""
Выполнить подключение к RDP и следить за стабильностью соединения со стороны Оркестратора.
"""L-,W+: Выполнить подключение к RDP и следить за стабильностью соединения со стороны Оркестратора.
!ВНИМАНИЕ! - Подключение будет проигнорировано, если соединение по таком RDP ключу уже было инициализировано ранее.
2 способа использования функции:
@ -2288,8 +2215,7 @@ def RDPSessionConnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inHostStr=None
return True
def RDPSessionDisconnect(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList = None, inGSettings = None):
"""
Выполнить отключение RDP сессии и прекратить мониторить его активность.
"""L-,W+: Выполнить отключение RDP сессии и прекратить мониторить его активность.
.. code-block:: python
@ -2331,8 +2257,7 @@ def RDPSessionDisconnect(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList = No
return True
def RDPSessionReconnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inGSettings = None):
"""
Выполнить переподключение RDP сессии и продолжить мониторить его активность.
"""L-,W+: Выполнить переподключение RDP сессии и продолжить мониторить его активность.
.. code-block:: python
@ -2377,8 +2302,7 @@ def RDPSessionReconnect(inRDPSessionKeyStr, inRDPTemplateDict=None, inGSettings
return True
def RDPSessionMonitorStop(inRDPSessionKeyStr, inGSettings = None):
"""
Прекратить мониторить активность RDP соединения со стороны Оркестратора. Данная функция не уничтожает активное RDP соединение.
"""L-,W+: Прекратить мониторить активность RDP соединения со стороны Оркестратора. Данная функция не уничтожает активное RDP соединение.
.. code-block:: python
@ -2399,8 +2323,7 @@ def RDPSessionMonitorStop(inRDPSessionKeyStr, inGSettings = None):
return lResult
def RDPSessionLogoff(inRDPSessionKeyStr, inBreakTriggerProcessWOExeList = None, inGSettings = None):
"""
Выполнить отключение (logoff) на RDP сессии и прекратить мониторить активность со стороны Оркестратора.
"""L-,W+: Выполнить отключение (logoff) на RDP сессии и прекратить мониторить активность со стороны Оркестратора.
.. code-block:: python
@ -2485,8 +2408,7 @@ def RDPSessionResponsibilityCheck(inRDPSessionKeyStr, inGSettings = None):
return True
def RDPSessionProcessStartIfNotRunning(inRDPSessionKeyStr, inProcessNameWEXEStr, inFilePathStr, inFlagGetAbsPathBool=True, inGSettings = None):
"""
Выполнить запуск процесса на RDP сессии через графические UI инструменты (без Агента).
"""L-,W+: Выполнить запуск процесса на RDP сессии через графические UI инструменты (без Агента).
!ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом.
@ -2533,8 +2455,7 @@ def RDPSessionProcessStartIfNotRunning(inRDPSessionKeyStr, inProcessNameWEXEStr,
return lResult
def RDPSessionCMDRun(inRDPSessionKeyStr, inCMDStr, inModeStr="CROSSCHECK", inGSettings = None):
"""
Отправить CMD команду на удаленную сесиию через RDP окно (без Агента).
"""L-,W+: Отправить CMD команду на удаленную сесиию через RDP окно (без Агента).
!ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом.
@ -2589,8 +2510,7 @@ def RDPSessionCMDRun(inRDPSessionKeyStr, inCMDStr, inModeStr="CROSSCHECK", inGSe
return lResult
def RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceCloseBool, inGSettings = None):
"""
Отправка CMD команды в RDP окне на остановку процесса (без Агента).
"""L-,W+: Отправка CMD команды в RDP окне на остановку процесса (без Агента).
!ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом.
@ -2637,8 +2557,7 @@ def RDPSessionProcessStop(inRDPSessionKeyStr, inProcessNameWEXEStr, inFlagForceC
return lResult
def RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePathStr, inGSettings = None):
"""
Отправка файла со стороны Оркестратора на сторону RDP сессии через UI инструменты RDP окна (без Агента).
"""L-,W+: Отправка файла со стороны Оркестратора на сторону RDP сессии через UI инструменты RDP окна (без Агента).
!ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом.
@ -2685,8 +2604,7 @@ def RDPSessionFileStoredSend(inRDPSessionKeyStr, inHostFilePathStr, inRDPFilePat
return lResult
def RDPSessionFileStoredRecieve(inRDPSessionKeyStr, inRDPFilePathStr, inHostFilePathStr, inGSettings = None):
"""
Получение файла со стороны RDP сессии на сторону Оркестратора через UI инструменты RDP окна (без Агента).
"""L-,W+: Получение файла со стороны RDP сессии на сторону Оркестратора через UI инструменты RDP окна (без Агента).
!ВНИМАНИЕ! Данная функция может работать нестабильно из-за использования графических элементов UI при работе с RDP. Мы рекомендуем использовать конструкцию взаимодействия Оркестратора с Агентом.
@ -2768,8 +2686,7 @@ def Start(inDumpRestoreBool = True, inRunAsAdministratorBool = True):
Orchestrator(inDumpRestoreBool = True, inRunAsAdministratorBool = True)
def Orchestrator(inGSettings=None, inDumpRestoreBool = True, inRunAsAdministratorBool = True):
"""
Инициализация ядра Оркестратора (всех потоков)
"""L+,W+: Инициализация ядра Оркестратора (всех потоков)
:param inGSettings: Глобальный словарь настроек Оркестратора (синглтон)
:param inDumpRestoreBool: True - Восстановить информацию о RDP сессиях и StorageDict; False - не восстанавливать

Loading…
Cancel
Save