|
|
import psutil, datetime, logging, os, json
|
|
|
|
|
|
## # # # # # # # # # # # # # # # # ##
|
|
|
# GLOBAL PARAMETERS
|
|
|
gBuildFolderPathStr = '\\'.join(__file__.split('\\')[:-1])
|
|
|
gRobotRepositoryPathStr = os.popen(f'cd {gBuildFolderPathStr} && git rev-parse --show-toplevel').read().replace("\n",'').replace('/','\\') # needed for cmd and git pull
|
|
|
gRobotStartFilePathStr = os.path.join(gBuildFolderPathStr,r"pyRobotName_x64_Run.cmd") # path\to\start\file
|
|
|
gRobotProcessNameWOEXEStr = "pyRobotName" # RobotProcessName
|
|
|
gRobotADLoginStr = "AD LOGIN" # Login of the robot rdp session
|
|
|
gRobotADPasswordStr = "AD PASSWORD" # Password for rdp session
|
|
|
gRobotKeyStr = "pyRobotName" # Key for store OrchestratorConnector key-value (Orchstrator gSettings["Storage"][gRobotKeyStr])
|
|
|
gRDPSessionKeyStr = "pyRobotName"
|
|
|
gRDPSessionHostStr = "localhost" # Rdp session host
|
|
|
gRDPSessionPortStr = "3389" # Default RDP port is 3389
|
|
|
gControlPanelKeyStr = "pyRobotName" # Str key for RDP session key
|
|
|
gControlPanelCheckRobotProcessFromOrchestratorUserBool = True # Check process activity from orchestrator GUI session (with help of task manager, when users on the same machine)
|
|
|
# !! ATTENTION !! SCHEDULE TIME START STOP FILL BELOW IN ACTIVITY SECTION
|
|
|
gRobotToOrchestratorKeyList = ["Storage",gRobotKeyStr,"RobotToOrchestrator"]
|
|
|
gOrchestratorToRobotResetKeyList = ["Storage",gRobotKeyStr,"OrchestratorToRobotReset"]
|
|
|
gOrchestratorToRobotResetSafeStopKeyList = gOrchestratorToRobotResetKeyList+["TurnOffSafeBool"]
|
|
|
# # # # # # BUSINESS USER AD LOGIN # # # # # # # # # # # # # # #
|
|
|
gADLoginList = [
|
|
|
"ADLOGIN_1",
|
|
|
"ADLOGIN_2",
|
|
|
"ADLOGIN_3",
|
|
|
"ADLOGIN_4"
|
|
|
]
|
|
|
gADDomainNameStr = "MY-PC" # DOMAIN or EMPTY str if no domain
|
|
|
gADDomainIsDefaultBool = True # If domain is exist and is default (default = you can type login without domain name)
|
|
|
|
|
|
## # # # # # # # # # # # # # # # # ##
|
|
|
# ACTIVITY TEMPLATE START RDP & SEND CMD
|
|
|
gActivityROBOTStartTimeHH_MMStr = "01:01" # Time "HH:MM" [Server time] to execute activity, example "05:10"
|
|
|
gActivityROBOTStartWeekdayList = [0,1,2,3,4] # WeekdayList when atcivity is starting, default [0,1,2,3,4,5,6]
|
|
|
gActivityROBOTStartList = [
|
|
|
{ # Start RDP Session
|
|
|
"DefNameStr":"RDPSessionConnect", # Function name in RobotRDPActive.Processor
|
|
|
"ArgList":[], # Args list
|
|
|
"ArgDict":{"inRDPSessionKeyStr": gRDPSessionKeyStr, "inHostStr": gRDPSessionHostStr, "inPortStr": gRDPSessionPortStr, "inLoginStr": gRobotADLoginStr, "inPasswordStr": gRobotADPasswordStr} # Args dictionary
|
|
|
},
|
|
|
{ # Run robot file in RDP session
|
|
|
"DefNameStr":"RDPSessionProcessStartIfNotRunning", # Function name in RobotRDPActive.Processor
|
|
|
"ArgList":[], # Args list
|
|
|
"ArgDict":{"inRDPSessionKeyStr": gRDPSessionKeyStr, "inProcessNameWEXEStr": f"{gRobotProcessNameWOEXEStr}.exe", "inFilePathStr": gRobotStartFilePathStr, "inFlagGetAbsPathBool": False} # Args dictionary
|
|
|
}
|
|
|
]
|
|
|
|
|
|
## # # # # # # # # # # # # # # # # ##
|
|
|
# ACTIVITY TEMPLATE SAFE STOP (SIGNAL TO ROBOT TO STOP VIA ORCHESTRATOR CONNECTOR)
|
|
|
gActivityROBOTSafeStopTimeHH_MMStr = "23:40" # Time "HH:MM" [Server time] to execute activity, example "05:10"
|
|
|
gActivityROBOTSafeStopWeekdayList = [0,1,2,3,4] # WeekdayList when atcivity is starting, default [0,1,2,3,4,5,6]
|
|
|
gActivityROBOTSafeStopList = [
|
|
|
{
|
|
|
"Type": "GlobalDictKeyListValueSet",
|
|
|
"KeyList": gOrchestratorToRobotResetSafeStopKeyList,
|
|
|
"Value": True
|
|
|
},
|
|
|
#{
|
|
|
# "Type": "ProcessStop", # Activity type
|
|
|
# "Name": f"{gRobotProcessNameWOEXEStr}.exe", # proces name with .exe
|
|
|
# "FlagForce": False, # Safe kill
|
|
|
# "User": gRobotADLoginStr #Empty, user or %username%
|
|
|
#},
|
|
|
{
|
|
|
"Type": "GlobalDictKeyListValueOperator+", # Activity type
|
|
|
"KeyList": ['RobotRDPActive', 'ActivityList'], # RobotRDP Active ActivityList
|
|
|
"Value": [ # ActivityList - see upper
|
|
|
{ # Kill process
|
|
|
"DefNameStr": "RDPSessionMonitorStop", # Function name in RobotRDPActive.Processor
|
|
|
"ArgList": [], # Args list
|
|
|
"ArgDict": {"inRDPSessionKeyStr": gRDPSessionKeyStr} # Args dictionary
|
|
|
}
|
|
|
]
|
|
|
}
|
|
|
]
|
|
|
|
|
|
## # # # # # # # # # # # # # # # # ##
|
|
|
# ACTIVITY TEMPLATE FORCE STOP (SEND CMD TO STOP PROCESS & LOGOFF THE SESSION)
|
|
|
gActivityROBOTStopList = [
|
|
|
{ # Kill process
|
|
|
"DefNameStr":"RDPSessionProcessStop", # Function name in RobotRDPActive.Processor
|
|
|
"ArgList":[], # Args list
|
|
|
"ArgDict":{"inRDPSessionKeyStr": gRDPSessionKeyStr, "inProcessNameWEXEStr":f"{gRobotProcessNameWOEXEStr}.exe","inFlagForceCloseBool": True} # Args dictionary
|
|
|
},
|
|
|
{ # Logoff RDP Session
|
|
|
"DefNameStr":"RDPSessionLogoff", # Function name in RobotRDPActive.Processor
|
|
|
"ArgList":[], # Args list
|
|
|
"ArgDict":{"inRDPSessionKeyStr": gRDPSessionKeyStr} # Args dictionary
|
|
|
}
|
|
|
]
|
|
|
|
|
|
## # # # # # # # # # # # # # # # # ##
|
|
|
# CONTROL PANEL RENDER FOR HTML
|
|
|
def ControlPanelRenderDict(inRequest, inGSettings):
|
|
|
# window.prompt("Укажите дату лога в формате дд.мм.гггг",null)
|
|
|
lUAC = inRequest.OpenRPA["DefUserRoleAccessAsk"] # Alias for request user role ask
|
|
|
"""result={
|
|
|
"HeaderLeftText":"<Robot name>",
|
|
|
"HeaderRightText":"<header>",
|
|
|
"DataStorageKey":"Robot_Name", #Use key for set current dict in mGlobal.DataStorage["DataStorageKey"] on client side
|
|
|
"SubheaderText": "State: <span style=\"color:green\">Turned on</span>",
|
|
|
"BodyKeyValueList":[
|
|
|
{"Key":"Session list","Value":""},
|
|
|
{"Key":"Session list","Value":""}
|
|
|
],
|
|
|
"FooterText":"Last update: 9:38:00 09.10.2019",
|
|
|
"FooterButtonX2List":[
|
|
|
{"Text":"Turn on", "Color":"green", "Link":"", "OnClick": lOnClickRunButton.replace("\\","\\\\")},
|
|
|
],
|
|
|
"FooterButtonX1List":[
|
|
|
{"Text":"Kill", "Color":"red", "Link":"", "OnClick": lOnClickForceCloseButton.replace("\\","\\\\")}
|
|
|
]
|
|
|
}"""
|
|
|
# START :: Create activities :: START #
|
|
|
## Robot START (create RDP session, send CMD to start process)
|
|
|
lActivityROBOTStartEscaped = f"mGlobal.Processor.ServerOperatorPlus({json.dumps(['RobotRDPActive','ActivityList'])},{json.dumps(gActivityROBOTStartList)});".replace("\"","\'")
|
|
|
## Robot SAFE STOP (SAFE STOP COMMAND (FROM ROBOT RULES), Logoff must do robot when safe turn off)
|
|
|
lActivityROBOTSafeStopEscaped = f"mGlobal.Processor.Send({json.dumps(gActivityROBOTSafeStopList)});"
|
|
|
## Robot FORCE STOP (send CMD to stop process, logoff)
|
|
|
lActivityROBOTStopEscaped = f"mGlobal.Processor.ServerOperatorPlus({json.dumps(['RobotRDPActive','ActivityList'])},{json.dumps(gActivityROBOTStopList)});".replace("\"","\'")
|
|
|
## REPOSITORY GIT PULL (send CMD to git pull)
|
|
|
gRobotRepositoryPathEscapedStr = gRobotRepositoryPathStr.replace("\\","\\\\")
|
|
|
lActivityRepositoryGITPULL = f'mGlobal.Controller.CMDRunText(\"cd \\\"{gRobotRepositoryPathEscapedStr}\\\" && git reset --hard && git pull\");'.replace("\"",""")
|
|
|
lActivityRepositoryGITPULLHTML=f'<a onclick=\"{lActivityRepositoryGITPULL}\" style=\"color:orange\">Update GIT</a>'
|
|
|
# Activity download report ReportFileDocList
|
|
|
lActivityReportDownloadHTML=f'<a href=\"{gRobotKeyStr}/Reports/ReportFileDocList.xlsx\" target=\"_blank\" style=\"color:green\">Download</a>'
|
|
|
# Activity download report ReportPTSList
|
|
|
lActivityReportListDownloadHTML=f'<a href=\"{gRobotKeyStr}/Reports/ReportPTSList.xlsx\" target=\"_blank\" style=\"color:green\">Download</a>'
|
|
|
# END :: Create activities :: END #
|
|
|
|
|
|
# START :: Init result dict template :: START #
|
|
|
# lBodyKeyValue_r3_start=f'<a onclick="{lActivityROBOTStartEscaped}" style=\"color:green\">Start</a>'
|
|
|
lStatistics = TechDictKeyList_ItemGet(inDict = inGSettings, inKeyList = gRobotToOrchestratorKeyList+["Statistics"], inDefault={})
|
|
|
lResultDict={
|
|
|
"HeaderLeftText":"Robot description",
|
|
|
"HeaderRightText":"Robot",
|
|
|
"DataStorageKey":gControlPanelKeyStr, # CLIENT SIDE:: Use key for set current dict in mGlobal.DataStorage["DataStorageKey"] on client side
|
|
|
"SubheaderText":"<Subheader text, state filled below>",
|
|
|
"BodyKeyValueList":[
|
|
|
{"Key":"<b>Reports</b>","Value":""}
|
|
|
],
|
|
|
"FooterText":"Last update: 9:38:00 09.10.2019",
|
|
|
"FooterButtonX2List":[],
|
|
|
"FooterButtonX1List":[],
|
|
|
# "GlobalStorage": inGSettings.get("Storage",{}) # UNCOMMENT FOR DEBUG PURPOSE TO WATCH inGSettings on client side
|
|
|
}
|
|
|
# Start button
|
|
|
if lUAC([gRobotKeyStr,"Technical","Start"]): lResultDict["FooterButtonX2List"].append({"Text":"On", "Color":"green", "Link":"", "OnClick": lActivityROBOTStartEscaped})
|
|
|
# Stop safe button
|
|
|
if lUAC([gRobotKeyStr,"Technical","StopSafe"]): lResultDict["FooterButtonX2List"].append({"Text":"Off", "Color":"orange", "Link":"", "OnClick": lActivityROBOTSafeStopEscaped})
|
|
|
# Stop force button
|
|
|
if lUAC([gRobotKeyStr,"Technical","StopForce"]): lResultDict["FooterButtonX1List"].append({"Text":"Force ", "Color":"red", "Link":"", "OnClick": lActivityROBOTStopEscaped})
|
|
|
# END :: Init result dict template :: END #
|
|
|
|
|
|
# START :: Fill BodyKeyValueList :: START #
|
|
|
# Download report button ReportFileDocList.xlsx
|
|
|
if lUAC([gRobotKeyStr,"Business","ReportFileDocListDownload"]): lResultDict["BodyKeyValueList"].append({"Key":"Report 1","Value":lActivityReportDownloadHTML})
|
|
|
# Download report button ReportList.xlsx
|
|
|
if lUAC([gRobotKeyStr,"Business","ReportListDownload"]): lResultDict["BodyKeyValueList"].append({"Key":"Report 2","Value":lActivityReportListDownloadHTML})
|
|
|
# Add Addendum title
|
|
|
if lUAC([gRobotKeyStr,"Technical"]): lResultDict["BodyKeyValueList"].append({"Key":"<b>Additional</b>","Value":""})
|
|
|
# Download log file
|
|
|
lActivityLogDownloadOnclickStr = """var MyDate = new Date();var MyDateString;MyDateString = MyDate.getFullYear() + "_" + ('0' + (MyDate.getMonth()+1)).slice(-2) + "_" + ('0' + MyDate.getDate()).slice(-2);
|
|
|
var lLogFileNameWOExtStr = window.prompt("Please enter the date in format yyyy_mm_dd (example 2020_06_16)",MyDateString); window.open('pyRobotName/Logs/'+lLogFileNameWOExtStr+'.log','_blank');""".replace("\"",""")
|
|
|
lActivityDayLogDownloadHTML = f'<a onclick=\"{lActivityLogDownloadOnclickStr}\" style=\"color:orange\">Download</a>'
|
|
|
if lUAC([gRobotKeyStr,"Technical","DayLogDownload"]): lResultDict["BodyKeyValueList"].append({"Key":"Log on date","Value":lActivityDayLogDownloadHTML})
|
|
|
# update git button button
|
|
|
if lUAC([gRobotKeyStr,"Technical","GITUpdate"]): lResultDict["BodyKeyValueList"].append({"Key": "GIT Repository", "Value": lActivityRepositoryGITPULLHTML})
|
|
|
# END :: Fill BodyKeyValueList :: END #
|
|
|
|
|
|
# START :: Fill SubheaderText :: START #
|
|
|
## FILL Robot state by the check the RDP session state
|
|
|
lSubheaderRunTrueText="State: <span style=\"color:green\">Turned on</span>"
|
|
|
lSubheaderRunFalseText="State: <span style=\"color:red\">Turned off</span>"
|
|
|
if gControlPanelCheckRobotProcessFromOrchestratorUserBool and gRDPSessionKeyStr in inGSettings["RobotRDPActive"]["RDPList"]:
|
|
|
lResultDict["SubheaderText"]=lSubheaderRunTrueText
|
|
|
else:
|
|
|
lResultDict["SubheaderText"]=lSubheaderRunFalseText
|
|
|
# END :: Fill SubheaderText :: END #
|
|
|
|
|
|
# Fill FooterText
|
|
|
lResultDict["FooterText"]=f'Last update: {datetime.datetime.now().strftime("%H:%M:%S %d.%m.%Y")}'
|
|
|
return lResultDict
|
|
|
|
|
|
# Technical def - Get item by the list of keys
|
|
|
def TechDictKeyList_ItemGet(inDict, inKeyList, inDefault={}):
|
|
|
lResult=inDict
|
|
|
for lItem in inKeyList:
|
|
|
if lResult:
|
|
|
lResult = lResult.get(lItem,None)
|
|
|
if lResult is None:
|
|
|
lResult=inDefault
|
|
|
return lResult
|
|
|
|
|
|
# Orchestrator - pyRobot business user-role access
|
|
|
# Role model - if len of keys in dict is 0 - all access. If at least len is 1 - only this access
|
|
|
# "pyRobot":{
|
|
|
# "Business": {
|
|
|
# "Report": {
|
|
|
# "ReportFileDocListDownload": {}, # Download a report
|
|
|
# "ReportListDownload": {}, # Download a report
|
|
|
# "DayLogDownload": {}, # Download a report
|
|
|
# },
|
|
|
# },
|
|
|
# "Technical": { # Technical functions - for developers
|
|
|
# "GITUpdate": {}, # Action to update git repository
|
|
|
# "Start": {}, # Action for start robot
|
|
|
# "StopForce": {}, # Action for the stop force
|
|
|
# "StopSafe": {} # Actions for the safe stop
|
|
|
# }
|
|
|
# }
|
|
|
# }
|
|
|
# USAGE in .py
|
|
|
# inRequest.OpenRPA["DefUserRoleAccessAsk"](["Orchestrator","RDPActive","Controls"]) - return True or False
|
|
|
# inRequest.OpenRPA["DefUserRoleHierarchyGet"]() - Return dict of the role hierarchy or {}
|
|
|
gRuleDomainUserDict = {
|
|
|
"MethodMatchURLBeforeList": [
|
|
|
{"Method": "GET", "MatchType": "Beginwith", "URL": "/", "FlagAccess": True},
|
|
|
{"Method": "POST", "MatchType": "Beginwith", "URL": "/", "FlagAccess": True}
|
|
|
],
|
|
|
"ControlPanelKeyAllowedList": [gControlPanelKeyStr], # If empty - all is allowed ["RobotScreenActive", ""]
|
|
|
"RoleHierarchyAllowedDict": {
|
|
|
gRobotKeyStr:{
|
|
|
"Business": {
|
|
|
"ReportFileDocListDownload": {}, # Download a report
|
|
|
"ReportListDownload": {}, # Download a report
|
|
|
},
|
|
|
"Technical": { # Technical functions - for developers
|
|
|
"DayLogDownload": {}, # Download a report
|
|
|
# "GITUpdate": {}, # Action to update git repository
|
|
|
# "Start": {}, # Action for start robot
|
|
|
# "StopForce": {}, # Action for the stop force
|
|
|
# "StopSafe": {} # Actions for the safe stop
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#Orchestrator settings update
|
|
|
def SettingsUpdate(inGSettings):
|
|
|
# Add user roles
|
|
|
for lUserNameStr in gADLoginList:
|
|
|
# Case add domain + user
|
|
|
inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"].update({(gADDomainNameStr.upper(),lUserNameStr.upper()):gRuleDomainUserDict})
|
|
|
if gADDomainIsDefaultBool:
|
|
|
# Case add default domain + user
|
|
|
inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"].update({("",lUserNameStr.upper()):gRuleDomainUserDict})
|
|
|
#Add RobotRDPActive in control panel
|
|
|
inGSettings["ControlPanelDict"]["RobotList"].append({"RenderFunction": ControlPanelRenderDict, "KeyStr": gControlPanelKeyStr})
|
|
|
# Add folder to server to download files
|
|
|
lReportFolderItem = {
|
|
|
"Method": "GET",
|
|
|
"URL": f"/{gRobotKeyStr}/Reports/", # URL of the request
|
|
|
"MatchType": "BeginWith", # "BeginWith|Contains|Equal|EqualCase",
|
|
|
# "ResponseFilePath": "", #Absolute or relative path
|
|
|
"ResponseFolderPath": os.path.join(gBuildFolderPathStr, "Reports"),
|
|
|
# Absolute or relative path
|
|
|
"ResponseContentType": "application/octet-stream", #HTTP Content-type
|
|
|
# "ResponseDefRequestGlobal": None #Function with str result
|
|
|
}
|
|
|
inGSettings["Server"]["URLList"].append(lReportFolderItem)
|
|
|
# Add folder to server to download files
|
|
|
lReportFolderItem = {
|
|
|
"Method": "GET",
|
|
|
"URL": f"/{gRobotKeyStr}/Logs/", # URL of the request
|
|
|
"MatchType": "BeginWith", # "BeginWith|Contains|Equal|EqualCase",
|
|
|
# "ResponseFilePath": "", #Absolute or relative path
|
|
|
"ResponseFolderPath": os.path.join(gBuildFolderPathStr, "Logs"),
|
|
|
# Absolute or relative path
|
|
|
"ResponseContentType": "application/octet-stream", #HTTP Content-type
|
|
|
# "ResponseDefRequestGlobal": None #Function with str result
|
|
|
}
|
|
|
inGSettings["Server"]["URLList"].append(lReportFolderItem)
|
|
|
# AUTOSTART Robot
|
|
|
inGSettings["OrchestratorStart"]["ActivityList"].append(
|
|
|
{
|
|
|
"Type": "GlobalDictKeyListValueOperator+", #Activity type
|
|
|
"KeyList": ['RobotRDPActive','ActivityList'], # RobotRDP Active ActivityList
|
|
|
"Value": gActivityROBOTStartList # ActivityList - see upper
|
|
|
}
|
|
|
)
|
|
|
# Add scheduler activity in Scheduler.ActivityTimeList
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # #
|
|
|
lActivityTimeItemRobotStart = {
|
|
|
"TimeHH:MM": gActivityROBOTStartTimeHH_MMStr, #Time [HH:MM] to trigger activity
|
|
|
"WeekdayList": gActivityROBOTStartWeekdayList, #List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7]
|
|
|
"Activity":{
|
|
|
"Type": "GlobalDictKeyListValueSet", #Activity type
|
|
|
"KeyList": ['RobotRDPActive','ActivityList'], # RobotRDP Active ActivityList
|
|
|
"Value": gActivityROBOTStartList # ActivityList - see upper
|
|
|
}
|
|
|
}
|
|
|
inGSettings["Scheduler"]["ActivityTimeList"].append(lActivityTimeItemRobotStart)
|
|
|
for lItem in gActivityROBOTSafeStopList: # Temporary method while Scheduler apply only 1 activity in 1 item
|
|
|
inGSettings["Scheduler"]["ActivityTimeList"].append({
|
|
|
"TimeHH:MM": gActivityROBOTSafeStopTimeHH_MMStr, # Time [HH:MM] to trigger activity
|
|
|
"WeekdayList": gActivityROBOTSafeStopWeekdayList,
|
|
|
"Activity": lItem # Run actiovity 0 from list # List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7]
|
|
|
})
|
|
|
return inGSettings |