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,339 @@
1
+ import ast
2
+ import inspect
3
+ import re
4
+ import sys
5
+ import threading
6
+ import time
7
+ import typing
8
+ from functools import wraps
9
+ from types import ModuleType, UnionType
10
+ from typing import Union, get_args, get_origin
11
+
12
+ from pandacommon.pandalogger.LogWrapper import LogWrapper
13
+
14
+ import pandaserver.jobdispatcher.Protocol as Protocol
15
+ from pandaserver.config import panda_config
16
+ from pandaserver.dataservice.ddm import rucioAPI
17
+ from pandaserver.srvcore import CoreUtils
18
+
19
+ TIME_OUT = "TimeOut"
20
+
21
+ MESSAGE_SSL = "SSL secure connection is required"
22
+ MESSAGE_PROD_ROLE = "production or pilot role required"
23
+ MESSAGE_TASK_ID = "jediTaskID must be an integer"
24
+ MESSAGE_DATABASE = "database error in the PanDA server"
25
+ MESSAGE_JSON = "failed to load JSON"
26
+
27
+
28
+ def get_endpoint(protocol):
29
+ if protocol not in ["http", "https"]:
30
+ return False, "Protocol must be either 'http' or 'https'"
31
+
32
+ try:
33
+ if protocol == "https":
34
+ endpoint = f"{panda_config.pserverhost}:{panda_config.pserverport}"
35
+ else:
36
+ endpoint = f"{panda_config.pserverhosthttp}:{panda_config.pserverporthttp}"
37
+ except Exception as e:
38
+ return False, str(e)
39
+
40
+ return True, endpoint
41
+
42
+
43
+ def extract_allowed_methods(module: ModuleType) -> list:
44
+ """
45
+ Generate the allowed methods dynamically with all function names present in the API module, excluding
46
+ functions imported from other modules or the init_task_buffer function
47
+
48
+ :param module: The module to extract the allowed methods from
49
+ :return: A list of allowed method names
50
+ """
51
+ return [
52
+ name
53
+ for name, obj in inspect.getmembers(module, inspect.isfunction)
54
+ if obj.__module__ == module.__name__ and name != "init_task_buffer" and name.startswith("_") is False
55
+ ]
56
+
57
+
58
+ def generate_response(success, message="", data=None):
59
+ response = {"success": success, "message": message, "data": data}
60
+ return response
61
+
62
+
63
+ # get FQANs
64
+ def get_fqan(req):
65
+ fqans = []
66
+ for tmp_key in req.subprocess_env:
67
+ tmp_value = req.subprocess_env[tmp_key]
68
+ # Scan VOMS attributes
69
+ # compact style
70
+ if tmp_key.startswith("GRST_CRED_") and tmp_value.startswith("VOMS"):
71
+ fqan = tmp_value.split()[-1]
72
+ fqans.append(fqan)
73
+
74
+ # old style
75
+ elif tmp_key.startswith("GRST_CONN_"):
76
+ tmp_items = tmp_value.split(":")
77
+ if len(tmp_items) == 2 and tmp_items[0] == "fqan":
78
+ fqans.append(tmp_items[-1])
79
+
80
+ return fqans
81
+
82
+
83
+ def get_email_address(user, tmp_logger):
84
+ tmp_logger.debug(f"Getting mail address for {user}")
85
+ n_tries = 3
86
+ email = None
87
+ try:
88
+ for attempt in range(n_tries):
89
+ status, user_info = rucioAPI.finger(user)
90
+ if status:
91
+ email = user_info["email"]
92
+ tmp_logger.debug(f"User {user} got email {email}")
93
+ break
94
+ else:
95
+ tmp_logger.debug(f"Attempt {attempt + 1} of {n_tries} failed. Retrying...")
96
+ time.sleep(1)
97
+ except Exception:
98
+ error_type, error_value = sys.exc_info()[:2]
99
+ tmp_logger.error(f"Failed to convert email address {user} : {error_type} {error_value}")
100
+
101
+ return email
102
+
103
+
104
+ def get_request_method(req):
105
+ # Extract the http method like GET, POST, ... from the request environment
106
+ environ = req.subprocess_env
107
+ request_method = environ.get("REQUEST_METHOD", None) # GET, POST, PUT, DELETE
108
+ return request_method
109
+
110
+
111
+ # get DN
112
+ def get_dn(req):
113
+ real_dn = ""
114
+ if "SSL_CLIENT_S_DN" in req.subprocess_env:
115
+ # remove redundant CN
116
+ real_dn = CoreUtils.get_bare_dn(req.subprocess_env["SSL_CLIENT_S_DN"], keep_proxy=True)
117
+ return real_dn
118
+
119
+
120
+ # check role
121
+ def has_production_role(req):
122
+ # check DN
123
+ user = get_dn(req)
124
+ for sdn in panda_config.production_dns:
125
+ if sdn in user:
126
+ return True
127
+ # get FQANs
128
+ fqans = get_fqan(req)
129
+ # loop over all FQANs
130
+ for fqan in fqans:
131
+ # check production role
132
+ for rolePat in [
133
+ "/atlas/usatlas/Role=production",
134
+ "/atlas/Role=production",
135
+ "^/[^/]+/Role=production",
136
+ ]:
137
+ if fqan.startswith(rolePat):
138
+ return True
139
+ if re.search(rolePat, fqan):
140
+ return True
141
+ return False
142
+
143
+
144
+ def extract_production_working_groups(fqans):
145
+ # Extract working groups with production role from FQANs
146
+ wg_prod_roles = []
147
+ for fqan in fqans:
148
+ # Match FQANs with 'Role=production' and extract the working group
149
+ match = re.search(r"/atlas/([^/]+)/Role=production", fqan)
150
+ if match:
151
+ working_group = match.group(1)
152
+ # Exclude 'usatlas' and ensure uniqueness
153
+ if working_group and working_group not in ["usatlas"] + wg_prod_roles:
154
+ wg_prod_roles.extend([working_group, f"gr_{working_group}"]) # Add group and prefixed variant
155
+
156
+ return wg_prod_roles
157
+
158
+
159
+ def extract_primary_production_working_group(fqans):
160
+ working_group = None
161
+ for fqan in fqans:
162
+ match = re.search("/[^/]+/([^/]+)/Role=production", fqan)
163
+ if match:
164
+ # ignore usatlas since it is used as atlas prod role
165
+ tmp_working_group = match.group(1)
166
+ if tmp_working_group not in ["", "usatlas"]:
167
+ working_group = tmp_working_group.split("-")[-1].lower()
168
+
169
+ return working_group
170
+
171
+
172
+ # security check
173
+ def is_secure(req, logger=None):
174
+ # check security
175
+ if not Protocol.isSecure(req):
176
+ return False
177
+
178
+ # disable limited proxy
179
+ if "/CN=limited proxy" in req.subprocess_env["SSL_CLIENT_S_DN"]:
180
+ if logger:
181
+ logger.warning(f"access via limited proxy : {req.subprocess_env['SSL_CLIENT_S_DN']}")
182
+ return False
183
+
184
+ return True
185
+
186
+
187
+ def normalize_type(t):
188
+ mapping = {
189
+ typing.List: list,
190
+ typing.Dict: dict,
191
+ typing.Set: set,
192
+ typing.Tuple: tuple,
193
+ }
194
+ return mapping.get(t, t)
195
+
196
+
197
+ def request_validation(logger, secure=True, production=False, request_method=None):
198
+ def decorator(func):
199
+ @wraps(func)
200
+ def wrapper(req, *args, **kwargs):
201
+ # Generate a logger with the underlying function name
202
+ tmp_logger = LogWrapper(logger, func.__name__)
203
+ tmp_logger_context = LogWrapper(logger, f"{func.__name__} args:{args} kwargs:{kwargs}")
204
+
205
+ # expected and received request methods
206
+ expected_request_method = request_method
207
+ received_request_method = get_request_method(req)
208
+
209
+ # check SSL if required
210
+ if secure and not is_secure(req, tmp_logger):
211
+ tmp_logger.error(f"{MESSAGE_SSL}")
212
+ return generate_response(False, message=MESSAGE_SSL)
213
+
214
+ # check production role if required
215
+ if production and not has_production_role(req):
216
+ tmp_logger.error(f"{MESSAGE_PROD_ROLE}")
217
+ return generate_response(False, message=MESSAGE_PROD_ROLE)
218
+
219
+ # check method if required
220
+ if expected_request_method and expected_request_method != received_request_method:
221
+ message = f"expecting {expected_request_method}, received {req.subprocess_env.get('REQUEST_METHOD', None)}"
222
+ tmp_logger.error(f"{message}")
223
+ return generate_response(False, message=message)
224
+
225
+ # Get function signature and type hints
226
+ sig = inspect.signature(func)
227
+ args_tmp = (req,) + args
228
+ try:
229
+ bound_args = sig.bind(*args_tmp, **kwargs)
230
+ except TypeError as e:
231
+ message = f"Argument error: {str(e)}"
232
+ tmp_logger_context.error(message)
233
+ return generate_response(False, message=message)
234
+ bound_args.apply_defaults()
235
+
236
+ for param_name, param_value in bound_args.arguments.items():
237
+ # tmp_logger.debug(f"Got parameter '{param_name}' with value '{param_value}' and type '{type(param_value)}'")
238
+
239
+ # Skip the first argument (req)
240
+ if param_name == "req":
241
+ continue
242
+
243
+ # Skip if no type hint
244
+ expected_type = sig.parameters[param_name].annotation
245
+ if expected_type is inspect.Parameter.empty:
246
+ continue
247
+
248
+ # Skip if value is the default value
249
+ default_value = sig.parameters[param_name].default
250
+ if default_value == param_value:
251
+ continue
252
+
253
+ # Handle generics like List[int]
254
+ origin = get_origin(expected_type)
255
+ args = get_args(expected_type)
256
+
257
+ # GET methods are URL encoded. Parameters will lose the type and come as string. We need to cast them to the expected type
258
+ if received_request_method == "GET":
259
+ try:
260
+ tmp_logger.debug(f"Casting '{param_name}' to type {expected_type.__name__}.")
261
+ tmp_logger.debug(type(param_value))
262
+ if param_value == "None" and default_value is None:
263
+ param_value = None
264
+ # Don't cast if the type is already a string
265
+ elif expected_type is str:
266
+ pass
267
+ # Booleans need to be handled separately, since bool("False") == True
268
+ elif expected_type is bool:
269
+ param_value = param_value.lower() in ("true", "1")
270
+ # Convert to float first, then to int. This is a courtesy for cases passing decimal numbers.
271
+ elif expected_type is int:
272
+ param_value = int(float(param_value))
273
+ elif origin is list and args:
274
+ element_type = args[0] # Get the type inside List[<type>]
275
+
276
+ # If only one element, convert it to a list
277
+ if isinstance(param_value, str):
278
+ param_value = [param_value]
279
+
280
+ # Convert the elements of the list to the expected type
281
+ if element_type is int:
282
+ param_value = [int(float(i)) for i in param_value] # Convert list items to int
283
+ elif element_type is float:
284
+ param_value = [float(i) for i in param_value] # Convert list items to float
285
+ elif element_type is bool:
286
+ param_value = [i.lower() in ("true", "1") for i in param_value] # Convert list items to bool
287
+ else:
288
+ # Normalize type, e.g. typing.Dict -> dict
289
+ expected_type = normalize_type(expected_type)
290
+ if not isinstance(param_value, expected_type):
291
+ param_value = ast.literal_eval(param_value)
292
+ if not isinstance(param_value, expected_type):
293
+ raise TypeError(f"Expected {expected_type}, received {type(param_value)}")
294
+ bound_args.arguments[param_name] = param_value # Ensure the cast value is used
295
+ except (ValueError, TypeError):
296
+ message = f"Type error: '{param_name}' with value '{param_value}' could not be casted to type {expected_type.__name__} from {type(param_value).__name__}."
297
+ tmp_logger_context.error(message)
298
+ return generate_response(False, message=message)
299
+
300
+ # Check type
301
+ if origin and (origin is not Union and origin is not UnionType): # Handle generics (e.g., List[int])
302
+ if not isinstance(param_value, origin):
303
+ message = f"Type error: '{param_name}' must be of type {origin.__name__}, got {type(param_value).__name__}."
304
+ tmp_logger_context.error(message)
305
+ return generate_response(False, message=message)
306
+
307
+ if args: # Check inner types for lists, dicts, etc.
308
+ if origin is list and not all(isinstance(i, args[0]) for i in param_value):
309
+ message = f"Type error: All elements in '{param_name}' must be {args[0].__name__}."
310
+ tmp_logger_context.error(message)
311
+ return generate_response(False, message=message)
312
+ elif not isinstance(param_value, expected_type) and not (param_value is None and param_value == default_value):
313
+ message = f"Type error: '{param_name}' must be of type {expected_type.__name__}, got {type(param_value).__name__}."
314
+ tmp_logger_context.error(message)
315
+ return generate_response(False, message=message)
316
+
317
+ return func(*bound_args.args, **bound_args.kwargs)
318
+
319
+ return wrapper
320
+
321
+ return decorator
322
+
323
+
324
+ # a wrapper to install timeout into a method
325
+ class TimedMethod:
326
+ def __init__(self, method, timeout):
327
+ self.method = method
328
+ self.timeout = timeout
329
+ self.result = TIME_OUT
330
+
331
+ # method emulation
332
+ def __call__(self, *var, **kwargs):
333
+ self.result = self.method(*var, **kwargs)
334
+
335
+ # run
336
+ def run(self, *var, **kwargs):
337
+ thr = threading.Thread(target=self, args=var, kwargs=kwargs)
338
+ thr.start()
339
+ thr.join()