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,443 @@
1
+ import copy
2
+ import os
3
+ import socket
4
+ import sys
5
+ import traceback
6
+
7
+ from pandacommon.pandalogger.PandaLogger import PandaLogger
8
+
9
+ from pandajedi.jedibrokerage import AtlasBrokerUtils
10
+ from pandajedi.jediconfig import jedi_config
11
+ from pandajedi.jedicore.MsgWrapper import MsgWrapper
12
+ from pandaserver.dataservice import DataServiceUtils
13
+ from pandaserver.srvcore import CoreUtils
14
+ from pandaserver.taskbuffer import JediTaskSpec, JobUtils
15
+
16
+ from .JumboWatchDog import JumboWatchDog
17
+ from .TypicalWatchDogBase import TypicalWatchDogBase
18
+
19
+ logger = PandaLogger().getLogger(__name__.split(".")[-1])
20
+
21
+
22
+ # watchdog for ATLAS production
23
+ class AtlasProdWatchDog(TypicalWatchDogBase):
24
+ # constructor
25
+ def __init__(self, taskBufferIF, ddmIF):
26
+ TypicalWatchDogBase.__init__(self, taskBufferIF, ddmIF)
27
+ self.pid = f"{socket.getfqdn().split('.')[0]}-{os.getpid()}-dog"
28
+
29
+ # main
30
+ def doAction(self):
31
+ try:
32
+ # get logger
33
+ tmpLog = MsgWrapper(logger)
34
+ tmpLog.debug("start")
35
+
36
+ # actions based on task progress
37
+ self.do_task_progress_based_actions(tmpLog)
38
+
39
+ # action for reassign
40
+ self.doActionForReassign(tmpLog)
41
+
42
+ # action for throttled
43
+ self.doActionForThrottled(tmpLog)
44
+
45
+ # action for high prio pending
46
+ for minPriority, timeoutVal in [
47
+ (950, 10),
48
+ (900, 30),
49
+ ]:
50
+ self.doActionForHighPrioPending(tmpLog, minPriority, timeoutVal)
51
+
52
+ # action to set scout job data w/o scouts
53
+ self.doActionToSetScoutJobData(tmpLog)
54
+
55
+ # action to throttle jobs in paused tasks
56
+ self.doActionToThrottleJobInPausedTasks(tmpLog)
57
+
58
+ # action for jumbo
59
+ jumbo = JumboWatchDog(self.taskBufferIF, self.ddmIF, tmpLog, "atlas", "managed")
60
+ jumbo.run()
61
+
62
+ # action to provoke (mark files ready) data carousel tasks to start if DDM rules of input DS are done
63
+ self.doActionToProvokeDCTasks(tmpLog)
64
+
65
+ except Exception:
66
+ errtype, errvalue = sys.exc_info()[:2]
67
+ tmpLog.error(f"failed with {errtype.__name__}:{errvalue} {traceback.format_exc()}")
68
+ # return
69
+ tmpLog.debug("done")
70
+ return self.SC_SUCCEEDED
71
+
72
+ # actions based on task progress
73
+ def do_task_progress_based_actions(self, g_tmp_log: MsgWrapper) -> None:
74
+ """
75
+ Take actions based on task progress
76
+ 1) boost priority of tasks which have finished >95% of input files and have <=100 remaining jobs to prio 900
77
+ 2) reassign such tasks to Express global share if not already
78
+ 3) pause tasks with high failure rate
79
+
80
+ :param g_tmp_log: logger
81
+ :return: None
82
+ """
83
+ # get work queue mapper
84
+ workQueueMapper = self.taskBufferIF.getWorkQueueMap()
85
+ # get list of work queues
86
+ workQueueList = workQueueMapper.getAlignedQueueList(self.vo, self.prodSourceLabel)
87
+ resource_types = self.taskBufferIF.load_resource_types()
88
+
89
+ # get config values
90
+ failure_checker = "watchdog"
91
+ max_job_failure_rate_key = f"MAX_JOB_FAILURE_RATE_TO_PAUSE_{self.prodSourceLabel}"
92
+ max_job_failure_rate_base = self.taskBufferIF.getConfigValue(failure_checker, max_job_failure_rate_key, "jedi")
93
+ max_hep_score_failure_rate_key = f"MAX_HEP_SCORE_FAILURE_RATE_TO_PAUSE_{self.prodSourceLabel}"
94
+ max_hep_score_failure_rate_base = self.taskBufferIF.getConfigValue(failure_checker, max_hep_score_failure_rate_key, "jedi")
95
+ min_jobs_to_pause_key = f"MIN_JOBS_TO_PAUSE_{self.prodSourceLabel}"
96
+ min_jobs_to_pause = self.taskBufferIF.getConfigValue(failure_checker, min_jobs_to_pause_key, "jedi")
97
+ if min_jobs_to_pause is None:
98
+ min_jobs_to_pause = 1000
99
+ min_remaining_jobs_to_pause_key = f"MIN_REMAINING_JOBS_TO_PAUSE_{self.prodSourceLabel}"
100
+ min_remaining_jobs_to_pause = self.taskBufferIF.getConfigValue(failure_checker, min_remaining_jobs_to_pause_key, "jedi")
101
+ if min_remaining_jobs_to_pause is None:
102
+ min_remaining_jobs_to_pause = 100
103
+
104
+ # loop over all work queues
105
+ g_tmp_log.debug("start do_task_progress_based_actions")
106
+ for workQueue in workQueueList:
107
+ break_loop = False # for special workqueues we only need to iterate once
108
+ for resource_type in resource_types:
109
+ g_tmp_log.debug(f"start workQueue={workQueue.queue_name} resource_type={resource_type.resource_name}")
110
+ # get tasks to be boosted
111
+ if workQueue.is_global_share:
112
+ task_criteria = {"gshare": workQueue.queue_name, "resource_type": resource_type.resource_name}
113
+ else:
114
+ break_loop = True
115
+ task_criteria = {"workQueue_ID": workQueue.queue_id}
116
+
117
+ # define max failure rate
118
+ max_job_failure_rate = self.taskBufferIF.getConfigValue(failure_checker, f"{max_job_failure_rate_key}_{workQueue.queue_name}", "jedi")
119
+ if max_job_failure_rate is None:
120
+ max_job_failure_rate = max_job_failure_rate_base
121
+ max_hep_score_failure_rate = self.taskBufferIF.getConfigValue(
122
+ failure_checker, f"{max_hep_score_failure_rate_key}_{workQueue.queue_name}", "jedi"
123
+ )
124
+ if max_hep_score_failure_rate is None:
125
+ max_hep_score_failure_rate = max_hep_score_failure_rate_base
126
+
127
+ dataset_criteria = {"masterID": None, "type": ["input", "pseudo_input"]}
128
+ task_param_list = ["jediTaskID", "currentPriority", "parent_tid", "gshare", "requestType", "splitRule"]
129
+ dataset_param_list = ["nFiles", "nFilesUsed", "nFilesTobeUsed", "nFilesFinished", "nFilesFailed"]
130
+ taskVarList = self.taskBufferIF.getTasksWithCriteria_JEDI(
131
+ self.vo,
132
+ self.prodSourceLabel,
133
+ ["running"],
134
+ taskCriteria=task_criteria,
135
+ datasetCriteria=dataset_criteria,
136
+ taskParamList=task_param_list,
137
+ datasetParamList=dataset_param_list,
138
+ taskLockColumn="throttledTime",
139
+ taskLockInterval=20,
140
+ )
141
+ boostedPrio = 900
142
+ toBoostRatio = 0.95
143
+ for taskParam, datasetParam in taskVarList:
144
+ jediTaskID = taskParam["jediTaskID"]
145
+ currentPriority = taskParam["currentPriority"]
146
+ parent_tid = taskParam["parent_tid"]
147
+ gshare = taskParam["gshare"]
148
+ request_type = taskParam["requestType"]
149
+ split_rule = taskParam["splitRule"]
150
+ # check parent
151
+ parentState = None
152
+ if parent_tid not in [None, jediTaskID]:
153
+ parentState = self.taskBufferIF.checkParentTask_JEDI(parent_tid, jediTaskID)
154
+ if parentState != "completed":
155
+ g_tmp_log.info(
156
+ f"#ATM #KV label={self.prodSourceLabel} jediTaskID={jediTaskID} skip prio boost since parent_id={parent_tid} has parent_status={parentState}"
157
+ )
158
+ continue
159
+ nFiles = datasetParam["nFiles"]
160
+ nFilesFinished = datasetParam["nFilesFinished"]
161
+ nFilesFailed = datasetParam["nFilesFailed"]
162
+ # get num jobs
163
+ nJobs = self.taskBufferIF.getNumJobsForTask_JEDI(jediTaskID)
164
+ nRemJobs = None
165
+ if nJobs is not None:
166
+ try:
167
+ nRemJobs = int(float(nFiles - nFilesFinished - nFilesFailed) * float(nJobs) / float(nFiles))
168
+ except Exception:
169
+ pass
170
+ failure_metrics = self.taskBufferIF.get_task_failure_metrics(jediTaskID)
171
+
172
+ tmpStr = f"jediTaskID={jediTaskID} nFiles={nFiles} nFilesFinishedFailed={nFilesFinished + nFilesFailed} "
173
+ tmpStr += f"nJobs={nJobs} nRemJobs={nRemJobs} parent_tid={parent_tid} parentStatus={parentState} failure_metrics={failure_metrics}"
174
+ g_tmp_log.debug(tmpStr)
175
+
176
+ try:
177
+ if nRemJobs is not None and float(nFilesFinished + nFilesFailed) / float(nFiles) >= toBoostRatio and nRemJobs <= 100:
178
+ # skip high enough
179
+ if currentPriority < boostedPrio:
180
+ g_tmp_log.info(
181
+ f" >>> action=priority_boosting of jediTaskID={jediTaskID} to priority={boostedPrio} #ATM #KV label={self.prodSourceLabel} "
182
+ )
183
+ self.taskBufferIF.changeTaskPriorityPanda(jediTaskID, boostedPrio)
184
+
185
+ # skip express or non global share
186
+ newShare = "Express"
187
+ newShareType = self.prodSourceLabel
188
+ if gshare != newShare and workQueue.is_global_share and workQueue.queue_type == newShareType:
189
+ g_tmp_log.info(
190
+ f" >>> action=gshare_reassignment jediTaskID={jediTaskID} from gshare_old={gshare} to gshare_new={newShare} #ATM #KV label={self.prodSourceLabel}"
191
+ )
192
+ self.taskBufferIF.reassignShare([jediTaskID], newShare, True)
193
+ g_tmp_log.debug(f"reassigned jediTaskID={jediTaskID}")
194
+ except Exception:
195
+ pass
196
+
197
+ # check failure rate
198
+ failure_key = None
199
+ bad_value = None
200
+ if JediTaskSpec.is_auto_pause_disabled(split_rule):
201
+ # auto pause disabled
202
+ pass
203
+ elif not failure_metrics:
204
+ # failure metrics is unavailable
205
+ pass
206
+ elif nJobs is None or nJobs < min_jobs_to_pause:
207
+ # total num jobs is small
208
+ pass
209
+ elif nRemJobs is None or nRemJobs < min_remaining_jobs_to_pause:
210
+ # remaining num jobs is small
211
+ pass
212
+ elif (
213
+ max_job_failure_rate is not None
214
+ and failure_metrics["single_failure_rate"] is not None
215
+ and failure_metrics["single_failure_rate"] >= max_job_failure_rate > 0
216
+ ):
217
+ # job failure rate is high
218
+ failure_key = "single_failure_rate"
219
+ bad_value = failure_metrics[failure_key]
220
+ g_tmp_log.info(
221
+ f" >>> action=pausing_high_failure_rate jediTaskID={jediTaskID} job_failure_rate={bad_value:.2f} "
222
+ f"(max_allowed={max_job_failure_rate}) #ATM #KV label={self.prodSourceLabel}"
223
+ )
224
+ self.taskBufferIF.sendCommandTaskPanda(
225
+ jediTaskID, f"{failure_checker} due to high job failure rate {bad_value:.2f} > {max_job_failure_rate}", True, "pause"
226
+ )
227
+ elif (
228
+ max_hep_score_failure_rate is not None
229
+ and failure_metrics["hep_score_failure_rate"] is not None
230
+ and failure_metrics["hep_score_failure_rate"] >= max_hep_score_failure_rate > 0
231
+ ):
232
+ # failed HEP score rate is high
233
+ failure_key = "hep_score_failure_rate"
234
+ bad_value = failure_metrics[failure_key]
235
+ g_tmp_log.info(
236
+ f" >>> action=pausing_high_failure_rate jediTaskID={jediTaskID} hep_score_failure_rate={bad_value:.2f} "
237
+ f"(max_allowed={max_hep_score_failure_rate}) #ATM #KV label={self.prodSourceLabel}"
238
+ )
239
+ self.taskBufferIF.sendCommandTaskPanda(
240
+ jediTaskID, f"{failure_checker} due to high HEP score failure rate {bad_value:.2f} > {max_hep_score_failure_rate}", True, "pause"
241
+ )
242
+ if failure_key is not None:
243
+ # get tasks with the same requestType to be paused
244
+ if request_type:
245
+ task_criteria = copy.copy(task_criteria)
246
+ task_criteria["requestType"] = request_type
247
+ tasks_with_same_request_type = self.taskBufferIF.getTasksWithCriteria_JEDI(
248
+ self.vo,
249
+ self.prodSourceLabel,
250
+ ["running"],
251
+ taskCriteria=task_criteria,
252
+ taskParamList=["jediTaskID", "splitRule"],
253
+ )
254
+ for other_task_param, _ in tasks_with_same_request_type:
255
+ other_jedi_task_id = other_task_param["jediTaskID"]
256
+ # auto pause disabled
257
+ if JediTaskSpec.is_auto_pause_disabled(other_jedi_task_id):
258
+ continue
259
+ if other_jedi_task_id != jediTaskID:
260
+ g_tmp_log.info(
261
+ f" >>> action=pausing_high_failure_rate jediTaskID={other_jedi_task_id} due to requestType={request_type} shared by {jediTaskID} "
262
+ f"#ATM #KV label={self.prodSourceLabel}"
263
+ )
264
+ if failure_key == "single_failure_rate":
265
+ msg = f"{failure_checker} due to high job failure rate in another task {jediTaskID} ({bad_value:.2f} > {max_job_failure_rate})"
266
+ else:
267
+ msg = f"{failure_checker} due to high HEP score failure rate in another task {jediTaskID} ({bad_value:.2f} > {max_hep_score_failure_rate})"
268
+ self.taskBufferIF.sendCommandTaskPanda(
269
+ other_jedi_task_id,
270
+ msg,
271
+ True,
272
+ "pause",
273
+ )
274
+ g_tmp_log.debug(f"paused jediTaskID={jediTaskID}")
275
+
276
+ if break_loop:
277
+ break
278
+
279
+ # action for reassignment
280
+ def doActionForReassign(self, gTmpLog):
281
+ # get DDM I/F
282
+ ddmIF = self.ddmIF.getInterface(self.vo)
283
+ # get site mapper
284
+ siteMapper = self.taskBufferIF.get_site_mapper()
285
+ # get tasks to get reassigned
286
+ taskList = self.taskBufferIF.getTasksToReassign_JEDI(self.vo, self.prodSourceLabel)
287
+
288
+ gTmpLog.debug(f"got {len(taskList)} tasks to reassign")
289
+ for taskSpec in taskList:
290
+ tmpLog = MsgWrapper(logger, f"< jediTaskID={taskSpec.jediTaskID} >")
291
+ tmpLog.debug("start to reassign")
292
+ # DDM backend
293
+ ddmBackEnd = taskSpec.getDdmBackEnd()
294
+ # get datasets
295
+ tmpStat, datasetSpecList = self.taskBufferIF.getDatasetsWithJediTaskID_JEDI(taskSpec.jediTaskID, ["output", "log"])
296
+ if tmpStat is not True:
297
+ tmpLog.error("failed to get datasets")
298
+ continue
299
+
300
+ # re-run task brokerage
301
+ if taskSpec.nucleus in [None, ""]:
302
+ taskSpec.status = "assigning"
303
+ taskSpec.oldStatus = None
304
+ taskSpec.setToRegisterDatasets()
305
+ self.taskBufferIF.updateTask_JEDI(taskSpec, {"jediTaskID": taskSpec.jediTaskID}, setOldModTime=True)
306
+ tmpLog.debug(f"#ATM #KV label=managed action=trigger_new_brokerage by setting task_status={taskSpec.status}")
307
+ continue
308
+
309
+ # get nucleus
310
+ nucleusSpec = siteMapper.getNucleus(taskSpec.nucleus)
311
+ if nucleusSpec is None:
312
+ tmpLog.error(f"nucleus={taskSpec.nucleus} doesn't exist")
313
+ continue
314
+
315
+ # set nucleus
316
+ retMap = {taskSpec.jediTaskID: AtlasBrokerUtils.getDictToSetNucleus(nucleusSpec, datasetSpecList)}
317
+ self.taskBufferIF.setCloudToTasks_JEDI(retMap)
318
+
319
+ # get nucleus
320
+ t1SiteName = nucleusSpec.getOnePandaSite()
321
+ t1Site = siteMapper.getSite(t1SiteName)
322
+
323
+ # loop over all datasets
324
+ isOK = True
325
+ for datasetSpec in datasetSpecList:
326
+ tmpLog.debug(f"dataset={datasetSpec.datasetName}")
327
+ if DataServiceUtils.getDistributedDestination(datasetSpec.storageToken) is not None:
328
+ tmpLog.debug(f"skip {datasetSpec.datasetName} is distributed")
329
+ continue
330
+ # get location
331
+ location = siteMapper.getDdmEndpoint(
332
+ t1Site.sitename, datasetSpec.storageToken, taskSpec.prodSourceLabel, JobUtils.translate_tasktype_to_jobtype(taskSpec.taskType)
333
+ )
334
+ # make subscription
335
+ try:
336
+ tmpLog.debug(f"registering subscription to {location} with backend={ddmBackEnd}")
337
+ tmpStat = ddmIF.registerDatasetSubscription(datasetSpec.datasetName, location, "Production Output", asynchronous=True)
338
+ if tmpStat is not True:
339
+ tmpLog.error("failed to make subscription")
340
+ isOK = False
341
+ break
342
+ except Exception:
343
+ errtype, errvalue = sys.exc_info()[:2]
344
+ tmpLog.warning(f"failed to make subscription with {errtype.__name__}:{errvalue}")
345
+ isOK = False
346
+ break
347
+ # succeeded
348
+ if isOK:
349
+ # activate task
350
+ if taskSpec.oldStatus in ["assigning", "exhausted", None]:
351
+ taskSpec.status = "ready"
352
+ else:
353
+ taskSpec.status = taskSpec.oldStatus
354
+ taskSpec.oldStatus = None
355
+ self.taskBufferIF.updateTask_JEDI(taskSpec, {"jediTaskID": taskSpec.jediTaskID}, setOldModTime=True)
356
+ tmpLog.debug("finished to reassign")
357
+
358
+ # action for throttled tasks
359
+ def doActionForThrottled(self, gTmpLog):
360
+ # release tasks
361
+ nTasks = self.taskBufferIF.releaseThrottledTasks_JEDI(self.vo, self.prodSourceLabel)
362
+ gTmpLog.debug(f"released {nTasks} tasks")
363
+
364
+ # throttle tasks
365
+ nTasks = self.taskBufferIF.throttleTasks_JEDI(self.vo, self.prodSourceLabel, jedi_config.watchdog.waitForThrottled)
366
+ gTmpLog.debug(f"throttled {nTasks} tasks")
367
+
368
+ # action for high priority pending tasks
369
+ def doActionForHighPrioPending(self, gTmpLog, minPriority, timeoutVal):
370
+ timeoutForPending = None
371
+ # try to get the timeout from the config files
372
+ if hasattr(jedi_config.watchdog, "timeoutForPendingVoLabel"):
373
+ timeoutForPending = CoreUtils.getConfigParam(jedi_config.watchdog.timeoutForPendingVoLabel, self.vo, self.prodSourceLabel)
374
+ if timeoutForPending is None:
375
+ timeoutForPending = jedi_config.watchdog.timeoutForPending
376
+ timeoutForPending = int(timeoutForPending) * 24
377
+ tmpRet, _ = self.taskBufferIF.reactivatePendingTasks_JEDI(self.vo, self.prodSourceLabel, timeoutVal, timeoutForPending, minPriority=minPriority)
378
+ if tmpRet is None:
379
+ # failed
380
+ gTmpLog.error(f"failed to reactivate high priority (>{minPriority}) tasks")
381
+ else:
382
+ gTmpLog.info(f"reactivated high priority (>{minPriority}) {tmpRet} tasks")
383
+
384
+ # action to throttle jobs in paused tasks
385
+ def doActionToThrottleJobInPausedTasks(self, gTmpLog):
386
+ tmpRet = self.taskBufferIF.throttleJobsInPausedTasks_JEDI(self.vo, self.prodSourceLabel)
387
+ if tmpRet is None:
388
+ # failed
389
+ gTmpLog.error("failed to thottle jobs in paused tasks")
390
+ else:
391
+ for jediTaskID, pandaIDs in tmpRet.items():
392
+ gTmpLog.info(f"throttled jobs in paused jediTaskID={jediTaskID} successfully")
393
+ tmpRet = self.taskBufferIF.killJobs(pandaIDs, "reassign", "51", True)
394
+ gTmpLog.info(f"reassigned {len(pandaIDs)} jobs in paused jediTaskID={jediTaskID} with {tmpRet}")
395
+
396
+ # action to provoke (mark files ready) data carousel tasks to start if DDM rules of input DS are done
397
+ def doActionToProvokeDCTasks(self, gTmpLog):
398
+ # lock
399
+ got_lock = self.taskBufferIF.lockProcess_JEDI(
400
+ vo=self.vo,
401
+ prodSourceLabel=self.prodSourceLabel,
402
+ cloud=None,
403
+ workqueue_id=None,
404
+ resource_name=None,
405
+ component="AtlasProdWatchDog.doActionToProvokeDCT",
406
+ pid=self.pid,
407
+ timeLimit=30,
408
+ )
409
+ if not got_lock:
410
+ gTmpLog.debug("doActionToProvokeDCTasks locked by another process. Skipped")
411
+ return
412
+ # run
413
+ res_dict = self.taskBufferIF.get_pending_dc_tasks_JEDI(task_type="prod", time_limit_minutes=60)
414
+ if res_dict is None:
415
+ # failed
416
+ gTmpLog.error("failed to get pending DC tasks")
417
+ elif not res_dict:
418
+ # empty
419
+ gTmpLog.debug("no pending DC task; skipped")
420
+ else:
421
+ gTmpLog.debug(f"got {len(res_dict)} DC tasks to provoke")
422
+ ddm_if = self.ddmIF.getInterface(self.vo)
423
+ # loop over pending DC tasks
424
+ for task_id, ds_name_list in res_dict.items():
425
+ if not ds_name_list:
426
+ continue
427
+ total_all_ok = True
428
+ for ds_name in ds_name_list:
429
+ ret_data = ddm_if.get_rules_state(ds_name)
430
+ try:
431
+ all_ok, rule_dict = ret_data
432
+ total_all_ok = total_all_ok and all_ok
433
+ except ValueError:
434
+ gTmpLog.error(f"failed to get rule info for task={task_id}. data={ret_data}")
435
+ total_all_ok = False
436
+ break
437
+ if total_all_ok:
438
+ # all rules ok; provoke the task
439
+ gTmpLog.info(f"provoking task {task_id}")
440
+ self.taskBufferIF.updateInputDatasetsStaged_JEDI(task_id, None, None, by="AtlasProdWatchDog")
441
+ gTmpLog.info(f"all staging rules of task {task_id} are OK; provoked")
442
+ else:
443
+ gTmpLog.debug(f"not all staging rules of task {task_id} are OK; skipped ")