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,268 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import sys
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
from pandacommon.pandalogger.PandaLogger import PandaLogger
|
|
6
|
+
from pandacommon.pandautils.PandaUtils import naive_utcnow
|
|
7
|
+
|
|
8
|
+
from pandajedi.jediconfig import jedi_config
|
|
9
|
+
from pandajedi.jedicore import Interaction
|
|
10
|
+
from pandajedi.jedicore.FactoryBase import FactoryBase
|
|
11
|
+
from pandajedi.jedicore.MsgWrapper import MsgWrapper
|
|
12
|
+
from pandajedi.jedicore.ThreadUtils import ListWithLock, ThreadPool, WorkerThread
|
|
13
|
+
|
|
14
|
+
from .JediKnight import JediKnight
|
|
15
|
+
|
|
16
|
+
logger = PandaLogger().getLogger(__name__.split(".")[-1])
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# worker class to refine TASK_PARAM to fill JEDI tables
|
|
20
|
+
class TaskBroker(JediKnight, FactoryBase):
|
|
21
|
+
# constructor
|
|
22
|
+
def __init__(self, commuChannel, taskBufferIF, ddmIF, vos, prodSourceLabels):
|
|
23
|
+
self.vos = self.parseInit(vos)
|
|
24
|
+
self.prodSourceLabels = self.parseInit(prodSourceLabels)
|
|
25
|
+
JediKnight.__init__(self, commuChannel, taskBufferIF, ddmIF, logger)
|
|
26
|
+
FactoryBase.__init__(self, self.vos, self.prodSourceLabels, logger, jedi_config.taskbroker.modConfig)
|
|
27
|
+
|
|
28
|
+
# main
|
|
29
|
+
def start(self):
|
|
30
|
+
# start base classes
|
|
31
|
+
JediKnight.start(self)
|
|
32
|
+
FactoryBase.initializeMods(self, self.taskBufferIF, self.ddmIF)
|
|
33
|
+
# go into main loop
|
|
34
|
+
while True:
|
|
35
|
+
startTime = naive_utcnow()
|
|
36
|
+
try:
|
|
37
|
+
# get logger
|
|
38
|
+
tmpLog = MsgWrapper(logger)
|
|
39
|
+
tmpLog.debug("start TaskBroker")
|
|
40
|
+
# get work queue mapper
|
|
41
|
+
workQueueMapper = self.taskBufferIF.getWorkQueueMap()
|
|
42
|
+
resource_types = self.taskBufferIF.load_resource_types()
|
|
43
|
+
|
|
44
|
+
# loop over all vos
|
|
45
|
+
for vo in self.vos:
|
|
46
|
+
# loop over all sourceLabels
|
|
47
|
+
for prodSourceLabel in self.prodSourceLabels:
|
|
48
|
+
# loop over all work queues
|
|
49
|
+
for workQueue in workQueueMapper.getAlignedQueueList(vo, prodSourceLabel):
|
|
50
|
+
for resource_type in resource_types:
|
|
51
|
+
wq_name = "_".join(workQueue.queue_name.split(" "))
|
|
52
|
+
msgLabel = f"vo={vo} label={prodSourceLabel} queue={wq_name} resource_type={resource_type.resource_name}: "
|
|
53
|
+
tmpLog.debug(msgLabel + "start")
|
|
54
|
+
# get the list of tasks to check
|
|
55
|
+
tmpList = self.taskBufferIF.getTasksToCheckAssignment_JEDI(vo, prodSourceLabel, workQueue, resource_type.resource_name)
|
|
56
|
+
if tmpList is None:
|
|
57
|
+
# failed
|
|
58
|
+
tmpLog.error(msgLabel + "failed to get the list of tasks to check")
|
|
59
|
+
else:
|
|
60
|
+
tmpLog.debug(msgLabel + f"got tasks_to_check={len(tmpList)}")
|
|
61
|
+
# put to a locked list
|
|
62
|
+
taskList = ListWithLock(tmpList)
|
|
63
|
+
# make thread pool
|
|
64
|
+
threadPool = ThreadPool()
|
|
65
|
+
# make workers
|
|
66
|
+
nWorker = jedi_config.taskbroker.nWorkers
|
|
67
|
+
for iWorker in range(nWorker):
|
|
68
|
+
thr = TaskCheckerThread(taskList, threadPool, self.taskBufferIF, self.ddmIF, self, vo, prodSourceLabel)
|
|
69
|
+
thr.start()
|
|
70
|
+
# join
|
|
71
|
+
threadPool.join()
|
|
72
|
+
# get the list of tasks to assign
|
|
73
|
+
tmpList = self.taskBufferIF.getTasksToAssign_JEDI(vo, prodSourceLabel, workQueue, resource_type.resource_name)
|
|
74
|
+
if tmpList is None:
|
|
75
|
+
# failed
|
|
76
|
+
tmpLog.error(msgLabel + "failed to get the list of tasks to assign")
|
|
77
|
+
else:
|
|
78
|
+
tmpLog.debug(msgLabel + f"got tasks_to_assign={len(tmpList)}")
|
|
79
|
+
# put to a locked list
|
|
80
|
+
taskList = ListWithLock(tmpList)
|
|
81
|
+
# make thread pool
|
|
82
|
+
threadPool = ThreadPool()
|
|
83
|
+
# make workers
|
|
84
|
+
nWorker = jedi_config.taskbroker.nWorkers
|
|
85
|
+
for iWorker in range(nWorker):
|
|
86
|
+
thr = TaskBrokerThread(
|
|
87
|
+
taskList,
|
|
88
|
+
threadPool,
|
|
89
|
+
self.taskBufferIF,
|
|
90
|
+
self.ddmIF,
|
|
91
|
+
self,
|
|
92
|
+
vo,
|
|
93
|
+
prodSourceLabel,
|
|
94
|
+
workQueue,
|
|
95
|
+
resource_type.resource_name,
|
|
96
|
+
)
|
|
97
|
+
thr.start()
|
|
98
|
+
# join
|
|
99
|
+
threadPool.join()
|
|
100
|
+
tmpLog.debug(msgLabel + "done")
|
|
101
|
+
except Exception:
|
|
102
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
103
|
+
tmpLog.error(f"failed in {self.__class__.__name__}.start() with {errtype.__name__} {errvalue}")
|
|
104
|
+
tmpLog.debug("done")
|
|
105
|
+
# sleep if needed
|
|
106
|
+
loopCycle = jedi_config.taskbroker.loopCycle
|
|
107
|
+
timeDelta = naive_utcnow() - startTime
|
|
108
|
+
sleepPeriod = loopCycle - timeDelta.seconds
|
|
109
|
+
if sleepPeriod > 0:
|
|
110
|
+
time.sleep(sleepPeriod)
|
|
111
|
+
# randomize cycle
|
|
112
|
+
self.randomSleep(max_val=loopCycle)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
# thread for real worker
|
|
116
|
+
class TaskCheckerThread(WorkerThread):
|
|
117
|
+
# constructor
|
|
118
|
+
def __init__(self, taskList, threadPool, taskbufferIF, ddmIF, implFactory, vo, prodSourceLabel):
|
|
119
|
+
# initialize woker with no semaphore
|
|
120
|
+
WorkerThread.__init__(self, None, threadPool, logger)
|
|
121
|
+
# attributres
|
|
122
|
+
self.taskList = taskList
|
|
123
|
+
self.taskBufferIF = taskbufferIF
|
|
124
|
+
self.ddmIF = ddmIF.getInterface(vo)
|
|
125
|
+
self.implFactory = implFactory
|
|
126
|
+
self.vo = vo
|
|
127
|
+
self.prodSourceLabel = prodSourceLabel
|
|
128
|
+
|
|
129
|
+
# main
|
|
130
|
+
def runImpl(self):
|
|
131
|
+
while True:
|
|
132
|
+
try:
|
|
133
|
+
# get a part of list
|
|
134
|
+
nTasks = 100
|
|
135
|
+
taskList = self.taskList.get(nTasks)
|
|
136
|
+
totalTasks, idxTasks = self.taskList.stat()
|
|
137
|
+
# no more datasets
|
|
138
|
+
if len(taskList) == 0:
|
|
139
|
+
self.logger.debug(f"{self.__class__.__name__} terminating since no more items")
|
|
140
|
+
return
|
|
141
|
+
# make logger
|
|
142
|
+
tmpLog = MsgWrapper(self.logger)
|
|
143
|
+
tmpLog.info(f"start TaskCheckerThread {idxTasks}/{totalTasks} for jediTaskID={taskList}")
|
|
144
|
+
tmpStat = Interaction.SC_SUCCEEDED
|
|
145
|
+
# get TaskSpecs
|
|
146
|
+
taskSpecList = []
|
|
147
|
+
for jediTaskID in taskList:
|
|
148
|
+
tmpRet, taskSpec = self.taskBufferIF.getTaskWithID_JEDI(jediTaskID, False)
|
|
149
|
+
if tmpRet and taskSpec is not None:
|
|
150
|
+
taskSpecList.append(taskSpec)
|
|
151
|
+
else:
|
|
152
|
+
tmpLog.error(f"failed to get taskSpec for jediTaskID={jediTaskID}")
|
|
153
|
+
if taskSpecList != []:
|
|
154
|
+
# get impl
|
|
155
|
+
if tmpStat == Interaction.SC_SUCCEEDED:
|
|
156
|
+
tmpLog.info("getting Impl")
|
|
157
|
+
try:
|
|
158
|
+
impl = self.implFactory.getImpl(self.vo, self.prodSourceLabel)
|
|
159
|
+
if impl is None:
|
|
160
|
+
# task brokerage is undefined
|
|
161
|
+
tmpLog.error(f"task broker is undefined for vo={self.vo} sourceLabel={self.prodSourceLabel}")
|
|
162
|
+
tmpStat = Interaction.SC_FAILED
|
|
163
|
+
except Exception:
|
|
164
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
165
|
+
tmpLog.error(f"getImpl failed with {errtype.__name__}:{errvalue}")
|
|
166
|
+
tmpStat = Interaction.SC_FAILED
|
|
167
|
+
# check
|
|
168
|
+
if tmpStat == Interaction.SC_SUCCEEDED:
|
|
169
|
+
tmpLog.info(f"check with {impl.__class__.__name__}")
|
|
170
|
+
try:
|
|
171
|
+
tmpStat, taskCloudMap = impl.doCheck(taskSpecList)
|
|
172
|
+
except Exception:
|
|
173
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
174
|
+
tmpLog.error(f"doCheck failed with {errtype.__name__}:{errvalue}")
|
|
175
|
+
tmpStat = Interaction.SC_FAILED
|
|
176
|
+
# update
|
|
177
|
+
if tmpStat != Interaction.SC_SUCCEEDED:
|
|
178
|
+
tmpLog.error("failed to check assignment")
|
|
179
|
+
else:
|
|
180
|
+
tmpRet = self.taskBufferIF.setCloudToTasks_JEDI(taskCloudMap)
|
|
181
|
+
tmpLog.info(f"done with {tmpRet} for {str(taskCloudMap)}")
|
|
182
|
+
except Exception:
|
|
183
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
184
|
+
logger.error(f"{self.__class__.__name__} failed in runImpl() with {errtype.__name__}:{errvalue}")
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
# thread for real worker
|
|
188
|
+
class TaskBrokerThread(WorkerThread):
|
|
189
|
+
# constructor
|
|
190
|
+
def __init__(self, taskList, threadPool, taskbufferIF, ddmIF, implFactory, vo, prodSourceLabel, workQueue, resource_name):
|
|
191
|
+
# initialize woker with no semaphore
|
|
192
|
+
WorkerThread.__init__(self, None, threadPool, logger)
|
|
193
|
+
# attributres
|
|
194
|
+
self.taskList = taskList
|
|
195
|
+
self.taskBufferIF = taskbufferIF
|
|
196
|
+
self.ddmIF = ddmIF.getInterface(vo)
|
|
197
|
+
self.implFactory = implFactory
|
|
198
|
+
self.vo = vo
|
|
199
|
+
self.prodSourceLabel = prodSourceLabel
|
|
200
|
+
self.workQueue = workQueue
|
|
201
|
+
self.resource_name = resource_name
|
|
202
|
+
|
|
203
|
+
# main
|
|
204
|
+
def runImpl(self):
|
|
205
|
+
while True:
|
|
206
|
+
try:
|
|
207
|
+
# get a part of list
|
|
208
|
+
nTasks = 100
|
|
209
|
+
taskList = self.taskList.get(nTasks)
|
|
210
|
+
totalTasks, idxTasks = self.taskList.stat()
|
|
211
|
+
# no more datasets
|
|
212
|
+
if len(taskList) == 0:
|
|
213
|
+
self.logger.debug(f"{self.__class__.__name__} terminating since no more items")
|
|
214
|
+
return
|
|
215
|
+
# make logger
|
|
216
|
+
tmpLog = MsgWrapper(self.logger)
|
|
217
|
+
tmpLog.info(f"start TaskBrokerThread {idxTasks}/{totalTasks} for jediTaskID={taskList}")
|
|
218
|
+
tmpStat = Interaction.SC_SUCCEEDED
|
|
219
|
+
# get TaskSpecs
|
|
220
|
+
tmpListToAssign = []
|
|
221
|
+
for tmpTaskItem in taskList:
|
|
222
|
+
tmpListItem = self.taskBufferIF.getTasksToBeProcessed_JEDI(
|
|
223
|
+
None, None, None, None, None, simTasks=[tmpTaskItem], readMinFiles=True, fullSimulation=True
|
|
224
|
+
)
|
|
225
|
+
if tmpListItem is None:
|
|
226
|
+
# failed
|
|
227
|
+
tmpLog.error(f"failed to get the input chunks for jediTaskID={tmpTaskItem}")
|
|
228
|
+
tmpStat = Interaction.SC_FAILED
|
|
229
|
+
break
|
|
230
|
+
tmpListToAssign += tmpListItem
|
|
231
|
+
# get impl
|
|
232
|
+
if tmpStat == Interaction.SC_SUCCEEDED:
|
|
233
|
+
tmpLog.info("getting Impl")
|
|
234
|
+
try:
|
|
235
|
+
impl = self.implFactory.getImpl(self.vo, self.prodSourceLabel)
|
|
236
|
+
if impl is None:
|
|
237
|
+
# task refiner is undefined
|
|
238
|
+
tmpLog.error(f"task broker is undefined for vo={self.vo} sourceLabel={self.prodSourceLabel}")
|
|
239
|
+
tmpStat = Interaction.SC_FAILED
|
|
240
|
+
except Exception:
|
|
241
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
242
|
+
tmpLog.error(f"getImpl failed with {errtype.__name__}:{errvalue}")
|
|
243
|
+
tmpStat = Interaction.SC_FAILED
|
|
244
|
+
# brokerage
|
|
245
|
+
if tmpStat == Interaction.SC_SUCCEEDED:
|
|
246
|
+
tmpLog.info(f"brokerage with {impl.__class__.__name__} for {len(tmpListToAssign)} tasks ")
|
|
247
|
+
try:
|
|
248
|
+
tmpStat = impl.doBrokerage(tmpListToAssign, self.vo, self.prodSourceLabel, self.workQueue, self.resource_name)
|
|
249
|
+
except Exception:
|
|
250
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
251
|
+
tmpLog.error(f"doBrokerage failed with {errtype.__name__}:{errvalue}")
|
|
252
|
+
tmpStat = Interaction.SC_FAILED
|
|
253
|
+
# register
|
|
254
|
+
if tmpStat != Interaction.SC_SUCCEEDED:
|
|
255
|
+
tmpLog.error("failed")
|
|
256
|
+
else:
|
|
257
|
+
tmpLog.info("done")
|
|
258
|
+
except Exception:
|
|
259
|
+
errtype, errvalue = sys.exc_info()[:2]
|
|
260
|
+
logger.error(f"{self.__class__.__name__} failed in runImpl() with {errtype.__name__}:{errvalue}")
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
# launch
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def launcher(commuChannel, taskBufferIF, ddmIF, vos=None, prodSourceLabels=None):
|
|
267
|
+
p = TaskBroker(commuChannel, taskBufferIF, ddmIF, vos, prodSourceLabels)
|
|
268
|
+
p.start()
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
import socket
|
|
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
|
|
12
|
+
from pandajedi.jedicore.MsgWrapper import MsgWrapper
|
|
13
|
+
from pandajedi.jedicore.ThreadUtils import ListWithLock, ThreadPool, WorkerThread
|
|
14
|
+
from pandajedi.jedirefine import RefinerUtils
|
|
15
|
+
from pandaserver.srvcore import CoreUtils
|
|
16
|
+
from pandaserver.taskbuffer.JediTaskSpec import JediTaskSpec
|
|
17
|
+
|
|
18
|
+
from .JediKnight import JediKnight
|
|
19
|
+
|
|
20
|
+
logger = PandaLogger().getLogger(__name__.split(".")[-1])
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# worker class to kill/amend tasks
|
|
24
|
+
class TaskCommando(JediKnight):
|
|
25
|
+
# constructor
|
|
26
|
+
def __init__(self, commuChannel, taskBufferIF, ddmIF, vos, prodSourceLabels):
|
|
27
|
+
self.vos = self.parseInit(vos)
|
|
28
|
+
self.prodSourceLabels = self.parseInit(prodSourceLabels)
|
|
29
|
+
self.pid = f"{socket.getfqdn().split('.')[0]}-{os.getpid()}-dog"
|
|
30
|
+
JediKnight.__init__(self, commuChannel, taskBufferIF, ddmIF, logger)
|
|
31
|
+
|
|
32
|
+
# main
|
|
33
|
+
def start(self):
|
|
34
|
+
# start base classes
|
|
35
|
+
JediKnight.start(self)
|
|
36
|
+
# go into main loop
|
|
37
|
+
while True:
|
|
38
|
+
startTime = naive_utcnow()
|
|
39
|
+
try:
|
|
40
|
+
# get logger
|
|
41
|
+
tmpLog = MsgWrapper(logger)
|
|
42
|
+
tmpLog.debug("start")
|
|
43
|
+
# loop over all vos
|
|
44
|
+
for vo in self.vos:
|
|
45
|
+
# loop over all sourceLabels
|
|
46
|
+
for prodSourceLabel in self.prodSourceLabels:
|
|
47
|
+
# get the list of tasks to exec command
|
|
48
|
+
tmpList = self.taskBufferIF.getTasksToExecCommand_JEDI(vo, prodSourceLabel)
|
|
49
|
+
if tmpList is None:
|
|
50
|
+
# failed
|
|
51
|
+
tmpLog.error(f"failed to get the task list for vo={vo} label={prodSourceLabel}")
|
|
52
|
+
else:
|
|
53
|
+
tmpLog.debug(f"got {len(tmpList)} tasks")
|
|
54
|
+
# put to a locked list
|
|
55
|
+
taskList = ListWithLock(tmpList)
|
|
56
|
+
# make thread pool
|
|
57
|
+
threadPool = ThreadPool()
|
|
58
|
+
# make workers
|
|
59
|
+
nWorker = jedi_config.taskrefine.nWorkers
|
|
60
|
+
for iWorker in range(nWorker):
|
|
61
|
+
thr = TaskCommandoThread(taskList, threadPool, self.taskBufferIF, self.ddmIF, self.pid)
|
|
62
|
+
thr.start()
|
|
63
|
+
# join
|
|
64
|
+
threadPool.join()
|
|
65
|
+
tmpLog.debug("done")
|
|
66
|
+
except Exception as e:
|
|
67
|
+
tmpLog.error(f"failed in {self.__class__.__name__}.start() with {str(e)} {traceback.format_exc()}")
|
|
68
|
+
# sleep if needed
|
|
69
|
+
loopCycle = jedi_config.tcommando.loopCycle
|
|
70
|
+
timeDelta = naive_utcnow() - startTime
|
|
71
|
+
sleepPeriod = loopCycle - timeDelta.seconds
|
|
72
|
+
if sleepPeriod > 0:
|
|
73
|
+
time.sleep(sleepPeriod)
|
|
74
|
+
# randomize cycle
|
|
75
|
+
self.randomSleep(max_val=loopCycle)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# thread for real worker
|
|
79
|
+
class TaskCommandoThread(WorkerThread):
|
|
80
|
+
# constructor
|
|
81
|
+
def __init__(self, taskList, threadPool, taskbufferIF, ddmIF, pid):
|
|
82
|
+
# initialize woker with no semaphore
|
|
83
|
+
WorkerThread.__init__(self, None, threadPool, logger)
|
|
84
|
+
# attributres
|
|
85
|
+
self.taskList = taskList
|
|
86
|
+
self.taskBufferIF = taskbufferIF
|
|
87
|
+
self.ddmIF = ddmIF
|
|
88
|
+
self.msgType = "taskcommando"
|
|
89
|
+
self.pid = pid
|
|
90
|
+
|
|
91
|
+
# main
|
|
92
|
+
def runImpl(self):
|
|
93
|
+
while True:
|
|
94
|
+
try:
|
|
95
|
+
# get a part of list
|
|
96
|
+
nTasks = 10
|
|
97
|
+
taskList = self.taskList.get(nTasks)
|
|
98
|
+
# no more datasets
|
|
99
|
+
if len(taskList) == 0:
|
|
100
|
+
self.logger.debug(f"{self.__class__.__name__} terminating since no more items")
|
|
101
|
+
return
|
|
102
|
+
# loop over all tasks
|
|
103
|
+
for jediTaskID, commandMap in taskList:
|
|
104
|
+
# make logger
|
|
105
|
+
tmpLog = MsgWrapper(self.logger, f" < jediTaskID={jediTaskID} >")
|
|
106
|
+
commandStr = commandMap["command"]
|
|
107
|
+
commentStr = commandMap["comment"]
|
|
108
|
+
oldStatus = commandMap["oldStatus"]
|
|
109
|
+
tmpLog.info(f"start for {commandStr}")
|
|
110
|
+
tmpStat = Interaction.SC_SUCCEEDED
|
|
111
|
+
if commandStr in ["kill", "finish", "reassign"]:
|
|
112
|
+
tmpMsg = f"executing {commandStr}"
|
|
113
|
+
tmpLog.info(tmpMsg)
|
|
114
|
+
tmpLog.sendMsg(tmpMsg, self.msgType)
|
|
115
|
+
# loop twice to see immediate result
|
|
116
|
+
for iLoop in range(2):
|
|
117
|
+
# get active PandaIDs to be killed
|
|
118
|
+
if commandStr == "reassign" and commentStr is not None and "soft reassign" in commentStr:
|
|
119
|
+
pandaIDs = self.taskBufferIF.getQueuedPandaIDsWithTask_JEDI(jediTaskID)
|
|
120
|
+
elif commandStr == "reassign" and commentStr is not None and "nokill reassign" in commentStr:
|
|
121
|
+
pandaIDs = []
|
|
122
|
+
else:
|
|
123
|
+
pandaIDs = self.taskBufferIF.getPandaIDsWithTask_JEDI(jediTaskID, True)
|
|
124
|
+
if pandaIDs is None:
|
|
125
|
+
tmpLog.error(f"failed to get PandaIDs for jediTaskID={jediTaskID}")
|
|
126
|
+
tmpStat = Interaction.SC_FAILED
|
|
127
|
+
# kill jobs or update task
|
|
128
|
+
if tmpStat == Interaction.SC_SUCCEEDED:
|
|
129
|
+
if pandaIDs == []:
|
|
130
|
+
# done since no active jobs
|
|
131
|
+
tmpMsg = "completed cleaning jobs"
|
|
132
|
+
tmpLog.sendMsg(tmpMsg, self.msgType)
|
|
133
|
+
tmpLog.info(tmpMsg)
|
|
134
|
+
tmpTaskSpec = JediTaskSpec()
|
|
135
|
+
tmpTaskSpec.jediTaskID = jediTaskID
|
|
136
|
+
updateTaskStatus = True
|
|
137
|
+
if commandStr != "reassign":
|
|
138
|
+
# reset oldStatus
|
|
139
|
+
# keep oldStatus for task reassignment since it is reset when actually reassigned
|
|
140
|
+
tmpTaskSpec.forceUpdate("oldStatus")
|
|
141
|
+
else:
|
|
142
|
+
# extract cloud or site
|
|
143
|
+
if commentStr is not None:
|
|
144
|
+
tmp_instructions = CoreUtils.parse_reassign_comment(commentStr)
|
|
145
|
+
reassign_target = tmp_instructions.get("target")
|
|
146
|
+
reassign_value = tmp_instructions.get("value")
|
|
147
|
+
back_to_old_status = tmp_instructions.get("back_to_old_status")
|
|
148
|
+
tmpItems = commentStr.split(":")
|
|
149
|
+
if reassign_target == "cloud":
|
|
150
|
+
tmpTaskSpec.cloud = reassign_value
|
|
151
|
+
elif reassign_target == "nucleus":
|
|
152
|
+
tmpTaskSpec.nucleus = reassign_value
|
|
153
|
+
else:
|
|
154
|
+
tmpTaskSpec.site = reassign_value
|
|
155
|
+
tmpMsg = f"set {reassign_target}={reassign_value}"
|
|
156
|
+
if back_to_old_status:
|
|
157
|
+
tmpMsg += f", while keeping status={oldStatus}"
|
|
158
|
+
tmpLog.sendMsg(tmpMsg, self.msgType)
|
|
159
|
+
tmpLog.info(tmpMsg)
|
|
160
|
+
# back to oldStatus if necessary
|
|
161
|
+
if back_to_old_status:
|
|
162
|
+
tmpTaskSpec.status = oldStatus
|
|
163
|
+
tmpTaskSpec.forceUpdate("oldStatus")
|
|
164
|
+
updateTaskStatus = False
|
|
165
|
+
if commandStr == "reassign":
|
|
166
|
+
tmpTaskSpec.forceUpdate("errorDialog")
|
|
167
|
+
if commandStr == "finish":
|
|
168
|
+
# update datasets
|
|
169
|
+
tmpLog.info("updating datasets to finish")
|
|
170
|
+
tmpStat = self.taskBufferIF.updateDatasetsToFinishTask_JEDI(jediTaskID, self.pid)
|
|
171
|
+
if not tmpStat:
|
|
172
|
+
tmpLog.info("wait until datasets are updated to finish")
|
|
173
|
+
# ignore failGoalUnreached when manually finished
|
|
174
|
+
tmpStat, taskSpec = self.taskBufferIF.getTaskWithID_JEDI(jediTaskID)
|
|
175
|
+
tmpTaskSpec.splitRule = taskSpec.splitRule
|
|
176
|
+
tmpTaskSpec.unsetFailGoalUnreached()
|
|
177
|
+
if updateTaskStatus:
|
|
178
|
+
tmpTaskSpec.status = JediTaskSpec.commandStatusMap()[commandStr]["done"]
|
|
179
|
+
tmpMsg = f"set task_status={tmpTaskSpec.status}"
|
|
180
|
+
tmpLog.sendMsg(tmpMsg, self.msgType)
|
|
181
|
+
tmpLog.info(tmpMsg)
|
|
182
|
+
tmpRet = self.taskBufferIF.updateTask_JEDI(tmpTaskSpec, {"jediTaskID": jediTaskID}, setOldModTime=True)
|
|
183
|
+
tmpLog.info(f"done with {str(tmpRet)}")
|
|
184
|
+
break
|
|
185
|
+
else:
|
|
186
|
+
# kill only in the first loop
|
|
187
|
+
if iLoop > 0:
|
|
188
|
+
break
|
|
189
|
+
# wait or kill jobs
|
|
190
|
+
if commentStr and "soft finish" in commentStr:
|
|
191
|
+
queuedPandaIDs = self.taskBufferIF.getQueuedPandaIDsWithTask_JEDI(jediTaskID)
|
|
192
|
+
tmpMsg = f"trying to kill {len(queuedPandaIDs)} queued jobs for soft finish"
|
|
193
|
+
tmpLog.info(tmpMsg)
|
|
194
|
+
tmpRet = self.taskBufferIF.killJobs(queuedPandaIDs, commentStr, "52", True)
|
|
195
|
+
tmpMsg = f"wating {len(pandaIDs)} jobs for soft finish"
|
|
196
|
+
tmpLog.info(tmpMsg)
|
|
197
|
+
tmpRet = True
|
|
198
|
+
tmpLog.info(f"done with {str(tmpRet)}")
|
|
199
|
+
break
|
|
200
|
+
else:
|
|
201
|
+
tmpMsg = f"trying to kill {len(pandaIDs)} jobs"
|
|
202
|
+
tmpLog.info(tmpMsg)
|
|
203
|
+
tmpLog.sendMsg(tmpMsg, self.msgType)
|
|
204
|
+
if commandStr in ["finish"]:
|
|
205
|
+
# force kill
|
|
206
|
+
tmpRet = self.taskBufferIF.killJobs(pandaIDs, commentStr, "52", True)
|
|
207
|
+
elif commandStr in ["reassign"]:
|
|
208
|
+
# force kill
|
|
209
|
+
tmpRet = self.taskBufferIF.killJobs(pandaIDs, commentStr, "51", True)
|
|
210
|
+
else:
|
|
211
|
+
# normal kill
|
|
212
|
+
tmpRet = self.taskBufferIF.killJobs(pandaIDs, commentStr, "50", True)
|
|
213
|
+
tmpLog.info(f"done with {str(tmpRet)}")
|
|
214
|
+
elif commandStr in ["retry", "incexec"]:
|
|
215
|
+
tmpMsg = f"executing {commandStr}"
|
|
216
|
+
tmpLog.info(tmpMsg)
|
|
217
|
+
tmpLog.sendMsg(tmpMsg, self.msgType)
|
|
218
|
+
# change task params for incexec
|
|
219
|
+
if commandStr == "incexec":
|
|
220
|
+
try:
|
|
221
|
+
# read task params
|
|
222
|
+
taskParam = self.taskBufferIF.getTaskParamsWithID_JEDI(jediTaskID)
|
|
223
|
+
taskParamMap = RefinerUtils.decodeJSON(taskParam)
|
|
224
|
+
# remove old sandbox file specified in the previous reattempt
|
|
225
|
+
taskParamMap.pop("fixedSandbox", None)
|
|
226
|
+
# convert new params
|
|
227
|
+
decoded = RefinerUtils.decodeJSON(commentStr)
|
|
228
|
+
if isinstance(decoded, dict):
|
|
229
|
+
# old style
|
|
230
|
+
newParamMap = decoded
|
|
231
|
+
command_qualifiers = []
|
|
232
|
+
else:
|
|
233
|
+
# new style
|
|
234
|
+
newParamMap, command_qualifiers = decoded
|
|
235
|
+
# change params
|
|
236
|
+
for newKey, newVal in newParamMap.items():
|
|
237
|
+
if newVal is None:
|
|
238
|
+
# delete
|
|
239
|
+
if newKey in taskParamMap:
|
|
240
|
+
del taskParamMap[newKey]
|
|
241
|
+
else:
|
|
242
|
+
# change
|
|
243
|
+
taskParamMap[newKey] = newVal
|
|
244
|
+
# overwrite sandbox
|
|
245
|
+
if "fixedSandbox" in taskParamMap:
|
|
246
|
+
# noBuild
|
|
247
|
+
for tmpParam in taskParamMap["jobParameters"]:
|
|
248
|
+
if tmpParam["type"] == "constant" and re.search("^-a [^ ]+$", tmpParam["value"]) is not None:
|
|
249
|
+
tmpParam["value"] = f"-a {taskParamMap['fixedSandbox']}"
|
|
250
|
+
# build
|
|
251
|
+
if "buildSpec" in taskParamMap:
|
|
252
|
+
taskParamMap["buildSpec"]["archiveName"] = taskParamMap["fixedSandbox"]
|
|
253
|
+
# merge
|
|
254
|
+
if "mergeSpec" in taskParamMap:
|
|
255
|
+
taskParamMap["mergeSpec"]["jobParameters"] = re.sub(
|
|
256
|
+
"-a [^ ]+", f"-a {taskParamMap['fixedSandbox']}", taskParamMap["mergeSpec"]["jobParameters"]
|
|
257
|
+
)
|
|
258
|
+
# encode new param
|
|
259
|
+
strTaskParams = RefinerUtils.encodeJSON(taskParamMap)
|
|
260
|
+
tmpRet = self.taskBufferIF.updateTaskParams_JEDI(jediTaskID, strTaskParams)
|
|
261
|
+
if tmpRet is not True:
|
|
262
|
+
tmpLog.error("failed to update task params")
|
|
263
|
+
continue
|
|
264
|
+
except Exception as e:
|
|
265
|
+
tmpLog.error(f"failed to change task params with {str(e)} {traceback.format_exc()}")
|
|
266
|
+
continue
|
|
267
|
+
else:
|
|
268
|
+
# command qualifiers for retry
|
|
269
|
+
command_qualifiers = commentStr.split()
|
|
270
|
+
# retry child tasks
|
|
271
|
+
retryChildTasks = "sole" not in command_qualifiers
|
|
272
|
+
# discard events
|
|
273
|
+
discardEvents = "discard" in command_qualifiers
|
|
274
|
+
# release un-staged files
|
|
275
|
+
releaseUnstaged = "staged" in command_qualifiers
|
|
276
|
+
# keep gshare and priority
|
|
277
|
+
keep_share_priority = "keep" in command_qualifiers
|
|
278
|
+
# ignore limit for hard-exhausted
|
|
279
|
+
ignore_hard_exhausted = "transcend" in command_qualifiers
|
|
280
|
+
# retry the task
|
|
281
|
+
tmpRet, newTaskStatus, retried_tasks = self.taskBufferIF.retryTask_JEDI(
|
|
282
|
+
jediTaskID,
|
|
283
|
+
commandStr,
|
|
284
|
+
retryChildTasks=retryChildTasks,
|
|
285
|
+
discardEvents=discardEvents,
|
|
286
|
+
release_unstaged=releaseUnstaged,
|
|
287
|
+
keep_share_priority=keep_share_priority,
|
|
288
|
+
ignore_hard_exhausted=ignore_hard_exhausted,
|
|
289
|
+
)
|
|
290
|
+
if tmpRet is True:
|
|
291
|
+
tmpMsg = f"set task_status={newTaskStatus}"
|
|
292
|
+
tmpLog.sendMsg(tmpMsg, self.msgType)
|
|
293
|
+
tmpLog.info(tmpMsg)
|
|
294
|
+
if newTaskStatus in ["rerefine", "ready"]:
|
|
295
|
+
tmpStat, task_spec = self.taskBufferIF.getTaskWithID_JEDI(jediTaskID)
|
|
296
|
+
if tmpStat and task_spec.is_msg_driven():
|
|
297
|
+
# msg driven
|
|
298
|
+
if newTaskStatus == "rerefine":
|
|
299
|
+
push_ret = self.taskBufferIF.push_task_trigger_message("jedi_contents_feeder", jediTaskID)
|
|
300
|
+
if push_ret:
|
|
301
|
+
tmpLog.debug("pushed trigger message to jedi_contents_feeder")
|
|
302
|
+
else:
|
|
303
|
+
tmpLog.warning("failed to push trigger message to jedi_contents_feeder")
|
|
304
|
+
elif newTaskStatus == "ready":
|
|
305
|
+
push_ret = self.taskBufferIF.push_task_trigger_message("jedi_job_generator", jediTaskID)
|
|
306
|
+
if push_ret:
|
|
307
|
+
tmpLog.debug("pushed trigger message to jedi_job_generator")
|
|
308
|
+
else:
|
|
309
|
+
tmpLog.warning("failed to push trigger message to jedi_job_generator")
|
|
310
|
+
# reset global share and priority
|
|
311
|
+
if not keep_share_priority:
|
|
312
|
+
for task_id in retried_tasks:
|
|
313
|
+
try:
|
|
314
|
+
global_share = RefinerUtils.get_initial_global_share(self.taskBufferIF, task_id)
|
|
315
|
+
self.taskBufferIF.reassignShare([task_id], global_share, True)
|
|
316
|
+
tmp_msg = f"reset gshare={global_share} to jediTaskID={task_id}"
|
|
317
|
+
tmpLog.info(tmp_msg)
|
|
318
|
+
except Exception as e:
|
|
319
|
+
tmpLog.error(f"failed to reset gshare for {task_id} with {str(e)}")
|
|
320
|
+
|
|
321
|
+
tmpLog.info(f"done with {tmpRet}")
|
|
322
|
+
else:
|
|
323
|
+
tmpLog.error("unknown command")
|
|
324
|
+
except Exception as e:
|
|
325
|
+
errStr = f"{self.__class__.__name__} failed in runImpl() with {str(e)} {traceback.format_exc()} "
|
|
326
|
+
logger.error(errStr)
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
# launch
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def launcher(commuChannel, taskBufferIF, ddmIF, vos=None, prodSourceLabels=None):
|
|
333
|
+
p = TaskCommando(commuChannel, taskBufferIF, ddmIF, vos, prodSourceLabels)
|
|
334
|
+
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 generator
|
|
10
|
+
class TaskGenerator(FactoryBase):
|
|
11
|
+
# constructor
|
|
12
|
+
def __init__(self, vo, sourceLabel):
|
|
13
|
+
FactoryBase.__init__(self, vo, sourceLabel, logger, jedi_config.taskgen.modConfig)
|
|
14
|
+
|
|
15
|
+
# main
|
|
16
|
+
def doGenerate(self, taskSpec, taskParamMap, **varMap):
|
|
17
|
+
return self.getImpl(taskSpec.vo, taskSpec.prodSourceLabel).doGenerate(taskSpec, taskParamMap, **varMap)
|