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,611 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import itertools
|
|
3
|
+
import sys
|
|
4
|
+
import time
|
|
5
|
+
import traceback
|
|
6
|
+
|
|
7
|
+
from pandacommon.pandalogger.PandaLogger import PandaLogger
|
|
8
|
+
from pandacommon.pandautils.PandaUtils import naive_utcnow
|
|
9
|
+
|
|
10
|
+
from pandajedi.jediconfig import jedi_config
|
|
11
|
+
from pandajedi.jedicore import Interaction, JediException
|
|
12
|
+
from pandajedi.jedicore.FactoryBase import FactoryBase
|
|
13
|
+
from pandajedi.jedicore.MsgWrapper import MsgWrapper
|
|
14
|
+
from pandajedi.jedicore.ThreadUtils import ListWithLock, ThreadPool, WorkerThread
|
|
15
|
+
from pandajedi.jedirefine import RefinerUtils
|
|
16
|
+
from pandaserver.dataservice.ddm import rucioAPI
|
|
17
|
+
from pandaserver.taskbuffer.DataCarousel import DataCarouselInterface
|
|
18
|
+
from pandaserver.taskbuffer.JediTaskSpec import JediTaskSpec
|
|
19
|
+
|
|
20
|
+
from .JediKnight import JediKnight
|
|
21
|
+
|
|
22
|
+
logger = PandaLogger().getLogger(__name__.split(".")[-1])
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# worker class to refine TASK_PARAM to fill JEDI tables
|
|
26
|
+
class TaskRefiner(JediKnight, FactoryBase):
|
|
27
|
+
# constructor
|
|
28
|
+
def __init__(self, commuChannel, taskBufferIF, ddmIF, vos, prodSourceLabels):
|
|
29
|
+
self.vos = self.parseInit(vos)
|
|
30
|
+
self.prodSourceLabels = self.parseInit(prodSourceLabels)
|
|
31
|
+
JediKnight.__init__(self, commuChannel, taskBufferIF, ddmIF, logger)
|
|
32
|
+
FactoryBase.__init__(self, self.vos, self.prodSourceLabels, logger, jedi_config.taskrefine.modConfig)
|
|
33
|
+
|
|
34
|
+
# main
|
|
35
|
+
def start(self):
|
|
36
|
+
# start base classes
|
|
37
|
+
JediKnight.start(self)
|
|
38
|
+
FactoryBase.initializeMods(self, self.taskBufferIF, self.ddmIF)
|
|
39
|
+
# get data carousel interface
|
|
40
|
+
data_carousel_interface = DataCarouselInterface(self.taskBufferIF)
|
|
41
|
+
if data_carousel_interface is None:
|
|
42
|
+
# data carousel interface is undefined
|
|
43
|
+
logger.error(f"data carousel interface is undefined; skipped")
|
|
44
|
+
return
|
|
45
|
+
# go into main loop
|
|
46
|
+
while True:
|
|
47
|
+
startTime = naive_utcnow()
|
|
48
|
+
try:
|
|
49
|
+
# get logger
|
|
50
|
+
tmpLog = MsgWrapper(logger)
|
|
51
|
+
tmpLog.debug("start")
|
|
52
|
+
# loop over all vos
|
|
53
|
+
for vo in self.vos:
|
|
54
|
+
# loop over all sourceLabels
|
|
55
|
+
for prodSourceLabel in self.prodSourceLabels:
|
|
56
|
+
# get the list of tasks to refine
|
|
57
|
+
tmpList = self.taskBufferIF.getTasksToRefine_JEDI(vo, prodSourceLabel)
|
|
58
|
+
if tmpList is None:
|
|
59
|
+
# failed
|
|
60
|
+
tmpLog.error("failed to get the list of tasks to refine")
|
|
61
|
+
else:
|
|
62
|
+
tmpLog.debug(f"got {len(tmpList)} tasks")
|
|
63
|
+
# put to a locked list
|
|
64
|
+
taskList = ListWithLock(tmpList)
|
|
65
|
+
# make thread pool
|
|
66
|
+
threadPool = ThreadPool()
|
|
67
|
+
# get work queue mapper
|
|
68
|
+
workQueueMapper = self.taskBufferIF.getWorkQueueMap()
|
|
69
|
+
# make workers
|
|
70
|
+
nWorker = jedi_config.taskrefine.nWorkers
|
|
71
|
+
for _ in range(nWorker):
|
|
72
|
+
thr = TaskRefinerThread(taskList, threadPool, self.taskBufferIF, self.ddmIF, self, workQueueMapper, data_carousel_interface)
|
|
73
|
+
thr.start()
|
|
74
|
+
# join
|
|
75
|
+
threadPool.join()
|
|
76
|
+
except Exception:
|
|
77
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
78
|
+
tmpLog.error(f"failed in {self.__class__.__name__}.start() with {errtype.__name__} {errvalue}")
|
|
79
|
+
tmpLog.error(f"Traceback: {traceback.format_exc()}")
|
|
80
|
+
# sleep if needed
|
|
81
|
+
loopCycle = jedi_config.taskrefine.loopCycle
|
|
82
|
+
timeDelta = naive_utcnow() - startTime
|
|
83
|
+
sleepPeriod = loopCycle - timeDelta.seconds
|
|
84
|
+
if sleepPeriod > 0:
|
|
85
|
+
time.sleep(sleepPeriod)
|
|
86
|
+
# randomize cycle
|
|
87
|
+
self.randomSleep(max_val=loopCycle)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
# thread for real worker
|
|
91
|
+
class TaskRefinerThread(WorkerThread):
|
|
92
|
+
# constructor
|
|
93
|
+
def __init__(self, taskList, threadPool, taskbufferIF, ddmIF, implFactory, workQueueMapper, data_carousel_interface=None):
|
|
94
|
+
# initialize worker with no semaphore
|
|
95
|
+
WorkerThread.__init__(self, None, threadPool, logger)
|
|
96
|
+
# attributes
|
|
97
|
+
self.taskList = taskList
|
|
98
|
+
self.taskBufferIF = taskbufferIF
|
|
99
|
+
self.ddmIF = ddmIF
|
|
100
|
+
self.implFactory = implFactory
|
|
101
|
+
self.workQueueMapper = workQueueMapper
|
|
102
|
+
self.data_carousel_interface = data_carousel_interface
|
|
103
|
+
self.msgType = "taskrefiner"
|
|
104
|
+
|
|
105
|
+
# main
|
|
106
|
+
def runImpl(self):
|
|
107
|
+
while True:
|
|
108
|
+
try:
|
|
109
|
+
# get a part of list
|
|
110
|
+
nTasks = 10
|
|
111
|
+
taskList = self.taskList.get(nTasks)
|
|
112
|
+
# no more datasets
|
|
113
|
+
if len(taskList) == 0:
|
|
114
|
+
self.logger.info(f"{self.__class__.__name__} terminating since no more items")
|
|
115
|
+
return
|
|
116
|
+
# loop over all tasks
|
|
117
|
+
for jediTaskID, splitRule, taskStatus, parent_tid in taskList:
|
|
118
|
+
# make logger
|
|
119
|
+
tmpLog = MsgWrapper(self.logger, f"< jediTaskID={jediTaskID} >", monToken=f"<jediTaskID={jediTaskID}>")
|
|
120
|
+
tmpLog.debug("start")
|
|
121
|
+
tmpStat = Interaction.SC_SUCCEEDED
|
|
122
|
+
errStr = ""
|
|
123
|
+
prodSourceLabel = None
|
|
124
|
+
# read task parameters
|
|
125
|
+
try:
|
|
126
|
+
taskParam = None
|
|
127
|
+
taskParam = self.taskBufferIF.getTaskParamsWithID_JEDI(jediTaskID)
|
|
128
|
+
taskParamMap = RefinerUtils.decodeJSON(taskParam)
|
|
129
|
+
except Exception:
|
|
130
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
131
|
+
errStr = f"conversion to map from json failed with {errtype.__name__}:{errvalue}"
|
|
132
|
+
tmpLog.debug(taskParam)
|
|
133
|
+
tmpLog.error(errStr)
|
|
134
|
+
continue
|
|
135
|
+
tmpStat = Interaction.SC_FAILED
|
|
136
|
+
# get impl
|
|
137
|
+
if tmpStat == Interaction.SC_SUCCEEDED:
|
|
138
|
+
tmpLog.info("getting Impl")
|
|
139
|
+
try:
|
|
140
|
+
# get VO and sourceLabel
|
|
141
|
+
vo = taskParamMap["vo"]
|
|
142
|
+
prodSourceLabel = taskParamMap["prodSourceLabel"]
|
|
143
|
+
taskType = taskParamMap["taskType"]
|
|
144
|
+
tmpLog.info(f"vo={vo} sourceLabel={prodSourceLabel} taskType={taskType}")
|
|
145
|
+
# get impl
|
|
146
|
+
impl = self.implFactory.instantiateImpl(vo, prodSourceLabel, taskType, self.taskBufferIF, self.ddmIF)
|
|
147
|
+
if impl is None:
|
|
148
|
+
# task refiner is undefined
|
|
149
|
+
errStr = f"task refiner is undefined for vo={vo} sourceLabel={prodSourceLabel}"
|
|
150
|
+
tmpLog.error(errStr)
|
|
151
|
+
tmpStat = Interaction.SC_FAILED
|
|
152
|
+
# get data carousel config map
|
|
153
|
+
dc_config_map = self.data_carousel_interface.dc_config_map
|
|
154
|
+
except Exception:
|
|
155
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
156
|
+
errStr = f"failed to get task refiner with {errtype.__name__}:{errvalue}"
|
|
157
|
+
tmpLog.error(errStr)
|
|
158
|
+
tmpStat = Interaction.SC_FAILED
|
|
159
|
+
# adjust task parameters
|
|
160
|
+
if tmpStat == Interaction.SC_SUCCEEDED:
|
|
161
|
+
tmpLog.info("adjusting task parameters")
|
|
162
|
+
try:
|
|
163
|
+
# Data Carousel; for all analysis tasks, and production tasks with "panda_data_carousel"
|
|
164
|
+
if dc_config_map and ((taskType == "anal" and prodSourceLabel == "user") or taskParamMap.get("panda_data_carousel")):
|
|
165
|
+
if taskParamMap.get("noInput"):
|
|
166
|
+
# noInput task, skipped
|
|
167
|
+
pass
|
|
168
|
+
elif taskType == "anal" and (taskParamMap.get("nFiles") or taskParamMap.get("nEvents") or taskParamMap.get("skipFilesUsedBy")):
|
|
169
|
+
# for analysis tasks with nFiles or nEvents or skipFilesUsedBy, task does not need all files from inputs, not to stage, skipped
|
|
170
|
+
pass
|
|
171
|
+
elif "inputPreStaging" not in taskParamMap:
|
|
172
|
+
if dc_config_map.early_access_users and dc_config_map.early_access_users[0] == "ALL":
|
|
173
|
+
# enable input pre-staging for all users
|
|
174
|
+
taskParamMap["inputPreStaging"] = True
|
|
175
|
+
tmpLog.info(f"set inputPreStaging for data carousel ALL users")
|
|
176
|
+
elif (user_name := taskParamMap.get("userName")) in dc_config_map.early_access_users:
|
|
177
|
+
# enable input pre-staging for early access user
|
|
178
|
+
taskParamMap["inputPreStaging"] = True
|
|
179
|
+
tmpLog.info(f"set inputPreStaging for data carousel early access user {user_name}")
|
|
180
|
+
except Exception:
|
|
181
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
182
|
+
errStr = f"failed to adjust task parameters with {errtype.__name__}:{errvalue}"
|
|
183
|
+
tmpLog.error(errStr)
|
|
184
|
+
tmpStat = Interaction.SC_FAILED
|
|
185
|
+
# extract common parameters
|
|
186
|
+
if tmpStat == Interaction.SC_SUCCEEDED:
|
|
187
|
+
tmpLog.info("extracting common")
|
|
188
|
+
try:
|
|
189
|
+
# initialize impl
|
|
190
|
+
impl.initializeRefiner(tmpLog)
|
|
191
|
+
impl.oldTaskStatus = taskStatus
|
|
192
|
+
# extract common parameters
|
|
193
|
+
impl.extractCommon(jediTaskID, taskParamMap, self.workQueueMapper, splitRule)
|
|
194
|
+
# set parent tid
|
|
195
|
+
if parent_tid not in [None, jediTaskID]:
|
|
196
|
+
impl.taskSpec.parent_tid = parent_tid
|
|
197
|
+
except Exception:
|
|
198
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
199
|
+
# on hold in case of external error
|
|
200
|
+
if errtype == JediException.ExternalTempError:
|
|
201
|
+
tmpErrStr = f"pending due to external problem. {errvalue}"
|
|
202
|
+
setFrozenTime = True
|
|
203
|
+
impl.taskSpec.status = taskStatus
|
|
204
|
+
impl.taskSpec.setOnHold()
|
|
205
|
+
impl.taskSpec.setErrDiag(tmpErrStr)
|
|
206
|
+
# not to update some task attributes
|
|
207
|
+
impl.taskSpec.resetRefinedAttrs()
|
|
208
|
+
tmpLog.info(tmpErrStr)
|
|
209
|
+
self.taskBufferIF.updateTask_JEDI(
|
|
210
|
+
impl.taskSpec,
|
|
211
|
+
{"jediTaskID": impl.taskSpec.jediTaskID},
|
|
212
|
+
oldStatus=[taskStatus],
|
|
213
|
+
insertUnknown=impl.unknownDatasetList,
|
|
214
|
+
setFrozenTime=setFrozenTime,
|
|
215
|
+
)
|
|
216
|
+
continue
|
|
217
|
+
errStr = f"failed to extract common parameters with {errtype.__name__}:{errvalue} {traceback.format_exc()}"
|
|
218
|
+
tmpLog.error(errStr)
|
|
219
|
+
tmpStat = Interaction.SC_FAILED
|
|
220
|
+
# check attribute length
|
|
221
|
+
if tmpStat == Interaction.SC_SUCCEEDED:
|
|
222
|
+
tmpLog.info("checking attribute length")
|
|
223
|
+
if not impl.taskSpec.checkAttrLength():
|
|
224
|
+
tmpLog.error(impl.taskSpec.errorDialog)
|
|
225
|
+
tmpStat = Interaction.SC_FAILED
|
|
226
|
+
# check parent
|
|
227
|
+
noWaitParent = False
|
|
228
|
+
parentState = None
|
|
229
|
+
if tmpStat == Interaction.SC_SUCCEEDED and parent_tid not in [None, jediTaskID]:
|
|
230
|
+
tmpLog.info("check parent task")
|
|
231
|
+
try:
|
|
232
|
+
tmpStat = self.taskBufferIF.checkParentTask_JEDI(parent_tid, jediTaskID)
|
|
233
|
+
parentState = tmpStat
|
|
234
|
+
if tmpStat == "completed":
|
|
235
|
+
# parent is done
|
|
236
|
+
tmpStat = Interaction.SC_SUCCEEDED
|
|
237
|
+
elif tmpStat is None or tmpStat == "running":
|
|
238
|
+
if not impl.taskSpec.noWaitParent():
|
|
239
|
+
# parent is running
|
|
240
|
+
errStr = f"pending until parent task {parent_tid} is done"
|
|
241
|
+
impl.taskSpec.status = taskStatus
|
|
242
|
+
impl.taskSpec.setOnHold()
|
|
243
|
+
impl.taskSpec.setErrDiag(errStr)
|
|
244
|
+
# not to update some task attributes
|
|
245
|
+
impl.taskSpec.resetRefinedAttrs()
|
|
246
|
+
tmpLog.info(errStr)
|
|
247
|
+
self.taskBufferIF.updateTask_JEDI(
|
|
248
|
+
impl.taskSpec, {"jediTaskID": impl.taskSpec.jediTaskID}, oldStatus=[taskStatus], setFrozenTime=False
|
|
249
|
+
)
|
|
250
|
+
continue
|
|
251
|
+
else:
|
|
252
|
+
# not wait for parent
|
|
253
|
+
tmpStat = Interaction.SC_SUCCEEDED
|
|
254
|
+
noWaitParent = True
|
|
255
|
+
else:
|
|
256
|
+
# parent is corrupted
|
|
257
|
+
tmpStat = Interaction.SC_FAILED
|
|
258
|
+
tmpErrStr = f"parent task {parent_tid} failed to complete"
|
|
259
|
+
impl.taskSpec.setErrDiag(tmpErrStr)
|
|
260
|
+
except Exception:
|
|
261
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
262
|
+
errStr = f"failed to check parent task with {errtype.__name__}:{errvalue}"
|
|
263
|
+
tmpLog.error(errStr)
|
|
264
|
+
tmpStat = Interaction.SC_FAILED
|
|
265
|
+
|
|
266
|
+
# refine
|
|
267
|
+
if tmpStat == Interaction.SC_SUCCEEDED:
|
|
268
|
+
tmpLog.info(f"refining with {impl.__class__.__name__}")
|
|
269
|
+
try:
|
|
270
|
+
tmpStat = impl.doRefine(jediTaskID, taskParamMap)
|
|
271
|
+
except Exception:
|
|
272
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
273
|
+
# wait unknown input if noWaitParent or waitInput
|
|
274
|
+
toFinish = False
|
|
275
|
+
if (
|
|
276
|
+
((impl.taskSpec.noWaitParent() or impl.taskSpec.waitInput()) and errtype == JediException.UnknownDatasetError)
|
|
277
|
+
or parentState == "running"
|
|
278
|
+
or errtype in [Interaction.JEDITemporaryError, JediException.ExternalTempError, JediException.TempBadStorageError]
|
|
279
|
+
):
|
|
280
|
+
if impl.taskSpec.noWaitParent() and errtype == JediException.UnknownDatasetError and parentState != "running":
|
|
281
|
+
if impl.taskSpec.allowEmptyInput():
|
|
282
|
+
tmpErrStr = f"finishing due to missing input while parent is {parentState}"
|
|
283
|
+
toFinish = True
|
|
284
|
+
setFrozenTime = False
|
|
285
|
+
else:
|
|
286
|
+
tmpErrStr = f"pending due to missing input while parent is {parentState}"
|
|
287
|
+
setFrozenTime = True
|
|
288
|
+
elif impl.taskSpec.noWaitParent() or parentState == "running":
|
|
289
|
+
tmpErrStr = f"pending until parent produces input. parent is {parentState}"
|
|
290
|
+
setFrozenTime = False
|
|
291
|
+
elif errtype == Interaction.JEDITemporaryError or errtype == JediException.ExternalTempError:
|
|
292
|
+
tmpErrStr = f"pending due to external temporary problem. {errvalue}"
|
|
293
|
+
setFrozenTime = True
|
|
294
|
+
elif errtype == JediException.TempBadStorageError:
|
|
295
|
+
tmpErrStr = f"pending due to temporary storage issue. {errvalue}"
|
|
296
|
+
setFrozenTime = True
|
|
297
|
+
else:
|
|
298
|
+
tmpErrStr = "pending until input is staged"
|
|
299
|
+
setFrozenTime = True
|
|
300
|
+
if toFinish:
|
|
301
|
+
impl.taskSpec.status = "finishing"
|
|
302
|
+
else:
|
|
303
|
+
impl.taskSpec.status = taskStatus
|
|
304
|
+
impl.taskSpec.setOnHold()
|
|
305
|
+
impl.taskSpec.setErrDiag(tmpErrStr)
|
|
306
|
+
# not to update some task attributes
|
|
307
|
+
impl.taskSpec.resetRefinedAttrs()
|
|
308
|
+
tmpLog.info(tmpErrStr)
|
|
309
|
+
self.taskBufferIF.updateTask_JEDI(
|
|
310
|
+
impl.taskSpec,
|
|
311
|
+
{"jediTaskID": impl.taskSpec.jediTaskID},
|
|
312
|
+
oldStatus=[taskStatus],
|
|
313
|
+
insertUnknown=impl.unknownDatasetList,
|
|
314
|
+
setFrozenTime=setFrozenTime,
|
|
315
|
+
)
|
|
316
|
+
continue
|
|
317
|
+
elif (
|
|
318
|
+
not (impl.taskSpec.noWaitParent() or impl.taskSpec.waitInput())
|
|
319
|
+
and errtype == JediException.UnknownDatasetError
|
|
320
|
+
and impl.taskSpec.allowEmptyInput()
|
|
321
|
+
):
|
|
322
|
+
impl.taskSpec.status = "finishing"
|
|
323
|
+
tmpErrStr = f"finishing due to missing input after parent is {parentState}"
|
|
324
|
+
impl.taskSpec.setErrDiag(tmpErrStr)
|
|
325
|
+
# not to update some task attributes
|
|
326
|
+
impl.taskSpec.resetRefinedAttrs()
|
|
327
|
+
tmpLog.info(tmpErrStr)
|
|
328
|
+
self.taskBufferIF.updateTask_JEDI(
|
|
329
|
+
impl.taskSpec, {"jediTaskID": impl.taskSpec.jediTaskID}, oldStatus=[taskStatus], insertUnknown=impl.unknownDatasetList
|
|
330
|
+
)
|
|
331
|
+
continue
|
|
332
|
+
else:
|
|
333
|
+
errStr = f"failed to refine task with {errtype.__name__}:{errvalue}"
|
|
334
|
+
tmpLog.error(errStr)
|
|
335
|
+
tmpStat = Interaction.SC_FAILED
|
|
336
|
+
# data carousel (input pre-staging) ; currently for all analysis tasks, and production tasks with "panda_data_carousel"
|
|
337
|
+
if tmpStat == Interaction.SC_SUCCEEDED:
|
|
338
|
+
# set of datasets requiring and not requiring staging
|
|
339
|
+
to_staging_datasets = set()
|
|
340
|
+
no_staging_datasets = set()
|
|
341
|
+
disk_datasets = set()
|
|
342
|
+
# check datasets to pre-stage
|
|
343
|
+
if taskParamMap.get("inputPreStaging") and (
|
|
344
|
+
(taskParamMap.get("taskType") == "anal" and taskParamMap.get("prodSourceLabel") == "user")
|
|
345
|
+
or taskParamMap.get("panda_data_carousel")
|
|
346
|
+
):
|
|
347
|
+
tmpLog.info("checking about data carousel")
|
|
348
|
+
try:
|
|
349
|
+
# get the list of dataset names (and DIDs) required to check; currently only master input datasets
|
|
350
|
+
dsname_list = []
|
|
351
|
+
for dataset_spec in impl.inMasterDatasetSpec:
|
|
352
|
+
dataset_name = dataset_spec.datasetName
|
|
353
|
+
dataset_did = None
|
|
354
|
+
try:
|
|
355
|
+
dataset_did = rucioAPI.get_did_str(dataset_name)
|
|
356
|
+
except Exception:
|
|
357
|
+
pass
|
|
358
|
+
dsname_list.append(dataset_name)
|
|
359
|
+
if dataset_did is not None:
|
|
360
|
+
dsname_list.append(dataset_did)
|
|
361
|
+
# check input datasets to prestage
|
|
362
|
+
try:
|
|
363
|
+
prestaging_list, ds_list_dict = self.data_carousel_interface.get_input_datasets_to_prestage(
|
|
364
|
+
jediTaskID, taskParamMap, dsname_list=dsname_list
|
|
365
|
+
)
|
|
366
|
+
except Exception as e:
|
|
367
|
+
# got error (e.g. due to DDM error); skip and retry in next cycle
|
|
368
|
+
tmpLog.error(f"failed to check input datasets to prestage ; got {e} ; skip and retry next time")
|
|
369
|
+
continue
|
|
370
|
+
# found no datasets only on tape to prestage
|
|
371
|
+
if pseudo_coll_list := ds_list_dict["pseudo_coll_list"]:
|
|
372
|
+
# update no_staging_datasets with pseudo inputs
|
|
373
|
+
tmpLog.debug(f"pseudo inputs: {pseudo_coll_list}")
|
|
374
|
+
no_staging_datasets.update(set(pseudo_coll_list))
|
|
375
|
+
if empty_coll_list := ds_list_dict["empty_coll_list"]:
|
|
376
|
+
# update no_staging_datasets with empty input collections
|
|
377
|
+
tmpLog.debug(f"empty input collections: {empty_coll_list}")
|
|
378
|
+
no_staging_datasets.update(set(empty_coll_list))
|
|
379
|
+
if unfound_coll_list := ds_list_dict["unfound_coll_list"]:
|
|
380
|
+
# some input collections unfound
|
|
381
|
+
if taskParamMap.get("waitInput"):
|
|
382
|
+
# task has waitInput; to be checked again by TaskRefiner later
|
|
383
|
+
tmpLog.debug(f"task has waitInput, waiting for input collections to be created: {unfound_coll_list}; skipped")
|
|
384
|
+
else:
|
|
385
|
+
# not to wait input; update no_staging_datasets with unfound input collections
|
|
386
|
+
tmpLog.debug(f"some input collections not found: {unfound_coll_list}")
|
|
387
|
+
no_staging_datasets.update(set(unfound_coll_list))
|
|
388
|
+
if no_tape_coll_did_list := ds_list_dict["no_tape_coll_did_list"]:
|
|
389
|
+
# update no_staging_datasets for all collections without constituent datasets on tape source
|
|
390
|
+
tmpLog.debug(f"collections without constituent datasets on tape source: {no_tape_coll_did_list}")
|
|
391
|
+
no_staging_datasets.update(set(no_tape_coll_did_list))
|
|
392
|
+
if to_skip_ds_list := ds_list_dict["to_skip_ds_list"]:
|
|
393
|
+
# update no_staging_datasets with secondary datasets
|
|
394
|
+
tmpLog.debug(f"datasets not required to check about data carousel (non-master input): {to_skip_ds_list}")
|
|
395
|
+
no_staging_datasets.update(set(to_skip_ds_list))
|
|
396
|
+
if datadisk_ds_list := ds_list_dict["datadisk_ds_list"]:
|
|
397
|
+
# update no_staging_datasets with datasets already on datadisks
|
|
398
|
+
tmpLog.debug(f"datasets already on datadisks: {datadisk_ds_list}")
|
|
399
|
+
no_staging_datasets.update(set(datadisk_ds_list))
|
|
400
|
+
disk_datasets.update(set(datadisk_ds_list))
|
|
401
|
+
if unfound_ds_list := ds_list_dict["unfound_ds_list"]:
|
|
402
|
+
# some datasets unfound
|
|
403
|
+
if taskParamMap.get("waitInput"):
|
|
404
|
+
# task has waitInput; to be checked again by TaskRefiner later
|
|
405
|
+
tmpLog.debug(f"task has waitInput, waiting for input datasets to be created: {unfound_ds_list}; skipped")
|
|
406
|
+
else:
|
|
407
|
+
# not to wait input; update no_staging_datasets with datasets unfound on tape or datadisk (regardless of local/scratch disks)
|
|
408
|
+
tmpLog.debug(f"some input datasets not found on tape or datadisk: {unfound_ds_list}")
|
|
409
|
+
no_staging_datasets.update(set(unfound_ds_list))
|
|
410
|
+
if not prestaging_list and (not unfound_coll_list or not taskParamMap.get("waitInput")):
|
|
411
|
+
# all input collections do not need staging (found, or unfound but waiting)
|
|
412
|
+
tmpLog.info("no need to prestage, try to resume task from staging")
|
|
413
|
+
# no dataset needs pre-staging; resume task from staging
|
|
414
|
+
self.taskBufferIF.sendCommandTaskPanda(jediTaskID, "TaskRefiner. No need to prestage. Resumed from staging", True, "resume")
|
|
415
|
+
if prestaging_list:
|
|
416
|
+
# something to prestage
|
|
417
|
+
if to_reuse_staging_ds_list := ds_list_dict["to_reuse_staging_ds_list"]:
|
|
418
|
+
# update to_staging_datasets with datasets to reuse existing staging DDM rules (de facto already staging, still need to submit DC requests)
|
|
419
|
+
tmpLog.debug(f"datasets to reuse existing staging DDM rules: {to_reuse_staging_ds_list}")
|
|
420
|
+
to_staging_datasets.update(set(to_reuse_staging_ds_list))
|
|
421
|
+
if to_reuse_staged_ds_list := ds_list_dict["to_reuse_staged_ds_list"]:
|
|
422
|
+
# update no_staging_datasets with datasets already staged (de facto already on disk)
|
|
423
|
+
tmpLog.debug(f"datasets already staged by existing DDM rules: {to_reuse_staged_ds_list}")
|
|
424
|
+
no_staging_datasets.update(set(to_reuse_staged_ds_list))
|
|
425
|
+
if tape_coll_did_list := ds_list_dict["tape_coll_did_list"]:
|
|
426
|
+
# update to_staging_datasets with collections with datasets only on tapes
|
|
427
|
+
to_staging_datasets.update(set(tape_coll_did_list))
|
|
428
|
+
if tape_ds_list := ds_list_dict["tape_ds_list"]:
|
|
429
|
+
# update to_staging_datasets with datasets only on tapes
|
|
430
|
+
to_staging_datasets.update(set(tape_ds_list))
|
|
431
|
+
if to_pin_ds_list := ds_list_dict["to_pin_ds_list"]:
|
|
432
|
+
# update no_staging_datasets with datasets to pin on datadisks (already on disk but without rule)
|
|
433
|
+
tmpLog.debug(f"datasets to pin to datadisks: {to_pin_ds_list}")
|
|
434
|
+
no_staging_datasets.update(set(to_pin_ds_list))
|
|
435
|
+
# submit options
|
|
436
|
+
dc_submit_options = {}
|
|
437
|
+
if taskParamMap.get("remove_rule_when_done"):
|
|
438
|
+
# remove rule when done
|
|
439
|
+
dc_submit_options["remove_when_done"] = True
|
|
440
|
+
if task_type := taskParamMap.get("taskType"):
|
|
441
|
+
dc_submit_options["task_type"] = task_type
|
|
442
|
+
# if task_user := taskParamMap.get("userName"):
|
|
443
|
+
# dc_submit_options["task_user"] = task_user
|
|
444
|
+
# if task_group := taskParamMap.get("workingGroup"):
|
|
445
|
+
# dc_submit_options["task_group"] = task_group
|
|
446
|
+
# submit data carousel requests for dataset to pre-stage
|
|
447
|
+
tmpLog.info("to prestage, submitting data carousel requests")
|
|
448
|
+
tmp_ret = self.data_carousel_interface.submit_data_carousel_requests(jediTaskID, prestaging_list, options=dc_submit_options)
|
|
449
|
+
if tmp_ret:
|
|
450
|
+
tmpLog.info("submitted data carousel requests")
|
|
451
|
+
if to_staging_datasets <= no_staging_datasets:
|
|
452
|
+
tmpLog.info("all datasets do not need staging (to pin or already staged); skip staging")
|
|
453
|
+
elif disk_datasets:
|
|
454
|
+
tmpLog.info("some datasets are on datadisks; skip staging")
|
|
455
|
+
else:
|
|
456
|
+
taskParamMap["toStaging"] = True
|
|
457
|
+
tmpLog.info("set toStaging")
|
|
458
|
+
else:
|
|
459
|
+
# failed to submit data carousel requests; skip and retry in next cycle
|
|
460
|
+
tmpLog.error("failed to submit data carousel requests; skip and retry next time")
|
|
461
|
+
continue
|
|
462
|
+
if related_dcreq_ids := ds_list_dict["related_dcreq_ids"]:
|
|
463
|
+
tmp_ret = self.data_carousel_interface.add_data_carousel_relations(jediTaskID, related_dcreq_ids)
|
|
464
|
+
if tmp_ret:
|
|
465
|
+
tmpLog.info(f"added relations to existing data carousel requests: {related_dcreq_ids}")
|
|
466
|
+
else:
|
|
467
|
+
tmpLog.error(f"failed to add relations to existing data carousel requests: {related_dcreq_ids}; skipped")
|
|
468
|
+
except Exception:
|
|
469
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
470
|
+
errStr = f"failed to check about data carousel with {errtype.__name__}:{errvalue}"
|
|
471
|
+
tmpLog.error(errStr)
|
|
472
|
+
tmpStat = Interaction.SC_FAILED
|
|
473
|
+
# staging
|
|
474
|
+
if tmpStat == Interaction.SC_SUCCEEDED:
|
|
475
|
+
if "toStaging" in taskParamMap and taskStatus not in ["staged", "rerefine"]:
|
|
476
|
+
errStr = "wait until staging is done"
|
|
477
|
+
impl.taskSpec.status = "staging"
|
|
478
|
+
impl.taskSpec.oldStatus = taskStatus
|
|
479
|
+
impl.taskSpec.setErrDiag(errStr)
|
|
480
|
+
# not to update some task attributes
|
|
481
|
+
impl.taskSpec.resetRefinedAttrs()
|
|
482
|
+
tmpLog.info(errStr)
|
|
483
|
+
self.taskBufferIF.updateTask_JEDI(
|
|
484
|
+
impl.taskSpec, {"jediTaskID": impl.taskSpec.jediTaskID}, oldStatus=[taskStatus], updateDEFT=False, setFrozenTime=False
|
|
485
|
+
)
|
|
486
|
+
tmpLog.info("update task status to staging")
|
|
487
|
+
continue
|
|
488
|
+
# adjust specs after refining
|
|
489
|
+
if tmpStat == Interaction.SC_SUCCEEDED:
|
|
490
|
+
try:
|
|
491
|
+
if impl.taskSpec.inputPreStaging():
|
|
492
|
+
# for now, no staging for all secondary datasets
|
|
493
|
+
tmp_ds_set = set()
|
|
494
|
+
for dataset_spec in impl.inSecDatasetSpecList:
|
|
495
|
+
dataset_spec.set_no_staging(True)
|
|
496
|
+
tmp_ds_set.add(dataset_spec.datasetName)
|
|
497
|
+
if tmp_ds_set:
|
|
498
|
+
tmpLog.debug(f"set no_staging for secondary datasets: {list(tmp_ds_set)}")
|
|
499
|
+
if no_staging_datasets:
|
|
500
|
+
# discard None if any
|
|
501
|
+
no_staging_datasets.discard(None)
|
|
502
|
+
# set no_staging attribute for datasets not requiring staging
|
|
503
|
+
tmp_ds_set = set()
|
|
504
|
+
for dataset_spec in impl.inMasterDatasetSpec:
|
|
505
|
+
dataset_name = dataset_spec.datasetName
|
|
506
|
+
dataset_did = None
|
|
507
|
+
try:
|
|
508
|
+
dataset_did = rucioAPI.get_did_str(dataset_name)
|
|
509
|
+
except Exception:
|
|
510
|
+
pass
|
|
511
|
+
if (
|
|
512
|
+
dataset_name in no_staging_datasets
|
|
513
|
+
or dataset_did in no_staging_datasets
|
|
514
|
+
or (dataset_name not in to_staging_datasets and dataset_did not in to_staging_datasets)
|
|
515
|
+
):
|
|
516
|
+
dataset_spec.set_no_staging(True)
|
|
517
|
+
tmp_ds_set.add(dataset_name)
|
|
518
|
+
if tmp_ds_set:
|
|
519
|
+
tmpLog.debug(f"set no_staging for master datasets not to stage: {list(tmp_ds_set)}")
|
|
520
|
+
except Exception:
|
|
521
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
522
|
+
errStr = f"failed to adjust spec after refining {errtype.__name__}:{errvalue}"
|
|
523
|
+
tmpLog.error(errStr)
|
|
524
|
+
tmpStat = Interaction.SC_FAILED
|
|
525
|
+
# register
|
|
526
|
+
if tmpStat != Interaction.SC_SUCCEEDED:
|
|
527
|
+
tmpLog.error("failed to refine the task")
|
|
528
|
+
if impl is None or impl.taskSpec is None:
|
|
529
|
+
tmpTaskSpec = JediTaskSpec()
|
|
530
|
+
tmpTaskSpec.jediTaskID = jediTaskID
|
|
531
|
+
else:
|
|
532
|
+
tmpTaskSpec = impl.taskSpec
|
|
533
|
+
tmpTaskSpec.status = "tobroken"
|
|
534
|
+
if errStr != "":
|
|
535
|
+
tmpTaskSpec.setErrDiag(errStr, True)
|
|
536
|
+
self.taskBufferIF.updateTask_JEDI(tmpTaskSpec, {"jediTaskID": tmpTaskSpec.jediTaskID}, oldStatus=[taskStatus])
|
|
537
|
+
else:
|
|
538
|
+
tmpLog.info("registering")
|
|
539
|
+
# fill JEDI tables
|
|
540
|
+
try:
|
|
541
|
+
# enable protection against task duplication
|
|
542
|
+
if "uniqueTaskName" in taskParamMap and taskParamMap["uniqueTaskName"] and not impl.taskSpec.checkPreProcessed():
|
|
543
|
+
uniqueTaskName = True
|
|
544
|
+
else:
|
|
545
|
+
uniqueTaskName = False
|
|
546
|
+
strTaskParams = None
|
|
547
|
+
if impl.updatedTaskParams is not None:
|
|
548
|
+
strTaskParams = RefinerUtils.encodeJSON(impl.updatedTaskParams)
|
|
549
|
+
if taskStatus in ["registered", "staged"]:
|
|
550
|
+
# unset pre-process flag
|
|
551
|
+
if impl.taskSpec.checkPreProcessed():
|
|
552
|
+
impl.taskSpec.setPostPreProcess()
|
|
553
|
+
# full registration
|
|
554
|
+
tmpStat, newTaskStatus = self.taskBufferIF.registerTaskInOneShot_JEDI(
|
|
555
|
+
jediTaskID,
|
|
556
|
+
impl.taskSpec,
|
|
557
|
+
impl.inMasterDatasetSpec,
|
|
558
|
+
impl.inSecDatasetSpecList,
|
|
559
|
+
impl.outDatasetSpecList,
|
|
560
|
+
impl.outputTemplateMap,
|
|
561
|
+
impl.jobParamsTemplate,
|
|
562
|
+
strTaskParams,
|
|
563
|
+
impl.unmergeMasterDatasetSpec,
|
|
564
|
+
impl.unmergeDatasetSpecMap,
|
|
565
|
+
uniqueTaskName,
|
|
566
|
+
taskStatus,
|
|
567
|
+
)
|
|
568
|
+
if not tmpStat:
|
|
569
|
+
tmpErrStr = "failed to register the task to JEDI in a single shot"
|
|
570
|
+
tmpLog.error(tmpErrStr)
|
|
571
|
+
tmpTaskSpec = JediTaskSpec()
|
|
572
|
+
tmpTaskSpec.status = newTaskStatus
|
|
573
|
+
tmpTaskSpec.errorDialog = impl.taskSpec.errorDialog
|
|
574
|
+
tmpTaskSpec.setErrDiag(tmpErrStr, True)
|
|
575
|
+
self.taskBufferIF.updateTask_JEDI(tmpTaskSpec, {"jediTaskID": impl.taskSpec.jediTaskID}, oldStatus=[taskStatus])
|
|
576
|
+
tmp_msg = f"set task_status={newTaskStatus} sourceLabel={prodSourceLabel}"
|
|
577
|
+
tmpLog.info(tmp_msg)
|
|
578
|
+
tmpLog.sendMsg(tmp_msg, self.msgType)
|
|
579
|
+
# send message to contents feeder if the task is registered
|
|
580
|
+
if tmpStat and impl.taskSpec.is_msg_driven():
|
|
581
|
+
push_ret = self.taskBufferIF.push_task_trigger_message("jedi_contents_feeder", jediTaskID, task_spec=impl.taskSpec)
|
|
582
|
+
if push_ret:
|
|
583
|
+
tmpLog.debug("pushed trigger message to jedi_contents_feeder")
|
|
584
|
+
else:
|
|
585
|
+
tmpLog.warning("failed to push trigger message to jedi_contents_feeder")
|
|
586
|
+
else:
|
|
587
|
+
# disable scouts if previous attempt didn't use it
|
|
588
|
+
if not impl.taskSpec.useScout(splitRule):
|
|
589
|
+
impl.taskSpec.setUseScout(False)
|
|
590
|
+
# disallow to reset some attributes
|
|
591
|
+
impl.taskSpec.reserve_old_attributes()
|
|
592
|
+
# update task with new params
|
|
593
|
+
self.taskBufferIF.updateTask_JEDI(impl.taskSpec, {"jediTaskID": impl.taskSpec.jediTaskID}, oldStatus=[taskStatus])
|
|
594
|
+
# appending for incremental execution
|
|
595
|
+
tmpStat = self.taskBufferIF.appendDatasets_JEDI(jediTaskID, impl.inMasterDatasetSpec, impl.inSecDatasetSpecList)
|
|
596
|
+
if not tmpStat:
|
|
597
|
+
tmpLog.error("failed to append datasets for incexec")
|
|
598
|
+
except Exception:
|
|
599
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
600
|
+
tmpErrStr = f"failed to register the task to JEDI with {errtype.__name__}:{errvalue}"
|
|
601
|
+
tmpLog.error(tmpErrStr)
|
|
602
|
+
else:
|
|
603
|
+
tmpLog.info("done")
|
|
604
|
+
except Exception:
|
|
605
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
606
|
+
logger.error(f"{self.__class__.__name__} failed in runImpl() with {errtype.__name__}:{errvalue}")
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
def launcher(commuChannel, taskBufferIF, ddmIF, vos=None, prodSourceLabels=None):
|
|
610
|
+
p = TaskRefiner(commuChannel, taskBufferIF, ddmIF, vos, prodSourceLabels)
|
|
611
|
+
p.start()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from pandacommon.pandalogger.PandaLogger import PandaLogger
|
|
2
|
+
|
|
3
|
+
from pandajedi.jediconfig import jedi_config
|
|
4
|
+
from pandajedi.jedicore.FactoryBase import FactoryBase
|
|
5
|
+
|
|
6
|
+
logger = PandaLogger().getLogger(__name__.split(".")[-1])
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# factory class for task setup
|
|
10
|
+
class TaskSetupper(FactoryBase):
|
|
11
|
+
# constructor
|
|
12
|
+
def __init__(self, vo, sourceLabel):
|
|
13
|
+
FactoryBase.__init__(self, vo, sourceLabel, logger, jedi_config.tasksetup.modConfig)
|
|
14
|
+
|
|
15
|
+
# main
|
|
16
|
+
def doSetup(self, taskSpec, datasetToRegister, pandaJobs):
|
|
17
|
+
return self.getImpl(taskSpec.vo, taskSpec.prodSourceLabel).doSetup(taskSpec, datasetToRegister, pandaJobs)
|