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,772 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
|
|
3
|
+
from pandacommon.pandalogger.LogWrapper import LogWrapper
|
|
4
|
+
from pandacommon.pandautils.PandaUtils import get_sql_IN_bind_variables, naive_utcnow
|
|
5
|
+
|
|
6
|
+
from pandaserver.config import panda_config
|
|
7
|
+
from pandaserver.taskbuffer.DataCarousel import (
|
|
8
|
+
DataCarouselRequestSpec,
|
|
9
|
+
DataCarouselRequestStatus,
|
|
10
|
+
get_resubmit_request_spec,
|
|
11
|
+
)
|
|
12
|
+
from pandaserver.taskbuffer.db_proxy_mods.base_module import BaseModule, varNUMBER
|
|
13
|
+
from pandaserver.taskbuffer.JediTaskSpec import JediTaskSpec
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# Module class to define Data Carousel related methods
|
|
17
|
+
class DataCarouselModule(BaseModule):
|
|
18
|
+
# constructor
|
|
19
|
+
def __init__(self, log_stream: LogWrapper):
|
|
20
|
+
super().__init__(log_stream)
|
|
21
|
+
|
|
22
|
+
# query data carousel request ID by dataset
|
|
23
|
+
def get_data_carousel_request_id_by_dataset_JEDI(self, dataset):
|
|
24
|
+
comment = " /* JediDBProxy.get_data_carousel_request_id_by_dataset_JEDI */"
|
|
25
|
+
tmp_log = self.create_tagged_logger(comment, f"dataset={dataset}")
|
|
26
|
+
tmp_log.debug("start")
|
|
27
|
+
try:
|
|
28
|
+
# sql to query request of the dataset
|
|
29
|
+
status_var_names_str, status_var_map = get_sql_IN_bind_variables(DataCarouselRequestStatus.reusable_statuses, prefix=":status_")
|
|
30
|
+
sql_query = (
|
|
31
|
+
f"SELECT request_id "
|
|
32
|
+
f"FROM {panda_config.schemaJEDI}.data_carousel_requests "
|
|
33
|
+
f"WHERE dataset=:dataset "
|
|
34
|
+
f"AND status IN ({status_var_names_str}) "
|
|
35
|
+
)
|
|
36
|
+
var_map = {":dataset": dataset}
|
|
37
|
+
var_map.update(status_var_map)
|
|
38
|
+
self.cur.execute(sql_query + comment, var_map)
|
|
39
|
+
res = self.cur.fetchone()
|
|
40
|
+
if res is None:
|
|
41
|
+
tmp_log.debug("no such request")
|
|
42
|
+
self._commit()
|
|
43
|
+
return None
|
|
44
|
+
request_id = res[0]
|
|
45
|
+
tmp_log.debug(f"found request_id={request_id}")
|
|
46
|
+
self._commit()
|
|
47
|
+
return request_id
|
|
48
|
+
except Exception:
|
|
49
|
+
# roll back
|
|
50
|
+
self._rollback()
|
|
51
|
+
# error
|
|
52
|
+
self.dump_error_message(tmp_log)
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
# insert data carousel requests
|
|
56
|
+
def insert_data_carousel_requests_JEDI(self, task_id, dc_req_specs):
|
|
57
|
+
comment = " /* JediDBProxy.insert_data_carousel_requests_JEDI */"
|
|
58
|
+
tmp_log = self.create_tagged_logger(comment, f"jediTaskID={task_id}")
|
|
59
|
+
tmp_log.debug("start")
|
|
60
|
+
try:
|
|
61
|
+
# start transaction
|
|
62
|
+
self.conn.begin()
|
|
63
|
+
# insert requests
|
|
64
|
+
n_req_inserted = 0
|
|
65
|
+
n_rel_inserted = 0
|
|
66
|
+
n_req_reused = 0
|
|
67
|
+
n_rel_reused = 0
|
|
68
|
+
for dc_req_spec in dc_req_specs:
|
|
69
|
+
# sql to query request of the dataset
|
|
70
|
+
status_var_names_str, status_var_map = get_sql_IN_bind_variables(DataCarouselRequestStatus.reusable_statuses, prefix=":status")
|
|
71
|
+
sql_query = (
|
|
72
|
+
f"SELECT request_id "
|
|
73
|
+
f"FROM {panda_config.schemaJEDI}.data_carousel_requests "
|
|
74
|
+
f"WHERE dataset=:dataset "
|
|
75
|
+
f"AND status IN ({status_var_names_str}) "
|
|
76
|
+
)
|
|
77
|
+
var_map = {":dataset": dc_req_spec.dataset}
|
|
78
|
+
var_map.update(status_var_map)
|
|
79
|
+
self.cur.execute(sql_query + comment, var_map)
|
|
80
|
+
res = self.cur.fetchall()
|
|
81
|
+
# check if already existing request for the dataset
|
|
82
|
+
the_request_id = None
|
|
83
|
+
if res:
|
|
84
|
+
# have existing request; reuse it
|
|
85
|
+
for (request_id,) in res:
|
|
86
|
+
the_request_id = request_id
|
|
87
|
+
n_req_reused += 1
|
|
88
|
+
break
|
|
89
|
+
else:
|
|
90
|
+
# no existing request; insert new one
|
|
91
|
+
# sql to insert request
|
|
92
|
+
sql_insert_request = (
|
|
93
|
+
f"INSERT INTO {panda_config.schemaJEDI}.data_carousel_requests ({dc_req_spec.columnNames()}) "
|
|
94
|
+
f"{dc_req_spec.bindValuesExpression()} "
|
|
95
|
+
f"RETURNING request_id INTO :new_request_id "
|
|
96
|
+
)
|
|
97
|
+
var_map = dc_req_spec.valuesMap(useSeq=True)
|
|
98
|
+
var_map[":new_request_id"] = self.cur.var(varNUMBER)
|
|
99
|
+
self.cur.execute(sql_insert_request + comment, var_map)
|
|
100
|
+
the_request_id = int(self.getvalue_corrector(self.cur.getvalue(var_map[":new_request_id"])))
|
|
101
|
+
n_req_inserted += 1
|
|
102
|
+
if the_request_id is None:
|
|
103
|
+
raise RuntimeError("the_request_id is None")
|
|
104
|
+
# sql to query relation
|
|
105
|
+
sql_rel_query = (
|
|
106
|
+
f"SELECT request_id, task_id "
|
|
107
|
+
f"FROM {panda_config.schemaJEDI}.data_carousel_relations "
|
|
108
|
+
f"WHERE request_id=:request_id AND task_id=:task_id "
|
|
109
|
+
)
|
|
110
|
+
var_map = {":request_id": the_request_id, ":task_id": task_id}
|
|
111
|
+
self.cur.execute(sql_rel_query + comment, var_map)
|
|
112
|
+
res = self.cur.fetchall()
|
|
113
|
+
if res:
|
|
114
|
+
# have existing relation; skipped
|
|
115
|
+
n_rel_reused += 1
|
|
116
|
+
else:
|
|
117
|
+
# sql to insert relation
|
|
118
|
+
sql_insert_relation = (
|
|
119
|
+
f"INSERT INTO {panda_config.schemaJEDI}.data_carousel_relations (request_id, task_id) " f"VALUES(:request_id, :task_id) "
|
|
120
|
+
)
|
|
121
|
+
self.cur.execute(sql_insert_relation + comment, var_map)
|
|
122
|
+
n_rel_inserted += 1
|
|
123
|
+
# commit
|
|
124
|
+
if not self._commit():
|
|
125
|
+
raise RuntimeError("Commit error")
|
|
126
|
+
# return
|
|
127
|
+
tmp_log.debug(
|
|
128
|
+
f"inserted {n_req_inserted}/{len(dc_req_specs)} requests and {n_rel_inserted} relations ; reused {n_req_reused} requests and {n_rel_reused} relations"
|
|
129
|
+
)
|
|
130
|
+
return n_req_inserted
|
|
131
|
+
except Exception:
|
|
132
|
+
# roll back
|
|
133
|
+
self._rollback()
|
|
134
|
+
# error
|
|
135
|
+
self.dump_error_message(tmp_log)
|
|
136
|
+
return None
|
|
137
|
+
|
|
138
|
+
# update a data carousel request
|
|
139
|
+
def update_data_carousel_request_JEDI(self, dc_req_spec):
|
|
140
|
+
comment = " /* JediDBProxy.update_data_carousel_request_JEDI */"
|
|
141
|
+
tmp_log = self.create_tagged_logger(comment, f"request_id={dc_req_spec.request_id}")
|
|
142
|
+
tmp_log.debug("start")
|
|
143
|
+
try:
|
|
144
|
+
# start transaction
|
|
145
|
+
self.conn.begin()
|
|
146
|
+
# sql to update request
|
|
147
|
+
dc_req_spec.modification_time = naive_utcnow()
|
|
148
|
+
sql_update = (
|
|
149
|
+
f"UPDATE {panda_config.schemaJEDI}.data_carousel_requests " f"SET {dc_req_spec.bindUpdateChangesExpression()} " "WHERE request_id=:request_id "
|
|
150
|
+
)
|
|
151
|
+
var_map = dc_req_spec.valuesMap(useSeq=False, onlyChanged=True)
|
|
152
|
+
var_map[":request_id"] = dc_req_spec.request_id
|
|
153
|
+
self.cur.execute(sql_update + comment, var_map)
|
|
154
|
+
# commit
|
|
155
|
+
if not self._commit():
|
|
156
|
+
raise RuntimeError("Commit error")
|
|
157
|
+
# return
|
|
158
|
+
tmp_log.debug(f"updated {dc_req_spec.bindUpdateChangesExpression()}")
|
|
159
|
+
return dc_req_spec
|
|
160
|
+
except Exception:
|
|
161
|
+
# roll back
|
|
162
|
+
self._rollback()
|
|
163
|
+
# error
|
|
164
|
+
self.dump_error_message(tmp_log)
|
|
165
|
+
return None
|
|
166
|
+
|
|
167
|
+
# insert data carousel relations
|
|
168
|
+
def insert_data_carousel_relations_JEDI(self, task_id, request_ids):
|
|
169
|
+
comment = " /* JediDBProxy.insert_data_carousel_relations_JEDI */"
|
|
170
|
+
tmp_log = self.create_tagged_logger(comment, f"jediTaskID={task_id}")
|
|
171
|
+
tmp_log.debug("start")
|
|
172
|
+
try:
|
|
173
|
+
# start transaction
|
|
174
|
+
self.conn.begin()
|
|
175
|
+
# insert relations
|
|
176
|
+
n_rel_inserted = 0
|
|
177
|
+
n_rel_reused = 0
|
|
178
|
+
for request_id in request_ids:
|
|
179
|
+
# sql to query relation
|
|
180
|
+
sql_rel_query = (
|
|
181
|
+
f"SELECT request_id, task_id "
|
|
182
|
+
f"FROM {panda_config.schemaJEDI}.data_carousel_relations "
|
|
183
|
+
f"WHERE request_id=:request_id AND task_id=:task_id "
|
|
184
|
+
)
|
|
185
|
+
var_map = {":request_id": request_id, ":task_id": task_id}
|
|
186
|
+
self.cur.execute(sql_rel_query + comment, var_map)
|
|
187
|
+
res = self.cur.fetchall()
|
|
188
|
+
if res:
|
|
189
|
+
# have existing relation; skipped
|
|
190
|
+
n_rel_reused += 1
|
|
191
|
+
else:
|
|
192
|
+
# sql to insert relation
|
|
193
|
+
sql_insert_relation = (
|
|
194
|
+
f"INSERT INTO {panda_config.schemaJEDI}.data_carousel_relations (request_id, task_id) " f"VALUES(:request_id, :task_id) "
|
|
195
|
+
)
|
|
196
|
+
self.cur.execute(sql_insert_relation + comment, var_map)
|
|
197
|
+
n_rel_inserted += 1
|
|
198
|
+
# commit
|
|
199
|
+
if not self._commit():
|
|
200
|
+
raise RuntimeError("Commit error")
|
|
201
|
+
# return
|
|
202
|
+
tmp_log.debug(f"inserted {n_rel_inserted} relations ; reused {n_rel_reused} relations")
|
|
203
|
+
return n_rel_inserted
|
|
204
|
+
except Exception:
|
|
205
|
+
# roll back
|
|
206
|
+
self._rollback()
|
|
207
|
+
# error
|
|
208
|
+
self.dump_error_message(tmp_log)
|
|
209
|
+
return None
|
|
210
|
+
|
|
211
|
+
# get data carousel queued requests and info of their related tasks
|
|
212
|
+
def get_data_carousel_queued_requests_JEDI(self):
|
|
213
|
+
comment = " /* JediDBProxy.get_data_carousel_queued_requests_JEDI */"
|
|
214
|
+
tmp_log = self.create_tagged_logger(comment)
|
|
215
|
+
tmp_log.debug("start")
|
|
216
|
+
try:
|
|
217
|
+
# initialize
|
|
218
|
+
ret_list = []
|
|
219
|
+
# start transaction
|
|
220
|
+
self.conn.begin()
|
|
221
|
+
# sql to query queued requests with gshare and priority info from related tasks
|
|
222
|
+
sql_query_req = (
|
|
223
|
+
f"SELECT {DataCarouselRequestSpec.columnNames()} " f"FROM {panda_config.schemaJEDI}.data_carousel_requests " f"WHERE status=:status "
|
|
224
|
+
)
|
|
225
|
+
var_map = {":status": DataCarouselRequestStatus.queued}
|
|
226
|
+
self.cur.execute(sql_query_req + comment, var_map)
|
|
227
|
+
res_list = self.cur.fetchall()
|
|
228
|
+
if res_list:
|
|
229
|
+
for res in res_list:
|
|
230
|
+
# make request spec
|
|
231
|
+
dc_req_spec = DataCarouselRequestSpec()
|
|
232
|
+
dc_req_spec.pack(res)
|
|
233
|
+
# query info of related tasks
|
|
234
|
+
sql_query_tasks = (
|
|
235
|
+
f"SELECT t.jediTaskID, t.gshare, COALESCE(t.currentPriority, t.taskPriority), t.taskType, t.userName, t.workingGroup "
|
|
236
|
+
f"FROM {panda_config.schemaJEDI}.data_carousel_relations rel, {panda_config.schemaJEDI}.JEDI_Tasks t "
|
|
237
|
+
f"WHERE rel.request_id=:request_id AND rel.task_id=t.jediTaskID "
|
|
238
|
+
)
|
|
239
|
+
var_map = {":request_id": dc_req_spec.request_id}
|
|
240
|
+
self.cur.execute(sql_query_tasks + comment, var_map)
|
|
241
|
+
res_tasks = self.cur.fetchall()
|
|
242
|
+
task_specs = []
|
|
243
|
+
for task_id, gshare, priority, task_type, user_name, working_group in res_tasks:
|
|
244
|
+
task_spec = JediTaskSpec()
|
|
245
|
+
task_spec.jediTaskID = task_id
|
|
246
|
+
task_spec.gshare = gshare
|
|
247
|
+
task_spec.currentPriority = priority
|
|
248
|
+
task_spec.taskType = task_type
|
|
249
|
+
task_spec.userName = user_name
|
|
250
|
+
task_spec.workingGroup = working_group
|
|
251
|
+
task_specs.append(task_spec)
|
|
252
|
+
# add
|
|
253
|
+
ret_list.append((dc_req_spec, task_specs))
|
|
254
|
+
else:
|
|
255
|
+
tmp_log.debug("no queued request")
|
|
256
|
+
# commit
|
|
257
|
+
if not self._commit():
|
|
258
|
+
raise RuntimeError("Commit error")
|
|
259
|
+
# return
|
|
260
|
+
tmp_log.debug(f"got {len(ret_list)} queued requests")
|
|
261
|
+
return ret_list
|
|
262
|
+
except Exception:
|
|
263
|
+
# roll back
|
|
264
|
+
self._rollback()
|
|
265
|
+
# error
|
|
266
|
+
self.dump_error_message(tmp_log)
|
|
267
|
+
return None
|
|
268
|
+
|
|
269
|
+
# get data carousel requests of tasks by task status
|
|
270
|
+
def get_data_carousel_requests_by_task_status_JEDI(self, status_filter_list=None, status_exclusion_list=None):
|
|
271
|
+
comment = " /* JediDBProxy.get_data_carousel_requests_by_task_status_JEDI */"
|
|
272
|
+
tmp_log = self.create_tagged_logger(comment)
|
|
273
|
+
tmp_log.debug("start")
|
|
274
|
+
try:
|
|
275
|
+
# initialize
|
|
276
|
+
ret_requests_map = {}
|
|
277
|
+
ret_relation_map = {}
|
|
278
|
+
# start transaction
|
|
279
|
+
self.conn.begin()
|
|
280
|
+
# sql to query queued requests with gshare and priority info from related tasks
|
|
281
|
+
sql_query_id = (
|
|
282
|
+
f"SELECT rel.request_id, rel.task_id "
|
|
283
|
+
f"FROM {panda_config.schemaJEDI}.data_carousel_relations rel, {panda_config.schemaJEDI}.JEDI_Tasks t "
|
|
284
|
+
f"WHERE rel.task_id=t.jediTaskID "
|
|
285
|
+
)
|
|
286
|
+
var_map = {}
|
|
287
|
+
if status_filter_list:
|
|
288
|
+
status_var_names_str, status_var_map = get_sql_IN_bind_variables(status_filter_list, prefix=":status")
|
|
289
|
+
sql_query_id += f"AND t.status IN ({status_var_names_str}) "
|
|
290
|
+
var_map.update(status_var_map)
|
|
291
|
+
tmp_log.debug(f"status filter: {status_filter_list}")
|
|
292
|
+
if status_exclusion_list:
|
|
293
|
+
antistatus_var_names_str, antistatus_var_map = get_sql_IN_bind_variables(status_exclusion_list, prefix=":antistatus")
|
|
294
|
+
sql_query_id += f"AND t.status NOT IN ({antistatus_var_names_str}) "
|
|
295
|
+
var_map.update(antistatus_var_map)
|
|
296
|
+
tmp_log.debug(f"status exclusion filter: {status_exclusion_list}")
|
|
297
|
+
self.cur.execute(sql_query_id + comment, var_map)
|
|
298
|
+
res_list = self.cur.fetchall()
|
|
299
|
+
if res_list:
|
|
300
|
+
for request_id, task_id in res_list:
|
|
301
|
+
# fill relation map
|
|
302
|
+
ret_relation_map.setdefault(task_id, [])
|
|
303
|
+
ret_relation_map[task_id].append(request_id)
|
|
304
|
+
if request_id in ret_requests_map:
|
|
305
|
+
# already got the request spec; skip
|
|
306
|
+
continue
|
|
307
|
+
else:
|
|
308
|
+
# query info of related tasks
|
|
309
|
+
sql_query_requests = (
|
|
310
|
+
f"SELECT {DataCarouselRequestSpec.columnNames()} "
|
|
311
|
+
f"FROM {panda_config.schemaJEDI}.data_carousel_requests "
|
|
312
|
+
f"WHERE request_id=:request_id "
|
|
313
|
+
)
|
|
314
|
+
var_map = {":request_id": request_id}
|
|
315
|
+
self.cur.execute(sql_query_requests + comment, var_map)
|
|
316
|
+
req_res_list = self.cur.fetchall()
|
|
317
|
+
# make request spec
|
|
318
|
+
dc_req_spec = DataCarouselRequestSpec()
|
|
319
|
+
for req_res in req_res_list:
|
|
320
|
+
dc_req_spec.pack(req_res)
|
|
321
|
+
break
|
|
322
|
+
# fill requests map
|
|
323
|
+
ret_requests_map[request_id] = dc_req_spec
|
|
324
|
+
else:
|
|
325
|
+
tmp_log.debug("no request")
|
|
326
|
+
# commit
|
|
327
|
+
if not self._commit():
|
|
328
|
+
raise RuntimeError("Commit error")
|
|
329
|
+
# return
|
|
330
|
+
tmp_log.debug(f"got {len(ret_requests_map)} requests of {len(ret_relation_map)} active tasks")
|
|
331
|
+
return ret_requests_map, ret_relation_map
|
|
332
|
+
except Exception:
|
|
333
|
+
# roll back
|
|
334
|
+
self._rollback()
|
|
335
|
+
# error
|
|
336
|
+
self.dump_error_message(tmp_log)
|
|
337
|
+
return None
|
|
338
|
+
|
|
339
|
+
# get related tasks and their info of a data carousel request
|
|
340
|
+
def get_related_tasks_of_data_carousel_request_JEDI(self, request_id, status_filter_list=None, status_exclusion_list=None):
|
|
341
|
+
comment = " /* JediDBProxy.get_related_tasks_of_data_carousel_request_JEDI */"
|
|
342
|
+
tmp_log = self.create_tagged_logger(comment, f"request_id={request_id}")
|
|
343
|
+
tmp_log.debug("start")
|
|
344
|
+
try:
|
|
345
|
+
# initialize
|
|
346
|
+
ret_tasks_dict = {}
|
|
347
|
+
# start transaction
|
|
348
|
+
self.conn.begin()
|
|
349
|
+
# sql to query related tasks
|
|
350
|
+
sql_query = (
|
|
351
|
+
f"SELECT rel.task_id, t.status "
|
|
352
|
+
f"FROM {panda_config.schemaJEDI}.data_carousel_relations rel, {panda_config.schemaJEDI}.JEDI_Tasks t "
|
|
353
|
+
f"WHERE rel.task_id=t.jediTaskID "
|
|
354
|
+
f"AND rel.request_id=:request_id "
|
|
355
|
+
)
|
|
356
|
+
var_map = {":request_id": request_id}
|
|
357
|
+
if status_filter_list:
|
|
358
|
+
status_var_names_str, status_var_map = get_sql_IN_bind_variables(status_filter_list, prefix=":status")
|
|
359
|
+
sql_query += f"AND t.status IN ({status_var_names_str}) "
|
|
360
|
+
var_map.update(status_var_map)
|
|
361
|
+
tmp_log.debug(f"status filter: {status_filter_list}")
|
|
362
|
+
if status_exclusion_list:
|
|
363
|
+
antistatus_var_names_str, antistatus_var_map = get_sql_IN_bind_variables(status_exclusion_list, prefix=":antistatus")
|
|
364
|
+
sql_query += f"AND t.status NOT IN ({antistatus_var_names_str}) "
|
|
365
|
+
var_map.update(antistatus_var_map)
|
|
366
|
+
tmp_log.debug(f"status exclusion filter: {status_exclusion_list}")
|
|
367
|
+
self.cur.execute(sql_query + comment, var_map)
|
|
368
|
+
res_list = self.cur.fetchall()
|
|
369
|
+
if res_list:
|
|
370
|
+
for task_id, status in res_list:
|
|
371
|
+
ret_tasks_dict[task_id] = {"task_id": task_id, "status": status}
|
|
372
|
+
else:
|
|
373
|
+
tmp_log.debug("no related task")
|
|
374
|
+
# commit
|
|
375
|
+
if not self._commit():
|
|
376
|
+
raise RuntimeError("Commit error")
|
|
377
|
+
# return
|
|
378
|
+
tmp_log.debug(f"got {len(ret_tasks_dict)} related tasks")
|
|
379
|
+
return ret_tasks_dict
|
|
380
|
+
except Exception:
|
|
381
|
+
# roll back
|
|
382
|
+
self._rollback()
|
|
383
|
+
# error
|
|
384
|
+
self.dump_error_message(tmp_log)
|
|
385
|
+
return None
|
|
386
|
+
|
|
387
|
+
# get data carousel staging requests
|
|
388
|
+
def get_data_carousel_staging_requests_JEDI(self, time_limit_minutes=5):
|
|
389
|
+
comment = " /* JediDBProxy.get_data_carousel_staging_requests_JEDI */"
|
|
390
|
+
tmp_log = self.create_tagged_logger(comment)
|
|
391
|
+
tmp_log.debug("start")
|
|
392
|
+
try:
|
|
393
|
+
# initialize
|
|
394
|
+
ret_list = []
|
|
395
|
+
# start transaction
|
|
396
|
+
self.conn.begin()
|
|
397
|
+
# sql to query staging requests
|
|
398
|
+
sql_query_req = (
|
|
399
|
+
f"SELECT {DataCarouselRequestSpec.columnNames()} "
|
|
400
|
+
f"FROM {panda_config.schemaJEDI}.data_carousel_requests "
|
|
401
|
+
f"WHERE status=:status "
|
|
402
|
+
f"AND ( check_time IS NULL OR check_time<=:check_time_max ) "
|
|
403
|
+
)
|
|
404
|
+
now_time = naive_utcnow()
|
|
405
|
+
var_map = {":status": DataCarouselRequestStatus.staging, ":check_time_max": now_time - datetime.timedelta(minutes=time_limit_minutes)}
|
|
406
|
+
self.cur.execute(sql_query_req + comment, var_map)
|
|
407
|
+
res_list = self.cur.fetchall()
|
|
408
|
+
if res_list:
|
|
409
|
+
now_time = naive_utcnow()
|
|
410
|
+
sql_update = f"UPDATE {panda_config.schemaJEDI}.data_carousel_requests " f"SET check_time=:check_time " f"WHERE request_id=:request_id "
|
|
411
|
+
for res in res_list:
|
|
412
|
+
# make request spec
|
|
413
|
+
dc_req_spec = DataCarouselRequestSpec()
|
|
414
|
+
dc_req_spec.pack(res)
|
|
415
|
+
# update check time
|
|
416
|
+
var_map = {":request_id": dc_req_spec.request_id, ":check_time": now_time}
|
|
417
|
+
self.cur.execute(sql_update + comment, var_map)
|
|
418
|
+
# add
|
|
419
|
+
ret_list.append(dc_req_spec)
|
|
420
|
+
else:
|
|
421
|
+
tmp_log.debug("no staging request")
|
|
422
|
+
# commit
|
|
423
|
+
if not self._commit():
|
|
424
|
+
raise RuntimeError("Commit error")
|
|
425
|
+
# return
|
|
426
|
+
tmp_log.debug(f"got {len(ret_list)} staging requests")
|
|
427
|
+
return ret_list
|
|
428
|
+
except Exception:
|
|
429
|
+
# roll back
|
|
430
|
+
self._rollback()
|
|
431
|
+
# error
|
|
432
|
+
self.dump_error_message(tmp_log)
|
|
433
|
+
return None
|
|
434
|
+
|
|
435
|
+
# delete data carousel requests
|
|
436
|
+
def delete_data_carousel_requests_JEDI(self, request_id_list):
|
|
437
|
+
comment = " /* JediDBProxy.delete_data_carousel_requests_JEDI */"
|
|
438
|
+
tmp_log = self.create_tagged_logger(comment)
|
|
439
|
+
tmp_log.debug("start")
|
|
440
|
+
try:
|
|
441
|
+
# start transaction
|
|
442
|
+
self.conn.begin()
|
|
443
|
+
# sql to delete terminated requests
|
|
444
|
+
status_var_names_str, status_var_map = get_sql_IN_bind_variables(DataCarouselRequestStatus.final_statuses, prefix=":status")
|
|
445
|
+
sql_delete_req = (
|
|
446
|
+
f"DELETE FROM {panda_config.schemaJEDI}.data_carousel_requests " f"WHERE request_id=:request_id " f"AND status IN ({status_var_names_str}) "
|
|
447
|
+
)
|
|
448
|
+
var_map_base = {}
|
|
449
|
+
var_map_base.update(status_var_map)
|
|
450
|
+
var_map_list = []
|
|
451
|
+
for request_id in request_id_list:
|
|
452
|
+
var_map = var_map_base.copy()
|
|
453
|
+
var_map[":request_id"] = request_id
|
|
454
|
+
var_map_list.append(var_map)
|
|
455
|
+
self.cur.executemany(sql_delete_req + comment, var_map_list)
|
|
456
|
+
ret_req = self.cur.rowcount
|
|
457
|
+
# sql to delete relations
|
|
458
|
+
sql_delete_rel = (
|
|
459
|
+
f"DELETE FROM {panda_config.schemaJEDI}.data_carousel_relations rel "
|
|
460
|
+
f"WHERE rel.request_id NOT IN "
|
|
461
|
+
f"(SELECT req.request_id FROM {panda_config.schemaJEDI}.data_carousel_requests req) "
|
|
462
|
+
)
|
|
463
|
+
self.cur.execute(sql_delete_rel + comment, {})
|
|
464
|
+
ret_rel = self.cur.rowcount
|
|
465
|
+
# commit
|
|
466
|
+
if not self._commit():
|
|
467
|
+
raise RuntimeError("Commit error")
|
|
468
|
+
# return
|
|
469
|
+
tmp_log.debug(f"cleaned up {ret_req}/{len(request_id_list)} requests and {ret_rel} relations")
|
|
470
|
+
return ret_req
|
|
471
|
+
except Exception:
|
|
472
|
+
# roll back
|
|
473
|
+
self._rollback()
|
|
474
|
+
# error
|
|
475
|
+
self.dump_error_message(tmp_log)
|
|
476
|
+
return None
|
|
477
|
+
|
|
478
|
+
# clean up data carousel requests
|
|
479
|
+
def clean_up_data_carousel_requests_JEDI(self, time_limit_days=30):
|
|
480
|
+
comment = " /* JediDBProxy.clean_up_data_carousel_requests_JEDI */"
|
|
481
|
+
tmp_log = self.create_tagged_logger(comment)
|
|
482
|
+
tmp_log.debug("start")
|
|
483
|
+
try:
|
|
484
|
+
# start transaction
|
|
485
|
+
self.conn.begin()
|
|
486
|
+
# sql to delete terminated requests
|
|
487
|
+
now_time = naive_utcnow()
|
|
488
|
+
status_var_names_str, status_var_map = get_sql_IN_bind_variables(DataCarouselRequestStatus.final_statuses, prefix=":status")
|
|
489
|
+
sql_delete_req = (
|
|
490
|
+
f"DELETE FROM {panda_config.schemaJEDI}.data_carousel_requests " f"WHERE status IN ({status_var_names_str}) " f"AND end_time<=:end_time_max "
|
|
491
|
+
)
|
|
492
|
+
var_map = {":end_time_max": now_time - datetime.timedelta(days=time_limit_days)}
|
|
493
|
+
var_map.update(status_var_map)
|
|
494
|
+
self.cur.execute(sql_delete_req + comment, var_map)
|
|
495
|
+
ret_req = self.cur.rowcount
|
|
496
|
+
# sql to delete relations
|
|
497
|
+
sql_delete_rel = (
|
|
498
|
+
f"DELETE FROM {panda_config.schemaJEDI}.data_carousel_relations rel "
|
|
499
|
+
f"WHERE rel.request_id NOT IN "
|
|
500
|
+
f"(SELECT req.request_id FROM {panda_config.schemaJEDI}.data_carousel_requests req) "
|
|
501
|
+
)
|
|
502
|
+
self.cur.execute(sql_delete_rel + comment, {})
|
|
503
|
+
ret_rel = self.cur.rowcount
|
|
504
|
+
# commit
|
|
505
|
+
if not self._commit():
|
|
506
|
+
raise RuntimeError("Commit error")
|
|
507
|
+
# return
|
|
508
|
+
tmp_log.debug(f"cleaned up {ret_req} requests and {ret_rel} relations older than {time_limit_days} days")
|
|
509
|
+
return ret_req
|
|
510
|
+
except Exception:
|
|
511
|
+
# roll back
|
|
512
|
+
self._rollback()
|
|
513
|
+
# error
|
|
514
|
+
self.dump_error_message(tmp_log)
|
|
515
|
+
return None
|
|
516
|
+
|
|
517
|
+
# cancel a data carousel request
|
|
518
|
+
def cancel_data_carousel_request_JEDI(self, request_id):
|
|
519
|
+
comment = " /* JediDBProxy.cancel_data_carousel_request_JEDI */"
|
|
520
|
+
tmp_log = self.create_tagged_logger(comment, f"request_id={request_id}")
|
|
521
|
+
tmp_log.debug("start")
|
|
522
|
+
try:
|
|
523
|
+
# start transaction
|
|
524
|
+
self.conn.begin()
|
|
525
|
+
# sql to update request status to cancelled
|
|
526
|
+
now_time = naive_utcnow()
|
|
527
|
+
status_var_names_str, status_var_map = get_sql_IN_bind_variables(DataCarouselRequestStatus.active_statuses, prefix=":old_status")
|
|
528
|
+
sql_update = (
|
|
529
|
+
f"UPDATE {panda_config.schemaJEDI}.data_carousel_requests "
|
|
530
|
+
f"SET status=:new_status, end_time=:now_time, modification_time=:now_time "
|
|
531
|
+
f"WHERE request_id=:request_id "
|
|
532
|
+
f"AND status IN ({status_var_names_str}) "
|
|
533
|
+
)
|
|
534
|
+
var_map = {
|
|
535
|
+
":request_id": request_id,
|
|
536
|
+
":new_status": DataCarouselRequestStatus.cancelled,
|
|
537
|
+
":now_time": now_time,
|
|
538
|
+
}
|
|
539
|
+
var_map.update(status_var_map)
|
|
540
|
+
self.cur.execute(sql_update + comment, var_map)
|
|
541
|
+
ret_req = self.cur.rowcount
|
|
542
|
+
if not ret_req:
|
|
543
|
+
tmp_log.warning(f"already terminated; cannot be cancelled ; skipped")
|
|
544
|
+
else:
|
|
545
|
+
tmp_log.debug(f"cancelled request")
|
|
546
|
+
# commit
|
|
547
|
+
if not self._commit():
|
|
548
|
+
raise RuntimeError("Commit error")
|
|
549
|
+
# return
|
|
550
|
+
return ret_req
|
|
551
|
+
except Exception:
|
|
552
|
+
# roll back
|
|
553
|
+
self._rollback()
|
|
554
|
+
# error
|
|
555
|
+
self.dump_error_message(tmp_log)
|
|
556
|
+
return None
|
|
557
|
+
|
|
558
|
+
# retire a data carousel request
|
|
559
|
+
def retire_data_carousel_request_JEDI(self, request_id):
|
|
560
|
+
comment = " /* JediDBProxy.retire_data_carousel_request_JEDI */"
|
|
561
|
+
tmp_log = self.create_tagged_logger(comment, f"request_id={request_id}")
|
|
562
|
+
tmp_log.debug("start")
|
|
563
|
+
try:
|
|
564
|
+
# start transaction
|
|
565
|
+
self.conn.begin()
|
|
566
|
+
# sql to update request status to retired
|
|
567
|
+
now_time = naive_utcnow()
|
|
568
|
+
sql_update = (
|
|
569
|
+
f"UPDATE {panda_config.schemaJEDI}.data_carousel_requests "
|
|
570
|
+
f"SET status=:new_status, modification_time=:now_time "
|
|
571
|
+
f"WHERE request_id=:request_id "
|
|
572
|
+
f"AND status=:old_status "
|
|
573
|
+
)
|
|
574
|
+
var_map = {
|
|
575
|
+
":request_id": request_id,
|
|
576
|
+
":old_status": DataCarouselRequestStatus.done,
|
|
577
|
+
":new_status": DataCarouselRequestStatus.retired,
|
|
578
|
+
":now_time": now_time,
|
|
579
|
+
}
|
|
580
|
+
self.cur.execute(sql_update + comment, var_map)
|
|
581
|
+
ret_req = self.cur.rowcount
|
|
582
|
+
if not ret_req:
|
|
583
|
+
tmp_log.warning(f"not done; cannot be retired ; skipped")
|
|
584
|
+
else:
|
|
585
|
+
tmp_log.debug(f"retired request")
|
|
586
|
+
# commit
|
|
587
|
+
if not self._commit():
|
|
588
|
+
raise RuntimeError("Commit error")
|
|
589
|
+
# return
|
|
590
|
+
return ret_req
|
|
591
|
+
except Exception:
|
|
592
|
+
# roll back
|
|
593
|
+
self._rollback()
|
|
594
|
+
# error
|
|
595
|
+
self.dump_error_message(tmp_log)
|
|
596
|
+
return None
|
|
597
|
+
|
|
598
|
+
# resubmit a data carousel request
|
|
599
|
+
def resubmit_data_carousel_request_JEDI(self, request_id, exclude_prev_dst=False):
|
|
600
|
+
comment = " /* JediDBProxy.resubmit_data_carousel_request_JEDI */"
|
|
601
|
+
tmp_log = self.create_tagged_logger(comment, f"request_id={request_id} exclude_prev_dst={exclude_prev_dst}")
|
|
602
|
+
tmp_log.debug("start")
|
|
603
|
+
try:
|
|
604
|
+
# start transaction
|
|
605
|
+
self.conn.begin()
|
|
606
|
+
# get request spec
|
|
607
|
+
dc_req_spec = None
|
|
608
|
+
status_var_names_str, status_var_map = get_sql_IN_bind_variables(DataCarouselRequestStatus.resubmittable_statuses, prefix=":status")
|
|
609
|
+
sql_query_req = (
|
|
610
|
+
f"SELECT {DataCarouselRequestSpec.columnNames()} "
|
|
611
|
+
f"FROM {panda_config.schemaJEDI}.data_carousel_requests "
|
|
612
|
+
f"WHERE request_id=:request_id "
|
|
613
|
+
f"AND status IN ({status_var_names_str}) "
|
|
614
|
+
)
|
|
615
|
+
var_map = {":request_id": request_id}
|
|
616
|
+
var_map.update(status_var_map)
|
|
617
|
+
self.cur.execute(sql_query_req + comment, var_map)
|
|
618
|
+
res_list = self.cur.fetchall()
|
|
619
|
+
for res in res_list:
|
|
620
|
+
# make request spec
|
|
621
|
+
dc_req_spec = DataCarouselRequestSpec()
|
|
622
|
+
dc_req_spec.pack(res)
|
|
623
|
+
break
|
|
624
|
+
# prepare new request spec to resubmit
|
|
625
|
+
if dc_req_spec:
|
|
626
|
+
dc_req_spec_to_resubmit = get_resubmit_request_spec(dc_req_spec, exclude_prev_dst)
|
|
627
|
+
else:
|
|
628
|
+
# roll back
|
|
629
|
+
self._rollback()
|
|
630
|
+
return False
|
|
631
|
+
# sql to update old request status (staging to cancelled, done to retired, others intact)
|
|
632
|
+
now_time = naive_utcnow()
|
|
633
|
+
if dc_req_spec.status == DataCarouselRequestStatus.staging:
|
|
634
|
+
new_status = DataCarouselRequestStatus.cancelled
|
|
635
|
+
sql_update = (
|
|
636
|
+
f"UPDATE {panda_config.schemaJEDI}.data_carousel_requests "
|
|
637
|
+
f"SET status=:new_status, end_time=:now_time, modification_time=:now_time "
|
|
638
|
+
f"WHERE request_id=:request_id "
|
|
639
|
+
)
|
|
640
|
+
var_map = {
|
|
641
|
+
":request_id": request_id,
|
|
642
|
+
":new_status": new_status,
|
|
643
|
+
":now_time": now_time,
|
|
644
|
+
}
|
|
645
|
+
self.cur.execute(sql_update + comment, var_map)
|
|
646
|
+
ret_req = self.cur.rowcount
|
|
647
|
+
if not ret_req:
|
|
648
|
+
tmp_log.warning(f"cannot be cancelled ; skipped")
|
|
649
|
+
# roll back
|
|
650
|
+
self._rollback()
|
|
651
|
+
return False
|
|
652
|
+
else:
|
|
653
|
+
tmp_log.debug(f"cancelled request")
|
|
654
|
+
elif dc_req_spec.status == DataCarouselRequestStatus.done:
|
|
655
|
+
new_status = DataCarouselRequestStatus.retired
|
|
656
|
+
sql_update = (
|
|
657
|
+
f"UPDATE {panda_config.schemaJEDI}.data_carousel_requests "
|
|
658
|
+
f"SET status=:new_status, modification_time=:now_time "
|
|
659
|
+
f"WHERE request_id=:request_id "
|
|
660
|
+
)
|
|
661
|
+
var_map = {
|
|
662
|
+
":request_id": request_id,
|
|
663
|
+
":new_status": new_status,
|
|
664
|
+
":now_time": now_time,
|
|
665
|
+
}
|
|
666
|
+
self.cur.execute(sql_update + comment, var_map)
|
|
667
|
+
ret_req = self.cur.rowcount
|
|
668
|
+
if not ret_req:
|
|
669
|
+
tmp_log.warning(f"cannot be retired ; skipped")
|
|
670
|
+
# roll back
|
|
671
|
+
self._rollback()
|
|
672
|
+
return False
|
|
673
|
+
else:
|
|
674
|
+
tmp_log.debug(f"retired request")
|
|
675
|
+
else:
|
|
676
|
+
tmp_log.debug(f"already {dc_req_spec.status} ; skipped")
|
|
677
|
+
# resubmit new request
|
|
678
|
+
# sql to insert request
|
|
679
|
+
sql_insert_request = (
|
|
680
|
+
f"INSERT INTO {panda_config.schemaJEDI}.data_carousel_requests ({dc_req_spec_to_resubmit.columnNames()}) "
|
|
681
|
+
f"{dc_req_spec_to_resubmit.bindValuesExpression()} "
|
|
682
|
+
f"RETURNING request_id INTO :new_request_id "
|
|
683
|
+
)
|
|
684
|
+
var_map = dc_req_spec_to_resubmit.valuesMap(useSeq=True)
|
|
685
|
+
var_map[":new_request_id"] = self.cur.var(varNUMBER)
|
|
686
|
+
self.cur.execute(sql_insert_request + comment, var_map)
|
|
687
|
+
new_request_id = int(self.getvalue_corrector(self.cur.getvalue(var_map[":new_request_id"])))
|
|
688
|
+
if new_request_id is None:
|
|
689
|
+
raise RuntimeError("new_request_id is None")
|
|
690
|
+
tmp_log.debug(f"resubmitted request with new_request_id={new_request_id}")
|
|
691
|
+
# sql to update relations according to the relations of the old request
|
|
692
|
+
sql_update_relations = (
|
|
693
|
+
f"UPDATE {panda_config.schemaJEDI}.data_carousel_relations " f"SET request_id=:new_request_id " f"WHERE request_id=:old_request_id "
|
|
694
|
+
)
|
|
695
|
+
var_map = {":new_request_id": new_request_id, ":old_request_id": request_id}
|
|
696
|
+
self.cur.execute(sql_update_relations + comment, var_map)
|
|
697
|
+
ret_rel = self.cur.rowcount
|
|
698
|
+
tmp_log.debug(f"updated {ret_rel} relations about new_request_id={new_request_id}")
|
|
699
|
+
# fill new request_id
|
|
700
|
+
dc_req_spec_resubmitted = dc_req_spec_to_resubmit
|
|
701
|
+
dc_req_spec_resubmitted.request_id = new_request_id
|
|
702
|
+
# commit
|
|
703
|
+
if not self._commit():
|
|
704
|
+
raise RuntimeError("Commit error")
|
|
705
|
+
# return
|
|
706
|
+
return dc_req_spec_resubmitted
|
|
707
|
+
except Exception:
|
|
708
|
+
# roll back
|
|
709
|
+
self._rollback()
|
|
710
|
+
# error
|
|
711
|
+
self.dump_error_message(tmp_log)
|
|
712
|
+
return None
|
|
713
|
+
|
|
714
|
+
# get pending data carousel tasks and their input datasets
|
|
715
|
+
def get_pending_dc_tasks_JEDI(self, task_type="prod", time_limit_minutes=60):
|
|
716
|
+
comment = " /* JediDBProxy.get_pending_dc_tasks_JEDI */"
|
|
717
|
+
tmp_log = self.create_tagged_logger(comment)
|
|
718
|
+
tmp_log.debug("start")
|
|
719
|
+
try:
|
|
720
|
+
# sql to get pending tasks
|
|
721
|
+
sql_tasks = (
|
|
722
|
+
"SELECT tabT.jediTaskID, tabT.splitRule "
|
|
723
|
+
"FROM {0}.JEDI_Tasks tabT, {0}.JEDI_AUX_Status_MinTaskID tabA "
|
|
724
|
+
"WHERE tabT.status=:status AND tabA.status=tabT.status "
|
|
725
|
+
"AND tabT.taskType=:taskType AND tabT.modificationTime<:timeLimit".format(panda_config.schemaJEDI)
|
|
726
|
+
)
|
|
727
|
+
# sql to get input dataset
|
|
728
|
+
sql_ds = (
|
|
729
|
+
"SELECT tabD.datasetID, tabD.datasetName "
|
|
730
|
+
"FROM {0}.JEDI_Datasets tabD "
|
|
731
|
+
"WHERE tabD.jediTaskID=:jediTaskID AND tabD.type IN (:type1, :type2) ".format(panda_config.schemaJEDI)
|
|
732
|
+
)
|
|
733
|
+
# initialize
|
|
734
|
+
ret_tasks_dict = {}
|
|
735
|
+
# start transaction
|
|
736
|
+
self.conn.begin()
|
|
737
|
+
# get pending tasks
|
|
738
|
+
var_map = {":status": "pending", ":taskType": task_type}
|
|
739
|
+
var_map[":timeLimit"] = naive_utcnow() - datetime.timedelta(minutes=time_limit_minutes)
|
|
740
|
+
self.cur.execute(sql_tasks + comment, var_map)
|
|
741
|
+
res = self.cur.fetchall()
|
|
742
|
+
if res:
|
|
743
|
+
for task_id, split_rule in res:
|
|
744
|
+
tmp_taskspec = JediTaskSpec()
|
|
745
|
+
tmp_taskspec.splitRule = split_rule
|
|
746
|
+
if tmp_taskspec.inputPreStaging():
|
|
747
|
+
# is data carousel task
|
|
748
|
+
var_map = {
|
|
749
|
+
":jediTaskID": task_id,
|
|
750
|
+
":type1": "input",
|
|
751
|
+
":type2": "pseudo_input",
|
|
752
|
+
}
|
|
753
|
+
self.cur.execute(sql_ds + comment, var_map)
|
|
754
|
+
ds_res = self.cur.fetchall()
|
|
755
|
+
if ds_res:
|
|
756
|
+
ret_tasks_dict[task_id] = []
|
|
757
|
+
for ds_id, ds_name in ds_res:
|
|
758
|
+
ret_tasks_dict[task_id].append(ds_name)
|
|
759
|
+
else:
|
|
760
|
+
tmp_log.debug("no pending task")
|
|
761
|
+
# commit
|
|
762
|
+
if not self._commit():
|
|
763
|
+
raise RuntimeError("Commit error")
|
|
764
|
+
# return
|
|
765
|
+
tmp_log.debug(f"found pending dc tasks: {ret_tasks_dict}")
|
|
766
|
+
return ret_tasks_dict
|
|
767
|
+
except Exception:
|
|
768
|
+
# roll back
|
|
769
|
+
self._rollback()
|
|
770
|
+
# error
|
|
771
|
+
self.dump_error_message(tmp_log)
|
|
772
|
+
return None
|