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
|
File without changes
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import traceback
|
|
2
|
+
|
|
3
|
+
from pandacommon.pandalogger.PandaLogger import PandaLogger
|
|
4
|
+
|
|
5
|
+
from pandajedi.jedicore.MsgWrapper import MsgWrapper
|
|
6
|
+
from pandaserver.dataservice import DataServiceUtils
|
|
7
|
+
from pandaserver.taskbuffer import EventServiceUtils, JobUtils
|
|
8
|
+
|
|
9
|
+
from .TaskSetupperBase import TaskSetupperBase
|
|
10
|
+
|
|
11
|
+
logger = PandaLogger().getLogger(__name__.split(".")[-1])
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# task setup for ATLAS
|
|
15
|
+
class AtlasTaskSetupper(TaskSetupperBase):
|
|
16
|
+
# constructor
|
|
17
|
+
def __init__(self, taskBufferIF, ddmIF):
|
|
18
|
+
TaskSetupperBase.__init__(self, taskBufferIF, ddmIF)
|
|
19
|
+
self.user_container_lifetime = taskBufferIF.getConfigValue("user_output", "OUTPUT_CONTAINER_LIFETIME", "jedi")
|
|
20
|
+
if not self.user_container_lifetime:
|
|
21
|
+
self.user_container_lifetime = 14
|
|
22
|
+
|
|
23
|
+
# main to setup task
|
|
24
|
+
def doSetup(self, taskSpec, datasetToRegister, pandaJobs):
|
|
25
|
+
# make logger
|
|
26
|
+
tmpLog = MsgWrapper(logger, f"< jediTaskID={taskSpec.jediTaskID} >")
|
|
27
|
+
tmpLog.info(f"start label={taskSpec.prodSourceLabel} taskType={taskSpec.taskType}")
|
|
28
|
+
|
|
29
|
+
# returns
|
|
30
|
+
retFatal = self.SC_FATAL
|
|
31
|
+
retOK = self.SC_SUCCEEDED
|
|
32
|
+
|
|
33
|
+
try:
|
|
34
|
+
# get DDM I/F
|
|
35
|
+
ddmIF = self.ddmIF.getInterface(taskSpec.vo)
|
|
36
|
+
# register datasets
|
|
37
|
+
if datasetToRegister != [] or taskSpec.prodSourceLabel in ["user"]:
|
|
38
|
+
# prod vs anal
|
|
39
|
+
userSetup = False
|
|
40
|
+
if taskSpec.prodSourceLabel in ["user"]:
|
|
41
|
+
userSetup = True
|
|
42
|
+
# collect datasetID to register datasets/containers just in case
|
|
43
|
+
for tmpPandaJob in pandaJobs:
|
|
44
|
+
if not tmpPandaJob.produceUnMerge():
|
|
45
|
+
for tmpFileSpec in tmpPandaJob.Files:
|
|
46
|
+
if tmpFileSpec.type in ["output", "log"]:
|
|
47
|
+
if tmpFileSpec.datasetID not in datasetToRegister:
|
|
48
|
+
datasetToRegister.append(tmpFileSpec.datasetID)
|
|
49
|
+
tmpLog.info(f"datasetToRegister={str(datasetToRegister)}")
|
|
50
|
+
# get site mapper
|
|
51
|
+
siteMapper = self.taskBufferIF.get_site_mapper()
|
|
52
|
+
|
|
53
|
+
# loop over all datasets
|
|
54
|
+
avDatasetList = []
|
|
55
|
+
cnDatasetMap = {}
|
|
56
|
+
for datasetID in datasetToRegister:
|
|
57
|
+
# get output and log datasets
|
|
58
|
+
tmpLog.info(f"getting datasetSpec with datasetID={datasetID}")
|
|
59
|
+
tmpStat, datasetSpec = self.taskBufferIF.getDatasetWithID_JEDI(taskSpec.jediTaskID, datasetID)
|
|
60
|
+
if not tmpStat:
|
|
61
|
+
tmpLog.error("failed to get output and log datasets")
|
|
62
|
+
return retFatal
|
|
63
|
+
if datasetSpec.isPseudo():
|
|
64
|
+
tmpLog.info("skip pseudo dataset")
|
|
65
|
+
continue
|
|
66
|
+
# DDM backend
|
|
67
|
+
ddmBackEnd = taskSpec.getDdmBackEnd()
|
|
68
|
+
tmpLog.info(f"checking {datasetSpec.datasetName}")
|
|
69
|
+
# secondary nucleus
|
|
70
|
+
nucleusSpec = siteMapper.getNucleus(taskSpec.nucleus)
|
|
71
|
+
secNucleusSpecBase = None
|
|
72
|
+
if nucleusSpec and not taskSpec.is_intermediate_task():
|
|
73
|
+
secondaryNucleus = nucleusSpec.get_secondary_nucleus()
|
|
74
|
+
if secondaryNucleus:
|
|
75
|
+
secNucleusSpecBase = siteMapper.getNucleus(secondaryNucleus)
|
|
76
|
+
# check if dataset and container are available in DDM
|
|
77
|
+
for targetName in [datasetSpec.datasetName, datasetSpec.containerName]:
|
|
78
|
+
if targetName is None:
|
|
79
|
+
continue
|
|
80
|
+
if targetName not in avDatasetList:
|
|
81
|
+
# set lifetime
|
|
82
|
+
if targetName.startswith("panda"):
|
|
83
|
+
if datasetSpec.type == "trn_log" and taskSpec.prodSourceLabel == "managed":
|
|
84
|
+
lifetime = 365
|
|
85
|
+
else:
|
|
86
|
+
lifetime = 14
|
|
87
|
+
else:
|
|
88
|
+
lifetime = None
|
|
89
|
+
# check dataset/container in DDM
|
|
90
|
+
tmpList = ddmIF.listDatasets(targetName)
|
|
91
|
+
if tmpList == []:
|
|
92
|
+
# get location
|
|
93
|
+
location = None
|
|
94
|
+
locForRule = None
|
|
95
|
+
if targetName == datasetSpec.datasetName:
|
|
96
|
+
# dataset
|
|
97
|
+
if datasetSpec.site in ["", None]:
|
|
98
|
+
if DataServiceUtils.getDistributedDestination(datasetSpec.storageToken) is not None:
|
|
99
|
+
locForRule = datasetSpec.destination
|
|
100
|
+
elif DataServiceUtils.getDestinationSE(datasetSpec.storageToken) is not None:
|
|
101
|
+
location = DataServiceUtils.getDestinationSE(datasetSpec.storageToken)
|
|
102
|
+
else:
|
|
103
|
+
tmpLog.info(f"site={datasetSpec.site} token={datasetSpec.storageToken}")
|
|
104
|
+
location = siteMapper.getDdmEndpoint(
|
|
105
|
+
datasetSpec.site,
|
|
106
|
+
datasetSpec.storageToken,
|
|
107
|
+
taskSpec.prodSourceLabel,
|
|
108
|
+
JobUtils.translate_tasktype_to_jobtype(taskSpec.taskType),
|
|
109
|
+
)
|
|
110
|
+
if locForRule is None:
|
|
111
|
+
locForRule = location
|
|
112
|
+
# set metadata
|
|
113
|
+
if taskSpec.prodSourceLabel in ["managed", "test"] and targetName == datasetSpec.datasetName:
|
|
114
|
+
metaData = {}
|
|
115
|
+
metaData["task_id"] = taskSpec.jediTaskID
|
|
116
|
+
if taskSpec.campaign not in [None, ""]:
|
|
117
|
+
metaData["campaign"] = taskSpec.campaign
|
|
118
|
+
if datasetSpec.getTransient() is not None:
|
|
119
|
+
metaData["transient"] = datasetSpec.getTransient()
|
|
120
|
+
else:
|
|
121
|
+
metaData = None
|
|
122
|
+
# use secondary nucleus only for production output
|
|
123
|
+
if (
|
|
124
|
+
secNucleusSpecBase
|
|
125
|
+
and taskSpec.prodSourceLabel in ["managed", "test"]
|
|
126
|
+
and targetName == datasetSpec.datasetName
|
|
127
|
+
and datasetSpec.type == "output"
|
|
128
|
+
):
|
|
129
|
+
secNucleusSpec = secNucleusSpecBase
|
|
130
|
+
else:
|
|
131
|
+
secNucleusSpec = None
|
|
132
|
+
# register dataset/container
|
|
133
|
+
tmpLog.info(f"registering {targetName} with location={location} backend={ddmBackEnd} lifetime={lifetime} meta={str(metaData)}")
|
|
134
|
+
tmpStat = ddmIF.registerNewDataset(targetName, backEnd=ddmBackEnd, location=location, lifetime=lifetime, metaData=metaData)
|
|
135
|
+
if not tmpStat:
|
|
136
|
+
tmpLog.error(f"failed to register {targetName}")
|
|
137
|
+
return retFatal
|
|
138
|
+
# procedures for user
|
|
139
|
+
if userSetup or DataServiceUtils.getDistributedDestination(datasetSpec.storageToken) is not None or secNucleusSpec:
|
|
140
|
+
# register location
|
|
141
|
+
tmpToRegister = False
|
|
142
|
+
if userSetup and targetName == datasetSpec.datasetName and datasetSpec.site not in ["", None]:
|
|
143
|
+
if taskSpec.workingGroup:
|
|
144
|
+
userName = taskSpec.workingGroup
|
|
145
|
+
else:
|
|
146
|
+
userName = taskSpec.userName
|
|
147
|
+
grouping = None
|
|
148
|
+
tmpToRegister = True
|
|
149
|
+
elif DataServiceUtils.getDistributedDestination(datasetSpec.storageToken) is not None:
|
|
150
|
+
userName = None
|
|
151
|
+
grouping = "NONE"
|
|
152
|
+
tmpToRegister = True
|
|
153
|
+
elif secNucleusSpec:
|
|
154
|
+
userName = None
|
|
155
|
+
grouping = None
|
|
156
|
+
tmpToRegister = True
|
|
157
|
+
locForRule = siteMapper.getDdmEndpoint(
|
|
158
|
+
secNucleusSpec.getOnePandaSite(),
|
|
159
|
+
datasetSpec.storageToken,
|
|
160
|
+
taskSpec.prodSourceLabel,
|
|
161
|
+
JobUtils.translate_tasktype_to_jobtype(taskSpec.taskType),
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
if tmpToRegister:
|
|
165
|
+
activity = DataServiceUtils.getActivityForOut(taskSpec.prodSourceLabel)
|
|
166
|
+
tmpLog.info(
|
|
167
|
+
"registering location={} lifetime={} days activity={} grouping={} "
|
|
168
|
+
"owner={}".format(locForRule, lifetime, activity, grouping, userName)
|
|
169
|
+
)
|
|
170
|
+
tmpStat = ddmIF.registerDatasetLocation(
|
|
171
|
+
targetName, locForRule, owner=userName, lifetime=lifetime, backEnd=ddmBackEnd, activity=activity, grouping=grouping
|
|
172
|
+
)
|
|
173
|
+
if not tmpStat:
|
|
174
|
+
tmpLog.error(f"failed to register location {locForRule} for {targetName}")
|
|
175
|
+
return retFatal
|
|
176
|
+
# double copy
|
|
177
|
+
if userSetup and datasetSpec.type == "output":
|
|
178
|
+
if datasetSpec.destination != datasetSpec.site:
|
|
179
|
+
tmpLog.info(f"skip making double copy as destination={datasetSpec.destination} is not site={datasetSpec.site}")
|
|
180
|
+
else:
|
|
181
|
+
second_copy = True
|
|
182
|
+
try:
|
|
183
|
+
if taskSpec.site:
|
|
184
|
+
panda_site = siteMapper.getSite(taskSpec.site)
|
|
185
|
+
if panda_site.catchall and "skip_2nd_copy" in panda_site.catchall:
|
|
186
|
+
tmpLog.info(f"skip making double copy as specified in {panda_site} catchall")
|
|
187
|
+
second_copy = False
|
|
188
|
+
except Exception:
|
|
189
|
+
second_copy = True
|
|
190
|
+
|
|
191
|
+
if second_copy:
|
|
192
|
+
locForDouble = f"(type=SCRATCHDISK)\\notforextracopy=True\\{locForRule}"
|
|
193
|
+
tmpMsg = "registering double copy "
|
|
194
|
+
tmpMsg += f'location="{locForDouble}" lifetime={lifetime}days activity={activity} for dataset={targetName}'
|
|
195
|
+
tmpLog.info(tmpMsg)
|
|
196
|
+
tmpStat = ddmIF.registerDatasetLocation(
|
|
197
|
+
targetName,
|
|
198
|
+
locForDouble,
|
|
199
|
+
copies=1,
|
|
200
|
+
owner=userName,
|
|
201
|
+
lifetime=lifetime,
|
|
202
|
+
activity=activity,
|
|
203
|
+
grouping="NONE",
|
|
204
|
+
weight="freespace",
|
|
205
|
+
ignore_availability=False,
|
|
206
|
+
)
|
|
207
|
+
if not tmpStat:
|
|
208
|
+
tmpLog.error(f"failed to register double copy location {locForDouble} for {targetName}")
|
|
209
|
+
return retFatal
|
|
210
|
+
# container-level rules for user
|
|
211
|
+
if userSetup and datasetSpec.type == "output" and targetName == datasetSpec.containerName:
|
|
212
|
+
# rule to keep the outputs where they are produced
|
|
213
|
+
container_location = "type=SCRATCHDISK"
|
|
214
|
+
tmpLog.info(f"registering container-level rule for {targetName}")
|
|
215
|
+
tmpStat = ddmIF.registerDatasetLocation(
|
|
216
|
+
targetName,
|
|
217
|
+
container_location,
|
|
218
|
+
owner=userName,
|
|
219
|
+
lifetime=self.user_container_lifetime,
|
|
220
|
+
backEnd=ddmBackEnd,
|
|
221
|
+
activity=activity,
|
|
222
|
+
grouping="DATASET",
|
|
223
|
+
)
|
|
224
|
+
if not tmpStat:
|
|
225
|
+
tmpLog.error(f"failed to register location {container_location} for container {targetName}")
|
|
226
|
+
return retFatal
|
|
227
|
+
# rule with 2 copies and no grouping
|
|
228
|
+
container_location = f"(type=SCRATCHDISK)\\notforextracopy=True"
|
|
229
|
+
tmpLog.info(f"registering container-level 2nd copy rule for {targetName}")
|
|
230
|
+
tmpStat = ddmIF.registerDatasetLocation(
|
|
231
|
+
targetName,
|
|
232
|
+
container_location,
|
|
233
|
+
copies=1,
|
|
234
|
+
owner=userName,
|
|
235
|
+
lifetime=self.user_container_lifetime,
|
|
236
|
+
activity=activity,
|
|
237
|
+
grouping="NONE",
|
|
238
|
+
weight="freespace",
|
|
239
|
+
ignore_availability=False,
|
|
240
|
+
)
|
|
241
|
+
if not tmpStat:
|
|
242
|
+
tmpLog.error(f"failed to register 2nd copy location {container_location} for container {targetName}")
|
|
243
|
+
return retFatal
|
|
244
|
+
avDatasetList.append(targetName)
|
|
245
|
+
else:
|
|
246
|
+
tmpLog.info(f"{targetName} already registered")
|
|
247
|
+
# check if dataset is in the container
|
|
248
|
+
if datasetSpec.containerName is not None and datasetSpec.containerName != datasetSpec.datasetName:
|
|
249
|
+
# get list of constituent datasets in the container
|
|
250
|
+
if datasetSpec.containerName not in cnDatasetMap:
|
|
251
|
+
cnDatasetMap[datasetSpec.containerName] = ddmIF.listDatasetsInContainer(datasetSpec.containerName)
|
|
252
|
+
# add dataset
|
|
253
|
+
if datasetSpec.datasetName not in cnDatasetMap[datasetSpec.containerName]:
|
|
254
|
+
tmpLog.info(f"adding {datasetSpec.datasetName} to {datasetSpec.containerName}")
|
|
255
|
+
tmpStat = ddmIF.addDatasetsToContainer(datasetSpec.containerName, [datasetSpec.datasetName], backEnd=ddmBackEnd)
|
|
256
|
+
if not tmpStat:
|
|
257
|
+
tmpLog.error(f"failed to add {datasetSpec.datasetName} to {datasetSpec.containerName}")
|
|
258
|
+
return retFatal
|
|
259
|
+
cnDatasetMap[datasetSpec.containerName].append(datasetSpec.datasetName)
|
|
260
|
+
else:
|
|
261
|
+
tmpLog.info(f"{datasetSpec.datasetName} already in {datasetSpec.containerName}")
|
|
262
|
+
# update dataset
|
|
263
|
+
datasetSpec.status = "registered"
|
|
264
|
+
self.taskBufferIF.updateDataset_JEDI(datasetSpec, {"jediTaskID": taskSpec.jediTaskID, "datasetID": datasetID})
|
|
265
|
+
# register ES datasets
|
|
266
|
+
if taskSpec.registerEsFiles():
|
|
267
|
+
targetName = EventServiceUtils.getEsDatasetName(taskSpec.jediTaskID)
|
|
268
|
+
location = None
|
|
269
|
+
metaData = {}
|
|
270
|
+
metaData["task_id"] = taskSpec.jediTaskID
|
|
271
|
+
metaData["hidden"] = True
|
|
272
|
+
tmpLog.info(f"registering ES dataset {targetName} with location={location} meta={str(metaData)}")
|
|
273
|
+
tmpStat = ddmIF.registerNewDataset(targetName, location=location, metaData=metaData, resurrect=True)
|
|
274
|
+
if not tmpStat:
|
|
275
|
+
tmpLog.error(f"failed to register ES dataset {targetName}")
|
|
276
|
+
return retFatal
|
|
277
|
+
# register rule
|
|
278
|
+
location = "type=DATADISK"
|
|
279
|
+
activity = DataServiceUtils.getActivityForOut(taskSpec.prodSourceLabel)
|
|
280
|
+
grouping = "NONE"
|
|
281
|
+
tmpLog.info(f"registering location={location} activity={activity} grouping={grouping}")
|
|
282
|
+
tmpStat = ddmIF.registerDatasetLocation(targetName, location, activity=activity, grouping=grouping)
|
|
283
|
+
if not tmpStat:
|
|
284
|
+
tmpLog.error(f"failed to register location {location} with {activity} for {targetName}")
|
|
285
|
+
return retFatal
|
|
286
|
+
# open datasets
|
|
287
|
+
if taskSpec.prodSourceLabel in ["managed", "test"]:
|
|
288
|
+
# get the list of output/log datasets
|
|
289
|
+
outDatasetList = []
|
|
290
|
+
for tmpPandaJob in pandaJobs:
|
|
291
|
+
for tmpFileSpec in tmpPandaJob.Files:
|
|
292
|
+
if tmpFileSpec.type in ["output", "log"]:
|
|
293
|
+
if tmpFileSpec.destinationDBlock not in outDatasetList:
|
|
294
|
+
outDatasetList.append(tmpFileSpec.destinationDBlock)
|
|
295
|
+
# open datasets
|
|
296
|
+
for outDataset in outDatasetList:
|
|
297
|
+
tmpLog.info(f"open {outDataset}")
|
|
298
|
+
ddmIF.openDataset(outDataset)
|
|
299
|
+
# unset lifetime
|
|
300
|
+
ddmIF.setDatasetMetadata(outDataset, "lifetime", None)
|
|
301
|
+
# return
|
|
302
|
+
tmpLog.info("done")
|
|
303
|
+
return retOK
|
|
304
|
+
except Exception as e:
|
|
305
|
+
tmpLog.error(f"doSetup failed with {str(e)}")
|
|
306
|
+
tb = traceback.format_exc()
|
|
307
|
+
taskSpec.setErrDiag(tmpLog.uploadLog(taskSpec.jediTaskID))
|
|
308
|
+
tmpLog.error(tb)
|
|
309
|
+
return retFatal
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from pandacommon.pandalogger.PandaLogger import PandaLogger
|
|
2
|
+
|
|
3
|
+
from .TaskSetupperBase import TaskSetupperBase
|
|
4
|
+
|
|
5
|
+
logger = PandaLogger().getLogger(__name__.split(".")[-1])
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# task setup for general purpose
|
|
9
|
+
class GenTaskSetupper(TaskSetupperBase):
|
|
10
|
+
# constructor
|
|
11
|
+
def __init__(self, taskBufferIF, ddmIF):
|
|
12
|
+
TaskSetupperBase.__init__(self, taskBufferIF, ddmIF)
|
|
13
|
+
|
|
14
|
+
# main to setup task
|
|
15
|
+
def doSetup(self, taskSpec, datasetToRegister, pandaJobs):
|
|
16
|
+
return self.SC_SUCCEEDED
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import traceback
|
|
2
|
+
|
|
3
|
+
from pandacommon.pandalogger.PandaLogger import PandaLogger
|
|
4
|
+
|
|
5
|
+
from pandajedi.jedicore.MsgWrapper import MsgWrapper
|
|
6
|
+
|
|
7
|
+
from .TaskSetupperBase import TaskSetupperBase
|
|
8
|
+
|
|
9
|
+
logger = PandaLogger().getLogger(__name__.split(".")[-1])
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# task setup for general purpose
|
|
13
|
+
class SimpleTaskSetupper(TaskSetupperBase):
|
|
14
|
+
# constructor
|
|
15
|
+
def __init__(self, taskBufferIF, ddmIF):
|
|
16
|
+
TaskSetupperBase.__init__(self, taskBufferIF, ddmIF)
|
|
17
|
+
|
|
18
|
+
# main to setup task
|
|
19
|
+
def doSetup(self, taskSpec, datasetToRegister, pandaJobs):
|
|
20
|
+
# make logger
|
|
21
|
+
tmpLog = MsgWrapper(logger, f"< jediTaskID={taskSpec.jediTaskID} >")
|
|
22
|
+
tmpLog.info(f"start label={taskSpec.prodSourceLabel} taskType={taskSpec.taskType}")
|
|
23
|
+
# returns
|
|
24
|
+
retFatal = self.SC_FATAL
|
|
25
|
+
retOK = self.SC_SUCCEEDED
|
|
26
|
+
try:
|
|
27
|
+
# get DDM I/F
|
|
28
|
+
ddmIF = self.ddmIF.getInterface(taskSpec.vo, taskSpec.cloud)
|
|
29
|
+
# skip if DDM I/F is inactive
|
|
30
|
+
if not ddmIF:
|
|
31
|
+
tmpLog.info("skip due to inactive DDM I/F")
|
|
32
|
+
return retOK
|
|
33
|
+
# collect datasetID to register datasets/containers just in case
|
|
34
|
+
for tmpPandaJob in pandaJobs:
|
|
35
|
+
if not tmpPandaJob.produceUnMerge():
|
|
36
|
+
for tmpFileSpec in tmpPandaJob.Files:
|
|
37
|
+
if tmpFileSpec.type in ["output", "log"]:
|
|
38
|
+
if tmpFileSpec.datasetID not in datasetToRegister:
|
|
39
|
+
datasetToRegister.append(tmpFileSpec.datasetID)
|
|
40
|
+
# register datasets
|
|
41
|
+
if datasetToRegister:
|
|
42
|
+
tmpLog.info(f"datasetToRegister={str(datasetToRegister)}")
|
|
43
|
+
# get site mapper
|
|
44
|
+
siteMapper = self.taskBufferIF.get_site_mapper()
|
|
45
|
+
|
|
46
|
+
# loop over all datasets
|
|
47
|
+
avDatasetList = []
|
|
48
|
+
cnDatasetMap = {}
|
|
49
|
+
ddmBackEnd = "rucio"
|
|
50
|
+
for datasetID in datasetToRegister:
|
|
51
|
+
# get output and log datasets
|
|
52
|
+
tmpLog.info(f"getting datasetSpec with datasetID={datasetID}")
|
|
53
|
+
tmpStat, datasetSpec = self.taskBufferIF.getDatasetWithID_JEDI(taskSpec.jediTaskID, datasetID)
|
|
54
|
+
if not tmpStat:
|
|
55
|
+
tmpLog.error("failed to get output and log datasets")
|
|
56
|
+
return retFatal
|
|
57
|
+
if datasetSpec.isPseudo():
|
|
58
|
+
tmpLog.info("skip pseudo dataset")
|
|
59
|
+
continue
|
|
60
|
+
|
|
61
|
+
# set lifetime
|
|
62
|
+
key_name = f"DATASET_LIFETIME_{datasetSpec.type}"
|
|
63
|
+
lifetime = self.taskBufferIF.getConfigValue("task_setup", key_name, "jedi", taskSpec.cloud)
|
|
64
|
+
if not lifetime:
|
|
65
|
+
lifetime = self.taskBufferIF.getConfigValue("task_setup", key_name, "jedi", taskSpec.vo)
|
|
66
|
+
|
|
67
|
+
tmpLog.info(f"checking {datasetSpec.datasetName}")
|
|
68
|
+
# check if dataset and container are available in DDM
|
|
69
|
+
for targetName in [datasetSpec.datasetName, datasetSpec.containerName]:
|
|
70
|
+
if not targetName:
|
|
71
|
+
continue
|
|
72
|
+
if targetName in avDatasetList:
|
|
73
|
+
tmpLog.info(f"{targetName} already registered")
|
|
74
|
+
continue
|
|
75
|
+
# check dataset/container in DDM
|
|
76
|
+
tmpList = ddmIF.listDatasets(targetName)
|
|
77
|
+
if not tmpList:
|
|
78
|
+
# get location
|
|
79
|
+
location = None
|
|
80
|
+
locForRule = None
|
|
81
|
+
if targetName == datasetSpec.datasetName:
|
|
82
|
+
# dataset
|
|
83
|
+
tmpLog.info(f"dest={datasetSpec.destination}")
|
|
84
|
+
if datasetSpec.destination:
|
|
85
|
+
if siteMapper.checkSite(datasetSpec.destination):
|
|
86
|
+
location = siteMapper.getSite(datasetSpec.destination).ddm_output["default"]
|
|
87
|
+
else:
|
|
88
|
+
location = datasetSpec.destination
|
|
89
|
+
if locForRule is None:
|
|
90
|
+
locForRule = location
|
|
91
|
+
# set metadata
|
|
92
|
+
if targetName == datasetSpec.datasetName:
|
|
93
|
+
metaData = {}
|
|
94
|
+
metaData["task_id"] = taskSpec.jediTaskID
|
|
95
|
+
if taskSpec.campaign:
|
|
96
|
+
metaData["campaign"] = taskSpec.campaign
|
|
97
|
+
else:
|
|
98
|
+
metaData = None
|
|
99
|
+
# register dataset/container
|
|
100
|
+
tmpLog.info(f"registering {targetName} with location={location} backend={ddmBackEnd} lifetime={lifetime} meta={str(metaData)}")
|
|
101
|
+
tmpStat = ddmIF.registerNewDataset(targetName, backEnd=ddmBackEnd, location=location, lifetime=lifetime, metaData=metaData)
|
|
102
|
+
if not tmpStat:
|
|
103
|
+
tmpLog.error(f"failed to register {targetName}")
|
|
104
|
+
return retFatal
|
|
105
|
+
# register location
|
|
106
|
+
if locForRule:
|
|
107
|
+
"""
|
|
108
|
+
if taskSpec.workingGroup:
|
|
109
|
+
userName = taskSpec.workingGroup
|
|
110
|
+
else:
|
|
111
|
+
userName = taskSpec.userName
|
|
112
|
+
"""
|
|
113
|
+
userName = None
|
|
114
|
+
activity = None
|
|
115
|
+
grouping = None
|
|
116
|
+
tmpLog.info(
|
|
117
|
+
f"registering location={locForRule} lifetime={lifetime} days activity={activity} grouping={grouping} owner={userName}"
|
|
118
|
+
)
|
|
119
|
+
tmpStat = ddmIF.registerDatasetLocation(
|
|
120
|
+
targetName, locForRule, owner=userName, lifetime=lifetime, backEnd=ddmBackEnd, activity=activity, grouping=grouping
|
|
121
|
+
)
|
|
122
|
+
if not tmpStat:
|
|
123
|
+
tmpLog.error(f"failed to register location {locForRule} for {targetName}")
|
|
124
|
+
return retFatal
|
|
125
|
+
avDatasetList.append(targetName)
|
|
126
|
+
|
|
127
|
+
# check if dataset is in the container
|
|
128
|
+
if datasetSpec.containerName and datasetSpec.containerName != datasetSpec.datasetName:
|
|
129
|
+
# get list of constituent datasets in the container
|
|
130
|
+
if datasetSpec.containerName not in cnDatasetMap:
|
|
131
|
+
cnDatasetMap[datasetSpec.containerName] = ddmIF.listDatasetsInContainer(datasetSpec.containerName)
|
|
132
|
+
# add dataset
|
|
133
|
+
if datasetSpec.datasetName not in cnDatasetMap[datasetSpec.containerName]:
|
|
134
|
+
tmpLog.info(f"adding {datasetSpec.datasetName} to {datasetSpec.containerName}")
|
|
135
|
+
tmpStat = ddmIF.addDatasetsToContainer(datasetSpec.containerName, [datasetSpec.datasetName], backEnd=ddmBackEnd)
|
|
136
|
+
if not tmpStat:
|
|
137
|
+
tmpLog.error(f"failed to add {datasetSpec.datasetName} to {datasetSpec.containerName}")
|
|
138
|
+
return retFatal
|
|
139
|
+
cnDatasetMap[datasetSpec.containerName].append(datasetSpec.datasetName)
|
|
140
|
+
else:
|
|
141
|
+
tmpLog.info(f"{datasetSpec.datasetName} already in {datasetSpec.containerName}")
|
|
142
|
+
# update dataset
|
|
143
|
+
datasetSpec.status = "registered"
|
|
144
|
+
self.taskBufferIF.updateDataset_JEDI(datasetSpec, {"jediTaskID": taskSpec.jediTaskID, "datasetID": datasetID})
|
|
145
|
+
# return
|
|
146
|
+
tmpLog.info("done")
|
|
147
|
+
return retOK
|
|
148
|
+
except Exception as e:
|
|
149
|
+
errStr = f"doSetup failed with {str(e)}"
|
|
150
|
+
tmpLog.error(errStr + traceback.format_exc())
|
|
151
|
+
taskSpec.setErrDiag(errStr)
|
|
152
|
+
return retFatal
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from pandajedi.jedicore import Interaction
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
# base class for task setup
|
|
5
|
+
class TaskSetupperBase(object):
|
|
6
|
+
def __init__(self, taskBufferIF, ddmIF):
|
|
7
|
+
self.ddmIF = ddmIF
|
|
8
|
+
self.taskBufferIF = taskBufferIF
|
|
9
|
+
self.refresh()
|
|
10
|
+
|
|
11
|
+
def refresh(self):
|
|
12
|
+
self.siteMapper = self.taskBufferIF.get_site_mapper()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
Interaction.installSC(TaskSetupperBase)
|
|
File without changes
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Checking DB schema version for PanDA JEDI.
|
|
3
|
+
If there is an issue and the pandaEmailNotification var is
|
|
4
|
+
defined in panda_config, it will send an email notification.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from packaging import version
|
|
8
|
+
|
|
9
|
+
from pandajedi.jediconfig import jedi_config
|
|
10
|
+
from pandajedi.jedicore import JediDBSchemaInfo
|
|
11
|
+
from pandajedi.jedicore.JediDBProxy import DBProxy
|
|
12
|
+
from pandaserver.config import panda_config
|
|
13
|
+
from pandaserver.srvcore.MailUtils import MailUtils
|
|
14
|
+
|
|
15
|
+
proxyS = DBProxy()
|
|
16
|
+
proxyS.connect(jedi_config.db.dbhost, jedi_config.db.dbpasswd, jedi_config.db.dbuser, jedi_config.db.dbname)
|
|
17
|
+
|
|
18
|
+
sql = "select major || '.' || minor || '.' || patch from ATLAS_PANDA.pandadb_version where component = 'PanDA'"
|
|
19
|
+
|
|
20
|
+
res = proxyS.querySQL(sql)
|
|
21
|
+
dbVersion = res[0][0]
|
|
22
|
+
|
|
23
|
+
serverDBVersion = JediDBSchemaInfo.JediDBSchemaInfo().method()
|
|
24
|
+
|
|
25
|
+
if version.parse(dbVersion) >= version.parse(serverDBVersion):
|
|
26
|
+
print("DB schema check: OK")
|
|
27
|
+
else:
|
|
28
|
+
msgBody = (
|
|
29
|
+
"There is an issue with "
|
|
30
|
+
+ panda_config.pserveralias
|
|
31
|
+
+ ". PanDA DB schema installed is "
|
|
32
|
+
+ dbVersion
|
|
33
|
+
+ " while PanDA JEDI requires version "
|
|
34
|
+
+ serverDBVersion
|
|
35
|
+
+ " to be installed. Please check the official docs for instructions on how to upgrade the schema."
|
|
36
|
+
)
|
|
37
|
+
print(msgBody)
|
|
38
|
+
if "pandaEmailNotification" in panda_config.__dict__:
|
|
39
|
+
MailUtils().send(
|
|
40
|
+
panda_config.pandaEmailNotification, "PanDA DB Version installed is not correct for JEDI running on " + panda_config.pserveralias, msgBody
|
|
41
|
+
)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import uuid
|
|
3
|
+
|
|
4
|
+
from userinterface import Client
|
|
5
|
+
|
|
6
|
+
inFileList = ["file1", "file2", "file3"]
|
|
7
|
+
|
|
8
|
+
logDatasetName = f"panda.jeditest.log.{uuid.uuid4()}"
|
|
9
|
+
|
|
10
|
+
taskParamMap = {}
|
|
11
|
+
|
|
12
|
+
taskParamMap["nFilesPerJob"] = 1
|
|
13
|
+
taskParamMap["nFiles"] = len(inFileList)
|
|
14
|
+
# taskParamMap['nEventsPerInputFile'] = 10000
|
|
15
|
+
# taskParamMap['nEventsPerJob'] = 10000
|
|
16
|
+
# taskParamMap['nEvents'] = 25000
|
|
17
|
+
taskParamMap["noInput"] = True
|
|
18
|
+
taskParamMap["pfnList"] = inFileList
|
|
19
|
+
# taskParamMap['mergeOutput'] = True
|
|
20
|
+
taskParamMap["taskName"] = str(uuid.uuid4())
|
|
21
|
+
taskParamMap["userName"] = "someone"
|
|
22
|
+
taskParamMap["vo"] = "wlcg"
|
|
23
|
+
taskParamMap["taskPriority"] = 900
|
|
24
|
+
# taskParamMap['reqID'] = reqIdx
|
|
25
|
+
taskParamMap["architecture"] = ""
|
|
26
|
+
taskParamMap["transUses"] = ""
|
|
27
|
+
taskParamMap["transHome"] = None
|
|
28
|
+
taskParamMap["transPath"] = "https://atlpan.web.cern.ch/atlpan/bash-c"
|
|
29
|
+
taskParamMap["processingType"] = "step1"
|
|
30
|
+
taskParamMap["prodSourceLabel"] = "test"
|
|
31
|
+
taskParamMap["taskType"] = "test"
|
|
32
|
+
taskParamMap["workingGroup"] = "lsst"
|
|
33
|
+
# taskParamMap['coreCount'] = 1
|
|
34
|
+
# taskParamMap['walltime'] = 1
|
|
35
|
+
taskParamMap["cloud"] = "US"
|
|
36
|
+
taskParamMap["site"] = "BNL_OSG_1"
|
|
37
|
+
|
|
38
|
+
"""
|
|
39
|
+
taskParamMap['log'] = {'dataset': logDatasetName,
|
|
40
|
+
'type':'template',
|
|
41
|
+
'param_type':'log',
|
|
42
|
+
'token':'local',
|
|
43
|
+
'destination':'local',
|
|
44
|
+
'value':'{0}.${{SN}}.log.tgz'.format(logDatasetName)}
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
taskParamMap["jobParameters"] = [
|
|
48
|
+
{
|
|
49
|
+
"type": "constant",
|
|
50
|
+
"value": 'singularity exec docker://busybox echo "hello world with ${IN/L}"',
|
|
51
|
+
},
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
print(Client.insertTaskParams(taskParamMap))
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
from pandajedi.jedicore.JediTaskBufferInterface import JediTaskBufferInterface
|
|
4
|
+
from pandajedi.jediddm.DDMInterface import DDMInterface
|
|
5
|
+
from pandajedi.jedirefine import RefinerUtils
|
|
6
|
+
from pandaserver.taskbuffer.DataCarousel import DataCarouselInterface
|
|
7
|
+
|
|
8
|
+
vo = "atlas"
|
|
9
|
+
jediTaskID = int(sys.argv[1])
|
|
10
|
+
|
|
11
|
+
print("set tbIF")
|
|
12
|
+
tbIF = JediTaskBufferInterface()
|
|
13
|
+
tbIF.setupInterface(max_size=1)
|
|
14
|
+
|
|
15
|
+
print("set ddmIF")
|
|
16
|
+
ddmIF = DDMInterface()
|
|
17
|
+
ddmIF.setupInterface()
|
|
18
|
+
|
|
19
|
+
print("set DCIF")
|
|
20
|
+
data_carousel_interface = DataCarouselInterface(tbIF, ddmIF.getInterface(vo))
|
|
21
|
+
if data_carousel_interface is None:
|
|
22
|
+
# data carousel interface is undefined
|
|
23
|
+
errStr = f"data carousel interface is undefined for vo={vo}"
|
|
24
|
+
print(errStr)
|
|
25
|
+
sys.exit(1)
|
|
26
|
+
|
|
27
|
+
print(f"get task params of {jediTaskID}")
|
|
28
|
+
taskParam = tbIF.getTaskParamsWithID_JEDI(jediTaskID)
|
|
29
|
+
taskParamMap = RefinerUtils.decodeJSON(taskParam)
|
|
30
|
+
|
|
31
|
+
print(f"get_input_datasets_to_prestage")
|
|
32
|
+
prestaging_list, ret_map = data_carousel_interface.get_input_datasets_to_prestage(jediTaskID, taskParamMap)
|
|
33
|
+
|
|
34
|
+
if not prestaging_list:
|
|
35
|
+
# no dataset needs pre-staging; unset inputPreStaging
|
|
36
|
+
print("no need to prestage")
|
|
37
|
+
# resume the task from staging
|
|
38
|
+
print(f"resume task {jediTaskID}")
|
|
39
|
+
tbIF.sendCommandTaskPanda(jediTaskID, "Test addDataCarouselRequest. No need to prestage. Resumed from staging", True, "resume")
|
|
40
|
+
else:
|
|
41
|
+
# submit data carousel requests for dataset to pre-stage
|
|
42
|
+
print("to prestage, submitting data carousel requests")
|
|
43
|
+
tmp_ret = data_carousel_interface.submit_data_carousel_requests(jediTaskID, prestaging_list)
|
|
44
|
+
if tmp_ret:
|
|
45
|
+
print(f"submitted data carousel requests for {jediTaskID}: {tmp_ret}")
|
|
46
|
+
else:
|
|
47
|
+
print(f"failed to submit data carousel requests")
|