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.
- panda_server_source-0.8.0.dist-info/METADATA +55 -0
- panda_server_source-0.8.0.dist-info/RECORD +375 -0
- panda_server_source-0.8.0.dist-info/WHEEL +4 -0
- panda_server_source-0.8.0.dist-info/licenses/LICENSE.txt +202 -0
- pandajedi/__init__.py +0 -0
- pandajedi/jedibrokerage/AtlasAnalJobBroker.py +2343 -0
- pandajedi/jedibrokerage/AtlasBrokerUtils.py +1292 -0
- pandajedi/jedibrokerage/AtlasProdJobBroker.py +2064 -0
- pandajedi/jedibrokerage/AtlasProdTaskBroker.py +629 -0
- pandajedi/jedibrokerage/GenJobBroker.py +381 -0
- pandajedi/jedibrokerage/JobBrokerBase.py +133 -0
- pandajedi/jedibrokerage/TaskBrokerBase.py +15 -0
- pandajedi/jedibrokerage/__init__.py +0 -0
- pandajedi/jediconfig/__init__.py +0 -0
- pandajedi/jediconfig/jedi_config.py +40 -0
- pandajedi/jedicore/FactoryBase.py +182 -0
- pandajedi/jedicore/Interaction.py +433 -0
- pandajedi/jedicore/JediDBProxy.py +56 -0
- pandajedi/jedicore/JediDBProxyPool.py +37 -0
- pandajedi/jedicore/JediDBSchemaInfo.py +17 -0
- pandajedi/jedicore/JediException.py +13 -0
- pandajedi/jedicore/JediTaskBuffer.py +984 -0
- pandajedi/jedicore/JediTaskBufferInterface.py +50 -0
- pandajedi/jedicore/MsgWrapper.py +124 -0
- pandajedi/jedicore/ProcessUtils.py +34 -0
- pandajedi/jedicore/SiteCandidate.py +90 -0
- pandajedi/jedicore/ThreadUtils.py +205 -0
- pandajedi/jedicore/__init__.py +0 -0
- pandajedi/jediddm/AtlasDDMClient.py +1708 -0
- pandajedi/jediddm/DDMClientBase.py +16 -0
- pandajedi/jediddm/DDMInterface.py +83 -0
- pandajedi/jediddm/GenDDMClient.py +17 -0
- pandajedi/jediddm/__init__.py +0 -0
- pandajedi/jedidog/AtlasAnalWatchDog.py +648 -0
- pandajedi/jedidog/AtlasDataCarouselWatchDog.py +189 -0
- pandajedi/jedidog/AtlasDataLocalityUpdaterWatchDog.py +215 -0
- pandajedi/jedidog/AtlasProdWatchDog.py +443 -0
- pandajedi/jedidog/AtlasQueueFillerWatchDog.py +800 -0
- pandajedi/jedidog/AtlasTaskWithholderWatchDog.py +245 -0
- pandajedi/jedidog/AtlasWorkflowManagerWatchDog.py +63 -0
- pandajedi/jedidog/GenWatchDog.py +21 -0
- pandajedi/jedidog/JumboWatchDog.py +147 -0
- pandajedi/jedidog/TypicalWatchDogBase.py +122 -0
- pandajedi/jedidog/WatchDogBase.py +53 -0
- pandajedi/jedidog/__init__.py +0 -0
- pandajedi/jediexec/reniceJEDI.py +25 -0
- pandajedi/jedigen/AtlasTaskGenerator.py +110 -0
- pandajedi/jedigen/TaskGeneratorBase.py +15 -0
- pandajedi/jedigen/__init__.py +0 -0
- pandajedi/jedimsgprocessor/__init__.py +0 -0
- pandajedi/jedimsgprocessor/ai_parameter_adjuster_msg_processor +71 -0
- pandajedi/jedimsgprocessor/atlas_idds_msg_processor.py +66 -0
- pandajedi/jedimsgprocessor/base_msg_processor.py +33 -0
- pandajedi/jedimsgprocessor/forwarding_msg_processor.py +29 -0
- pandajedi/jedimsgprocessor/hpo_msg_processor.py +93 -0
- pandajedi/jedimsgprocessor/jedi_contents_feeder_msg_processor.py +63 -0
- pandajedi/jedimsgprocessor/jedi_job_generator_msg_processor.py +185 -0
- pandajedi/jedimsgprocessor/jedi_post_processor_msg_processor.py +82 -0
- pandajedi/jedimsgprocessor/kafka_msg_processor.py +44 -0
- pandajedi/jedimsgprocessor/panda_callback_msg_processor.py +182 -0
- pandajedi/jedimsgprocessor/panda_to_jedi_msg_processor.py +74 -0
- pandajedi/jedimsgprocessor/processing_msg_processor.py +134 -0
- pandajedi/jedimsgprocessor/status_report_msg_processor.py +129 -0
- pandajedi/jedimsgprocessor/tape_carousel_msg_processor.py +118 -0
- pandajedi/jedimsgprocessor/workflow_manager_msg_processor.py +89 -0
- pandajedi/jediorder/ContentsFeeder.py +785 -0
- pandajedi/jediorder/JediDaemon.py +27 -0
- pandajedi/jediorder/JediKnight.py +55 -0
- pandajedi/jediorder/JediMaster.py +238 -0
- pandajedi/jediorder/JediMsgProcessor.py +32 -0
- pandajedi/jediorder/JobBroker.py +33 -0
- pandajedi/jediorder/JobGenerator.py +2763 -0
- pandajedi/jediorder/JobSplitter.py +308 -0
- pandajedi/jediorder/JobThrottler.py +28 -0
- pandajedi/jediorder/PostProcessor.py +166 -0
- pandajedi/jediorder/TaskBroker.py +268 -0
- pandajedi/jediorder/TaskCommando.py +334 -0
- pandajedi/jediorder/TaskGenerator.py +17 -0
- pandajedi/jediorder/TaskRefiner.py +611 -0
- pandajedi/jediorder/TaskSetupper.py +17 -0
- pandajedi/jediorder/WatchDog.py +79 -0
- pandajedi/jediorder/__init__.py +0 -0
- pandajedi/jedipprocess/AtlasAnalPostProcessor.py +404 -0
- pandajedi/jedipprocess/AtlasPostProcessorUtils.py +50 -0
- pandajedi/jedipprocess/AtlasProdPostProcessor.py +178 -0
- pandajedi/jedipprocess/GenPostProcessor.py +35 -0
- pandajedi/jedipprocess/MailTemplates.py +185 -0
- pandajedi/jedipprocess/PostProcessorBase.py +269 -0
- pandajedi/jedipprocess/__init__.py +0 -0
- pandajedi/jedirefine/AtlasAnalTaskRefiner.py +259 -0
- pandajedi/jedirefine/AtlasProdTaskRefiner.py +162 -0
- pandajedi/jedirefine/GenTaskRefiner.py +61 -0
- pandajedi/jedirefine/RefinerUtils.py +154 -0
- pandajedi/jedirefine/TaskRefinerBase.py +996 -0
- pandajedi/jedirefine/__init__.py +0 -0
- pandajedi/jedisetup/AtlasTaskSetupper.py +309 -0
- pandajedi/jedisetup/GenTaskSetupper.py +16 -0
- pandajedi/jedisetup/SimpleTaskSetupper.py +152 -0
- pandajedi/jedisetup/TaskSetupperBase.py +15 -0
- pandajedi/jedisetup/__init__.py +0 -0
- pandajedi/jeditest/SchemaChecker.py +41 -0
- pandajedi/jeditest/addContWoSoTask.py +54 -0
- pandajedi/jeditest/addDataCarouselRequest.py +47 -0
- pandajedi/jeditest/addEventServiceTask.py +101 -0
- pandajedi/jeditest/addHpoTask.py +81 -0
- pandajedi/jeditest/addIDDSStageInRequest.py +56 -0
- pandajedi/jeditest/addNonAtlasTask.py +71 -0
- pandajedi/jeditest/addNonAtlasTaskEnc.py +64 -0
- pandajedi/jeditest/addTestTask.py +124 -0
- pandajedi/jeditest/addTestTaskParamToDEFT.py +70 -0
- pandajedi/jeditest/addTestTaskWithMerger.py +97 -0
- pandajedi/jeditest/brokerTest.py +78 -0
- pandajedi/jeditest/cancelDataCarouselRequest.py +35 -0
- pandajedi/jeditest/contentsFeederTest.py +28 -0
- pandajedi/jeditest/contentsFeederTestWithTask.py +18 -0
- pandajedi/jeditest/ddmTest.py +4 -0
- pandajedi/jeditest/jobGenForOneTask.py +38 -0
- pandajedi/jeditest/jobGeneratorTest.py +43 -0
- pandajedi/jeditest/jobSplitterTest.py +104 -0
- pandajedi/jeditest/jobThrottlerTest.py +22 -0
- pandajedi/jeditest/msgProcessorTest.py +9 -0
- pandajedi/jeditest/postProcessorTest.py +18 -0
- pandajedi/jeditest/resubmitDataCarouselRequest.py +35 -0
- pandajedi/jeditest/resubmitTaskParam.py +20 -0
- pandajedi/jeditest/taskBrokerTest.py +22 -0
- pandajedi/jeditest/taskBrokerTestWithTask.py +38 -0
- pandajedi/jeditest/taskBufferTest.py +5 -0
- pandajedi/jeditest/taskCommandoTest.py +28 -0
- pandajedi/jeditest/taskRefinerTest.py +30 -0
- pandajedi/jeditest/testOneTaskToRefine.py +49 -0
- pandajedi/jeditest/testOneTaskToTaskBroker.py +42 -0
- pandajedi/jeditest/testPandaDDMMap.py +62 -0
- pandajedi/jeditest/updateDataCarouselRequestParams.py +50 -0
- pandajedi/jeditest/watchDogTest.py +25 -0
- pandajedi/jeditest/workQueueTest.py +22 -0
- pandajedi/jedithrottle/AtlasAnalJobThrottler.py +19 -0
- pandajedi/jedithrottle/AtlasProdJobThrottler.py +18 -0
- pandajedi/jedithrottle/GenJobThrottler.py +26 -0
- pandajedi/jedithrottle/JobThrottlerBase.py +496 -0
- pandajedi/jedithrottle/__init__.py +0 -0
- pandaserver/__init__.py +0 -0
- pandaserver/api/__init__.py +0 -0
- pandaserver/api/v1/__init__.py +0 -0
- pandaserver/api/v1/common.py +339 -0
- pandaserver/api/v1/credential_management_api.py +372 -0
- pandaserver/api/v1/data_carousel_api.py +264 -0
- pandaserver/api/v1/event_api.py +269 -0
- pandaserver/api/v1/file_server_api.py +942 -0
- pandaserver/api/v1/harvester_api.py +445 -0
- pandaserver/api/v1/http_client.py +166 -0
- pandaserver/api/v1/idds_api.py +180 -0
- pandaserver/api/v1/job_api.py +463 -0
- pandaserver/api/v1/metaconfig_api.py +122 -0
- pandaserver/api/v1/pilot_api.py +895 -0
- pandaserver/api/v1/statistics_api.py +207 -0
- pandaserver/api/v1/system_api.py +186 -0
- pandaserver/api/v1/task_api.py +1520 -0
- pandaserver/api/v1/tests/__init__.py +0 -0
- pandaserver/api/v1/tests/credential_management_api_tests.py +116 -0
- pandaserver/api/v1/tests/data_carousel_api_tests.py +82 -0
- pandaserver/api/v1/tests/harvester_api_tests.py +188 -0
- pandaserver/api/v1/tests/idds_api_tests.py +45 -0
- pandaserver/api/v1/tests/job_api_tests.py +112 -0
- pandaserver/api/v1/tests/pilot_api_tests.py +154 -0
- pandaserver/api/v1/tests/statistics_api_tests.py +104 -0
- pandaserver/api/v1/tests/system_api_tests.py +58 -0
- pandaserver/api/v1/tests/task_api_tests.py +590 -0
- pandaserver/api/v1/version.py +2 -0
- pandaserver/api/v1/workflow_api.py +136 -0
- pandaserver/brokerage/SiteMapper.py +406 -0
- pandaserver/brokerage/__init__.py +0 -0
- pandaserver/brokerage/broker.py +272 -0
- pandaserver/config/__init__.py +0 -0
- pandaserver/config/config_utils.py +15 -0
- pandaserver/config/daemon_config.py +29 -0
- pandaserver/config/mcp_config.py +38 -0
- pandaserver/config/panda_config.py +233 -0
- pandaserver/configurator/Carbon.py +65 -0
- pandaserver/configurator/Configurator.py +908 -0
- pandaserver/configurator/__init__.py +0 -0
- pandaserver/configurator/aux.py +73 -0
- pandaserver/daemons/__init__.py +0 -0
- pandaserver/daemons/master.py +110 -0
- pandaserver/daemons/master_systemd.py +79 -0
- pandaserver/daemons/scripts/__init__.py +0 -0
- pandaserver/daemons/scripts/add_main.py +264 -0
- pandaserver/daemons/scripts/add_sub.py +221 -0
- pandaserver/daemons/scripts/cache_pilots.py +47 -0
- pandaserver/daemons/scripts/cache_schedconfig.py +286 -0
- pandaserver/daemons/scripts/carbon.py +50 -0
- pandaserver/daemons/scripts/configurator.py +94 -0
- pandaserver/daemons/scripts/copyArchive.py +1387 -0
- pandaserver/daemons/scripts/datasetManager.py +1154 -0
- pandaserver/daemons/scripts/dummy_test.py +25 -0
- pandaserver/daemons/scripts/evpPD2P.py +144 -0
- pandaserver/daemons/scripts/hs_scrapers.py +264 -0
- pandaserver/daemons/scripts/metric_collector.py +927 -0
- pandaserver/daemons/scripts/panda_activeusers_query.py +80 -0
- pandaserver/daemons/scripts/pilotStreaming.py +109 -0
- pandaserver/daemons/scripts/process_workflow_files_daemon.py +166 -0
- pandaserver/daemons/scripts/recover_lost_files_daemon.py +177 -0
- pandaserver/daemons/scripts/task_evaluator.py +405 -0
- pandaserver/daemons/scripts/tmpwatch.py +70 -0
- pandaserver/daemons/scripts/worker_synchronization.py +97 -0
- pandaserver/daemons/utils.py +753 -0
- pandaserver/dataservice/DataServiceUtils.py +323 -0
- pandaserver/dataservice/ErrorCode.py +25 -0
- pandaserver/dataservice/RecoverLostFilesCore.py +322 -0
- pandaserver/dataservice/__init__.py +0 -0
- pandaserver/dataservice/activator.py +79 -0
- pandaserver/dataservice/adder_atlas_plugin.py +1106 -0
- pandaserver/dataservice/adder_dummy_plugin.py +31 -0
- pandaserver/dataservice/adder_gen.py +954 -0
- pandaserver/dataservice/adder_plugin_base.py +27 -0
- pandaserver/dataservice/adder_result.py +75 -0
- pandaserver/dataservice/adder_simple_plugin.py +160 -0
- pandaserver/dataservice/closer.py +247 -0
- pandaserver/dataservice/closer_atlas_plugin.py +90 -0
- pandaserver/dataservice/ddm.py +1381 -0
- pandaserver/dataservice/ddm_handler.py +95 -0
- pandaserver/dataservice/dyn_data_distributer.py +824 -0
- pandaserver/dataservice/event_lookup_client_ei.py +77 -0
- pandaserver/dataservice/event_picker.py +268 -0
- pandaserver/dataservice/finisher.py +194 -0
- pandaserver/dataservice/setupper.py +225 -0
- pandaserver/dataservice/setupper_atlas_plugin.py +1851 -0
- pandaserver/dataservice/setupper_dummy_plugin.py +47 -0
- pandaserver/dataservice/setupper_plugin_base.py +67 -0
- pandaserver/jobdispatcher/DispatcherUtils.py +35 -0
- pandaserver/jobdispatcher/ErrorCode.py +19 -0
- pandaserver/jobdispatcher/JobDispatcher.py +1625 -0
- pandaserver/jobdispatcher/Protocol.py +443 -0
- pandaserver/jobdispatcher/Watcher.py +186 -0
- pandaserver/jobdispatcher/__init__.py +0 -0
- pandaserver/pandamcp/__init__.py +0 -0
- pandaserver/pandamcp/mcp_main.py +56 -0
- pandaserver/pandamcp/mcp_test_client.py +95 -0
- pandaserver/pandamcp/mcp_utils.py +74 -0
- pandaserver/proxycache/__init__.py +0 -0
- pandaserver/proxycache/panda_proxy_cache.py +240 -0
- pandaserver/proxycache/token_cache.py +141 -0
- pandaserver/server/.gacl +6 -0
- pandaserver/server/panda.py +539 -0
- pandaserver/srvcore/CoreUtils.py +572 -0
- pandaserver/srvcore/MailUtils.py +106 -0
- pandaserver/srvcore/__init__.py +0 -0
- pandaserver/srvcore/allowed_methods.py +100 -0
- pandaserver/srvcore/oidc_utils.py +152 -0
- pandaserver/srvcore/panda_request.py +196 -0
- pandaserver/srvcore/srv_msg_utils.py +42 -0
- pandaserver/taskbuffer/ConBridge.py +513 -0
- pandaserver/taskbuffer/DBProxyPool.py +95 -0
- pandaserver/taskbuffer/DataCarousel.py +3053 -0
- pandaserver/taskbuffer/DatasetSpec.py +137 -0
- pandaserver/taskbuffer/DdmSpec.py +201 -0
- pandaserver/taskbuffer/ErrorCode.py +87 -0
- pandaserver/taskbuffer/EventServiceUtils.py +396 -0
- pandaserver/taskbuffer/FileSpec.py +290 -0
- pandaserver/taskbuffer/GlobalShares.py +244 -0
- pandaserver/taskbuffer/HarvesterMetricsSpec.py +92 -0
- pandaserver/taskbuffer/Initializer.py +82 -0
- pandaserver/taskbuffer/InputChunk.py +1080 -0
- pandaserver/taskbuffer/JediCacheSpec.py +57 -0
- pandaserver/taskbuffer/JediDatasetSpec.py +588 -0
- pandaserver/taskbuffer/JediFileSpec.py +242 -0
- pandaserver/taskbuffer/JediTaskSpec.py +1687 -0
- pandaserver/taskbuffer/JobSpec.py +1006 -0
- pandaserver/taskbuffer/JobUtils.py +232 -0
- pandaserver/taskbuffer/NucleusSpec.py +116 -0
- pandaserver/taskbuffer/OraDBProxy.py +174 -0
- pandaserver/taskbuffer/PanDAMsgProcessor.py +8 -0
- pandaserver/taskbuffer/PandaDBSchemaInfo.py +18 -0
- pandaserver/taskbuffer/ParseJobXML.py +350 -0
- pandaserver/taskbuffer/PickleFileSpec.py +18 -0
- pandaserver/taskbuffer/PickleJobSpec.py +25 -0
- pandaserver/taskbuffer/PrioUtil.py +40 -0
- pandaserver/taskbuffer/ProcessGroups.py +111 -0
- pandaserver/taskbuffer/ResourceSpec.py +175 -0
- pandaserver/taskbuffer/SQLDumper.py +37 -0
- pandaserver/taskbuffer/SQLManager.py +60 -0
- pandaserver/taskbuffer/SiteSpec.py +304 -0
- pandaserver/taskbuffer/SupErrors.py +10 -0
- pandaserver/taskbuffer/TaskBuffer.py +2882 -0
- pandaserver/taskbuffer/TaskBufferInterface.py +163 -0
- pandaserver/taskbuffer/Utils.py +848 -0
- pandaserver/taskbuffer/WorkQueue.py +227 -0
- pandaserver/taskbuffer/WorkQueueMapper.py +203 -0
- pandaserver/taskbuffer/WorkerSpec.py +143 -0
- pandaserver/taskbuffer/WrappedCursor.py +487 -0
- pandaserver/taskbuffer/WrappedPickle.py +88 -0
- pandaserver/taskbuffer/WrappedPostgresConn.py +24 -0
- pandaserver/taskbuffer/__init__.py +0 -0
- pandaserver/taskbuffer/db_proxy_mods/OraDBProxy_structure.png +0 -0
- pandaserver/taskbuffer/db_proxy_mods/__init__.py +7 -0
- pandaserver/taskbuffer/db_proxy_mods/base_module.py +841 -0
- pandaserver/taskbuffer/db_proxy_mods/data_carousel_module.py +772 -0
- pandaserver/taskbuffer/db_proxy_mods/entity_module.py +3804 -0
- pandaserver/taskbuffer/db_proxy_mods/job_complex_module.py +5661 -0
- pandaserver/taskbuffer/db_proxy_mods/job_standalone_module.py +2640 -0
- pandaserver/taskbuffer/db_proxy_mods/metrics_module.py +874 -0
- pandaserver/taskbuffer/db_proxy_mods/misc_standalone_module.py +4272 -0
- pandaserver/taskbuffer/db_proxy_mods/task_complex_module.py +6172 -0
- pandaserver/taskbuffer/db_proxy_mods/task_event_module.py +4953 -0
- pandaserver/taskbuffer/db_proxy_mods/task_standalone_module.py +4999 -0
- pandaserver/taskbuffer/db_proxy_mods/task_utils_module.py +2063 -0
- pandaserver/taskbuffer/db_proxy_mods/worker_module.py +1944 -0
- pandaserver/taskbuffer/db_proxy_mods/workflow_module.py +832 -0
- pandaserver/taskbuffer/retryModule.py +552 -0
- pandaserver/taskbuffer/task_split_rules.py +308 -0
- pandaserver/taskbuffer/workflow_processor.py +249 -0
- pandaserver/taskbuffer/wrapped_oracle_conn.py +18 -0
- pandaserver/test/SchemaChecker.py +40 -0
- pandaserver/test/__init__.py +0 -0
- pandaserver/test/banUser.py +43 -0
- pandaserver/test/boostPrio.py +19 -0
- pandaserver/test/boostUser.py +35 -0
- pandaserver/test/callbackDDM.py +11 -0
- pandaserver/test/daod_on_demand.py +95 -0
- pandaserver/test/finishJob.py +184 -0
- pandaserver/test/finishTaskJEDI.py +11 -0
- pandaserver/test/getJobs.py +53 -0
- pandaserver/test/killJob.py +79 -0
- pandaserver/test/killJobLowPrio.py +99 -0
- pandaserver/test/killJobsInTask.py +56 -0
- pandaserver/test/killTask.py +80 -0
- pandaserver/test/killTaskJEDI.py +11 -0
- pandaserver/test/killUser.py +83 -0
- pandaserver/test/lsst/README.txt +7 -0
- pandaserver/test/lsst/lsstSubmit.py +139 -0
- pandaserver/test/lsst/lsstSubmitMERGEtest.py +141 -0
- pandaserver/test/lsst/lsstSubmitPhosim332.py +53 -0
- pandaserver/test/lsst/prepare-client-tarball-from-bigpanda-server.sh +41 -0
- pandaserver/test/reassignJobs.py +17 -0
- pandaserver/test/reassignSite.py +82 -0
- pandaserver/test/reassignTask.py +117 -0
- pandaserver/test/reassignWaiting.py +39 -0
- pandaserver/test/recoverLostFiles.py +7 -0
- pandaserver/test/reloadInputDS.py +51 -0
- pandaserver/test/sendCommandToJob.py +26 -0
- pandaserver/test/setDebugMode.py +38 -0
- pandaserver/test/setPriority.py +28 -0
- pandaserver/test/testEvgen.py +60 -0
- pandaserver/test/testEvgen17.py +58 -0
- pandaserver/test/testG4sim.py +81 -0
- pandaserver/test/testG4sim17.py +90 -0
- pandaserver/test/testGlobalShares.py +131 -0
- pandaserver/test/testReco.py +103 -0
- pandaserver/test/testSimulReco14.py +98 -0
- pandaserver/test/testSiteMap.py +26 -0
- pandaserver/test/testUpdateWorkerPilotStatus.py +9 -0
- pandaserver/userinterface/Client.py +1686 -0
- pandaserver/userinterface/UserIF.py +1799 -0
- pandaserver/userinterface/__init__.py +0 -0
- pandaserver/workflow/__init__.py +0 -0
- pandaserver/workflow/data_handler_plugins/base_data_handler.py +48 -0
- pandaserver/workflow/data_handler_plugins/ddm_collection_data_handler.py +100 -0
- pandaserver/workflow/data_handler_plugins/panda_task_data_handler.py +140 -0
- pandaserver/workflow/pcwl_test.py +122 -0
- pandaserver/workflow/pcwl_utils.py +384 -0
- pandaserver/workflow/psnakemake_container.json +68 -0
- pandaserver/workflow/psnakemake_task.json +62 -0
- pandaserver/workflow/psnakemake_test.py +60 -0
- pandaserver/workflow/snakeparser/__init__.py +3 -0
- pandaserver/workflow/snakeparser/extensions.py +74 -0
- pandaserver/workflow/snakeparser/log.py +53 -0
- pandaserver/workflow/snakeparser/names.py +3 -0
- pandaserver/workflow/snakeparser/parser.py +332 -0
- pandaserver/workflow/snakeparser/utils.py +29 -0
- pandaserver/workflow/step_handler_plugins/base_step_handler.py +85 -0
- pandaserver/workflow/step_handler_plugins/panda_task_step_handler.py +280 -0
- pandaserver/workflow/workflow_base.py +531 -0
- pandaserver/workflow/workflow_core.py +1974 -0
- pandaserver/workflow/workflow_core_smoketest.py +388 -0
- pandaserver/workflow/workflow_parser.py +222 -0
- pandaserver/workflow/workflow_utils.py +1047 -0
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
import os
|
|
3
|
+
import socket
|
|
4
|
+
import sys
|
|
5
|
+
import traceback
|
|
6
|
+
|
|
7
|
+
from pandacommon.pandalogger.PandaLogger import PandaLogger
|
|
8
|
+
|
|
9
|
+
from pandajedi.jedibrokerage import AtlasBrokerUtils
|
|
10
|
+
from pandajedi.jediconfig import jedi_config
|
|
11
|
+
from pandajedi.jedicore.MsgWrapper import MsgWrapper
|
|
12
|
+
from pandaserver.dataservice import DataServiceUtils
|
|
13
|
+
from pandaserver.srvcore import CoreUtils
|
|
14
|
+
from pandaserver.taskbuffer import JediTaskSpec, JobUtils
|
|
15
|
+
|
|
16
|
+
from .JumboWatchDog import JumboWatchDog
|
|
17
|
+
from .TypicalWatchDogBase import TypicalWatchDogBase
|
|
18
|
+
|
|
19
|
+
logger = PandaLogger().getLogger(__name__.split(".")[-1])
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# watchdog for ATLAS production
|
|
23
|
+
class AtlasProdWatchDog(TypicalWatchDogBase):
|
|
24
|
+
# constructor
|
|
25
|
+
def __init__(self, taskBufferIF, ddmIF):
|
|
26
|
+
TypicalWatchDogBase.__init__(self, taskBufferIF, ddmIF)
|
|
27
|
+
self.pid = f"{socket.getfqdn().split('.')[0]}-{os.getpid()}-dog"
|
|
28
|
+
|
|
29
|
+
# main
|
|
30
|
+
def doAction(self):
|
|
31
|
+
try:
|
|
32
|
+
# get logger
|
|
33
|
+
tmpLog = MsgWrapper(logger)
|
|
34
|
+
tmpLog.debug("start")
|
|
35
|
+
|
|
36
|
+
# actions based on task progress
|
|
37
|
+
self.do_task_progress_based_actions(tmpLog)
|
|
38
|
+
|
|
39
|
+
# action for reassign
|
|
40
|
+
self.doActionForReassign(tmpLog)
|
|
41
|
+
|
|
42
|
+
# action for throttled
|
|
43
|
+
self.doActionForThrottled(tmpLog)
|
|
44
|
+
|
|
45
|
+
# action for high prio pending
|
|
46
|
+
for minPriority, timeoutVal in [
|
|
47
|
+
(950, 10),
|
|
48
|
+
(900, 30),
|
|
49
|
+
]:
|
|
50
|
+
self.doActionForHighPrioPending(tmpLog, minPriority, timeoutVal)
|
|
51
|
+
|
|
52
|
+
# action to set scout job data w/o scouts
|
|
53
|
+
self.doActionToSetScoutJobData(tmpLog)
|
|
54
|
+
|
|
55
|
+
# action to throttle jobs in paused tasks
|
|
56
|
+
self.doActionToThrottleJobInPausedTasks(tmpLog)
|
|
57
|
+
|
|
58
|
+
# action for jumbo
|
|
59
|
+
jumbo = JumboWatchDog(self.taskBufferIF, self.ddmIF, tmpLog, "atlas", "managed")
|
|
60
|
+
jumbo.run()
|
|
61
|
+
|
|
62
|
+
# action to provoke (mark files ready) data carousel tasks to start if DDM rules of input DS are done
|
|
63
|
+
self.doActionToProvokeDCTasks(tmpLog)
|
|
64
|
+
|
|
65
|
+
except Exception:
|
|
66
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
67
|
+
tmpLog.error(f"failed with {errtype.__name__}:{errvalue} {traceback.format_exc()}")
|
|
68
|
+
# return
|
|
69
|
+
tmpLog.debug("done")
|
|
70
|
+
return self.SC_SUCCEEDED
|
|
71
|
+
|
|
72
|
+
# actions based on task progress
|
|
73
|
+
def do_task_progress_based_actions(self, g_tmp_log: MsgWrapper) -> None:
|
|
74
|
+
"""
|
|
75
|
+
Take actions based on task progress
|
|
76
|
+
1) boost priority of tasks which have finished >95% of input files and have <=100 remaining jobs to prio 900
|
|
77
|
+
2) reassign such tasks to Express global share if not already
|
|
78
|
+
3) pause tasks with high failure rate
|
|
79
|
+
|
|
80
|
+
:param g_tmp_log: logger
|
|
81
|
+
:return: None
|
|
82
|
+
"""
|
|
83
|
+
# get work queue mapper
|
|
84
|
+
workQueueMapper = self.taskBufferIF.getWorkQueueMap()
|
|
85
|
+
# get list of work queues
|
|
86
|
+
workQueueList = workQueueMapper.getAlignedQueueList(self.vo, self.prodSourceLabel)
|
|
87
|
+
resource_types = self.taskBufferIF.load_resource_types()
|
|
88
|
+
|
|
89
|
+
# get config values
|
|
90
|
+
failure_checker = "watchdog"
|
|
91
|
+
max_job_failure_rate_key = f"MAX_JOB_FAILURE_RATE_TO_PAUSE_{self.prodSourceLabel}"
|
|
92
|
+
max_job_failure_rate_base = self.taskBufferIF.getConfigValue(failure_checker, max_job_failure_rate_key, "jedi")
|
|
93
|
+
max_hep_score_failure_rate_key = f"MAX_HEP_SCORE_FAILURE_RATE_TO_PAUSE_{self.prodSourceLabel}"
|
|
94
|
+
max_hep_score_failure_rate_base = self.taskBufferIF.getConfigValue(failure_checker, max_hep_score_failure_rate_key, "jedi")
|
|
95
|
+
min_jobs_to_pause_key = f"MIN_JOBS_TO_PAUSE_{self.prodSourceLabel}"
|
|
96
|
+
min_jobs_to_pause = self.taskBufferIF.getConfigValue(failure_checker, min_jobs_to_pause_key, "jedi")
|
|
97
|
+
if min_jobs_to_pause is None:
|
|
98
|
+
min_jobs_to_pause = 1000
|
|
99
|
+
min_remaining_jobs_to_pause_key = f"MIN_REMAINING_JOBS_TO_PAUSE_{self.prodSourceLabel}"
|
|
100
|
+
min_remaining_jobs_to_pause = self.taskBufferIF.getConfigValue(failure_checker, min_remaining_jobs_to_pause_key, "jedi")
|
|
101
|
+
if min_remaining_jobs_to_pause is None:
|
|
102
|
+
min_remaining_jobs_to_pause = 100
|
|
103
|
+
|
|
104
|
+
# loop over all work queues
|
|
105
|
+
g_tmp_log.debug("start do_task_progress_based_actions")
|
|
106
|
+
for workQueue in workQueueList:
|
|
107
|
+
break_loop = False # for special workqueues we only need to iterate once
|
|
108
|
+
for resource_type in resource_types:
|
|
109
|
+
g_tmp_log.debug(f"start workQueue={workQueue.queue_name} resource_type={resource_type.resource_name}")
|
|
110
|
+
# get tasks to be boosted
|
|
111
|
+
if workQueue.is_global_share:
|
|
112
|
+
task_criteria = {"gshare": workQueue.queue_name, "resource_type": resource_type.resource_name}
|
|
113
|
+
else:
|
|
114
|
+
break_loop = True
|
|
115
|
+
task_criteria = {"workQueue_ID": workQueue.queue_id}
|
|
116
|
+
|
|
117
|
+
# define max failure rate
|
|
118
|
+
max_job_failure_rate = self.taskBufferIF.getConfigValue(failure_checker, f"{max_job_failure_rate_key}_{workQueue.queue_name}", "jedi")
|
|
119
|
+
if max_job_failure_rate is None:
|
|
120
|
+
max_job_failure_rate = max_job_failure_rate_base
|
|
121
|
+
max_hep_score_failure_rate = self.taskBufferIF.getConfigValue(
|
|
122
|
+
failure_checker, f"{max_hep_score_failure_rate_key}_{workQueue.queue_name}", "jedi"
|
|
123
|
+
)
|
|
124
|
+
if max_hep_score_failure_rate is None:
|
|
125
|
+
max_hep_score_failure_rate = max_hep_score_failure_rate_base
|
|
126
|
+
|
|
127
|
+
dataset_criteria = {"masterID": None, "type": ["input", "pseudo_input"]}
|
|
128
|
+
task_param_list = ["jediTaskID", "currentPriority", "parent_tid", "gshare", "requestType", "splitRule"]
|
|
129
|
+
dataset_param_list = ["nFiles", "nFilesUsed", "nFilesTobeUsed", "nFilesFinished", "nFilesFailed"]
|
|
130
|
+
taskVarList = self.taskBufferIF.getTasksWithCriteria_JEDI(
|
|
131
|
+
self.vo,
|
|
132
|
+
self.prodSourceLabel,
|
|
133
|
+
["running"],
|
|
134
|
+
taskCriteria=task_criteria,
|
|
135
|
+
datasetCriteria=dataset_criteria,
|
|
136
|
+
taskParamList=task_param_list,
|
|
137
|
+
datasetParamList=dataset_param_list,
|
|
138
|
+
taskLockColumn="throttledTime",
|
|
139
|
+
taskLockInterval=20,
|
|
140
|
+
)
|
|
141
|
+
boostedPrio = 900
|
|
142
|
+
toBoostRatio = 0.95
|
|
143
|
+
for taskParam, datasetParam in taskVarList:
|
|
144
|
+
jediTaskID = taskParam["jediTaskID"]
|
|
145
|
+
currentPriority = taskParam["currentPriority"]
|
|
146
|
+
parent_tid = taskParam["parent_tid"]
|
|
147
|
+
gshare = taskParam["gshare"]
|
|
148
|
+
request_type = taskParam["requestType"]
|
|
149
|
+
split_rule = taskParam["splitRule"]
|
|
150
|
+
# check parent
|
|
151
|
+
parentState = None
|
|
152
|
+
if parent_tid not in [None, jediTaskID]:
|
|
153
|
+
parentState = self.taskBufferIF.checkParentTask_JEDI(parent_tid, jediTaskID)
|
|
154
|
+
if parentState != "completed":
|
|
155
|
+
g_tmp_log.info(
|
|
156
|
+
f"#ATM #KV label={self.prodSourceLabel} jediTaskID={jediTaskID} skip prio boost since parent_id={parent_tid} has parent_status={parentState}"
|
|
157
|
+
)
|
|
158
|
+
continue
|
|
159
|
+
nFiles = datasetParam["nFiles"]
|
|
160
|
+
nFilesFinished = datasetParam["nFilesFinished"]
|
|
161
|
+
nFilesFailed = datasetParam["nFilesFailed"]
|
|
162
|
+
# get num jobs
|
|
163
|
+
nJobs = self.taskBufferIF.getNumJobsForTask_JEDI(jediTaskID)
|
|
164
|
+
nRemJobs = None
|
|
165
|
+
if nJobs is not None:
|
|
166
|
+
try:
|
|
167
|
+
nRemJobs = int(float(nFiles - nFilesFinished - nFilesFailed) * float(nJobs) / float(nFiles))
|
|
168
|
+
except Exception:
|
|
169
|
+
pass
|
|
170
|
+
failure_metrics = self.taskBufferIF.get_task_failure_metrics(jediTaskID)
|
|
171
|
+
|
|
172
|
+
tmpStr = f"jediTaskID={jediTaskID} nFiles={nFiles} nFilesFinishedFailed={nFilesFinished + nFilesFailed} "
|
|
173
|
+
tmpStr += f"nJobs={nJobs} nRemJobs={nRemJobs} parent_tid={parent_tid} parentStatus={parentState} failure_metrics={failure_metrics}"
|
|
174
|
+
g_tmp_log.debug(tmpStr)
|
|
175
|
+
|
|
176
|
+
try:
|
|
177
|
+
if nRemJobs is not None and float(nFilesFinished + nFilesFailed) / float(nFiles) >= toBoostRatio and nRemJobs <= 100:
|
|
178
|
+
# skip high enough
|
|
179
|
+
if currentPriority < boostedPrio:
|
|
180
|
+
g_tmp_log.info(
|
|
181
|
+
f" >>> action=priority_boosting of jediTaskID={jediTaskID} to priority={boostedPrio} #ATM #KV label={self.prodSourceLabel} "
|
|
182
|
+
)
|
|
183
|
+
self.taskBufferIF.changeTaskPriorityPanda(jediTaskID, boostedPrio)
|
|
184
|
+
|
|
185
|
+
# skip express or non global share
|
|
186
|
+
newShare = "Express"
|
|
187
|
+
newShareType = self.prodSourceLabel
|
|
188
|
+
if gshare != newShare and workQueue.is_global_share and workQueue.queue_type == newShareType:
|
|
189
|
+
g_tmp_log.info(
|
|
190
|
+
f" >>> action=gshare_reassignment jediTaskID={jediTaskID} from gshare_old={gshare} to gshare_new={newShare} #ATM #KV label={self.prodSourceLabel}"
|
|
191
|
+
)
|
|
192
|
+
self.taskBufferIF.reassignShare([jediTaskID], newShare, True)
|
|
193
|
+
g_tmp_log.debug(f"reassigned jediTaskID={jediTaskID}")
|
|
194
|
+
except Exception:
|
|
195
|
+
pass
|
|
196
|
+
|
|
197
|
+
# check failure rate
|
|
198
|
+
failure_key = None
|
|
199
|
+
bad_value = None
|
|
200
|
+
if JediTaskSpec.is_auto_pause_disabled(split_rule):
|
|
201
|
+
# auto pause disabled
|
|
202
|
+
pass
|
|
203
|
+
elif not failure_metrics:
|
|
204
|
+
# failure metrics is unavailable
|
|
205
|
+
pass
|
|
206
|
+
elif nJobs is None or nJobs < min_jobs_to_pause:
|
|
207
|
+
# total num jobs is small
|
|
208
|
+
pass
|
|
209
|
+
elif nRemJobs is None or nRemJobs < min_remaining_jobs_to_pause:
|
|
210
|
+
# remaining num jobs is small
|
|
211
|
+
pass
|
|
212
|
+
elif (
|
|
213
|
+
max_job_failure_rate is not None
|
|
214
|
+
and failure_metrics["single_failure_rate"] is not None
|
|
215
|
+
and failure_metrics["single_failure_rate"] >= max_job_failure_rate > 0
|
|
216
|
+
):
|
|
217
|
+
# job failure rate is high
|
|
218
|
+
failure_key = "single_failure_rate"
|
|
219
|
+
bad_value = failure_metrics[failure_key]
|
|
220
|
+
g_tmp_log.info(
|
|
221
|
+
f" >>> action=pausing_high_failure_rate jediTaskID={jediTaskID} job_failure_rate={bad_value:.2f} "
|
|
222
|
+
f"(max_allowed={max_job_failure_rate}) #ATM #KV label={self.prodSourceLabel}"
|
|
223
|
+
)
|
|
224
|
+
self.taskBufferIF.sendCommandTaskPanda(
|
|
225
|
+
jediTaskID, f"{failure_checker} due to high job failure rate {bad_value:.2f} > {max_job_failure_rate}", True, "pause"
|
|
226
|
+
)
|
|
227
|
+
elif (
|
|
228
|
+
max_hep_score_failure_rate is not None
|
|
229
|
+
and failure_metrics["hep_score_failure_rate"] is not None
|
|
230
|
+
and failure_metrics["hep_score_failure_rate"] >= max_hep_score_failure_rate > 0
|
|
231
|
+
):
|
|
232
|
+
# failed HEP score rate is high
|
|
233
|
+
failure_key = "hep_score_failure_rate"
|
|
234
|
+
bad_value = failure_metrics[failure_key]
|
|
235
|
+
g_tmp_log.info(
|
|
236
|
+
f" >>> action=pausing_high_failure_rate jediTaskID={jediTaskID} hep_score_failure_rate={bad_value:.2f} "
|
|
237
|
+
f"(max_allowed={max_hep_score_failure_rate}) #ATM #KV label={self.prodSourceLabel}"
|
|
238
|
+
)
|
|
239
|
+
self.taskBufferIF.sendCommandTaskPanda(
|
|
240
|
+
jediTaskID, f"{failure_checker} due to high HEP score failure rate {bad_value:.2f} > {max_hep_score_failure_rate}", True, "pause"
|
|
241
|
+
)
|
|
242
|
+
if failure_key is not None:
|
|
243
|
+
# get tasks with the same requestType to be paused
|
|
244
|
+
if request_type:
|
|
245
|
+
task_criteria = copy.copy(task_criteria)
|
|
246
|
+
task_criteria["requestType"] = request_type
|
|
247
|
+
tasks_with_same_request_type = self.taskBufferIF.getTasksWithCriteria_JEDI(
|
|
248
|
+
self.vo,
|
|
249
|
+
self.prodSourceLabel,
|
|
250
|
+
["running"],
|
|
251
|
+
taskCriteria=task_criteria,
|
|
252
|
+
taskParamList=["jediTaskID", "splitRule"],
|
|
253
|
+
)
|
|
254
|
+
for other_task_param, _ in tasks_with_same_request_type:
|
|
255
|
+
other_jedi_task_id = other_task_param["jediTaskID"]
|
|
256
|
+
# auto pause disabled
|
|
257
|
+
if JediTaskSpec.is_auto_pause_disabled(other_jedi_task_id):
|
|
258
|
+
continue
|
|
259
|
+
if other_jedi_task_id != jediTaskID:
|
|
260
|
+
g_tmp_log.info(
|
|
261
|
+
f" >>> action=pausing_high_failure_rate jediTaskID={other_jedi_task_id} due to requestType={request_type} shared by {jediTaskID} "
|
|
262
|
+
f"#ATM #KV label={self.prodSourceLabel}"
|
|
263
|
+
)
|
|
264
|
+
if failure_key == "single_failure_rate":
|
|
265
|
+
msg = f"{failure_checker} due to high job failure rate in another task {jediTaskID} ({bad_value:.2f} > {max_job_failure_rate})"
|
|
266
|
+
else:
|
|
267
|
+
msg = f"{failure_checker} due to high HEP score failure rate in another task {jediTaskID} ({bad_value:.2f} > {max_hep_score_failure_rate})"
|
|
268
|
+
self.taskBufferIF.sendCommandTaskPanda(
|
|
269
|
+
other_jedi_task_id,
|
|
270
|
+
msg,
|
|
271
|
+
True,
|
|
272
|
+
"pause",
|
|
273
|
+
)
|
|
274
|
+
g_tmp_log.debug(f"paused jediTaskID={jediTaskID}")
|
|
275
|
+
|
|
276
|
+
if break_loop:
|
|
277
|
+
break
|
|
278
|
+
|
|
279
|
+
# action for reassignment
|
|
280
|
+
def doActionForReassign(self, gTmpLog):
|
|
281
|
+
# get DDM I/F
|
|
282
|
+
ddmIF = self.ddmIF.getInterface(self.vo)
|
|
283
|
+
# get site mapper
|
|
284
|
+
siteMapper = self.taskBufferIF.get_site_mapper()
|
|
285
|
+
# get tasks to get reassigned
|
|
286
|
+
taskList = self.taskBufferIF.getTasksToReassign_JEDI(self.vo, self.prodSourceLabel)
|
|
287
|
+
|
|
288
|
+
gTmpLog.debug(f"got {len(taskList)} tasks to reassign")
|
|
289
|
+
for taskSpec in taskList:
|
|
290
|
+
tmpLog = MsgWrapper(logger, f"< jediTaskID={taskSpec.jediTaskID} >")
|
|
291
|
+
tmpLog.debug("start to reassign")
|
|
292
|
+
# DDM backend
|
|
293
|
+
ddmBackEnd = taskSpec.getDdmBackEnd()
|
|
294
|
+
# get datasets
|
|
295
|
+
tmpStat, datasetSpecList = self.taskBufferIF.getDatasetsWithJediTaskID_JEDI(taskSpec.jediTaskID, ["output", "log"])
|
|
296
|
+
if tmpStat is not True:
|
|
297
|
+
tmpLog.error("failed to get datasets")
|
|
298
|
+
continue
|
|
299
|
+
|
|
300
|
+
# re-run task brokerage
|
|
301
|
+
if taskSpec.nucleus in [None, ""]:
|
|
302
|
+
taskSpec.status = "assigning"
|
|
303
|
+
taskSpec.oldStatus = None
|
|
304
|
+
taskSpec.setToRegisterDatasets()
|
|
305
|
+
self.taskBufferIF.updateTask_JEDI(taskSpec, {"jediTaskID": taskSpec.jediTaskID}, setOldModTime=True)
|
|
306
|
+
tmpLog.debug(f"#ATM #KV label=managed action=trigger_new_brokerage by setting task_status={taskSpec.status}")
|
|
307
|
+
continue
|
|
308
|
+
|
|
309
|
+
# get nucleus
|
|
310
|
+
nucleusSpec = siteMapper.getNucleus(taskSpec.nucleus)
|
|
311
|
+
if nucleusSpec is None:
|
|
312
|
+
tmpLog.error(f"nucleus={taskSpec.nucleus} doesn't exist")
|
|
313
|
+
continue
|
|
314
|
+
|
|
315
|
+
# set nucleus
|
|
316
|
+
retMap = {taskSpec.jediTaskID: AtlasBrokerUtils.getDictToSetNucleus(nucleusSpec, datasetSpecList)}
|
|
317
|
+
self.taskBufferIF.setCloudToTasks_JEDI(retMap)
|
|
318
|
+
|
|
319
|
+
# get nucleus
|
|
320
|
+
t1SiteName = nucleusSpec.getOnePandaSite()
|
|
321
|
+
t1Site = siteMapper.getSite(t1SiteName)
|
|
322
|
+
|
|
323
|
+
# loop over all datasets
|
|
324
|
+
isOK = True
|
|
325
|
+
for datasetSpec in datasetSpecList:
|
|
326
|
+
tmpLog.debug(f"dataset={datasetSpec.datasetName}")
|
|
327
|
+
if DataServiceUtils.getDistributedDestination(datasetSpec.storageToken) is not None:
|
|
328
|
+
tmpLog.debug(f"skip {datasetSpec.datasetName} is distributed")
|
|
329
|
+
continue
|
|
330
|
+
# get location
|
|
331
|
+
location = siteMapper.getDdmEndpoint(
|
|
332
|
+
t1Site.sitename, datasetSpec.storageToken, taskSpec.prodSourceLabel, JobUtils.translate_tasktype_to_jobtype(taskSpec.taskType)
|
|
333
|
+
)
|
|
334
|
+
# make subscription
|
|
335
|
+
try:
|
|
336
|
+
tmpLog.debug(f"registering subscription to {location} with backend={ddmBackEnd}")
|
|
337
|
+
tmpStat = ddmIF.registerDatasetSubscription(datasetSpec.datasetName, location, "Production Output", asynchronous=True)
|
|
338
|
+
if tmpStat is not True:
|
|
339
|
+
tmpLog.error("failed to make subscription")
|
|
340
|
+
isOK = False
|
|
341
|
+
break
|
|
342
|
+
except Exception:
|
|
343
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
344
|
+
tmpLog.warning(f"failed to make subscription with {errtype.__name__}:{errvalue}")
|
|
345
|
+
isOK = False
|
|
346
|
+
break
|
|
347
|
+
# succeeded
|
|
348
|
+
if isOK:
|
|
349
|
+
# activate task
|
|
350
|
+
if taskSpec.oldStatus in ["assigning", "exhausted", None]:
|
|
351
|
+
taskSpec.status = "ready"
|
|
352
|
+
else:
|
|
353
|
+
taskSpec.status = taskSpec.oldStatus
|
|
354
|
+
taskSpec.oldStatus = None
|
|
355
|
+
self.taskBufferIF.updateTask_JEDI(taskSpec, {"jediTaskID": taskSpec.jediTaskID}, setOldModTime=True)
|
|
356
|
+
tmpLog.debug("finished to reassign")
|
|
357
|
+
|
|
358
|
+
# action for throttled tasks
|
|
359
|
+
def doActionForThrottled(self, gTmpLog):
|
|
360
|
+
# release tasks
|
|
361
|
+
nTasks = self.taskBufferIF.releaseThrottledTasks_JEDI(self.vo, self.prodSourceLabel)
|
|
362
|
+
gTmpLog.debug(f"released {nTasks} tasks")
|
|
363
|
+
|
|
364
|
+
# throttle tasks
|
|
365
|
+
nTasks = self.taskBufferIF.throttleTasks_JEDI(self.vo, self.prodSourceLabel, jedi_config.watchdog.waitForThrottled)
|
|
366
|
+
gTmpLog.debug(f"throttled {nTasks} tasks")
|
|
367
|
+
|
|
368
|
+
# action for high priority pending tasks
|
|
369
|
+
def doActionForHighPrioPending(self, gTmpLog, minPriority, timeoutVal):
|
|
370
|
+
timeoutForPending = None
|
|
371
|
+
# try to get the timeout from the config files
|
|
372
|
+
if hasattr(jedi_config.watchdog, "timeoutForPendingVoLabel"):
|
|
373
|
+
timeoutForPending = CoreUtils.getConfigParam(jedi_config.watchdog.timeoutForPendingVoLabel, self.vo, self.prodSourceLabel)
|
|
374
|
+
if timeoutForPending is None:
|
|
375
|
+
timeoutForPending = jedi_config.watchdog.timeoutForPending
|
|
376
|
+
timeoutForPending = int(timeoutForPending) * 24
|
|
377
|
+
tmpRet, _ = self.taskBufferIF.reactivatePendingTasks_JEDI(self.vo, self.prodSourceLabel, timeoutVal, timeoutForPending, minPriority=minPriority)
|
|
378
|
+
if tmpRet is None:
|
|
379
|
+
# failed
|
|
380
|
+
gTmpLog.error(f"failed to reactivate high priority (>{minPriority}) tasks")
|
|
381
|
+
else:
|
|
382
|
+
gTmpLog.info(f"reactivated high priority (>{minPriority}) {tmpRet} tasks")
|
|
383
|
+
|
|
384
|
+
# action to throttle jobs in paused tasks
|
|
385
|
+
def doActionToThrottleJobInPausedTasks(self, gTmpLog):
|
|
386
|
+
tmpRet = self.taskBufferIF.throttleJobsInPausedTasks_JEDI(self.vo, self.prodSourceLabel)
|
|
387
|
+
if tmpRet is None:
|
|
388
|
+
# failed
|
|
389
|
+
gTmpLog.error("failed to thottle jobs in paused tasks")
|
|
390
|
+
else:
|
|
391
|
+
for jediTaskID, pandaIDs in tmpRet.items():
|
|
392
|
+
gTmpLog.info(f"throttled jobs in paused jediTaskID={jediTaskID} successfully")
|
|
393
|
+
tmpRet = self.taskBufferIF.killJobs(pandaIDs, "reassign", "51", True)
|
|
394
|
+
gTmpLog.info(f"reassigned {len(pandaIDs)} jobs in paused jediTaskID={jediTaskID} with {tmpRet}")
|
|
395
|
+
|
|
396
|
+
# action to provoke (mark files ready) data carousel tasks to start if DDM rules of input DS are done
|
|
397
|
+
def doActionToProvokeDCTasks(self, gTmpLog):
|
|
398
|
+
# lock
|
|
399
|
+
got_lock = self.taskBufferIF.lockProcess_JEDI(
|
|
400
|
+
vo=self.vo,
|
|
401
|
+
prodSourceLabel=self.prodSourceLabel,
|
|
402
|
+
cloud=None,
|
|
403
|
+
workqueue_id=None,
|
|
404
|
+
resource_name=None,
|
|
405
|
+
component="AtlasProdWatchDog.doActionToProvokeDCT",
|
|
406
|
+
pid=self.pid,
|
|
407
|
+
timeLimit=30,
|
|
408
|
+
)
|
|
409
|
+
if not got_lock:
|
|
410
|
+
gTmpLog.debug("doActionToProvokeDCTasks locked by another process. Skipped")
|
|
411
|
+
return
|
|
412
|
+
# run
|
|
413
|
+
res_dict = self.taskBufferIF.get_pending_dc_tasks_JEDI(task_type="prod", time_limit_minutes=60)
|
|
414
|
+
if res_dict is None:
|
|
415
|
+
# failed
|
|
416
|
+
gTmpLog.error("failed to get pending DC tasks")
|
|
417
|
+
elif not res_dict:
|
|
418
|
+
# empty
|
|
419
|
+
gTmpLog.debug("no pending DC task; skipped")
|
|
420
|
+
else:
|
|
421
|
+
gTmpLog.debug(f"got {len(res_dict)} DC tasks to provoke")
|
|
422
|
+
ddm_if = self.ddmIF.getInterface(self.vo)
|
|
423
|
+
# loop over pending DC tasks
|
|
424
|
+
for task_id, ds_name_list in res_dict.items():
|
|
425
|
+
if not ds_name_list:
|
|
426
|
+
continue
|
|
427
|
+
total_all_ok = True
|
|
428
|
+
for ds_name in ds_name_list:
|
|
429
|
+
ret_data = ddm_if.get_rules_state(ds_name)
|
|
430
|
+
try:
|
|
431
|
+
all_ok, rule_dict = ret_data
|
|
432
|
+
total_all_ok = total_all_ok and all_ok
|
|
433
|
+
except ValueError:
|
|
434
|
+
gTmpLog.error(f"failed to get rule info for task={task_id}. data={ret_data}")
|
|
435
|
+
total_all_ok = False
|
|
436
|
+
break
|
|
437
|
+
if total_all_ok:
|
|
438
|
+
# all rules ok; provoke the task
|
|
439
|
+
gTmpLog.info(f"provoking task {task_id}")
|
|
440
|
+
self.taskBufferIF.updateInputDatasetsStaged_JEDI(task_id, None, None, by="AtlasProdWatchDog")
|
|
441
|
+
gTmpLog.info(f"all staging rules of task {task_id} are OK; provoked")
|
|
442
|
+
else:
|
|
443
|
+
gTmpLog.debug(f"not all staging rules of task {task_id} are OK; skipped ")
|