From d39ea067b172436d32053f618a53ab3018018eae Mon Sep 17 00:00:00 2001 From: Ivan Maslov Date: Fri, 26 Jun 2020 18:11:12 +0300 Subject: [PATCH] # Minor updates # TemplateControlPanel # TeplateSettings # Template CMD --- .../Settings/SettingsOrchestratorExample.py | 2 +- Orchestrator/Template_ControlPanel.py | 158 --------- Robot/Orchestrator_ControlPanel.py | 300 ++++++++++++++++++ Robot/pyRobotName_Settings.py | 122 +++++++ Robot/pyRobotName_x64_Run.cmd | 4 + 5 files changed, 427 insertions(+), 159 deletions(-) delete mode 100644 Orchestrator/Template_ControlPanel.py create mode 100644 Robot/Orchestrator_ControlPanel.py create mode 100644 Robot/pyRobotName_Settings.py create mode 100644 Robot/pyRobotName_x64_Run.cmd diff --git a/Orchestrator/Settings/SettingsOrchestratorExample.py b/Orchestrator/Settings/SettingsOrchestratorExample.py index f023aebc..8ea03d75 100644 --- a/Orchestrator/Settings/SettingsOrchestratorExample.py +++ b/Orchestrator/Settings/SettingsOrchestratorExample.py @@ -5,7 +5,7 @@ import sys # stdout fro logging import os # Init variables gControlPanelPyFilePathList = [ # .py file path list for call SettingsUpdate - r"" + #r"" ] def RenderRobotR01(inGlobalConfiguration): diff --git a/Orchestrator/Template_ControlPanel.py b/Orchestrator/Template_ControlPanel.py deleted file mode 100644 index 8e732156..00000000 --- a/Orchestrator/Template_ControlPanel.py +++ /dev/null @@ -1,158 +0,0 @@ -import psutil, datetime, logging, os, json -# # # # # # # ORCHESTRATOR CONTROL PANEL # # # # # # # -# Init parameters -gRobotStartFilePathStr = r"path\to\start\file" # path\to\start\file -gRobotProcessNameWOEXEStr = "process name" # RobotProcessName -gRobotADLoginStr = "Login" # Login of the robot session -gRobotADPasswordStr = "Password" # Password for session -gRobotKeyStr = "Robot_Template" -gRDPSessionKeyStr = "RDP_Template" -gRDPSessionHostStr = "localhost" # Rdp session host -gRDPSessionPortStr = "3389" # Default 3389 -gControlPanelKeyStr = "ControlPanel_Template" -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+["SafeTurnOffBool"] - -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# Activity list -## Robot START (create RDP session, send CMD to start process) -gActivityROBOTStartTimeHH_MMStr = "03:00" # 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 - } -] -## Robot FORCE STOP (send CMD to stop process, logoff) -gActivityROBOTStopTimeHH_MMStr = "08:00" # Time "HH:MM" [Server time] to execute activity, example "05:10" -gActivityROBOTStopWeekdayList = [0,1,2,3,4] # WeekdayList when atcivity is starting, default [0,1,2,3,4,5,6] -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 - } -] -# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# Function, which is generate Dict for front-endswith -def ControlPanelRenderDict(inGSettings): - """result={ - "HeaderLeftText":"", - "HeaderRightText":"
", - "DataStorageKey":"Robot_Name", #Use key for set current dict in mGlobal.DataStorage["DataStorageKey"] on client side - "SubheaderText": "State: Turned on", - "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.ServerValueOperatorPlus({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.ServerValueOperatorPlus({json.dumps(gOrchestratorToRobotResetSafeStopKeyList)},true);".replace("\"","\'") - ## Robot FORCE STOP (send CMD to stop process, logoff) - lActivityROBOTStopEscaped = f"mGlobal.Processor.ServerValueOperatorPlus({json.dumps(['RobotRDPActive','ActivityList'])},{json.dumps(gActivityROBOTStopList)});".replace("\"","\'") - # END :: Create activities :: END # - # START :: Init result dict template :: START # - # lBodyKeyValue_r3_start=f'Start' - lResultDict={ - "HeaderLeftText":"ROBOT KEYWORD", - "HeaderRightText":"ROBOT NAME", - "DataStorageKey":gControlPanelKeyStr, # CLIENT SIDE:: Use key for set current dict in mGlobal.DataStorage["DataStorageKey"] on client side - "SubheaderText":"", - "BodyKeyValueList":[ - {"Key":"Scheduler","Value":""}, - {"Key":"Start","Value":f"at {gActivityROBOTStartTimeHH_MMStr} in weekdays {gActivityROBOTStartWeekdayList}"}, - {"Key":"Stop (kill)","Value":f"at {gActivityROBOTStopTimeHH_MMStr} in weekdays {gActivityROBOTStopWeekdayList}"}, - {"Key":"Statistic","Value":""}, - {"Key":"...","Value":""} - ], - "FooterText":"Last update: 9:38:00 09.10.2019", - "FooterButtonX2List":[ - {"Text":"Turn on", "Color":"green", "Link":"", "OnClick": lActivityROBOTStartEscaped}, - {"Text":"Safe turn off", "Color":"orange", "Link":"", "OnClick": lActivityROBOTSafeStopEscaped} - ], - "FooterButtonX1List":[ - {"Text":"Kill", "Color":"red", "Link":"", "OnClick": lActivityROBOTStopEscaped} - ], - # "GlobalStorage": inGSettings.get("Storage",{}) # UNCOMMENT FOR DEBUG PURPOSE TO WATCH inGSettings on client side - } - # END :: Init result dict template :: END # - # START :: Fill BodyKeyValueList :: START # - - # END :: Fill BodyKeyValueList :: END # - # START :: Fill SubheaderText :: START # - ## FILL Robot state by the check the RDP session state - lSubheaderRunTrueText="State: Turned on" - lSubheaderRunFalseText="State: Turned off" - 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 -# # # # # # # # # # # # # # # # # # # # # # # # -# Scheduler to start/stop process -## Start ROBOT at time -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": "GlobalDictKeyListValueOperator+", #Activity type - "KeyList": ['RobotRDPActive','ActivityList'], # RobotRDP Active ActivityList - "Value": gActivityROBOTStartList # ActivityList - see upper - } -} -## Force stop ROBOT at time -lActivityTimeItemRobotStop = { - "TimeHH:MM": gActivityROBOTStopTimeHH_MMStr, #Time [HH:MM] to trigger activity - "WeekdayList": gActivityROBOTStopWeekdayList, #List of the weekday index when activity is applicable, Default [1,2,3,4,5,6,7] - "Activity":{ - "Type": "GlobalDictKeyListValueOperator+", #Activity type - "KeyList": ['RobotRDPActive','ActivityList'], # RobotRDP Active ActivityList - "Value": gActivityROBOTStopList # ActivityList - see upper - } -} -#Orchestrator settings update -def SettingsUpdate(inGSettings): - #Add RobotRDPActive in control panel - inGSettings["ControlPanelDict"]["RobotList"].append({"RenderFunction": ControlPanelRenderDict, "KeyStr": gControlPanelKeyStr}) - # Add scheduler activity in Scheduler.ActivityTimeList - inGSettings["Scheduler"]["ActivityTimeList"].append(lActivityTimeItemRobotStart) - inGSettings["Scheduler"]["ActivityTimeList"].append(lActivityTimeItemRobotStop) - return inGSettings \ No newline at end of file diff --git a/Robot/Orchestrator_ControlPanel.py b/Robot/Orchestrator_ControlPanel.py new file mode 100644 index 00000000..17541dfb --- /dev/null +++ b/Robot/Orchestrator_ControlPanel.py @@ -0,0 +1,300 @@ +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":"", + "HeaderRightText":"
", + "DataStorageKey":"Robot_Name", #Use key for set current dict in mGlobal.DataStorage["DataStorageKey"] on client side + "SubheaderText": "State: Turned on", + "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'Update GIT' + # Activity download report ReportFileDocList + lActivityReportDownloadHTML=f'Download' + # Activity download report ReportPTSList + lActivityReportListDownloadHTML=f'Download' + # END :: Create activities :: END # + + # START :: Init result dict template :: START # + # lBodyKeyValue_r3_start=f'Start' + 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":"", + "BodyKeyValueList":[ + {"Key":"Reports","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":"Additional","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'Download' + 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: Turned on" + lSubheaderRunFalseText="State: Turned off" + 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 \ No newline at end of file diff --git a/Robot/pyRobotName_Settings.py b/Robot/pyRobotName_Settings.py new file mode 100644 index 00000000..f87fb397 --- /dev/null +++ b/Robot/pyRobotName_Settings.py @@ -0,0 +1,122 @@ +#### Settings file - all initialization goes here! +import sys #For std operations +import logging #Logger for robot +import datetime #For test purpose +import os # os defs +import socket # Detect VM name +from pyOpenRPA.Robot import OrchestratorConnector # Lib for connection with orchestrator + +## # # # # # # # # # # # # # # # # ## +# GLOBAL PARAMETERS +gSettings = None +# Auto detect version which should be started +gHostnameVersionDict={ # Dict for versions + "MACHINE NAME DEV":"DEV", "MACHINE NAME TST":"TST", "MACHINE NAME PRD":"PRD" +} +gADLogin = "LOGIN"; gADPassword = "PASSWORD" +gResourceFullPath = os.path.join(os.getcwd(),"..\\Resources\\") +gSourceLocationRelative = r"..\Sources" # Path to Source folder, which contains package. Need if you want to import some py files from source package +sys.path.insert(0, os.path.abspath(gSourceLocationRelative)) # Add to has feature to import module from Source package pyPackageName +from pyPackage import pyModule # Import pyPackage from Source folder + +## # # # # # # # # # # # # # # # # ## +# ORCHESTRATOR CONNECTION PARAMETERS +lOrchestratorHost="localhost"; lOrchestratorPort=8080 +lOrchestratorProtocol="http"; lOrchestratorAuthToken="ORCHESTRATOR AUTH TOKEN" + +## # # # # # # # # # # # # # # # # ## +gVMHostNameStr = socket.gethostname().upper() # Get VM host name +gVersionStr = gHostnameVersionDict[gVMHostNameStr] # DEV Or TST or PRD +gCWDAbsPathStr = os.getcwd() + +## # # # # # # # # # # # # # # # # ## +# INIT GLOBAL DICT WITH ALL SETTINGS +if __name__ == "__main__": + gSettings={ + "VersionStr":gVersionStr, # DEV Or TST or PRD + "Package_1": { # package description + "TempFolderPath": os.path.abspath("Temp"), # Temp location settings + "Folder": { # Listen network folder + "FolderReadyPostfixStr":"Ready", # Folder ready postfix + "FolderPathList": [ # DEV is below. + { "PathStr": os.path.abspath(r"Test1"), "TypeStr": "TYPE1" }, + { "PathStr": os.path.abspath(r"Test2"), "TypeStr": "TYPE2" } + ] if gVersionStr == "DEV" else [ # DEV is upper, TST is below + {"PathStr": os.path.abspath(r"Test1"), "TypeStr": "TYPE1"}, + ] if gVersionStr == "TST" else [ # TST is upper, PRD is below + {"PathStr": os.path.abspath(r"Test2"), "TypeStr": "TYPE2"}, + ] if gVersionStr == "PRD" else [], # PRD is upper, None is below + }, + }, + "Package_2": { "Key1":"Value1" }, # package description + "Package_3": { "Key1":"Value1" }, # package description + "BI": { # BI TOOL TO COLLECT BUSINESS EFFECTS + "VersionStr": gVersionStr, # DEV, TST, PRD + "ADUserStr": gADLogin, # USER SESSION, where robot is starting + "VMNameStr": gVMHostNameStr # Test VM + }, + "Log": { # LOGGER + "Instance": logging.getLogger("pyFord"), + "ShowInConsoleBool" : True, #True - Show exception in console window + "FolderPathStr": f"Logs", #Folder path to save all logs + }, + "Orchestrator": { # ORCHESTRATOR + "Storage": { + "O2R_Reset": {}, # Orchestrator to robot reset storage + "R2O_Const": {}, # Robot to orchestrator constant storage + "O2R_Const": {} # Orchestrator to robot constant storage + }, + "TerminateDef": OrchestratorConnector.IntervalTerminateAll, # Call this function when program must be shutted down (to kill threads from OrchestratorConnector) + } + } + + ## # # # # # # # # # # # # # # # # ## + # ORCHESTRATOR CONNECTOR INIT + gSettings["OrchestratorConnector"]={ + "IntervalDataSendAsync": [ + #{ + # "Interval": 1.1, + # "RobotStorage": gSettings, + # "RobotStorageKey": "Statistics", + # "OrchestratorKeyList": ["Storage", "pyFord","RobotToOrchestrator","Statistics"], + # "OrchestratorProtocol": lOrchestratorProtocol, "OrchestratorHost": lOrchestratorHost, + # "OrchestratorPort": lOrchestratorPort, "OrchestratorAuthToken": lOrchestratorAuthToken + #} + ], + "IntervalDataReceiveResetAsync": [ + { + "Interval": 3, + "RobotStorage": gSettings, + "RobotStorageKey": "OrchestratorToRobotReset", + "RobotResetValue": {"TurnOffSafeBool":False}, + "OrchestratorKeyList": ["Storage", "pyFord","OrchestratorToRobotReset"], + "OrchestratorProtocol": lOrchestratorProtocol, "OrchestratorHost": lOrchestratorHost, + "OrchestratorPort": lOrchestratorPort, "OrchestratorAuthToken": lOrchestratorAuthToken + } + ], + "IntervalDataReceiveAsync": [ ] + } + OrchestratorConnector.LoggerSetLevelError() # Turn off many warnings from orchestrator connector logger + OrchestratorConnector.ConfigurationInit(gSettings["OrchestratorConnector"]) # Run OrchestratorConnector initialization + + ## # # # # # # # # # # # # # # # # ## + # LOGGER CONFIG + if not os.path.exists(gSettings["Log"]["FolderPathStr"]): + os.makedirs(gSettings["Log"]["FolderPathStr"]) + lL=gSettings["Log"]["Instance"] + lL.setLevel(logging.INFO if gVersionStr == "PRD" else logging.DEBUG) # Log debug if not prd + # create the logging file handler + lLFH = logging.FileHandler(os.path.join(gSettings["Log"]["FolderPathStr"], datetime.datetime.now().strftime("%Y_%m_%d") + ".log"), encoding ="UTF-8") + lLF = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + lLFH.setFormatter(lLF) + lL.addHandler(lLFH) # add handler to logger object + if gSettings["Log"]["ShowInConsoleBool"]: # Add console output + handler = logging.StreamHandler(sys.stdout); handler.setFormatter(lLF); lL.addHandler(handler) + + ## # # # # # # # # # # # # # # # # ## + # START ROBOT + lL.info("# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #") + lL.info("ROBOT NAME ITERATION START") + lL.info("# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #") + lL.info(f"VM host name: {gVMHostNameStr}, Program version {gVersionStr}, Working directory: {gCWDAbsPathStr}") # Init info + pyModule.pyModule(inGSettings = gSettings) # Execute main def in Source/pyPackage.pyModule.pyModule \ No newline at end of file diff --git a/Robot/pyRobotName_x64_Run.cmd b/Robot/pyRobotName_x64_Run.cmd new file mode 100644 index 00000000..4f34310f --- /dev/null +++ b/Robot/pyRobotName_x64_Run.cmd @@ -0,0 +1,4 @@ +cd %~dp0 +copy /Y ..\Resources\WPy64-3720\python-3.7.2.amd64\python.exe ..\Resources\WPy64-3720\python-3.7.2.amd64\pyRobotName.exe +..\Resources\WPy64-3720\python-3.7.2.amd64\pyRobotName.exe "pyRobotName_Settings.py" +pause >nul \ No newline at end of file