panda-server-source 0.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (375) hide show
  1. panda_server_source-0.8.0.dist-info/METADATA +55 -0
  2. panda_server_source-0.8.0.dist-info/RECORD +375 -0
  3. panda_server_source-0.8.0.dist-info/WHEEL +4 -0
  4. panda_server_source-0.8.0.dist-info/licenses/LICENSE.txt +202 -0
  5. pandajedi/__init__.py +0 -0
  6. pandajedi/jedibrokerage/AtlasAnalJobBroker.py +2343 -0
  7. pandajedi/jedibrokerage/AtlasBrokerUtils.py +1292 -0
  8. pandajedi/jedibrokerage/AtlasProdJobBroker.py +2064 -0
  9. pandajedi/jedibrokerage/AtlasProdTaskBroker.py +629 -0
  10. pandajedi/jedibrokerage/GenJobBroker.py +381 -0
  11. pandajedi/jedibrokerage/JobBrokerBase.py +133 -0
  12. pandajedi/jedibrokerage/TaskBrokerBase.py +15 -0
  13. pandajedi/jedibrokerage/__init__.py +0 -0
  14. pandajedi/jediconfig/__init__.py +0 -0
  15. pandajedi/jediconfig/jedi_config.py +40 -0
  16. pandajedi/jedicore/FactoryBase.py +182 -0
  17. pandajedi/jedicore/Interaction.py +433 -0
  18. pandajedi/jedicore/JediDBProxy.py +56 -0
  19. pandajedi/jedicore/JediDBProxyPool.py +37 -0
  20. pandajedi/jedicore/JediDBSchemaInfo.py +17 -0
  21. pandajedi/jedicore/JediException.py +13 -0
  22. pandajedi/jedicore/JediTaskBuffer.py +984 -0
  23. pandajedi/jedicore/JediTaskBufferInterface.py +50 -0
  24. pandajedi/jedicore/MsgWrapper.py +124 -0
  25. pandajedi/jedicore/ProcessUtils.py +34 -0
  26. pandajedi/jedicore/SiteCandidate.py +90 -0
  27. pandajedi/jedicore/ThreadUtils.py +205 -0
  28. pandajedi/jedicore/__init__.py +0 -0
  29. pandajedi/jediddm/AtlasDDMClient.py +1708 -0
  30. pandajedi/jediddm/DDMClientBase.py +16 -0
  31. pandajedi/jediddm/DDMInterface.py +83 -0
  32. pandajedi/jediddm/GenDDMClient.py +17 -0
  33. pandajedi/jediddm/__init__.py +0 -0
  34. pandajedi/jedidog/AtlasAnalWatchDog.py +648 -0
  35. pandajedi/jedidog/AtlasDataCarouselWatchDog.py +189 -0
  36. pandajedi/jedidog/AtlasDataLocalityUpdaterWatchDog.py +215 -0
  37. pandajedi/jedidog/AtlasProdWatchDog.py +443 -0
  38. pandajedi/jedidog/AtlasQueueFillerWatchDog.py +800 -0
  39. pandajedi/jedidog/AtlasTaskWithholderWatchDog.py +245 -0
  40. pandajedi/jedidog/AtlasWorkflowManagerWatchDog.py +63 -0
  41. pandajedi/jedidog/GenWatchDog.py +21 -0
  42. pandajedi/jedidog/JumboWatchDog.py +147 -0
  43. pandajedi/jedidog/TypicalWatchDogBase.py +122 -0
  44. pandajedi/jedidog/WatchDogBase.py +53 -0
  45. pandajedi/jedidog/__init__.py +0 -0
  46. pandajedi/jediexec/reniceJEDI.py +25 -0
  47. pandajedi/jedigen/AtlasTaskGenerator.py +110 -0
  48. pandajedi/jedigen/TaskGeneratorBase.py +15 -0
  49. pandajedi/jedigen/__init__.py +0 -0
  50. pandajedi/jedimsgprocessor/__init__.py +0 -0
  51. pandajedi/jedimsgprocessor/ai_parameter_adjuster_msg_processor +71 -0
  52. pandajedi/jedimsgprocessor/atlas_idds_msg_processor.py +66 -0
  53. pandajedi/jedimsgprocessor/base_msg_processor.py +33 -0
  54. pandajedi/jedimsgprocessor/forwarding_msg_processor.py +29 -0
  55. pandajedi/jedimsgprocessor/hpo_msg_processor.py +93 -0
  56. pandajedi/jedimsgprocessor/jedi_contents_feeder_msg_processor.py +63 -0
  57. pandajedi/jedimsgprocessor/jedi_job_generator_msg_processor.py +185 -0
  58. pandajedi/jedimsgprocessor/jedi_post_processor_msg_processor.py +82 -0
  59. pandajedi/jedimsgprocessor/kafka_msg_processor.py +44 -0
  60. pandajedi/jedimsgprocessor/panda_callback_msg_processor.py +182 -0
  61. pandajedi/jedimsgprocessor/panda_to_jedi_msg_processor.py +74 -0
  62. pandajedi/jedimsgprocessor/processing_msg_processor.py +134 -0
  63. pandajedi/jedimsgprocessor/status_report_msg_processor.py +129 -0
  64. pandajedi/jedimsgprocessor/tape_carousel_msg_processor.py +118 -0
  65. pandajedi/jedimsgprocessor/workflow_manager_msg_processor.py +89 -0
  66. pandajedi/jediorder/ContentsFeeder.py +785 -0
  67. pandajedi/jediorder/JediDaemon.py +27 -0
  68. pandajedi/jediorder/JediKnight.py +55 -0
  69. pandajedi/jediorder/JediMaster.py +238 -0
  70. pandajedi/jediorder/JediMsgProcessor.py +32 -0
  71. pandajedi/jediorder/JobBroker.py +33 -0
  72. pandajedi/jediorder/JobGenerator.py +2763 -0
  73. pandajedi/jediorder/JobSplitter.py +308 -0
  74. pandajedi/jediorder/JobThrottler.py +28 -0
  75. pandajedi/jediorder/PostProcessor.py +166 -0
  76. pandajedi/jediorder/TaskBroker.py +268 -0
  77. pandajedi/jediorder/TaskCommando.py +334 -0
  78. pandajedi/jediorder/TaskGenerator.py +17 -0
  79. pandajedi/jediorder/TaskRefiner.py +611 -0
  80. pandajedi/jediorder/TaskSetupper.py +17 -0
  81. pandajedi/jediorder/WatchDog.py +79 -0
  82. pandajedi/jediorder/__init__.py +0 -0
  83. pandajedi/jedipprocess/AtlasAnalPostProcessor.py +404 -0
  84. pandajedi/jedipprocess/AtlasPostProcessorUtils.py +50 -0
  85. pandajedi/jedipprocess/AtlasProdPostProcessor.py +178 -0
  86. pandajedi/jedipprocess/GenPostProcessor.py +35 -0
  87. pandajedi/jedipprocess/MailTemplates.py +185 -0
  88. pandajedi/jedipprocess/PostProcessorBase.py +269 -0
  89. pandajedi/jedipprocess/__init__.py +0 -0
  90. pandajedi/jedirefine/AtlasAnalTaskRefiner.py +259 -0
  91. pandajedi/jedirefine/AtlasProdTaskRefiner.py +162 -0
  92. pandajedi/jedirefine/GenTaskRefiner.py +61 -0
  93. pandajedi/jedirefine/RefinerUtils.py +154 -0
  94. pandajedi/jedirefine/TaskRefinerBase.py +996 -0
  95. pandajedi/jedirefine/__init__.py +0 -0
  96. pandajedi/jedisetup/AtlasTaskSetupper.py +309 -0
  97. pandajedi/jedisetup/GenTaskSetupper.py +16 -0
  98. pandajedi/jedisetup/SimpleTaskSetupper.py +152 -0
  99. pandajedi/jedisetup/TaskSetupperBase.py +15 -0
  100. pandajedi/jedisetup/__init__.py +0 -0
  101. pandajedi/jeditest/SchemaChecker.py +41 -0
  102. pandajedi/jeditest/addContWoSoTask.py +54 -0
  103. pandajedi/jeditest/addDataCarouselRequest.py +47 -0
  104. pandajedi/jeditest/addEventServiceTask.py +101 -0
  105. pandajedi/jeditest/addHpoTask.py +81 -0
  106. pandajedi/jeditest/addIDDSStageInRequest.py +56 -0
  107. pandajedi/jeditest/addNonAtlasTask.py +71 -0
  108. pandajedi/jeditest/addNonAtlasTaskEnc.py +64 -0
  109. pandajedi/jeditest/addTestTask.py +124 -0
  110. pandajedi/jeditest/addTestTaskParamToDEFT.py +70 -0
  111. pandajedi/jeditest/addTestTaskWithMerger.py +97 -0
  112. pandajedi/jeditest/brokerTest.py +78 -0
  113. pandajedi/jeditest/cancelDataCarouselRequest.py +35 -0
  114. pandajedi/jeditest/contentsFeederTest.py +28 -0
  115. pandajedi/jeditest/contentsFeederTestWithTask.py +18 -0
  116. pandajedi/jeditest/ddmTest.py +4 -0
  117. pandajedi/jeditest/jobGenForOneTask.py +38 -0
  118. pandajedi/jeditest/jobGeneratorTest.py +43 -0
  119. pandajedi/jeditest/jobSplitterTest.py +104 -0
  120. pandajedi/jeditest/jobThrottlerTest.py +22 -0
  121. pandajedi/jeditest/msgProcessorTest.py +9 -0
  122. pandajedi/jeditest/postProcessorTest.py +18 -0
  123. pandajedi/jeditest/resubmitDataCarouselRequest.py +35 -0
  124. pandajedi/jeditest/resubmitTaskParam.py +20 -0
  125. pandajedi/jeditest/taskBrokerTest.py +22 -0
  126. pandajedi/jeditest/taskBrokerTestWithTask.py +38 -0
  127. pandajedi/jeditest/taskBufferTest.py +5 -0
  128. pandajedi/jeditest/taskCommandoTest.py +28 -0
  129. pandajedi/jeditest/taskRefinerTest.py +30 -0
  130. pandajedi/jeditest/testOneTaskToRefine.py +49 -0
  131. pandajedi/jeditest/testOneTaskToTaskBroker.py +42 -0
  132. pandajedi/jeditest/testPandaDDMMap.py +62 -0
  133. pandajedi/jeditest/updateDataCarouselRequestParams.py +50 -0
  134. pandajedi/jeditest/watchDogTest.py +25 -0
  135. pandajedi/jeditest/workQueueTest.py +22 -0
  136. pandajedi/jedithrottle/AtlasAnalJobThrottler.py +19 -0
  137. pandajedi/jedithrottle/AtlasProdJobThrottler.py +18 -0
  138. pandajedi/jedithrottle/GenJobThrottler.py +26 -0
  139. pandajedi/jedithrottle/JobThrottlerBase.py +496 -0
  140. pandajedi/jedithrottle/__init__.py +0 -0
  141. pandaserver/__init__.py +0 -0
  142. pandaserver/api/__init__.py +0 -0
  143. pandaserver/api/v1/__init__.py +0 -0
  144. pandaserver/api/v1/common.py +339 -0
  145. pandaserver/api/v1/credential_management_api.py +372 -0
  146. pandaserver/api/v1/data_carousel_api.py +264 -0
  147. pandaserver/api/v1/event_api.py +269 -0
  148. pandaserver/api/v1/file_server_api.py +942 -0
  149. pandaserver/api/v1/harvester_api.py +445 -0
  150. pandaserver/api/v1/http_client.py +166 -0
  151. pandaserver/api/v1/idds_api.py +180 -0
  152. pandaserver/api/v1/job_api.py +463 -0
  153. pandaserver/api/v1/metaconfig_api.py +122 -0
  154. pandaserver/api/v1/pilot_api.py +895 -0
  155. pandaserver/api/v1/statistics_api.py +207 -0
  156. pandaserver/api/v1/system_api.py +186 -0
  157. pandaserver/api/v1/task_api.py +1520 -0
  158. pandaserver/api/v1/tests/__init__.py +0 -0
  159. pandaserver/api/v1/tests/credential_management_api_tests.py +116 -0
  160. pandaserver/api/v1/tests/data_carousel_api_tests.py +82 -0
  161. pandaserver/api/v1/tests/harvester_api_tests.py +188 -0
  162. pandaserver/api/v1/tests/idds_api_tests.py +45 -0
  163. pandaserver/api/v1/tests/job_api_tests.py +112 -0
  164. pandaserver/api/v1/tests/pilot_api_tests.py +154 -0
  165. pandaserver/api/v1/tests/statistics_api_tests.py +104 -0
  166. pandaserver/api/v1/tests/system_api_tests.py +58 -0
  167. pandaserver/api/v1/tests/task_api_tests.py +590 -0
  168. pandaserver/api/v1/version.py +2 -0
  169. pandaserver/api/v1/workflow_api.py +136 -0
  170. pandaserver/brokerage/SiteMapper.py +406 -0
  171. pandaserver/brokerage/__init__.py +0 -0
  172. pandaserver/brokerage/broker.py +272 -0
  173. pandaserver/config/__init__.py +0 -0
  174. pandaserver/config/config_utils.py +15 -0
  175. pandaserver/config/daemon_config.py +29 -0
  176. pandaserver/config/mcp_config.py +38 -0
  177. pandaserver/config/panda_config.py +233 -0
  178. pandaserver/configurator/Carbon.py +65 -0
  179. pandaserver/configurator/Configurator.py +908 -0
  180. pandaserver/configurator/__init__.py +0 -0
  181. pandaserver/configurator/aux.py +73 -0
  182. pandaserver/daemons/__init__.py +0 -0
  183. pandaserver/daemons/master.py +110 -0
  184. pandaserver/daemons/master_systemd.py +79 -0
  185. pandaserver/daemons/scripts/__init__.py +0 -0
  186. pandaserver/daemons/scripts/add_main.py +264 -0
  187. pandaserver/daemons/scripts/add_sub.py +221 -0
  188. pandaserver/daemons/scripts/cache_pilots.py +47 -0
  189. pandaserver/daemons/scripts/cache_schedconfig.py +286 -0
  190. pandaserver/daemons/scripts/carbon.py +50 -0
  191. pandaserver/daemons/scripts/configurator.py +94 -0
  192. pandaserver/daemons/scripts/copyArchive.py +1387 -0
  193. pandaserver/daemons/scripts/datasetManager.py +1154 -0
  194. pandaserver/daemons/scripts/dummy_test.py +25 -0
  195. pandaserver/daemons/scripts/evpPD2P.py +144 -0
  196. pandaserver/daemons/scripts/hs_scrapers.py +264 -0
  197. pandaserver/daemons/scripts/metric_collector.py +927 -0
  198. pandaserver/daemons/scripts/panda_activeusers_query.py +80 -0
  199. pandaserver/daemons/scripts/pilotStreaming.py +109 -0
  200. pandaserver/daemons/scripts/process_workflow_files_daemon.py +166 -0
  201. pandaserver/daemons/scripts/recover_lost_files_daemon.py +177 -0
  202. pandaserver/daemons/scripts/task_evaluator.py +405 -0
  203. pandaserver/daemons/scripts/tmpwatch.py +70 -0
  204. pandaserver/daemons/scripts/worker_synchronization.py +97 -0
  205. pandaserver/daemons/utils.py +753 -0
  206. pandaserver/dataservice/DataServiceUtils.py +323 -0
  207. pandaserver/dataservice/ErrorCode.py +25 -0
  208. pandaserver/dataservice/RecoverLostFilesCore.py +322 -0
  209. pandaserver/dataservice/__init__.py +0 -0
  210. pandaserver/dataservice/activator.py +79 -0
  211. pandaserver/dataservice/adder_atlas_plugin.py +1106 -0
  212. pandaserver/dataservice/adder_dummy_plugin.py +31 -0
  213. pandaserver/dataservice/adder_gen.py +954 -0
  214. pandaserver/dataservice/adder_plugin_base.py +27 -0
  215. pandaserver/dataservice/adder_result.py +75 -0
  216. pandaserver/dataservice/adder_simple_plugin.py +160 -0
  217. pandaserver/dataservice/closer.py +247 -0
  218. pandaserver/dataservice/closer_atlas_plugin.py +90 -0
  219. pandaserver/dataservice/ddm.py +1381 -0
  220. pandaserver/dataservice/ddm_handler.py +95 -0
  221. pandaserver/dataservice/dyn_data_distributer.py +824 -0
  222. pandaserver/dataservice/event_lookup_client_ei.py +77 -0
  223. pandaserver/dataservice/event_picker.py +268 -0
  224. pandaserver/dataservice/finisher.py +194 -0
  225. pandaserver/dataservice/setupper.py +225 -0
  226. pandaserver/dataservice/setupper_atlas_plugin.py +1851 -0
  227. pandaserver/dataservice/setupper_dummy_plugin.py +47 -0
  228. pandaserver/dataservice/setupper_plugin_base.py +67 -0
  229. pandaserver/jobdispatcher/DispatcherUtils.py +35 -0
  230. pandaserver/jobdispatcher/ErrorCode.py +19 -0
  231. pandaserver/jobdispatcher/JobDispatcher.py +1625 -0
  232. pandaserver/jobdispatcher/Protocol.py +443 -0
  233. pandaserver/jobdispatcher/Watcher.py +186 -0
  234. pandaserver/jobdispatcher/__init__.py +0 -0
  235. pandaserver/pandamcp/__init__.py +0 -0
  236. pandaserver/pandamcp/mcp_main.py +56 -0
  237. pandaserver/pandamcp/mcp_test_client.py +95 -0
  238. pandaserver/pandamcp/mcp_utils.py +74 -0
  239. pandaserver/proxycache/__init__.py +0 -0
  240. pandaserver/proxycache/panda_proxy_cache.py +240 -0
  241. pandaserver/proxycache/token_cache.py +141 -0
  242. pandaserver/server/.gacl +6 -0
  243. pandaserver/server/panda.py +539 -0
  244. pandaserver/srvcore/CoreUtils.py +572 -0
  245. pandaserver/srvcore/MailUtils.py +106 -0
  246. pandaserver/srvcore/__init__.py +0 -0
  247. pandaserver/srvcore/allowed_methods.py +100 -0
  248. pandaserver/srvcore/oidc_utils.py +152 -0
  249. pandaserver/srvcore/panda_request.py +196 -0
  250. pandaserver/srvcore/srv_msg_utils.py +42 -0
  251. pandaserver/taskbuffer/ConBridge.py +513 -0
  252. pandaserver/taskbuffer/DBProxyPool.py +95 -0
  253. pandaserver/taskbuffer/DataCarousel.py +3053 -0
  254. pandaserver/taskbuffer/DatasetSpec.py +137 -0
  255. pandaserver/taskbuffer/DdmSpec.py +201 -0
  256. pandaserver/taskbuffer/ErrorCode.py +87 -0
  257. pandaserver/taskbuffer/EventServiceUtils.py +396 -0
  258. pandaserver/taskbuffer/FileSpec.py +290 -0
  259. pandaserver/taskbuffer/GlobalShares.py +244 -0
  260. pandaserver/taskbuffer/HarvesterMetricsSpec.py +92 -0
  261. pandaserver/taskbuffer/Initializer.py +82 -0
  262. pandaserver/taskbuffer/InputChunk.py +1080 -0
  263. pandaserver/taskbuffer/JediCacheSpec.py +57 -0
  264. pandaserver/taskbuffer/JediDatasetSpec.py +588 -0
  265. pandaserver/taskbuffer/JediFileSpec.py +242 -0
  266. pandaserver/taskbuffer/JediTaskSpec.py +1687 -0
  267. pandaserver/taskbuffer/JobSpec.py +1006 -0
  268. pandaserver/taskbuffer/JobUtils.py +232 -0
  269. pandaserver/taskbuffer/NucleusSpec.py +116 -0
  270. pandaserver/taskbuffer/OraDBProxy.py +174 -0
  271. pandaserver/taskbuffer/PanDAMsgProcessor.py +8 -0
  272. pandaserver/taskbuffer/PandaDBSchemaInfo.py +18 -0
  273. pandaserver/taskbuffer/ParseJobXML.py +350 -0
  274. pandaserver/taskbuffer/PickleFileSpec.py +18 -0
  275. pandaserver/taskbuffer/PickleJobSpec.py +25 -0
  276. pandaserver/taskbuffer/PrioUtil.py +40 -0
  277. pandaserver/taskbuffer/ProcessGroups.py +111 -0
  278. pandaserver/taskbuffer/ResourceSpec.py +175 -0
  279. pandaserver/taskbuffer/SQLDumper.py +37 -0
  280. pandaserver/taskbuffer/SQLManager.py +60 -0
  281. pandaserver/taskbuffer/SiteSpec.py +304 -0
  282. pandaserver/taskbuffer/SupErrors.py +10 -0
  283. pandaserver/taskbuffer/TaskBuffer.py +2882 -0
  284. pandaserver/taskbuffer/TaskBufferInterface.py +163 -0
  285. pandaserver/taskbuffer/Utils.py +848 -0
  286. pandaserver/taskbuffer/WorkQueue.py +227 -0
  287. pandaserver/taskbuffer/WorkQueueMapper.py +203 -0
  288. pandaserver/taskbuffer/WorkerSpec.py +143 -0
  289. pandaserver/taskbuffer/WrappedCursor.py +487 -0
  290. pandaserver/taskbuffer/WrappedPickle.py +88 -0
  291. pandaserver/taskbuffer/WrappedPostgresConn.py +24 -0
  292. pandaserver/taskbuffer/__init__.py +0 -0
  293. pandaserver/taskbuffer/db_proxy_mods/OraDBProxy_structure.png +0 -0
  294. pandaserver/taskbuffer/db_proxy_mods/__init__.py +7 -0
  295. pandaserver/taskbuffer/db_proxy_mods/base_module.py +841 -0
  296. pandaserver/taskbuffer/db_proxy_mods/data_carousel_module.py +772 -0
  297. pandaserver/taskbuffer/db_proxy_mods/entity_module.py +3804 -0
  298. pandaserver/taskbuffer/db_proxy_mods/job_complex_module.py +5661 -0
  299. pandaserver/taskbuffer/db_proxy_mods/job_standalone_module.py +2640 -0
  300. pandaserver/taskbuffer/db_proxy_mods/metrics_module.py +874 -0
  301. pandaserver/taskbuffer/db_proxy_mods/misc_standalone_module.py +4272 -0
  302. pandaserver/taskbuffer/db_proxy_mods/task_complex_module.py +6172 -0
  303. pandaserver/taskbuffer/db_proxy_mods/task_event_module.py +4953 -0
  304. pandaserver/taskbuffer/db_proxy_mods/task_standalone_module.py +4999 -0
  305. pandaserver/taskbuffer/db_proxy_mods/task_utils_module.py +2063 -0
  306. pandaserver/taskbuffer/db_proxy_mods/worker_module.py +1944 -0
  307. pandaserver/taskbuffer/db_proxy_mods/workflow_module.py +832 -0
  308. pandaserver/taskbuffer/retryModule.py +552 -0
  309. pandaserver/taskbuffer/task_split_rules.py +308 -0
  310. pandaserver/taskbuffer/workflow_processor.py +249 -0
  311. pandaserver/taskbuffer/wrapped_oracle_conn.py +18 -0
  312. pandaserver/test/SchemaChecker.py +40 -0
  313. pandaserver/test/__init__.py +0 -0
  314. pandaserver/test/banUser.py +43 -0
  315. pandaserver/test/boostPrio.py +19 -0
  316. pandaserver/test/boostUser.py +35 -0
  317. pandaserver/test/callbackDDM.py +11 -0
  318. pandaserver/test/daod_on_demand.py +95 -0
  319. pandaserver/test/finishJob.py +184 -0
  320. pandaserver/test/finishTaskJEDI.py +11 -0
  321. pandaserver/test/getJobs.py +53 -0
  322. pandaserver/test/killJob.py +79 -0
  323. pandaserver/test/killJobLowPrio.py +99 -0
  324. pandaserver/test/killJobsInTask.py +56 -0
  325. pandaserver/test/killTask.py +80 -0
  326. pandaserver/test/killTaskJEDI.py +11 -0
  327. pandaserver/test/killUser.py +83 -0
  328. pandaserver/test/lsst/README.txt +7 -0
  329. pandaserver/test/lsst/lsstSubmit.py +139 -0
  330. pandaserver/test/lsst/lsstSubmitMERGEtest.py +141 -0
  331. pandaserver/test/lsst/lsstSubmitPhosim332.py +53 -0
  332. pandaserver/test/lsst/prepare-client-tarball-from-bigpanda-server.sh +41 -0
  333. pandaserver/test/reassignJobs.py +17 -0
  334. pandaserver/test/reassignSite.py +82 -0
  335. pandaserver/test/reassignTask.py +117 -0
  336. pandaserver/test/reassignWaiting.py +39 -0
  337. pandaserver/test/recoverLostFiles.py +7 -0
  338. pandaserver/test/reloadInputDS.py +51 -0
  339. pandaserver/test/sendCommandToJob.py +26 -0
  340. pandaserver/test/setDebugMode.py +38 -0
  341. pandaserver/test/setPriority.py +28 -0
  342. pandaserver/test/testEvgen.py +60 -0
  343. pandaserver/test/testEvgen17.py +58 -0
  344. pandaserver/test/testG4sim.py +81 -0
  345. pandaserver/test/testG4sim17.py +90 -0
  346. pandaserver/test/testGlobalShares.py +131 -0
  347. pandaserver/test/testReco.py +103 -0
  348. pandaserver/test/testSimulReco14.py +98 -0
  349. pandaserver/test/testSiteMap.py +26 -0
  350. pandaserver/test/testUpdateWorkerPilotStatus.py +9 -0
  351. pandaserver/userinterface/Client.py +1686 -0
  352. pandaserver/userinterface/UserIF.py +1799 -0
  353. pandaserver/userinterface/__init__.py +0 -0
  354. pandaserver/workflow/__init__.py +0 -0
  355. pandaserver/workflow/data_handler_plugins/base_data_handler.py +48 -0
  356. pandaserver/workflow/data_handler_plugins/ddm_collection_data_handler.py +100 -0
  357. pandaserver/workflow/data_handler_plugins/panda_task_data_handler.py +140 -0
  358. pandaserver/workflow/pcwl_test.py +122 -0
  359. pandaserver/workflow/pcwl_utils.py +384 -0
  360. pandaserver/workflow/psnakemake_container.json +68 -0
  361. pandaserver/workflow/psnakemake_task.json +62 -0
  362. pandaserver/workflow/psnakemake_test.py +60 -0
  363. pandaserver/workflow/snakeparser/__init__.py +3 -0
  364. pandaserver/workflow/snakeparser/extensions.py +74 -0
  365. pandaserver/workflow/snakeparser/log.py +53 -0
  366. pandaserver/workflow/snakeparser/names.py +3 -0
  367. pandaserver/workflow/snakeparser/parser.py +332 -0
  368. pandaserver/workflow/snakeparser/utils.py +29 -0
  369. pandaserver/workflow/step_handler_plugins/base_step_handler.py +85 -0
  370. pandaserver/workflow/step_handler_plugins/panda_task_step_handler.py +280 -0
  371. pandaserver/workflow/workflow_base.py +531 -0
  372. pandaserver/workflow/workflow_core.py +1974 -0
  373. pandaserver/workflow/workflow_core_smoketest.py +388 -0
  374. pandaserver/workflow/workflow_parser.py +222 -0
  375. pandaserver/workflow/workflow_utils.py +1047 -0
@@ -0,0 +1,388 @@
1
+ import argparse
2
+ import sys
3
+
4
+ from pandacommon.pandautils.thread_utils import GenericThread
5
+
6
+ from pandaserver.config import panda_config
7
+ from pandaserver.taskbuffer.TaskBuffer import taskBuffer
8
+
9
+
10
+ def parse_args():
11
+ parser = argparse.ArgumentParser(description="Workflow core smoke test helper")
12
+ parser.add_argument("action", choices=["cancel_workflow"], help="Action to perform in the smoke test")
13
+ parser.add_argument("--force", action="store_true", help="Force into cancelled status")
14
+ parser.add_argument("workflow_id", help="Workflow ID to use in commented smoke test calls")
15
+ return parser.parse_args()
16
+
17
+
18
+ # parameters for the workflow
19
+ # prodsourcelabel = "user"
20
+ # username = "testuser"
21
+ # workflow_name = "test_workflow_bg_comb_00"
22
+
23
+ # workflow definition json
24
+ # wfd_json = json.dumps(
25
+ # json.loads(
26
+ # """
27
+ # {
28
+ # "root_inputs": {
29
+ # "sig_bg_comb.cwl#background": "mc16_5TeV.361238.Pythia8EvtGen_A3NNPDF23LO_minbias_inelastic_low.merge.HITS.e6446_s3238_s3250/",
30
+ # "sig_bg_comb.cwl#signal": "mc16_valid:mc16_valid.900248.PG_singlepion_flatPt2to50.simul.HITS.e8312_s3238_tid26378578_00"
31
+ # },
32
+ # "root_outputs": {"sig_bg_comb.cwl#combine/outDS": {"value": "user.me.my_outDS_005_combine"}},
33
+ # "nodes": [
34
+ # {
35
+ # "condition": null,
36
+ # "data": null,
37
+ # "id": 1,
38
+ # "in_loop": false,
39
+ # "inputs": {
40
+ # "sig_bg_comb.cwl#make_signal/opt_args": {
41
+ # "default": "--outputs abc.dat,def.zip --nFilesPerJob 5",
42
+ # "source": null
43
+ # },
44
+ # "sig_bg_comb.cwl#make_signal/opt_containerImage": {
45
+ # "default": "docker://busybox",
46
+ # "source": null
47
+ # },
48
+ # "sig_bg_comb.cwl#make_signal/opt_exec": {
49
+ # "default": "echo %IN > abc.dat; echo 123 > def.zip",
50
+ # "source": null
51
+ # },
52
+ # "sig_bg_comb.cwl#make_signal/opt_inDS": {
53
+ # "default": null,
54
+ # "source": "sig_bg_comb.cwl#signal"
55
+ # }
56
+ # },
57
+ # "is_head": false,
58
+ # "is_leaf": true,
59
+ # "is_tail": false,
60
+ # "is_workflow_output": false,
61
+ # "loop": false,
62
+ # "name": "make_signal",
63
+ # "output_types": [],
64
+ # "outputs": {
65
+ # "sig_bg_comb.cwl#make_signal/outDS": {}
66
+ # },
67
+ # "parents": [],
68
+ # "root_inputs": null,
69
+ # "scatter": null,
70
+ # "sub_nodes": [],
71
+ # "task_params": null,
72
+ # "type": "prun",
73
+ # "upper_root_inputs": null
74
+ # },
75
+ # {
76
+ # "condition": null,
77
+ # "data": null,
78
+ # "id": 2,
79
+ # "in_loop": false,
80
+ # "inputs": {
81
+ # "sig_bg_comb.cwl#make_background_1/opt_args": {
82
+ # "default": "--outputs opq.root,xyz.pool --nGBPerJob 10",
83
+ # "source": null
84
+ # },
85
+ # "sig_bg_comb.cwl#make_background_1/opt_exec": {
86
+ # "default": "echo %IN > opq.root; echo %IN > xyz.pool",
87
+ # "source": null
88
+ # },
89
+ # "sig_bg_comb.cwl#make_background_1/opt_inDS": {
90
+ # "default": null,
91
+ # "source": "sig_bg_comb.cwl#background"
92
+ # }
93
+ # },
94
+ # "is_head": false,
95
+ # "is_leaf": true,
96
+ # "is_tail": false,
97
+ # "is_workflow_output": false,
98
+ # "loop": false,
99
+ # "name": "make_background_1",
100
+ # "output_types": [],
101
+ # "outputs": {
102
+ # "sig_bg_comb.cwl#make_background_1/outDS": {}
103
+ # },
104
+ # "parents": [],
105
+ # "root_inputs": null,
106
+ # "scatter": null,
107
+ # "sub_nodes": [],
108
+ # "task_params": null,
109
+ # "type": "prun",
110
+ # "upper_root_inputs": null
111
+ # },
112
+ # {
113
+ # "condition": null,
114
+ # "data": null,
115
+ # "id": 3,
116
+ # "in_loop": false,
117
+ # "inputs": {
118
+ # "sig_bg_comb.cwl#premix/opt_args": {
119
+ # "default": "--outputs klm.root --secondaryDSs IN2:2:%{SECDS1}",
120
+ # "source": null
121
+ # },
122
+ # "sig_bg_comb.cwl#premix/opt_exec": {
123
+ # "default": "echo %IN %IN2 > klm.root",
124
+ # "source": null
125
+ # },
126
+ # "sig_bg_comb.cwl#premix/opt_inDS": {
127
+ # "default": null,
128
+ # "parent_id": 1,
129
+ # "source": "sig_bg_comb.cwl#make_signal/outDS"
130
+ # },
131
+ # "sig_bg_comb.cwl#premix/opt_inDsType": {
132
+ # "default": "def.zip",
133
+ # "source": null
134
+ # },
135
+ # "sig_bg_comb.cwl#premix/opt_secondaryDSs": {
136
+ # "default": null,
137
+ # "parent_id": [
138
+ # 2
139
+ # ],
140
+ # "source": [
141
+ # "sig_bg_comb.cwl#make_background_1/outDS"
142
+ # ]
143
+ # },
144
+ # "sig_bg_comb.cwl#premix/opt_secondaryDsTypes": {
145
+ # "default": [
146
+ # "xyz.pool"
147
+ # ],
148
+ # "source": null
149
+ # }
150
+ # },
151
+ # "is_head": false,
152
+ # "is_leaf": true,
153
+ # "is_tail": false,
154
+ # "is_workflow_output": false,
155
+ # "loop": false,
156
+ # "name": "premix",
157
+ # "output_types": [],
158
+ # "outputs": {
159
+ # "sig_bg_comb.cwl#premix/outDS": {}
160
+ # },
161
+ # "parents": [
162
+ # 1,
163
+ # 2
164
+ # ],
165
+ # "root_inputs": null,
166
+ # "scatter": null,
167
+ # "sub_nodes": [],
168
+ # "task_params": null,
169
+ # "type": "prun",
170
+ # "upper_root_inputs": null
171
+ # },
172
+ # {
173
+ # "condition": null,
174
+ # "data": null,
175
+ # "id": 4,
176
+ # "in_loop": false,
177
+ # "inputs": {
178
+ # "sig_bg_comb.cwl#generate_some/opt_args": {
179
+ # "default": "--outputs gen.root --nJobs 10",
180
+ # "source": null
181
+ # },
182
+ # "sig_bg_comb.cwl#generate_some/opt_exec": {
183
+ # "default": "echo %RNDM:10 > gen.root",
184
+ # "source": null
185
+ # }
186
+ # },
187
+ # "is_head": false,
188
+ # "is_leaf": true,
189
+ # "is_tail": false,
190
+ # "is_workflow_output": false,
191
+ # "loop": false,
192
+ # "name": "generate_some",
193
+ # "output_types": [],
194
+ # "outputs": {
195
+ # "sig_bg_comb.cwl#generate_some/outDS": {}
196
+ # },
197
+ # "parents": [],
198
+ # "root_inputs": null,
199
+ # "scatter": null,
200
+ # "sub_nodes": [],
201
+ # "task_params": null,
202
+ # "type": "prun",
203
+ # "upper_root_inputs": null
204
+ # },
205
+ # {
206
+ # "condition": null,
207
+ # "data": null,
208
+ # "id": 5,
209
+ # "in_loop": false,
210
+ # "inputs": {
211
+ # "sig_bg_comb.cwl#make_background_2/opt_args": {
212
+ # "default": "--outputs ooo.root,jjj.txt --secondaryDSs IN2:2:%{SECDS1}",
213
+ # "source": null
214
+ # },
215
+ # "sig_bg_comb.cwl#make_background_2/opt_containerImage": {
216
+ # "default": "docker://alpine",
217
+ # "source": null
218
+ # },
219
+ # "sig_bg_comb.cwl#make_background_2/opt_exec": {
220
+ # "default": "echo %IN > ooo.root; echo %IN2 > jjj.txt",
221
+ # "source": null
222
+ # },
223
+ # "sig_bg_comb.cwl#make_background_2/opt_inDS": {
224
+ # "default": null,
225
+ # "source": "sig_bg_comb.cwl#background"
226
+ # },
227
+ # "sig_bg_comb.cwl#make_background_2/opt_secondaryDSs": {
228
+ # "default": null,
229
+ # "parent_id": [
230
+ # 4
231
+ # ],
232
+ # "source": [
233
+ # "sig_bg_comb.cwl#generate_some/outDS"
234
+ # ]
235
+ # },
236
+ # "sig_bg_comb.cwl#make_background_2/opt_secondaryDsTypes": {
237
+ # "default": [
238
+ # "gen.root"
239
+ # ],
240
+ # "source": null
241
+ # }
242
+ # },
243
+ # "is_head": false,
244
+ # "is_leaf": true,
245
+ # "is_tail": false,
246
+ # "is_workflow_output": false,
247
+ # "loop": false,
248
+ # "name": "make_background_2",
249
+ # "output_types": [],
250
+ # "outputs": {
251
+ # "sig_bg_comb.cwl#make_background_2/outDS": {}
252
+ # },
253
+ # "parents": [
254
+ # 4
255
+ # ],
256
+ # "root_inputs": null,
257
+ # "scatter": null,
258
+ # "sub_nodes": [],
259
+ # "task_params": null,
260
+ # "type": "prun",
261
+ # "upper_root_inputs": null
262
+ # },
263
+ # {
264
+ # "condition": null,
265
+ # "data": null,
266
+ # "id": 6,
267
+ # "in_loop": false,
268
+ # "inputs": {
269
+ # "sig_bg_comb.cwl#combine/opt_args": {
270
+ # "default": "--outputs aaa.root --secondaryDSs IN2:2:%{SECDS1},IN3:5:%{SECDS2}",
271
+ # "source": null
272
+ # },
273
+ # "sig_bg_comb.cwl#combine/opt_exec": {
274
+ # "default": "echo %IN %IN2 %IN3 > aaa.root",
275
+ # "source": null
276
+ # },
277
+ # "sig_bg_comb.cwl#combine/opt_inDS": {
278
+ # "default": null,
279
+ # "parent_id": 1,
280
+ # "source": "sig_bg_comb.cwl#make_signal/outDS"
281
+ # },
282
+ # "sig_bg_comb.cwl#combine/opt_inDsType": {
283
+ # "default": "abc.dat",
284
+ # "source": null
285
+ # },
286
+ # "sig_bg_comb.cwl#combine/opt_secondaryDSs": {
287
+ # "default": null,
288
+ # "parent_id": [
289
+ # 3,
290
+ # 5
291
+ # ],
292
+ # "source": [
293
+ # "sig_bg_comb.cwl#premix/outDS",
294
+ # "sig_bg_comb.cwl#make_background_2/outDS"
295
+ # ]
296
+ # },
297
+ # "sig_bg_comb.cwl#combine/opt_secondaryDsTypes": {
298
+ # "default": [
299
+ # "klm.root",
300
+ # "ooo.root"
301
+ # ],
302
+ # "source": null
303
+ # }
304
+ # },
305
+ # "is_head": false,
306
+ # "is_leaf": true,
307
+ # "is_tail": true,
308
+ # "is_workflow_output": false,
309
+ # "loop": false,
310
+ # "name": "combine",
311
+ # "output_types": [],
312
+ # "outputs": {
313
+ # "sig_bg_comb.cwl#combine/outDS": {}
314
+ # },
315
+ # "parents": [
316
+ # 1,
317
+ # 3,
318
+ # 5
319
+ # ],
320
+ # "root_inputs": null,
321
+ # "scatter": null,
322
+ # "sub_nodes": [],
323
+ # "task_params": null,
324
+ # "type": "prun",
325
+ # "upper_root_inputs": null
326
+ # }
327
+ # ]
328
+ # }
329
+ # """
330
+ # )
331
+ # )
332
+
333
+
334
+ def main():
335
+ args = parse_args()
336
+ WFID = args.workflow_id
337
+ action = args.action
338
+ force = args.force
339
+
340
+ from pandaserver.workflow.workflow_core import WorkflowInterface
341
+
342
+ # interface for workflow operations
343
+ requester_id = GenericThread().get_full_id(__name__, sys.modules[__name__].__file__)
344
+ taskBuffer.init(
345
+ panda_config.dbhost,
346
+ panda_config.dbpasswd,
347
+ nDBConnection=panda_config.nDBConnection,
348
+ useTimeout=True,
349
+ requester=requester_id,
350
+ )
351
+
352
+ wfif = WorkflowInterface(taskBuffer)
353
+
354
+ # Test cases for workflow core
355
+
356
+ # Register the workflow
357
+ # print("Registering workflow...")
358
+ # wf_spec = wfif.register_workflow(
359
+ # prodsourcelabel=prodsourcelabel,
360
+ # username=username,
361
+ # workflow_name=workflow_name,
362
+ # workflow_definition_json=wfd_json,
363
+ # )
364
+
365
+ # Process the registered workflow
366
+ # wf_spec = taskBuffer.get_workflow(workflow_id=WFID)
367
+ # print("Processing registered workflow...")
368
+ # wfif.process_workflow_registered(wf_spec)
369
+
370
+ # wf_spec = taskBuffer.get_workflow(workflow_id=WFID)
371
+ # print("Processing checked workflow...")
372
+ # wfif.process_workflow_checked(wf_spec)
373
+
374
+ # wf_spec = taskBuffer.get_workflow(workflow_id=WFID)
375
+ # print("Processing starting workflow...")
376
+ # wfif.process_workflow_starting(wf_spec)
377
+
378
+ if args.action == "cancel_workflow":
379
+ print(f"Cancelling workflow_id={WFID} ...")
380
+ res = wfif.cancel_workflow(workflow_id=WFID, force=args.force)
381
+ if res:
382
+ print(f"Cancelled workflow_id={WFID} successfully.")
383
+ else:
384
+ print(f"Failed to cancel workflow_id={WFID}.")
385
+
386
+
387
+ if __name__ == "__main__":
388
+ main()
@@ -0,0 +1,222 @@
1
+ import copy
2
+ import json
3
+ import os
4
+ import re
5
+ import shlex
6
+ import sys
7
+ import tarfile
8
+ import tempfile
9
+ import traceback
10
+
11
+ import requests
12
+ from idds.atlas.workflowv2.atlaslocalpandawork import ATLASLocalPandaWork
13
+ from idds.atlas.workflowv2.atlaspandawork import ATLASPandaWork
14
+ from idds.workflowv2.workflow import AndCondition, Condition, OrCondition, Workflow
15
+ from pandaclient import PhpoScript, PrunScript
16
+ from pandacommon.pandalogger.LogWrapper import LogWrapper
17
+ from pandacommon.pandalogger.PandaLogger import PandaLogger
18
+ from ruamel.yaml import YAML
19
+
20
+ # from pandaserver.srvcore.CoreUtils import clean_user_id
21
+ from pandaserver.workflow import pcwl_utils, workflow_utils
22
+ from pandaserver.workflow.snakeparser import Parser
23
+
24
+ # supported workflow description languages
25
+ SUPPORTED_WORKFLOW_LANGUAGES = ["cwl", "snakemake"]
26
+
27
+ # main logger
28
+ logger = PandaLogger().getLogger(__name__.split(".")[-1])
29
+
30
+
31
+ # ==============================================================================
32
+ # Native PanDA workflow functions
33
+ # ==============================================================================
34
+
35
+
36
+ def json_serialize_default(obj):
37
+ """
38
+ Default JSON serializer for non-serializable objects of Node object
39
+
40
+ Args:
41
+ obj (Any): Object to serialize
42
+
43
+ Returns:
44
+ Any: JSON serializable object
45
+ """
46
+ # convert set to list
47
+ if isinstance(obj, set):
48
+ return list(obj)
49
+ elif isinstance(obj, workflow_utils.Node):
50
+ return obj.id
51
+ return obj
52
+
53
+
54
+ def parse_raw_request(sandbox_url, log_token, user_name, raw_request_dict) -> tuple[bool, bool, dict]:
55
+ """
56
+ Parse raw request with files in sandbox into workflow definition
57
+
58
+ Args:
59
+ sandbox_url (str): URL to download sandbox
60
+ log_token (str): Log token
61
+ user_name (str): User name
62
+ raw_request_dict (dict): Raw request dictionary
63
+
64
+ Returns:
65
+ bool: Whether the parsing is successful
66
+ bool: Whether the failure is fatal
67
+ dict: Workflow definition dictionary
68
+ """
69
+ tmp_log = LogWrapper(logger, log_token)
70
+ is_ok = True
71
+ is_fatal = False
72
+ # request_id = None
73
+ workflow_definition_dict = dict()
74
+
75
+ def _is_within_directory(base_dir: str, target_path: str) -> bool:
76
+ abs_base_dir = os.path.abspath(base_dir)
77
+ abs_target_path = os.path.abspath(target_path)
78
+ return os.path.commonpath([abs_base_dir, abs_target_path]) == abs_base_dir
79
+
80
+ def _safe_extract_tar_gz(tar_path: str, extract_dir: str):
81
+ with tarfile.open(tar_path, mode="r:gz") as tar:
82
+ members = tar.getmembers()
83
+ for member in members:
84
+ member_name = member.name
85
+ normalized_name = os.path.normpath(member_name)
86
+ # security checks for tar member name
87
+ if os.path.isabs(member_name):
88
+ raise ValueError(f"absolute path in tar member is not allowed: {member_name}")
89
+ if normalized_name in ("", ".", "..") or normalized_name.startswith(".." + os.path.sep):
90
+ raise ValueError(f"path traversal in tar member is not allowed: {member_name}")
91
+ if member.issym() or member.islnk():
92
+ raise ValueError(f"links in tar archive are not allowed: {member_name}")
93
+ if member.ischr() or member.isblk() or member.isfifo():
94
+ raise ValueError(f"special file in tar archive is not allowed: {member_name}")
95
+ # check that the extraction target is within the extract_dir
96
+ extraction_target = os.path.join(extract_dir, normalized_name)
97
+ if not _is_within_directory(extract_dir, extraction_target):
98
+ raise ValueError(f"tar member extracts outside target directory: {member_name}")
99
+ # all checks passed, safe to extract
100
+ tar.extractall(path=extract_dir, members=members)
101
+
102
+ try:
103
+ # use an isolated temp dir without changing process cwd
104
+ with tempfile.TemporaryDirectory() as tmp_dirname:
105
+ # download sandbox
106
+ tmp_log.info(f"downloading sandbox from {sandbox_url}")
107
+ with requests.get(sandbox_url, allow_redirects=True, stream=True) as r:
108
+ if r.status_code == 400:
109
+ tmp_log.error("not found")
110
+ is_fatal = True
111
+ is_ok = False
112
+ elif r.status_code != 200:
113
+ tmp_log.error(f"bad HTTP response {r.status_code}")
114
+ is_ok = False
115
+ # validate sandbox filename
116
+ sandbox_name = raw_request_dict.get("sandbox")
117
+ if is_ok:
118
+ if not isinstance(sandbox_name, str):
119
+ tmp_log.error("sandbox filename is missing or not a string")
120
+ is_fatal = True
121
+ is_ok = False
122
+ else:
123
+ # sandbox filename must not contain any path separators
124
+ seps = [os.path.sep]
125
+ if os.path.altsep:
126
+ seps.append(os.path.altsep)
127
+ if any(sep in sandbox_name for sep in seps):
128
+ tmp_log.error("sandbox filename must not contain path separators")
129
+ is_fatal = True
130
+ is_ok = False
131
+ else:
132
+ sandbox_name = os.path.basename(sandbox_name)
133
+ # extract sandbox
134
+ if is_ok:
135
+ sandbox_path = os.path.join(tmp_dirname, sandbox_name)
136
+ with open(sandbox_path, "wb") as fs:
137
+ for chunk in r.raw.stream(1024, decode_content=False):
138
+ if chunk:
139
+ fs.write(chunk)
140
+ fs.close()
141
+ try:
142
+ _safe_extract_tar_gz(sandbox_path, tmp_dirname)
143
+ except Exception as e:
144
+ dump_str = f"failed to extract {sandbox_name}: {traceback.format_exc()}"
145
+ tmp_log.error(dump_str)
146
+ is_fatal = True
147
+ is_ok = False
148
+ # parse workflow files
149
+ if is_ok:
150
+ tmp_log.info("parse workflow")
151
+ workflow_name = None
152
+ if (wf_lang := raw_request_dict["language"]) in SUPPORTED_WORKFLOW_LANGUAGES:
153
+ if wf_lang == "cwl":
154
+ workflow_name = raw_request_dict.get("workflow_name")
155
+ workflow_spec_file = os.path.join(tmp_dirname, raw_request_dict["workflowSpecFile"])
156
+ workflow_input_file = os.path.join(tmp_dirname, raw_request_dict["workflowInputFile"])
157
+ nodes, root_in = pcwl_utils.parse_workflow_file(workflow_spec_file, tmp_log)
158
+ with open(workflow_input_file) as workflow_input:
159
+ yaml = YAML(typ="safe", pure=True)
160
+ data = yaml.load(workflow_input)
161
+ elif wf_lang == "snakemake":
162
+ workflow_spec_file = os.path.join(tmp_dirname, raw_request_dict["workflowSpecFile"])
163
+ parser = Parser(workflow_spec_file, logger=tmp_log)
164
+ nodes, root_in = parser.parse_nodes()
165
+ data = dict()
166
+ # resolve nodes
167
+ s_id, t_nodes, nodes = workflow_utils.resolve_nodes(nodes, root_in, data, 0, set(), raw_request_dict["outDS"], tmp_log)
168
+ workflow_utils.set_workflow_outputs(nodes)
169
+ id_node_map = workflow_utils.get_node_id_map(nodes)
170
+ [node.resolve_params(raw_request_dict["taskParams"], id_node_map) for node in nodes]
171
+ dump_str = "the description was internally converted as follows\n" + workflow_utils.dump_nodes(nodes)
172
+ tmp_log.info(dump_str)
173
+ for node in nodes:
174
+ s_check, o_check = node.verify()
175
+ tmp_str = f"Verification failure in ID:{node.id} {o_check}"
176
+ if not s_check:
177
+ tmp_log.error(tmp_str)
178
+ dump_str += tmp_str
179
+ dump_str += "\n"
180
+ is_fatal = True
181
+ is_ok = False
182
+ else:
183
+ dump_str = f"{wf_lang} is not supported to describe the workflow"
184
+ tmp_log.error(dump_str)
185
+ is_fatal = True
186
+ is_ok = False
187
+ # genertate workflow definition
188
+ if is_ok:
189
+ # root inputs
190
+ root_inputs_dict = dict()
191
+ for k in root_in:
192
+ kk = k.split("#")[-1]
193
+ if kk in data:
194
+ root_inputs_dict[k] = data[kk]
195
+ # root outputs
196
+ root_outputs_dict = dict()
197
+ nodes_list = []
198
+ # nodes
199
+ for node in nodes:
200
+ nodes_list.append(vars(node))
201
+ if node.is_tail:
202
+ root_outputs_dict.update(node.outputs)
203
+ for out_val in root_outputs_dict.values():
204
+ out_val["output_types"] = node.output_types
205
+ # workflow definition
206
+ workflow_definition_dict = {
207
+ "workflow_name": workflow_name,
208
+ "user_name": user_name,
209
+ "root_inputs": root_inputs_dict,
210
+ "root_outputs": root_outputs_dict,
211
+ "nodes": nodes_list,
212
+ }
213
+ except Exception as e:
214
+ is_ok = False
215
+ is_fatal = True
216
+ tmp_log.error(f"failed to run with {str(e)} {traceback.format_exc()}")
217
+
218
+ # with tempfile.NamedTemporaryFile(delete=False, mode="w") as tmp_json:
219
+ # json.dump([is_ok, is_fatal, request_id, tmp_log.dumpToString()], tmp_json)
220
+ # print(tmp_json.name)
221
+
222
+ return is_ok, is_fatal, workflow_definition_dict