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,405 @@
1
+ import datetime
2
+ import functools
3
+ import json
4
+ import os
5
+ import socket
6
+ import sys
7
+ import traceback
8
+ from zlib import adler32
9
+
10
+ from pandacommon.pandalogger import logger_utils
11
+ from pandacommon.pandalogger.PandaLogger import PandaLogger
12
+ from pandacommon.pandautils.PandaUtils import naive_utcnow
13
+ from pandacommon.pandautils.thread_utils import GenericThread
14
+
15
+ from pandaserver.config import panda_config
16
+ from pandaserver.daemons.scripts.metric_collector import MetricsDB
17
+
18
+ # logger
19
+ main_logger = PandaLogger().getLogger("task_evaluator")
20
+
21
+ # dry run
22
+ DRY_RUN = False
23
+
24
+ # list of metrics in FetchData to fetch data and update to DB. Format: (metric, period_minutes)
25
+ metric_list = [
26
+ ("analy_task_eval", 10),
27
+ ]
28
+
29
+ # constant maps
30
+ # class_value_rank_map = {1: 'A_sites', 0: 'B_sites', -1: 'C_sites'}
31
+
32
+
33
+ class TaskEvaluationDB(object):
34
+ """
35
+ Proxy to access the task_evaluation table in DB
36
+ """
37
+
38
+ def __init__(self, tbuf):
39
+ self.tbuf = tbuf
40
+
41
+ def _decor(method):
42
+ def _decorator(_method, *args, **kwargs):
43
+ @functools.wraps(_method)
44
+ def _wrapped_method(self, *args, **kwargs):
45
+ try:
46
+ _method(self, *args, **kwargs)
47
+ except Exception as exc:
48
+ pass
49
+
50
+ return _wrapped_method
51
+
52
+ return _decorator(method)
53
+
54
+ def update(self, metric, entity_dict):
55
+ tmp_log = logger_utils.make_logger(main_logger, "TaskEvaluationDB.update")
56
+ tmp_log.debug(f"start metric={metric}")
57
+ # sql
58
+ sql_query_taskid = """SELECT jediTaskID """ """FROM ATLAS_PANDA.Task_Evaluation """ """WHERE metric = :metric """
59
+ sql_update = (
60
+ """UPDATE ATLAS_PANDA.Task_Evaluation SET """
61
+ """value_json = :patch_value_json, """
62
+ """timestamp = :timestamp """
63
+ """WHERE jediTaskID=:taskID AND metric=:metric """
64
+ )
65
+ sql_insert = """INSERT INTO ATLAS_PANDA.Task_Evaluation """ """VALUES ( """ """:taskID, :metric, :patch_value_json, :timestamp """ """) """
66
+ # now
67
+ now_time = naive_utcnow()
68
+ # get existing taskID list
69
+ res = self.tbuf.querySQL(sql_query_taskid, {":metric": metric})
70
+ existing_taskID_list = [taskID for (taskID,) in res]
71
+ # var map template
72
+ varMap_template = {
73
+ ":taskID": None,
74
+ ":metric": metric,
75
+ ":timestamp": now_time,
76
+ ":patch_value_json": None,
77
+ }
78
+ # make var map lists
79
+ update_varMap_list = []
80
+ insert_varMap_list = []
81
+ for taskID, v in entity_dict.items():
82
+ # values to json string
83
+ try:
84
+ patch_value_json = json.dumps(v)
85
+ except Exception:
86
+ tmp_log.error(traceback.format_exc() + " " + str(v))
87
+ return
88
+ # update varMap
89
+ varMap = varMap_template.copy()
90
+ varMap[":taskID"] = taskID
91
+ varMap[":patch_value_json"] = patch_value_json
92
+ # append to the list
93
+ if taskID in existing_taskID_list:
94
+ update_varMap_list.append(varMap)
95
+ else:
96
+ insert_varMap_list.append(varMap)
97
+ # update
98
+ n_row = self.tbuf.executemanySQL(sql_update, update_varMap_list)
99
+ if n_row < len(update_varMap_list):
100
+ tmp_log.warning(f"only {n_row}/{len(update_varMap_list)} rows updated for metric={metric}")
101
+ else:
102
+ tmp_log.debug(f"updated {len(update_varMap_list)} rows for metric={metric}")
103
+ # insert
104
+ n_row = self.tbuf.executemanySQL(sql_insert, insert_varMap_list)
105
+ if n_row is None:
106
+ # try to insert one by one
107
+ n_row = 0
108
+ for varMap in insert_varMap_list:
109
+ res = self.tbuf.querySQL(sql_insert, varMap)
110
+ try:
111
+ n_row += res
112
+ except TypeError:
113
+ pass
114
+ if n_row < len(insert_varMap_list):
115
+ tmp_log.warning(f"only {n_row}/{len(insert_varMap_list)} rows inserted for metric={metric}")
116
+ else:
117
+ tmp_log.debug(f"inserted {len(insert_varMap_list)} rows for metric={metric}")
118
+ # done
119
+ tmp_log.debug(f"done metric={metric}")
120
+
121
+ def get_metrics(self, metric, fresher_than_minutes_ago=120):
122
+ tmp_log = logger_utils.make_logger(main_logger, "TaskEvaluationDB.update")
123
+ tmp_log.debug(f"start metric={metric}")
124
+ # sql
125
+ sql_query = (
126
+ """SELECT jediTaskID, value_json """ """FROM ATLAS_PANDA.Task_Evaluation """ """WHERE metric = :metric """ """AND timestamp >= :min_timestamp """
127
+ )
128
+ # now
129
+ now_time = naive_utcnow()
130
+ # var map
131
+ varMap = {
132
+ ":metric": metric,
133
+ ":min_timestamp": now_time - datetime.timedelta(minutes=fresher_than_minutes_ago),
134
+ }
135
+ # query
136
+ res = self.tbuf.querySQL(sql_query, varMap)
137
+ if res is None:
138
+ tmp_log.warning(f"failed to query metric={metric}")
139
+ return
140
+ # return map
141
+ ret_map = {}
142
+ for taskID, value_json in res:
143
+ try:
144
+ value_dict = json.loads(value_json)
145
+ except Exception:
146
+ tmp_log.error(traceback.format_exc() + " " + str(taskID) + str(value_json))
147
+ else:
148
+ ret_map[taskID] = value_dict
149
+ # return
150
+ return ret_map
151
+
152
+ def clean_up(self, metric, fresher_than_minutes_ago=120):
153
+ tmp_log = logger_utils.make_logger(main_logger, "TaskEvaluationDB.clean_up")
154
+ tmp_log.debug(f"start metric={metric}")
155
+ # sql
156
+ sql_delete_terminated_tasks = (
157
+ "DELETE "
158
+ "FROM ATLAS_PANDA.Task_Evaluation te "
159
+ "WHERE te.jediTaskID IN ( "
160
+ "SELECT jt.jediTaskID "
161
+ "FROM ATLAS_PANDA.JEDI_Tasks jt, ATLAS_PANDA.Task_Evaluation tez "
162
+ "WHERE tez.jediTaskID = jt.jediTaskID "
163
+ "AND jt.status IN ('done', 'finished', 'failed', 'broken', 'aborted', 'exhausted') "
164
+ ") "
165
+ "AND te.metric = :metric "
166
+ "AND te.timestamp <= :max_timestamp "
167
+ )
168
+ # now
169
+ now_time = naive_utcnow()
170
+ # var map
171
+ varMap = {
172
+ ":metric": metric,
173
+ ":max_timestamp": now_time - datetime.timedelta(minutes=fresher_than_minutes_ago),
174
+ }
175
+ # clean up
176
+ n_row = self.tbuf.querySQL(sql_delete_terminated_tasks, varMap)
177
+ tmp_log.debug(f"cleaned up {n_row} rows for metric={metric}")
178
+
179
+
180
+ class FetchData(object):
181
+ """
182
+ methods to fetch or evaluate data values to store
183
+ """
184
+
185
+ def __init__(self, tbuf):
186
+ self.tbuf = tbuf
187
+ # initialize stored data
188
+ self.gshare_status = None
189
+
190
+ def analy_task_eval(self):
191
+ tmp_log = logger_utils.make_logger(main_logger, "FetchData")
192
+ # sql
193
+ sql_get_active_tasks = (
194
+ "SELECT jt.jediTaskID, jt.userName, jt.gshare "
195
+ "FROM ATLAS_PANDA.JEDI_Tasks jt, ATLAS_PANDA.JEDI_AUX_Status_MinTaskID asm "
196
+ "WHERE jt.taskType = 'anal' AND jt.prodSourceLabel = 'user' "
197
+ "AND jt.status=asm.status AND jt.jediTaskID >= asm.min_jediTaskID "
198
+ "AND jt.status IN ('scouting', 'scouted', 'running', 'pending', 'throttled') "
199
+ "AND jt.userName NOT IN ('gangarbt') "
200
+ "AND jt.modificationTime >= CURRENT_DATE - 30 "
201
+ )
202
+ sql_get_task_dsinfo = (
203
+ "SELECT ds.jediTaskID, SUM(ds.nFiles), SUM(ds.nFilesFinished), SUM(ds.nFilesFailed) "
204
+ "FROM ATLAS_PANDA.JEDI_Datasets ds "
205
+ "WHERE ds.jediTaskID = :taskID "
206
+ "AND ds.type IN ('input', 'pseudo_input') "
207
+ "AND ds.masterID IS NULL "
208
+ "GROUP BY ds.jediTaskID "
209
+ )
210
+ sql_get_task_n_jobs = (
211
+ "SELECT COUNT(*) FROM ( "
212
+ "SELECT DISTINCT c.PandaID "
213
+ "FROM ATLAS_PANDA.JEDI_Datasets ds, ATLAS_PANDA.JEDI_Dataset_Contents c "
214
+ "WHERE c.jediTaskID=ds.jediTaskID AND c.datasetID=ds.datasetID "
215
+ "AND ds.jediTaskID=:taskID AND ds.masterID IS NULL "
216
+ "AND ds.type IN ('input', 'pseudo_input') "
217
+ ") "
218
+ )
219
+ try:
220
+ # initialize
221
+ # tmp_site_dict = dict()
222
+ task_dict = dict()
223
+ # now time
224
+ now_time = naive_utcnow()
225
+ # MetricsDB
226
+ mdb = MetricsDB(self.tbuf)
227
+ # get user evaluation
228
+ ue_dict = mdb.get_metrics("analy_user_eval", "neither", fresher_than_minutes_ago=20)
229
+ # get active tasks
230
+ varMap = {}
231
+ active_tasks_list = self.tbuf.querySQL(sql_get_active_tasks, varMap)
232
+ taskID_list = [task[0] for task in active_tasks_list]
233
+ n_tot_tasks = len(active_tasks_list)
234
+ tmp_log.debug(f"got total {n_tot_tasks} tasks")
235
+ # counter
236
+ cc = 0
237
+ n_tasks_dict = {
238
+ 2: 0,
239
+ 1: 0,
240
+ 0: 0,
241
+ -1: 0,
242
+ }
243
+ # loop over tasks
244
+ for taskID, user, gshare in active_tasks_list:
245
+ # initialize
246
+ task_class = 1
247
+ n_files_total = 0
248
+ n_files_finished = 0
249
+ n_files_failed = 0
250
+ n_files_remaining = 0
251
+ pct_finished = 0
252
+ pct_failed = 0
253
+ n_jobs = 0
254
+ n_jobs_remaining = 0
255
+ # get dataset info of each task
256
+ varMap = {":taskID": taskID}
257
+ dsinfo_list = self.tbuf.querySQL(sql_get_task_dsinfo, varMap)
258
+ dsinfo_dict = {
259
+ tup[0]: {
260
+ "nFiles": tup[1],
261
+ "nFilesFinished": tup[2],
262
+ "nFilesFailed": tup[3],
263
+ }
264
+ for tup in dsinfo_list
265
+ }
266
+ # get n jobs of each task
267
+ tmp_res = self.tbuf.querySQL(sql_get_task_n_jobs, varMap)
268
+ for obj in tmp_res:
269
+ (n_jobs,) = obj
270
+ dsinfo_dict.setdefault(taskID, {})
271
+ dsinfo_dict[taskID]["nJobs"] = n_jobs
272
+ break
273
+ # get task proceeding progress
274
+ ds_info = dsinfo_dict.get(taskID)
275
+ if ds_info is not None:
276
+ n_files_total = ds_info.get("nFiles", 0)
277
+ n_files_finished = ds_info.get("nFilesFinished", 0)
278
+ n_files_failed = ds_info.get("nFilesFailed", 0)
279
+ n_files_remaining = max(n_files_total - n_files_finished - n_files_failed, 0)
280
+ n_jobs = ds_info.get("nJobs", 0)
281
+ if n_files_total > 0:
282
+ pct_finished = n_files_finished * 100 / n_files_total
283
+ pct_failed = n_files_failed * 100 / n_files_total
284
+ n_jobs_remaining = int(n_jobs * n_files_remaining / n_files_total)
285
+ # classify
286
+ if gshare == "Express Analysis":
287
+ # Express Analysis tasks always in class S
288
+ task_class = 2
289
+ else:
290
+ # parameters
291
+ progress_to_boost_A = self.tbuf.getConfigValue("analy_eval", "PROGRESS_TO_BOOST_A", default=90)
292
+ progress_to_boost_B = self.tbuf.getConfigValue("analy_eval", "PROGRESS_TO_BOOST_B", default=95)
293
+ max_rem_jobs_to_boost_A = self.tbuf.getConfigValue("analy_eval", "MAX_REM_JOBS_TO_BOOST_A", default=500)
294
+ max_rem_jobs_to_boost_B = self.tbuf.getConfigValue("analy_eval", "MAX_REM_JOBS_TO_BOOST_B", default=200)
295
+ # check usage of the user
296
+ usage_dict = ue_dict.get(user)
297
+ if usage_dict is None:
298
+ continue
299
+ if usage_dict["rem_slots_A"] <= 0:
300
+ if usage_dict["rem_slots_B"] <= 0:
301
+ task_class = -1
302
+ else:
303
+ task_class = 0
304
+ # boost for nearly done tasks
305
+ if task_class == 1 and pct_finished >= progress_to_boost_A and n_jobs_remaining > 0 and n_jobs_remaining <= max_rem_jobs_to_boost_A:
306
+ # almost done A-tasks, to boost
307
+ task_class = 2
308
+ elif task_class == 0 and pct_finished >= progress_to_boost_B and n_jobs_remaining > 0 and n_jobs_remaining <= max_rem_jobs_to_boost_B:
309
+ # almost done B-tasks, to boost
310
+ task_class = 2
311
+ # fill in task class
312
+ task_dict[taskID] = {
313
+ "task_id": taskID,
314
+ "user": user,
315
+ "gshare": gshare,
316
+ "n_files_total": n_files_total,
317
+ "n_files_finished": n_files_finished,
318
+ "n_files_failed": n_files_failed,
319
+ "pct_finished": pct_finished,
320
+ "pct_failed": pct_failed,
321
+ "class": task_class,
322
+ }
323
+ # counter
324
+ cc += 1
325
+ if cc % 5000 == 0:
326
+ tmp_log.debug(f"evaluated {cc:6d} tasks")
327
+ n_tasks_dict[task_class] += 1
328
+ tmp_log.debug(f"evaluated {cc:6d} tasks in total (S:{n_tasks_dict[2]}, A:{n_tasks_dict[1]}, B:{n_tasks_dict[0]}, C:{n_tasks_dict[-1]})")
329
+ # return
330
+ # tmp_log.debug('{}'.format(str([ v for v in task_dict.values() if v['class'] != 1 ])[:3000]))
331
+ tmp_log.debug("done")
332
+ return task_dict
333
+ except Exception:
334
+ tmp_log.error(traceback.format_exc())
335
+
336
+
337
+ # main
338
+ def main(tbuf=None, **kwargs):
339
+ # instantiate TB
340
+ if tbuf is None:
341
+ from pandaserver.taskbuffer.TaskBuffer import taskBuffer
342
+
343
+ requester_id = GenericThread().get_full_id(__name__, sys.modules[__name__].__file__)
344
+ taskBuffer.init(
345
+ panda_config.dbhost,
346
+ panda_config.dbpasswd,
347
+ nDBConnection=1,
348
+ useTimeout=True,
349
+ requester=requester_id,
350
+ )
351
+ else:
352
+ taskBuffer = tbuf
353
+ # pid
354
+ my_pid = os.getpid()
355
+ my_full_pid = f"{socket.getfqdn().split('.')[0]}-{os.getpgrp()}-{my_pid}"
356
+ # go
357
+ if DRY_RUN:
358
+ # dry run, regardless of lock, not update DB
359
+ fetcher = FetchData(taskBuffer)
360
+ # loop over all fetch data methods to run and update to DB
361
+ for metric_name, period in metric_list:
362
+ main_logger.debug(f"(dry-run) start {metric_name}")
363
+ # fetch data and update DB
364
+ the_method = getattr(fetcher, metric_name)
365
+ fetched_data = the_method()
366
+ if fetched_data is None:
367
+ main_logger.warning(f"(dry-run) {metric_name} got no valid data")
368
+ continue
369
+ main_logger.debug(f"(dry-run) done {metric_name}")
370
+ else:
371
+ # real run, will update DB
372
+ # instantiate
373
+ tedb = TaskEvaluationDB(taskBuffer)
374
+ fetcher = FetchData(taskBuffer)
375
+ # loop over all fetch data methods to run and update to DB
376
+ for metric_name, period in metric_list:
377
+ # metric lock
378
+ lock_component_name = f"pandaTaskEval.{metric_name:.30}.{adler32(metric_name.encode('utf-8')):0x}"
379
+ # try to get lock
380
+ got_lock = taskBuffer.lockProcess_PANDA(component=lock_component_name, pid=my_full_pid, time_limit=period)
381
+ if got_lock:
382
+ main_logger.debug(f"got lock of {metric_name}")
383
+ else:
384
+ main_logger.debug(f"{metric_name} locked by other process; skipped...")
385
+ continue
386
+ main_logger.debug(f"start {metric_name}")
387
+ # clean up
388
+ tedb.clean_up(metric=metric_name, fresher_than_minutes_ago=120)
389
+ main_logger.debug(f"cleaned up {metric_name}")
390
+ # fetch data and update DB
391
+ the_method = getattr(fetcher, metric_name)
392
+ fetched_data = the_method()
393
+ if fetched_data is None:
394
+ main_logger.warning(f"{metric_name} got no valid data")
395
+ continue
396
+ tedb.update(metric=metric_name, entity_dict=fetched_data)
397
+ main_logger.debug(f"done {metric_name}")
398
+ # stop taskBuffer if created inside this script
399
+ if tbuf is None:
400
+ taskBuffer.cleanup(requester=requester_id)
401
+
402
+
403
+ # run
404
+ if __name__ == "__main__":
405
+ main()
@@ -0,0 +1,70 @@
1
+ import datetime
2
+ import glob
3
+ import optparse
4
+ import os
5
+ import sys
6
+
7
+ from pandacommon.pandautils.PandaUtils import naive_utcnow
8
+
9
+
10
+ # main
11
+ def main(argv=tuple(), **kwargs):
12
+ # options
13
+ optP = optparse.OptionParser(conflict_handler="resolve")
14
+ optP.add_option(
15
+ "-t",
16
+ action="store_const",
17
+ const=True,
18
+ dest="test",
19
+ default=False,
20
+ help="test mode",
21
+ )
22
+ optP.add_option(
23
+ "-h",
24
+ action="store",
25
+ type="int",
26
+ dest="limit",
27
+ default=12,
28
+ help="time limit in hour",
29
+ )
30
+ options, args = optP.parse_args(args=argv[1:])
31
+
32
+ # patterns of tmp files
33
+ tmpPatts = ["/tmp/tmp*", "/tmp/atlpan/tmp*", "/tmp/pansrv/tmp*"]
34
+
35
+ # limit
36
+ timeLimit = naive_utcnow() - datetime.timedelta(hours=options.limit)
37
+
38
+ # loop over all pattern
39
+ for tmpPatt in tmpPatts:
40
+ tmpFiles = glob.glob(tmpPatt)
41
+ # loop over all files
42
+ for tmpFile in tmpFiles:
43
+ try:
44
+ print(f"INFO: tmpfile -> {tmpFile}")
45
+ # only file
46
+ if not os.path.isfile(tmpFile):
47
+ continue
48
+ # not symlink
49
+ if os.path.islink(tmpFile):
50
+ continue
51
+ # writable
52
+ if not os.access(tmpFile, os.W_OK):
53
+ continue
54
+ # check time stamp
55
+ timeStamp = os.path.getmtime(tmpFile)
56
+ timeStamp = datetime.datetime.fromtimestamp(timeStamp)
57
+ if timeStamp > timeLimit:
58
+ continue
59
+ # remove
60
+ print(f"INFO: remove {tmpFile}")
61
+ if not options.test:
62
+ os.remove(tmpFile)
63
+ except Exception:
64
+ errType, errValue = sys.exc_info()[:2]
65
+ print(f"ERROR: failed with {errType}:{errValue}")
66
+
67
+
68
+ # run
69
+ if __name__ == "__main__":
70
+ main(argv=sys.argv)
@@ -0,0 +1,97 @@
1
+ import sys
2
+ import time
3
+ import traceback
4
+
5
+ from pandacommon.pandalogger.PandaLogger import PandaLogger
6
+ from pandacommon.pandautils.thread_utils import GenericThread
7
+ from pandaserver.config import panda_config
8
+ from pandaserver.taskbuffer.Utils import create_shards
9
+
10
+ # logger
11
+ _logger = PandaLogger().getLogger("worker_sync")
12
+
13
+
14
+ def translate_status_to_command(pilot_status):
15
+ if pilot_status == "running":
16
+ return "SYNC_WORKERS_ACTIVATE"
17
+ if pilot_status == "finished":
18
+ return "SYNC_WORKERS_KILL"
19
+ return None
20
+
21
+
22
+ class WorkerSync(object):
23
+ def __init__(self, tbuf):
24
+ self._logger = _logger
25
+ self.tbuf = tbuf
26
+ return
27
+
28
+ def run(self):
29
+ """
30
+ Identifies workers with stale harvester states and newer pilot states
31
+ :return:
32
+ """
33
+
34
+ # timing
35
+ time_start = time.time()
36
+ self._logger.debug("Start.")
37
+
38
+ # variables for the harvester command
39
+ status = "new"
40
+ ack_requested = False
41
+ lock_interval = None
42
+ com_interval = None
43
+
44
+ try:
45
+ stale_workers_per_harvester = self.tbuf.get_workers_to_synchronize()
46
+ for harvester_id in stale_workers_per_harvester:
47
+ for pilot_status in stale_workers_per_harvester[harvester_id]:
48
+ command = translate_status_to_command(pilot_status)
49
+ if command:
50
+ workers = stale_workers_per_harvester[harvester_id][pilot_status]
51
+ for worker_shard in create_shards(workers, 100):
52
+ self._logger.debug(f"Processing harvester_id={harvester_id} pilot_status={pilot_status}. Workers to update: {worker_shard}")
53
+ self.tbuf.commandToHarvester(
54
+ harvester_id,
55
+ command,
56
+ ack_requested,
57
+ status,
58
+ lock_interval,
59
+ com_interval,
60
+ worker_shard,
61
+ )
62
+ except Exception:
63
+ self._logger.error(traceback.format_exc())
64
+
65
+ # timing
66
+ time_stop = time.time()
67
+ self._logger.debug(f"Done. Worker sync took: {time_stop - time_start} s")
68
+
69
+ return
70
+
71
+
72
+ # main
73
+ def main(tbuf=None, **kwargs):
74
+ # instantiate TB
75
+ if tbuf is None:
76
+ from pandaserver.taskbuffer.TaskBuffer import taskBuffer
77
+
78
+ requester_id = GenericThread().get_full_id(__name__, sys.modules[__name__].__file__)
79
+ taskBuffer.init(
80
+ panda_config.dbhost,
81
+ panda_config.dbpasswd,
82
+ nDBConnection=1,
83
+ useTimeout=True,
84
+ requester=requester_id,
85
+ )
86
+ else:
87
+ taskBuffer = tbuf
88
+ # run
89
+ WorkerSync(tbuf=taskBuffer).run()
90
+ # stop taskBuffer if created inside this script
91
+ if tbuf is None:
92
+ taskBuffer.cleanup(requester=requester_id)
93
+
94
+
95
+ # run
96
+ if __name__ == "__main__":
97
+ main()