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
File without changes
@@ -0,0 +1,116 @@
1
+ # TODO: the result of the tests depend on the cert/token used for the call. These particular results are for running with user pandasv1
2
+
3
+ import unittest
4
+ from datetime import datetime, timezone
5
+
6
+ from pandaserver.api.v1.http_client import HttpClient, api_url, api_url_ssl
7
+
8
+ # Get current UTC time with microseconds. The format needs to be compatible with the one used in the database
9
+ now_utc = datetime.now(timezone.utc)
10
+ formatted_time = now_utc.strftime("%d.%m.%y %H:%M:%S") + f".{now_utc.microsecond // 1000:02d}"
11
+
12
+ KEY = "test_key"
13
+ VALUE = "test_value"
14
+
15
+ NO_SSL_RESPONSE = {"success": False, "message": "SSL secure connection is required", "data": None}
16
+
17
+
18
+ class TestSecretManagementAPI(unittest.TestCase):
19
+ def setUp(self):
20
+ self.http_client = HttpClient()
21
+ self.urls = [api_url, api_url_ssl] # Run tests with both base URLs
22
+
23
+ def test_set_user_secrets(self):
24
+ for url in self.urls:
25
+ with self.subTest(base_url=url):
26
+ full_url = f"{url}/creds/set_user_secrets"
27
+ print(f"Testing URL: {full_url}")
28
+ data = {"key": KEY, "value": VALUE}
29
+ status, output = self.http_client.post(full_url, data)
30
+ print(output)
31
+ if url.startswith(api_url):
32
+ expected_response = NO_SSL_RESPONSE
33
+ else:
34
+ expected_response = {"success": True, "message": "OK", "data": None}
35
+ self.assertEqual(output, expected_response)
36
+
37
+ def test_get_user_secrets(self):
38
+ for url in self.urls:
39
+ with self.subTest(base_url=url):
40
+ full_url = f"{url}/creds/get_user_secrets"
41
+ print(f"Testing URL: {full_url}")
42
+ data = {"keys": KEY}
43
+ status, output = self.http_client.get(full_url, data)
44
+ print(output)
45
+ if url.startswith(api_url):
46
+ expected_response = NO_SSL_RESPONSE
47
+ else:
48
+ expected_response = {"success": True, "message": "", "data": '{"test_key": "test_value"}'}
49
+ self.assertEqual(output, expected_response)
50
+
51
+ def test_get_key_pair(self):
52
+ for url in self.urls:
53
+ with self.subTest(base_url=url):
54
+ full_url = f"{url}/creds/get_key_pair"
55
+ print(f"Testing URL: {full_url}")
56
+ data = {"public_key_name": "a", "private_key_name": "b"}
57
+ status, output = self.http_client.get(full_url, data)
58
+ print(output)
59
+ if url.startswith(api_url):
60
+ expected_response = NO_SSL_RESPONSE
61
+ else:
62
+ expected_response = {
63
+ "success": False,
64
+ "message": "Failed since 'pandasv1' not authorized with 'k' in ATLAS_PANDAMETA.USERS.GRIDPREF",
65
+ "data": None,
66
+ }
67
+ self.assertEqual(output, expected_response)
68
+
69
+ def test_get_proxy(self):
70
+ for url in self.urls:
71
+ with self.subTest(base_url=url):
72
+ full_url = f"{url}/creds/get_proxy"
73
+ print(f"Testing URL: {full_url}")
74
+ data = {"role": "atlas", "dn": "atlpilo2"}
75
+ status, output = self.http_client.get(full_url, data)
76
+ print(output)
77
+ if url.startswith(api_url):
78
+ expected_response = NO_SSL_RESPONSE
79
+ else:
80
+ expected_response = {"success": False, "message": "'proxy' not found for atlpilo2", "data": None}
81
+ self.assertEqual(output, expected_response)
82
+
83
+ def test_get_access_token(self):
84
+ for url in self.urls:
85
+ with self.subTest(base_url=url):
86
+ full_url = f"{url}/creds/get_access_token"
87
+ print(f"Testing URL: {full_url}")
88
+ data = {"client_name": "pilot_server"}
89
+ status, output = self.http_client.get(full_url, data)
90
+ print(output)
91
+ if url.startswith(api_url):
92
+ expected_response = NO_SSL_RESPONSE
93
+ else:
94
+ expected_response = {"success": False, "message": "failed since token key is invalid for pilot_server", "data": None}
95
+ self.assertEqual(output, expected_response)
96
+
97
+ def test_get_token_key(self):
98
+ for url in self.urls:
99
+ with self.subTest(base_url=url):
100
+ full_url = f"{url}/creds/get_token_key"
101
+ print(f"Testing URL: {full_url}")
102
+ data = {"client_name": "pilot_server"}
103
+ status, output = self.http_client.get(full_url, data)
104
+ print(output)
105
+ if url.startswith(api_url):
106
+ expected_response = NO_SSL_RESPONSE
107
+ else:
108
+ del output["data"]
109
+ del output["message"]
110
+ expected_response = {"success": True}
111
+ self.assertEqual(output, expected_response)
112
+
113
+
114
+ # Run tests
115
+ if __name__ == "__main__":
116
+ unittest.main()
@@ -0,0 +1,82 @@
1
+ # Description: Unit tests for the Data Carousel API methods
2
+ import os
3
+ import unittest
4
+ from datetime import datetime, timedelta
5
+
6
+ from pandaserver.api.v1.http_client import HttpClient, api_url_ssl
7
+
8
+ # to run the tests with a real Data Carousel request ID or dataset name by setting the environment variable
9
+ REQUEST_ID = int(os.environ.get("REQUEST_ID", None))
10
+ DATASET = str(os.environ.get("DATASET", None))
11
+
12
+
13
+ class TestDataCarouselAPI(unittest.TestCase):
14
+ def setUp(self):
15
+ self.http_client = HttpClient()
16
+
17
+ def test_change_staging_destination_by_request_id(self):
18
+ url = f"{api_url_ssl}/data_carousel/change_staging_destination"
19
+ print(f"Testing URL: {url}")
20
+ data = {"request_id": REQUEST_ID}
21
+ status, output = self.http_client.post(url, data)
22
+ print(status, output)
23
+ if status == 0 and output.get("data"):
24
+ self.assertEqual(output["data"].get("request_id"), REQUEST_ID)
25
+ self.assertIsInstance(output["data"].get("new_request_id"), int)
26
+
27
+ def test_change_staging_destination_by_dataset(self):
28
+ url = f"{api_url_ssl}/data_carousel/change_staging_destination"
29
+ print(f"Testing URL: {url}")
30
+ data = {"dataset": DATASET}
31
+ status, output = self.http_client.post(url, data)
32
+ print(status, output)
33
+ if status == 0 and output.get("data"):
34
+ self.assertEqual(output["data"].get("dataset"), DATASET)
35
+ self.assertIsInstance(output["data"].get("new_request_id"), int)
36
+
37
+ def test_change_staging_source_by_request_id(self):
38
+ url = f"{api_url_ssl}/data_carousel/change_staging_source"
39
+ print(f"Testing URL: {url}")
40
+ data = {"request_id": REQUEST_ID}
41
+ status, output = self.http_client.post(url, data)
42
+ print(status, output)
43
+ if status == 0 and output.get("data"):
44
+ self.assertEqual(output["data"].get("request_id"), REQUEST_ID)
45
+ self.assertIsInstance(output["data"].get("ddm_rule_id"), str)
46
+
47
+ def test_change_staging_source_by_dataset(self):
48
+ url = f"{api_url_ssl}/data_carousel/change_staging_source"
49
+ print(f"Testing URL: {url}")
50
+ data = {"dataset": DATASET}
51
+ status, output = self.http_client.post(url, data)
52
+ print(status, output)
53
+ if status == 0 and output.get("data"):
54
+ self.assertEqual(output["data"].get("dataset"), DATASET)
55
+ self.assertIsInstance(output["data"].get("ddm_rule_id"), str)
56
+
57
+ def test_force_to_staging_by_request_id(self):
58
+ url = f"{api_url_ssl}/data_carousel/force_to_staging"
59
+ print(f"Testing URL: {url}")
60
+ data = {"request_id": REQUEST_ID}
61
+ status, output = self.http_client.post(url, data)
62
+ print(status, output)
63
+ if status == 0 and output.get("data"):
64
+ self.assertEqual(output["data"].get("request_id"), REQUEST_ID)
65
+ self.assertEqual(output["data"].get("status"), "staging")
66
+ self.assertIsInstance(output["data"].get("ddm_rule_id"), str)
67
+
68
+ def test_force_to_staging_by_dataset(self):
69
+ url = f"{api_url_ssl}/data_carousel/force_to_staging"
70
+ print(f"Testing URL: {url}")
71
+ data = {"dataset": DATASET}
72
+ status, output = self.http_client.post(url, data)
73
+ print(status, output)
74
+ if status == 0 and output.get("data"):
75
+ self.assertEqual(output["data"].get("dataset"), DATASET)
76
+ self.assertEqual(output["data"].get("status"), "staging")
77
+ self.assertIsInstance(output["data"].get("ddm_rule_id"), str)
78
+
79
+
80
+ # Run tests
81
+ if __name__ == "__main__":
82
+ unittest.main()
@@ -0,0 +1,188 @@
1
+ import json
2
+ import unittest
3
+ from datetime import datetime, timezone
4
+
5
+ from pandaserver.api.v1.http_client import HttpClient, api_url_ssl
6
+
7
+ # Get current UTC time with microseconds. The format needs to be compatible with the one used in the database
8
+ now_utc = datetime.now(timezone.utc)
9
+ formatted_time = now_utc.strftime("%d.%m.%y %H:%M:%S") + f".{now_utc.microsecond // 1000:02d}"
10
+
11
+ HARVESTER_ID = "test_fbarreir"
12
+ HARVESTER_HOST = "test_fbarreir.cern.ch"
13
+ PANDA_QUEUE = "test_queue"
14
+
15
+
16
+ class TestHarvesterAPI(unittest.TestCase):
17
+ def setUp(self):
18
+ self.http_client = HttpClient()
19
+
20
+ def test_update_service_metrics(self):
21
+ url = f"{api_url_ssl}/harvester/update_service_metrics"
22
+ print(f"Testing URL: {url}")
23
+ harvester_id = HARVESTER_ID
24
+ harvester_host = HARVESTER_HOST
25
+ creation_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
26
+ metric = {
27
+ "rss_mib": 2737.36,
28
+ "memory_pc": 39.19,
29
+ "cpu_pc": 15.23,
30
+ "volume_data_pc": 20.0,
31
+ "cert_lifetime": {
32
+ "/data/atlpan/proxy/x509up_u25606_prod": 81,
33
+ "/data/atlpan/proxy/x509up_u25606_pilot": 81,
34
+ "/cephfs/atlpan/harvester/proxy/x509up_u25606_prod": 96,
35
+ "/cephfs/atlpan/harvester/proxy/x509up_u25606_pilot": 96,
36
+ },
37
+ }
38
+
39
+ # DBProxy expects the metrics in json format and stores them directly in the database
40
+ metrics = [[creation_time, harvester_host, json.dumps(metric)]]
41
+
42
+ data = {"harvester_id": harvester_id, "metrics": metrics}
43
+ status, output = self.http_client.post(url, data)
44
+ print(output)
45
+ expected_response = {"success": True, "message": "", "data": [True]}
46
+ self.assertEqual(output, expected_response)
47
+
48
+ def test_add_dialogs(self):
49
+ url = f"{api_url_ssl}/harvester/add_dialogs"
50
+ print(f"Testing URL: {url}")
51
+ harvester_id = HARVESTER_ID
52
+
53
+ dialog = {
54
+ "diagID": 1,
55
+ "moduleName": "test_module",
56
+ "identifier": "test identifier",
57
+ "creationTime": datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"),
58
+ "messageLevel": "INFO",
59
+ "diagMessage": "test message",
60
+ }
61
+
62
+ dialogs = [dialog]
63
+
64
+ data = {"harvester_id": harvester_id, "dialogs": dialogs}
65
+ status, output = self.http_client.post(url, data)
66
+ print(output)
67
+ expected_response = {"success": True, "message": "", "data": None}
68
+ self.assertEqual(output, expected_response)
69
+
70
+ def test_heartbeat(self):
71
+ url = f"{api_url_ssl}/harvester/heartbeat"
72
+ print(f"Testing URL: {url}")
73
+ harvester_id = HARVESTER_ID
74
+ data = {"harvester_id": harvester_id, "data": []}
75
+ status, output = self.http_client.post(url, data)
76
+
77
+ expected_response = {"success": True, "message": "", "data": None}
78
+ self.assertEqual(output, expected_response)
79
+
80
+ def test_get_worker_statistics(self):
81
+ url = f"{api_url_ssl}/harvester/get_worker_statistics"
82
+ print(f"Testing URL: {url}")
83
+ data = {}
84
+ status, output = self.http_client.get(url, data)
85
+ print(output)
86
+ # the statistics can't be predicted, so we just check the type of the response
87
+ self.assertEqual(True, output["success"])
88
+ self.assertEqual(dict, type(output["data"]))
89
+
90
+ def test_get_current_worker_id(self):
91
+ url = f"{api_url_ssl}/harvester/get_current_worker_id"
92
+ print(f"Testing URL: {url}")
93
+ data = {"harvester_id": HARVESTER_ID}
94
+ status, output = self.http_client.get(url, data)
95
+ print(output)
96
+ # the current/max worker id can't be predicted, so we just check the type of the response
97
+ self.assertEqual(True, output["success"])
98
+ self.assertEqual(int, type(output["data"]))
99
+
100
+ def test_report_worker_statistics(self):
101
+ url = f"{api_url_ssl}/harvester/report_worker_statistics"
102
+ print(f"Testing URL: {url}")
103
+ harvester_id = HARVESTER_ID
104
+ panda_queue = PANDA_QUEUE
105
+ # the json loads is done in DBProxy
106
+ statistics = json.dumps({"user": {"SCORE": {"running": 1, "submitted": 1}}, "managed": {"MCORE": {"running": 1, "submitted": 1}}})
107
+ data = {"harvester_id": harvester_id, "panda_queue": panda_queue, "statistics": statistics}
108
+ status, output = self.http_client.post(url, data)
109
+ print(output)
110
+ expected_response = {"success": True, "message": "OK", "data": None}
111
+ self.assertEqual(output, expected_response)
112
+
113
+ def test_update_workers(self):
114
+ url = f"{api_url_ssl}/harvester/update_workers"
115
+ print(f"Testing URL: {url}")
116
+ worker = {
117
+ "workerID": 1,
118
+ "batchID": 1,
119
+ "queueName": "queue1",
120
+ "status": "running",
121
+ "computingSite": "site1",
122
+ "nCore": 1,
123
+ "nodeID": None,
124
+ "submitTime": "02-NOV-24 00:02:18",
125
+ "startTime": "02-NOV-24 00:02:18",
126
+ "endTime": None,
127
+ "jobType": "managed",
128
+ "resourceType": "SCORE",
129
+ "nativeExitCode": None,
130
+ "nativeStatus": None,
131
+ "diagMessage": None,
132
+ "nJobs": 1,
133
+ "computingElement": "ce1",
134
+ "syncLevel": 0,
135
+ "submissionHost": "submissionhost1",
136
+ "harvesterHost": "harvesterhost1",
137
+ "errorCode": None,
138
+ "minRamCount": 2000,
139
+ }
140
+ workers = [worker]
141
+
142
+ harvester_id = HARVESTER_ID
143
+ data = {"harvester_id": harvester_id, "workers": workers}
144
+
145
+ status, output = self.http_client.post(url, data)
146
+ print(output)
147
+ expected_response = {"success": True, "message": "", "data": [True]}
148
+
149
+ self.assertEqual(output, expected_response)
150
+
151
+ def test_acquire_commands(self):
152
+ url = f"{api_url_ssl}/harvester/acquire_commands"
153
+ print(f"Testing URL: {url}")
154
+
155
+ harvester_id = HARVESTER_ID
156
+ n_commands = 1
157
+ data = {"harvester_id": harvester_id, "n_commands": n_commands}
158
+ status, output = self.http_client.post(url, data)
159
+ print(output)
160
+ # the commands can't be predicted, so we just check the type of the response
161
+ self.assertEqual(True, output["success"])
162
+ self.assertEqual(list, type(output["data"]))
163
+
164
+ def test_acknowledge_commands(self):
165
+ url = f"{api_url_ssl}/harvester/acknowledge_commands"
166
+ print(f"Testing URL: {url}")
167
+ command_ids = [1]
168
+ data = {"command_ids": command_ids}
169
+ status, output = self.http_client.post(url, data)
170
+ print(output)
171
+ expected_response = {"success": True, "message": "", "data": None}
172
+ self.assertEqual(output, expected_response)
173
+
174
+ def test_add_target_slots(self):
175
+ url = f"{api_url_ssl}/harvester/add_target_slots"
176
+ print(f"Testing URL: {url}")
177
+ panda_queue = PANDA_QUEUE
178
+ slots = 0
179
+ data = {"panda_queue": panda_queue, "slots": slots}
180
+ status, output = self.http_client.post(url, data)
181
+ print(output)
182
+ self.assertEqual(True, output["success"])
183
+ self.assertEqual(None, output["data"])
184
+
185
+
186
+ # Run tests
187
+ if __name__ == "__main__":
188
+ unittest.main()
@@ -0,0 +1,45 @@
1
+ # Description: Unit tests for the IDDS API methods
2
+ # TODO: These tests are placeholders and need to be completed
3
+ import unittest
4
+
5
+ from pandaserver.api.v1.http_client import HttpClient, api_url_ssl
6
+
7
+
8
+ class TestIDDSAPI(unittest.TestCase):
9
+ def setUp(self):
10
+ self.http_client = HttpClient()
11
+
12
+ def test_relay_idds_command(self):
13
+ url = f"{api_url_ssl}/idds/relay_idds_command"
14
+ print(f"Testing URL: {url}")
15
+ data = {}
16
+ status, output = self.http_client.get(url, data)
17
+ print(output)
18
+ output["status"] = status
19
+
20
+ # Remove the data field from the response for comparison
21
+ del output["data"]
22
+
23
+ expected_response = {"success": True, "message": "", "status": 0}
24
+
25
+ self.assertEqual(output, expected_response)
26
+
27
+ def test_execute_idds_workflow_command(self):
28
+ url = f"{api_url_ssl}/statistics/execute_idds_workflow_command"
29
+ print(f"Testing URL: {url}")
30
+ data = {}
31
+ status, output = self.http_client.get(url, data)
32
+ print(output)
33
+ output["status"] = status
34
+
35
+ # Remove the data field from the response for comparison
36
+ del output["data"]
37
+
38
+ expected_response = {"success": True, "message": "", "status": 0}
39
+
40
+ self.assertEqual(output, expected_response)
41
+
42
+
43
+ # Run tests
44
+ if __name__ == "__main__":
45
+ unittest.main()
@@ -0,0 +1,112 @@
1
+ # Description: Unit tests for the Job API methods
2
+ import os
3
+ import unittest
4
+
5
+ from pandaserver.api.v1.http_client import HttpClient, api_url_ssl
6
+
7
+ # To run tests with real IDs, set environment variables:
8
+ # PANDA_JOB_ID_TEST=<job_id> JEDI_TASK_ID_TEST=<task_id>
9
+ PANDA_JOB_ID = int(os.environ.get("PANDA_JOB_ID_TEST", -1))
10
+ JEDI_TASK_ID = int(os.environ.get("JEDI_TASK_ID_TEST", -1))
11
+
12
+
13
+ class TestJobAPI(unittest.TestCase):
14
+ def setUp(self):
15
+ self.http_client = HttpClient()
16
+
17
+ def test_get_status(self):
18
+ # def get_status(req: PandaRequest, job_ids: List[int], timeout: int = 60) -> Dict:
19
+ url = f"{api_url_ssl}/job/get_status"
20
+ print(f"Testing URL: {url}")
21
+ data = {"job_ids": [PANDA_JOB_ID]}
22
+ status, output = self.http_client.get(url, data)
23
+ print(output)
24
+ output["status"] = status
25
+ del output["data"]
26
+ del output["message"]
27
+
28
+ # Returns success=True regardless of whether job exists (returns empty or None entries)
29
+ expected_response = {"status": 0, "success": True}
30
+ self.assertEqual(output, expected_response)
31
+
32
+ def test_get_description(self):
33
+ # def get_description(req: PandaRequest, job_ids: List[int]) -> Dict:
34
+ url = f"{api_url_ssl}/job/get_description"
35
+ print(f"Testing URL: {url}")
36
+ data = {"job_ids": [PANDA_JOB_ID]}
37
+ status, output = self.http_client.get(url, data)
38
+ print(output)
39
+ output["status"] = status
40
+ del output["data"]
41
+ del output["message"]
42
+
43
+ # Returns success=True regardless (returns [None] for unknown job IDs)
44
+ expected_response = {"status": 0, "success": True}
45
+ self.assertEqual(output, expected_response)
46
+
47
+ def test_get_description_incl_archive(self):
48
+ # def get_description_incl_archive(req: PandaRequest, job_ids: List[int]) -> Dict:
49
+ url = f"{api_url_ssl}/job/get_description_incl_archive"
50
+ print(f"Testing URL: {url}")
51
+ data = {"job_ids": [PANDA_JOB_ID]}
52
+ status, output = self.http_client.get(url, data)
53
+ print(output)
54
+ output["status"] = status
55
+ del output["data"]
56
+ del output["message"]
57
+
58
+ # Returns success=True regardless (returns [None] for unknown job IDs)
59
+ expected_response = {"status": 0, "success": True}
60
+ self.assertEqual(output, expected_response)
61
+
62
+ def test_get_metadata_for_analysis_jobs(self):
63
+ # def get_metadata_for_analysis_jobs(req: PandaRequest, task_id: int) -> Dict:
64
+ url = f"{api_url_ssl}/job/get_metadata_for_analysis_jobs"
65
+ print(f"Testing URL: {url}")
66
+ data = {"task_id": JEDI_TASK_ID}
67
+ status, output = self.http_client.get(url, data)
68
+ print(output)
69
+ output["status"] = status
70
+ del output["data"]
71
+
72
+ if JEDI_TASK_ID == -1:
73
+ # Fake task returns success=True with "No metadata found" message
74
+ expected_response = {"status": 0, "success": True, "message": "No metadata found"}
75
+ else:
76
+ # Real task
77
+ expected_response = {"status": 0, "success": True, "message": ""}
78
+ output["message"] = ""
79
+ self.assertEqual(output, expected_response)
80
+
81
+ def test_kill(self):
82
+ # def kill(req, job_ids: List[int], code: int = None, ...) -> Dict:
83
+ url = f"{api_url_ssl}/job/kill"
84
+ print(f"Testing URL: {url}")
85
+ data = {"job_ids": [PANDA_JOB_ID]}
86
+ status, output = self.http_client.post(url, data)
87
+ print(output)
88
+ output["status"] = status
89
+ del output["data"]
90
+ del output["message"]
91
+
92
+ # killJobs always returns success=True
93
+ expected_response = {"status": 0, "success": True}
94
+ self.assertEqual(output, expected_response)
95
+
96
+ def test_reassign(self):
97
+ # def reassign(req: PandaRequest, job_ids: List[int]) -> Dict:
98
+ url = f"{api_url_ssl}/job/reassign"
99
+ print(f"Testing URL: {url}")
100
+ data = {"job_ids": [PANDA_JOB_ID]}
101
+ status, output = self.http_client.post(url, data)
102
+ print(output)
103
+ output["status"] = status
104
+ del output["message"]
105
+
106
+ # reassignJobs always returns success=True
107
+ expected_response = {"status": 0, "success": True, "data": None}
108
+ self.assertEqual(output, expected_response)
109
+
110
+
111
+ if __name__ == "__main__":
112
+ unittest.main()