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,77 @@
1
+ """
2
+ EventLookupClientEI is a class for looking up events in the EventIndex.
3
+ """
4
+ import os
5
+ import subprocess
6
+ import tempfile
7
+
8
+ from typing import List, Tuple
9
+
10
+
11
+ class EventLookupClientEI:
12
+ """
13
+ EventLookupClientEI is a class for looking up events in the EventIndex.
14
+ """
15
+ def do_lookup(self, event_run_list: List[Tuple[int, int]], stream: str = None, tokens: str = None, ami_tag: str = None) -> Tuple[List[str], str, str, str]:
16
+ """
17
+ Performs a lookup in the EventIndex for the given parameters.
18
+
19
+ Parameters:
20
+ event_run_list (List[Tuple[int, int]]): The list of run events.
21
+ stream (str): The name of the stream.
22
+ tokens (str): The tokens.
23
+ ami_tag (str): The AMI tag.
24
+
25
+ Returns:
26
+ Tuple[List[str], str, str, str]: A tuple containing the list of GUIDs, the command, the output, and the error.
27
+ """
28
+ command = os.path.join(
29
+ os.getenv(
30
+ "EIDIR",
31
+ "/cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase/x86_64/EIClient/current",
32
+ ),
33
+ "bin",
34
+ "event-lookup",
35
+ )
36
+ with tempfile.NamedTemporaryFile(mode="w+t") as tmp_event_file:
37
+ command += f" -F {tmp_event_file.name} "
38
+ for run_event in event_run_list:
39
+ # creating a preformatted string. The :08d and :09d parts are formatting these integers to be eight and nine digits long
40
+ tmp_string = f"{int(run_event[0]):08d} {int(run_event[1]):09d}\n"
41
+ tmp_event_file.write(tmp_string)
42
+ tmp_event_file.flush()
43
+ if stream not in [None, ""]:
44
+ command += f"-s {stream} "
45
+ if ami_tag not in [None, ""]:
46
+ command += f"-a {ami_tag} "
47
+ command += "-c plain "
48
+ with subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True,
49
+ universal_newlines=True) as execute_process:
50
+ tmp_output, tmp_error = execute_process.communicate()
51
+ guids = {}
52
+ if tokens == "":
53
+ tokens = None
54
+ try:
55
+ # The output is expected to be a string with multiple lines, each line containing information about a single event.
56
+ # Each line is split into items, the first two items are interpreted as integers representing a run number and an event number.
57
+ # These two numbers are combined into a tuple, run_event, which is used as a key in the guids dictionary.
58
+ # The fourth item in the line is appended to the string "Stream" to form tmp_token, and the third item is assigned to tmp_guid.
59
+ # An example input (tmp_output) is:
60
+ # 123 456 789abc StreamXYZ
61
+ # An example output (guids dictionary) is:
62
+ # (123, 456): {"789abc"}
63
+ for tmp_line in tmp_output.split("\n"):
64
+ tmp_items = tmp_line.split()
65
+ run_event = (int(tmp_items[0]), int(tmp_items[1]))
66
+ guids.setdefault(run_event, set())
67
+ # check type
68
+ tmp_token = "Stream" + tmp_items[3]
69
+ tmp_guid = tmp_items[2]
70
+ if not tokens or tokens == tmp_token:
71
+ guids[run_event].add(tmp_guid)
72
+ if not guids:
73
+ # add dummy
74
+ guids[None] = None
75
+ except Exception:
76
+ pass
77
+ return guids, command, tmp_output, tmp_error
@@ -0,0 +1,268 @@
1
+ """
2
+ add data to dataset
3
+
4
+ """
5
+
6
+ import fcntl
7
+ import os
8
+ import re
9
+ import sys
10
+ import traceback
11
+
12
+ from pandacommon.pandalogger.LogWrapper import LogWrapper
13
+ from pandacommon.pandalogger.PandaLogger import PandaLogger
14
+
15
+ from pandaserver.dataservice import dyn_data_distributer
16
+ from pandaserver.srvcore import CoreUtils
17
+ from pandaserver.userinterface import Client
18
+
19
+ # logger
20
+ _logger = PandaLogger().getLogger("event_picker")
21
+
22
+
23
+ class EventPicker:
24
+ """
25
+ A class used to add data to a dataset.
26
+ """
27
+
28
+ # constructor
29
+ def __init__(self, taskBuffer, siteMapper, evpFileName: str, ignoreError: bool):
30
+ """
31
+ Constructs all the necessary attributes for the EventPicker object.
32
+
33
+ Parameters:
34
+ taskBuffer : TaskBuffer
35
+ The task buffer that contains the jobs.
36
+ siteMapper : SiteMapper
37
+ The site mapper.
38
+ evpFileName : str
39
+ The name of the event picking file.
40
+ ignoreError : bool
41
+ Whether to ignore errors.
42
+ """
43
+ self.task_buffer = taskBuffer
44
+ self.site_mapper = siteMapper
45
+ self.ignore_error = ignoreError
46
+ self.event_picking_file_name = evpFileName
47
+ # logger
48
+ self.logger = LogWrapper(_logger)
49
+ dataset_lifetime = self.task_buffer.getConfigValue("event_picker", "EVP_DATASET_LIFETIME")
50
+ if not dataset_lifetime:
51
+ dataset_lifetime = 28
52
+ self.pd2p = dyn_data_distributer.DynDataDistributer([], self.site_mapper, token=" ", dataset_lifetime=dataset_lifetime)
53
+ self.user_dataset_name = ""
54
+ self.creation_time = ""
55
+ self.params = ""
56
+ self.locked_by = ""
57
+ self.event_picking_file = None
58
+ self.user_task_name = ""
59
+ self.user_dn = ""
60
+ # JEDI
61
+ self.jedi_task_id = None
62
+
63
+ # end with error
64
+ def end_with_error(self, message: str):
65
+ """
66
+ Ends the event picker with an error.
67
+
68
+ This method is called when an error occurs during the event picking process. It logs the error message,
69
+ unlocks and closes the event picking file, and removes it if the error is not to be ignored. It then uploads
70
+ the log and updates the task status in the task buffer.
71
+
72
+ Parameters:
73
+ message (str): The error message to be logged.
74
+ """
75
+ self.logger.error(message)
76
+ # unlock evp file
77
+ try:
78
+ fcntl.flock(self.event_picking_file.fileno(), fcntl.LOCK_UN)
79
+ self.event_picking_file.close()
80
+ if not self.ignore_error:
81
+ # remove evp file
82
+ os.remove(self.event_picking_file_name)
83
+ except Exception:
84
+ pass
85
+ # upload log
86
+ if self.jedi_task_id is not None:
87
+ out_log = self.upload_log()
88
+ self.task_buffer.updateTaskErrorDialogJEDI(self.jedi_task_id, f"event picking failed. {out_log}")
89
+ # update task
90
+ if not self.ignore_error:
91
+ self.task_buffer.updateTaskModTimeJEDI(self.jedi_task_id, "tobroken")
92
+ self.logger.debug(out_log)
93
+ self.logger.debug(f"end {self.event_picking_file_name}")
94
+
95
+ # upload log
96
+ def upload_log(self) -> str:
97
+ """
98
+ Uploads the log.
99
+
100
+ This method uploads the log of the EventPicker. It first checks if the jediTaskID is not None.
101
+ If it is None, it returns a message indicating that the jediTaskID could not be found.
102
+ Otherwise, it dumps the logger content to a string and attempts to upload it using the Client's upload_log method.
103
+ If the upload is not successful, it returns a message indicating the failure.
104
+ If the upload is successful and the output starts with "http", it returns a hyperlink to the log.
105
+ Otherwise, it returns the output of the upload_log method.
106
+
107
+ Returns:
108
+ str: The result of the log upload. This can be a message indicating an error, a hyperlink to the log, or the output of the upload_log method.
109
+ """
110
+ if self.jedi_task_id is None:
111
+ return "cannot find jediTaskID"
112
+ str_msg = self.logger.dumpToString()
113
+ status, output = Client.uploadLog(str_msg, self.jedi_task_id)
114
+ if status != 0:
115
+ return f"failed to upload log with {status}."
116
+ if output.startswith("http"):
117
+ return f'<a href="{output}">log</a>'
118
+ return output
119
+
120
+ def get_options_from_file(self) -> dict:
121
+ """
122
+ Gets options from the event picking file.
123
+
124
+ This method reads the event picking file and extracts options from it. The options are stored in a dictionary and returned.
125
+
126
+ Returns:
127
+ dict: A dictionary containing the options extracted from the event picking file.
128
+ """
129
+ options = {
130
+ "runEvent": [],
131
+ "eventPickDataType": "",
132
+ "eventPickStreamName": "",
133
+ "eventPickDS": [],
134
+ "eventPickAmiTag": "",
135
+ "eventPickNumSites": 1,
136
+ "inputFileList": [],
137
+ "tagDS": [],
138
+ "tagQuery": "",
139
+ "tagStreamRef": "",
140
+ "runEvtGuidMap": {},
141
+ "ei_api": "",
142
+ "userName": "",
143
+ "userTaskName": "",
144
+ "userDatasetName": "",
145
+ "lockedBy": "",
146
+ "creationTime": "",
147
+ "params": "",
148
+ }
149
+
150
+ for tmp_line in self.event_picking_file:
151
+ # regular expression to parse lines where a key and value are separated by an equal sign
152
+ tmp_match = re.search("^([^=]+)=(.+)$", tmp_line)
153
+ if tmp_match is not None:
154
+ key, value = tmp_match.groups()
155
+ if key in options:
156
+ if key == "runEvent":
157
+ tmp_run_event = value.split(",")
158
+ if len(tmp_run_event) == 2:
159
+ options[key].append(tmp_run_event)
160
+ elif key in ["eventPickDS", "inputFileList", "tagDS"]:
161
+ options[key] = value.split(",")
162
+ if key == "inputFileList":
163
+ options[key] = [item for item in options[key] if item != ""]
164
+ elif key == "eventPickNumSites":
165
+ options[key] = int(value)
166
+ elif key == "runEvtGuidMap":
167
+ options[key] = eval(value)
168
+ else:
169
+ options[key] = value
170
+ if key == "tagStreamRef" and not options[key].endswith("_ref"):
171
+ options[key] += "_ref"
172
+ return options
173
+
174
+ def get_jedi_task_id(self, options: dict) -> int:
175
+ """
176
+ Gets the jediTaskID.
177
+
178
+ This method gets the jediTaskID from the task buffer using the user's DN and task name.
179
+
180
+ Parameters:
181
+ options (dict): A dictionary containing the options extracted from the event picking file.
182
+
183
+ Returns:
184
+ int: The jediTaskID.
185
+ """
186
+ self.user_dn = options["userName"]
187
+ self.user_task_name = options["userTaskName"]
188
+ self.user_dataset_name = options["userDatasetName"]
189
+ self.locked_by = options["lockedBy"]
190
+ self.creation_time = options["creationTime"]
191
+ self.params = options["params"]
192
+
193
+ # extract task name
194
+ if self.user_task_name == "" and self.params != "":
195
+ # regular expression to parse the dataset name from a string where it is prefixed with --outDS and followed by either an equal sign or a space
196
+ tmp_match = re.search("--outDS(=| ) *([^ ]+)", self.params)
197
+ if tmp_match is not None:
198
+ self.user_task_name = tmp_match.group(2)
199
+ if not self.user_task_name.endswith("/"):
200
+ self.user_task_name += "/"
201
+
202
+ compact_dn = CoreUtils.clean_user_id(self.user_dn)
203
+ return self.task_buffer.getTaskIDwithTaskNameJEDI(compact_dn, self.user_task_name)
204
+
205
+ # main
206
+ def run(self) -> bool:
207
+ """
208
+ Starts the event picker.
209
+
210
+ Returns:
211
+ bool: True if the event picker ran successfully, False otherwise.
212
+ """
213
+ try:
214
+ self.logger.debug(f"start {self.event_picking_file_name}")
215
+ # lock event picking file
216
+ with open(self.event_picking_file_name) as self.event_picking_file:
217
+ try:
218
+ fcntl.flock(self.event_picking_file.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
219
+ except Exception:
220
+ # release
221
+ self.logger.debug(f"cannot lock {self.event_picking_file_name}")
222
+ return True
223
+
224
+ options = self.get_options_from_file()
225
+
226
+ self.jedi_task_id = self.get_jedi_task_id(options)
227
+
228
+ tmp_ret, location_map, all_files = self.pd2p.convert_evt_run_to_datasets(
229
+ options["runEvent"],
230
+ options["eventPickDataType"],
231
+ options["eventPickStreamName"],
232
+ options["eventPickDS"],
233
+ options["eventPickAmiTag"],
234
+ options["runEvtGuidMap"],
235
+ )
236
+
237
+ if not tmp_ret:
238
+ if "isFatal" in location_map and location_map["isFatal"] is True:
239
+ self.ignore_error = False
240
+ self.end_with_error("Failed to convert the run/event list to a dataset/file list")
241
+ return False
242
+
243
+ # use only files in the list
244
+ if options["inputFileList"]:
245
+ all_files = [tmp_file for tmp_file in all_files if tmp_file["lfn"] in options["inputFileList"]]
246
+
247
+ # remove redundant CN from DN
248
+ tmp_dn = CoreUtils.get_id_from_dn(self.user_dn)
249
+ tmp_ret = self.pd2p.register_dataset_container_with_datasets(
250
+ self.user_dataset_name,
251
+ all_files,
252
+ location_map,
253
+ n_sites=options["eventPickNumSites"],
254
+ owner=tmp_dn,
255
+ )
256
+
257
+ if not tmp_ret:
258
+ return False
259
+
260
+ fcntl.flock(self.event_picking_file.fileno(), fcntl.LOCK_UN)
261
+ os.remove(self.event_picking_file_name)
262
+
263
+ self.logger.debug(f"end {self.event_picking_file_name}")
264
+ return True
265
+ except Exception:
266
+ error_type, error_value = sys.exc_info()[:2]
267
+ self.end_with_error(f"Got exception {error_type}:{error_value} {traceback.format_exc()}")
268
+ return False
@@ -0,0 +1,194 @@
1
+ """
2
+ finish transferring jobs
3
+
4
+ """
5
+
6
+ import datetime
7
+ import json
8
+ import re
9
+ import sys
10
+ import threading
11
+ from typing import List
12
+
13
+ from pandacommon.pandalogger.LogWrapper import LogWrapper
14
+ from pandacommon.pandalogger.PandaLogger import PandaLogger
15
+ from pandacommon.pandautils.PandaUtils import naive_utcnow
16
+
17
+ # logger
18
+ _logger = PandaLogger().getLogger("finisher")
19
+
20
+
21
+ class Finisher(threading.Thread):
22
+ """
23
+ A class used to finish transferring jobs
24
+
25
+ Attributes
26
+ ----------
27
+ dataset : DatasetSpec
28
+ The dataset to be transferred
29
+ taskBuffer : TaskBuffer
30
+ The task buffer that contains the jobs
31
+ job : JobSpec, optional
32
+ The job to be transferred (default is None)
33
+ site : str, optional
34
+ The site where the job is to be transferred (default is None)
35
+
36
+ Methods
37
+ -------
38
+ run():
39
+ Starts the thread to finish transferring jobs
40
+ """
41
+
42
+ # constructor
43
+ def __init__(self, taskBuffer, dataset, job: str = None, site: str = None):
44
+ """
45
+ Constructs all the necessary attributes for the Finisher object.
46
+
47
+ Parameters
48
+ ----------
49
+ taskBuffer : TaskBuffer
50
+ The task buffer that contains the jobs
51
+ dataset : DatasetSpec
52
+ The dataset to be transferred
53
+ job : JobSpec, optional
54
+ The job to be transferred (default is None)
55
+ site : str, optional
56
+ The site where the job is to be transferred (default is None)
57
+ """
58
+ threading.Thread.__init__(self)
59
+ self.dataset = dataset
60
+ self.task_buffer = taskBuffer
61
+ self.job = job
62
+ self.site = site
63
+
64
+ def create_json_doc(self, job, failed_files: List[str], no_out_files: List[str]):
65
+ """
66
+ This function creates a JSON document for the jobs.
67
+
68
+ Parameters:
69
+ job (JobSpec): The job specification.
70
+ failed_files (list): List of failed files.
71
+ no_out_files (list): List of files with no output.
72
+
73
+ Returns:
74
+ str: The created JSON document as a string.
75
+ """
76
+ json_dict = {}
77
+ for file in job.Files:
78
+ if file.type in ["output", "log"]:
79
+ # skip failed or no-output files
80
+ if file.lfn in failed_files + no_out_files:
81
+ continue
82
+ file_dict = {
83
+ "guid": file.GUID,
84
+ "fsize": file.fsize,
85
+ "full_lfn": file.lfn,
86
+ }
87
+ if file.checksum.startswith("ad:"):
88
+ file_dict["adler32"] = re.sub("^ad:", "", file.checksum)
89
+ else:
90
+ file_dict["md5sum"] = re.sub("^md5:", "", file.checksum)
91
+ json_dict[file.lfn] = file_dict
92
+ return json.dumps(json_dict)
93
+
94
+ def update_job_output_report(self, job, failed_files: List[str], no_out_files: List[str]):
95
+ """
96
+ This function updates the job output report.
97
+
98
+ Parameters:
99
+ job (JobSpec): The job specification.
100
+ failed_files (list): List of failed files.
101
+ no_out_files (list): List of files with no output.
102
+ """
103
+ json_data = self.create_json_doc(job, failed_files, no_out_files)
104
+ record_status = "finished" if not failed_files else "failed"
105
+ tmp_ret = self.task_buffer.updateJobOutputReport(
106
+ panda_id=job.PandaID,
107
+ attempt_nr=job.attemptNr,
108
+ data=json_data,
109
+ )
110
+ if not tmp_ret:
111
+ self.task_buffer.insertJobOutputReport(
112
+ panda_id=job.PandaID,
113
+ prod_source_label=job.prodSourceLabel,
114
+ job_status=record_status,
115
+ attempt_nr=job.attemptNr,
116
+ data=json_data,
117
+ )
118
+
119
+ def check_file_status(self, job):
120
+ """
121
+ This function checks the status of the files for the job.
122
+
123
+ Parameters:
124
+ job (JobSpec): The job specification.
125
+
126
+ Returns:
127
+ tuple: A tuple containing three elements:
128
+ - bool: True if all files are ready, False otherwise.
129
+ - list: A list of failed files.
130
+ - list: A list of files with no output.
131
+ """
132
+ tmp_log = LogWrapper(_logger, f"check_file_status-{naive_utcnow().isoformat('/')}")
133
+ failed_files = []
134
+ no_out_files = []
135
+ for file in job.Files:
136
+ if file.type in ("output", "log"):
137
+ if file.status == "failed":
138
+ failed_files.append(file.lfn)
139
+ elif file.status == "nooutput":
140
+ no_out_files.append(file.lfn)
141
+ elif file.status != "ready":
142
+ tmp_log.debug(f"Job: {job.PandaID} file:{file.lfn} {file.status} != ready")
143
+ return False, failed_files, no_out_files
144
+ return True, failed_files, no_out_files
145
+
146
+ # main
147
+ def run(self):
148
+ """
149
+ Starts the thread to finish transferring jobs
150
+ """
151
+ tmp_log = LogWrapper(_logger, f"run-{naive_utcnow().isoformat('/')}")
152
+ # start
153
+ try:
154
+ by_call_back = False
155
+ if self.job is not None:
156
+ tmp_log.debug(f"start: {self.job.PandaID}")
157
+ panda_ids = [self.job.PandaID]
158
+ jobs = [self.job]
159
+ else:
160
+ by_call_back = True
161
+ tmp_log.debug(f"start: {self.dataset.name}")
162
+ panda_ids = self.task_buffer.updateOutFilesReturnPandaIDs(self.dataset.name)
163
+ # set flag for T2 cleanup
164
+ self.dataset.status = "cleanup"
165
+ self.task_buffer.updateDatasets([self.dataset])
166
+ jobs = self.task_buffer.peekJobs(panda_ids, fromDefined=False, fromArchived=False, fromWaiting=False)
167
+
168
+ tmp_log.debug(f"IDs: {panda_ids}")
169
+ if len(panda_ids) != 0:
170
+ # loop over all jobs
171
+ for job in jobs:
172
+ if job is None or job.jobStatus != "transferring":
173
+ continue
174
+ job_ready, failed_files, no_out_files = self.check_file_status(job)
175
+ # finish job
176
+ if job_ready:
177
+ if by_call_back:
178
+ tmp_log.debug(f"Job: {job.PandaID} all files ready")
179
+ else:
180
+ tmp_log.debug(f"Job: {job.PandaID} all files checked with catalog")
181
+ # create JSON
182
+ try:
183
+ self.update_job_output_report(job, failed_files, no_out_files)
184
+ except Exception:
185
+ exc_type, value, _ = sys.exc_info()
186
+ tmp_log.error(f"Job: {job.PandaID} {exc_type} {value}")
187
+ tmp_log.debug(f"Job: {job.PandaID} status: {job.jobStatus}")
188
+ if self.job is None:
189
+ tmp_log.debug(f"end: {self.dataset.name}")
190
+ else:
191
+ tmp_log.debug(f"end: {self.job.PandaID}")
192
+ except Exception:
193
+ exc_type, value, _ = sys.exc_info()
194
+ tmp_log.error(f"run() : {exc_type} {value}")