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,207 @@
|
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
|
|
3
|
+
from pandacommon.pandalogger.LogWrapper import LogWrapper
|
|
4
|
+
from pandacommon.pandalogger.PandaLogger import PandaLogger
|
|
5
|
+
|
|
6
|
+
from pandaserver.api.v1.common import generate_response, request_validation
|
|
7
|
+
from pandaserver.srvcore.panda_request import PandaRequest
|
|
8
|
+
from pandaserver.taskbuffer.TaskBuffer import TaskBuffer
|
|
9
|
+
|
|
10
|
+
_logger = PandaLogger().getLogger("api_statistics")
|
|
11
|
+
|
|
12
|
+
global_task_buffer = None
|
|
13
|
+
|
|
14
|
+
MAX_TIME_WINDOW = 60 * 24 * 7 # 7 days
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def init_task_buffer(task_buffer: TaskBuffer) -> None:
|
|
18
|
+
"""
|
|
19
|
+
Initialize the task buffer. This method needs to be called before any other method in this module.
|
|
20
|
+
"""
|
|
21
|
+
global global_task_buffer
|
|
22
|
+
global_task_buffer = task_buffer
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@request_validation(_logger, secure=False, request_method="GET")
|
|
26
|
+
def job_stats_by_cloud(req: PandaRequest, type: str = "production") -> Dict[str, Any]:
|
|
27
|
+
"""
|
|
28
|
+
Job statistics by cloud.
|
|
29
|
+
|
|
30
|
+
Get the job statistics by cloud, which includes the active jobs and jobs in final states modified in the last 12 hours. You have to filter the statistics by type, which can be either "production" or "analysis". Used by panglia monitoring. Requires a secure connection.
|
|
31
|
+
|
|
32
|
+
API details:
|
|
33
|
+
HTTP Method: GET
|
|
34
|
+
Path: /v1/statistics/job_stats_by_cloud
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
req(PandaRequest): internally generated request object
|
|
38
|
+
type(str): can be "analysis" or "production". Defaults to "production" when not provided.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
dict: The system response `{"success": success, "message": message, "data": data}`. When successful, the data field contains the job statistics by cloud. When unsuccessful, the message field contains the error message.
|
|
42
|
+
"""
|
|
43
|
+
tmp_logger = LogWrapper(_logger, f"job_stats_by_cloud < type={type} >")
|
|
44
|
+
|
|
45
|
+
tmp_logger.debug("Start")
|
|
46
|
+
|
|
47
|
+
if type not in ["production", "analysis"]:
|
|
48
|
+
tmp_logger.error("Invalid type parameter")
|
|
49
|
+
return generate_response(False, 'Parameter "type" needs to be either "production" or "analysis" ', {})
|
|
50
|
+
|
|
51
|
+
data = global_task_buffer.getJobStatisticsForExtIF(type)
|
|
52
|
+
success = data != {}
|
|
53
|
+
message = "" if success else "Database failure getting the job statistics"
|
|
54
|
+
tmp_logger.debug(f"Done. {message}")
|
|
55
|
+
|
|
56
|
+
return generate_response(success, message, data)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@request_validation(_logger, secure=False, request_method="GET")
|
|
60
|
+
def production_job_stats_by_cloud_and_processing_type(req: PandaRequest) -> Dict[str, Any]:
|
|
61
|
+
"""
|
|
62
|
+
Production job statistics by cloud and processing type.
|
|
63
|
+
|
|
64
|
+
Get the production job statistics by cloud and processing type, which includes the active jobs and jobs in final states modified in the last 12 hours. Used by panglia monitoring. Requires a secure connection.
|
|
65
|
+
|
|
66
|
+
API details:
|
|
67
|
+
HTTP Method: GET
|
|
68
|
+
Path: /v1/statistics/production_job_stats_by_cloud_and_processing_type
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
req(PandaRequest): internally generated request object
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
dict: The system response `{"success": success, "message": message, "data": data}`. When successful, the data field contains the job statistics by cloud. When unsuccessful, the message field contains the error message.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
tmp_logger = LogWrapper(_logger, "production_job_stats_by_cloud_and_processing_type")
|
|
78
|
+
|
|
79
|
+
tmp_logger.debug("Start")
|
|
80
|
+
data = global_task_buffer.getJobStatisticsForBamboo()
|
|
81
|
+
success = data != {}
|
|
82
|
+
message = "" if success else "Database failure getting the job statistics"
|
|
83
|
+
tmp_logger.debug(f"Done. {message}")
|
|
84
|
+
|
|
85
|
+
return generate_response(success, message, data)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@request_validation(_logger, secure=False, request_method="GET")
|
|
89
|
+
def active_job_stats_by_site(req: PandaRequest) -> Dict[str, Any]:
|
|
90
|
+
"""
|
|
91
|
+
Active job statistics by site
|
|
92
|
+
|
|
93
|
+
Get the active (not in a final state) job statistics by site. Used by Harvester. Requires a secure connection.
|
|
94
|
+
|
|
95
|
+
API details:
|
|
96
|
+
HTTP Method: GET
|
|
97
|
+
Path: /v1/statistics/active_job_stats_by_site
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
req(PandaRequest): internally generated request object
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
dict: The system response `{"success": success, "message": message, "data": data}`. When successful, the data field contains the job statistics by cloud. When unsuccessful, the message field contains the error message.
|
|
104
|
+
"""
|
|
105
|
+
tmp_logger = LogWrapper(_logger, "active_job_stats_by_site")
|
|
106
|
+
|
|
107
|
+
tmp_logger.debug("Start")
|
|
108
|
+
data = global_task_buffer.getJobStatistics()
|
|
109
|
+
success = data != {}
|
|
110
|
+
message = "" if success else "Database failure getting the job statistics"
|
|
111
|
+
tmp_logger.debug(f"Done. {message}")
|
|
112
|
+
|
|
113
|
+
return generate_response(success, message, data)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@request_validation(_logger, secure=False, request_method="GET")
|
|
117
|
+
def active_job_detailed_stats_by_site(req: PandaRequest) -> Dict[str, Any]:
|
|
118
|
+
"""
|
|
119
|
+
Active job detailed statistics by site, resource_type and prodsourcelabel
|
|
120
|
+
|
|
121
|
+
Get the active (not in a final state) job statistics by site, resource_type and prodsourcelabel. Used by Harvester.
|
|
122
|
+
|
|
123
|
+
API details:
|
|
124
|
+
HTTP Method: GET
|
|
125
|
+
Path: /v1/statistics/active_job_detailed_stats_by_site
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
req(PandaRequest): internally generated request object
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
dict: The system response `{"success": success, "message": message, "data": data}`. When successful, the data field contains the job statistics by site, resource_type and prodsourcelabel. When unsuccessful, the message field contains the error message.
|
|
132
|
+
"""
|
|
133
|
+
tmp_logger = LogWrapper(_logger, "active_job_detailed_stats_by_site")
|
|
134
|
+
|
|
135
|
+
tmp_logger.debug("Start")
|
|
136
|
+
data = global_task_buffer.getDetailedJobStatistics()
|
|
137
|
+
success = data != {}
|
|
138
|
+
message = "" if success else "Database failure getting the job statistics with resource_type and prodsourcelabel"
|
|
139
|
+
tmp_logger.debug(f"Done. {message}")
|
|
140
|
+
|
|
141
|
+
return generate_response(success, message, data)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@request_validation(_logger, secure=False, request_method="GET")
|
|
145
|
+
def job_stats_by_site_and_resource_type(req: PandaRequest, time_window: int = None) -> Dict[str, Any]:
|
|
146
|
+
"""
|
|
147
|
+
Job statistics by site and resource type
|
|
148
|
+
|
|
149
|
+
Get the job statistics by computing site (PanDA queue) and resource type (SCORE, MCORE, ...). This includes the active jobs and jobs in final states modified in the specified time window (default of 12 hours). Requires a secure connection.
|
|
150
|
+
|
|
151
|
+
API details:
|
|
152
|
+
HTTP Method: GET
|
|
153
|
+
Path: /v1/statistics/job_stats_by_site_and_resource_type
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
req(PandaRequest): internally generated request object
|
|
157
|
+
time_window(int, optional): time window in minutes for the statistics (affects only archived jobs)
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
dict: The system response `{"success": success, "message": message, "data": data}`. When successful, the data field contains the job statistics by cloud. When unsuccessful, the message field contains the error message.
|
|
161
|
+
"""
|
|
162
|
+
tmp_logger = LogWrapper(_logger, f"job_stats_by_site_and_resource_type < time_window={time_window} >")
|
|
163
|
+
|
|
164
|
+
tmp_logger.debug("Start")
|
|
165
|
+
if time_window is not None and (not isinstance(time_window, int) or time_window < 0 or time_window > MAX_TIME_WINDOW):
|
|
166
|
+
tmp_logger.error("Invalid time_window parameter")
|
|
167
|
+
return generate_response(False, 'Parameter "time_window" needs to be a positive integer smaller than 10080 min (7 days)', {})
|
|
168
|
+
|
|
169
|
+
data = global_task_buffer.getJobStatisticsPerSiteResource(time_window)
|
|
170
|
+
success = data != {}
|
|
171
|
+
message = "" if success else "Database failure getting the job statistics"
|
|
172
|
+
tmp_logger.debug(f"Done. {message}")
|
|
173
|
+
|
|
174
|
+
return generate_response(success, message, data)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@request_validation(_logger, secure=False, request_method="GET")
|
|
178
|
+
def job_stats_by_site_share_and_resource_type(req: PandaRequest, time_window: int = None) -> Dict[str, Any]:
|
|
179
|
+
"""
|
|
180
|
+
Job statistics by site, global share and resource type
|
|
181
|
+
|
|
182
|
+
Get the job statistics by computing site (PanDA queue), global share and resource type (SCORE, MCORE, ...). This includes the active jobs and jobs in final states modified in the specified time window (default of 12 hours). Requires a secure connection.
|
|
183
|
+
|
|
184
|
+
API details:
|
|
185
|
+
HTTP Method: GET
|
|
186
|
+
Path: /v1/statistics/job_stats_by_site_share_and_resource_type
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
req(PandaRequest): internally generated request object
|
|
190
|
+
time_window(int): time window in minutes for the statistics (affects only archived jobs)
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
dict: The system response `{"success": success, "message": message, "data": data}`. When successful, the data field contains the job statistics by cloud. When unsuccessful, the message field contains the error message.
|
|
194
|
+
"""
|
|
195
|
+
tmp_logger = LogWrapper(_logger, f"job_stats_by_site_share_and_resource_type < time_window={time_window} >")
|
|
196
|
+
|
|
197
|
+
tmp_logger.debug("Start")
|
|
198
|
+
if time_window is not None and (not isinstance(time_window, int) or time_window < 0 or time_window > MAX_TIME_WINDOW):
|
|
199
|
+
tmp_logger.error("Invalid time_window parameter")
|
|
200
|
+
return generate_response(False, 'Parameter "time_window" needs to be a positive integer smaller than 10080 min (7 days)', {})
|
|
201
|
+
|
|
202
|
+
data = global_task_buffer.get_job_statistics_per_site_label_resource(time_window)
|
|
203
|
+
success = data != {}
|
|
204
|
+
message = "" if success else "Database failure getting the job statistics"
|
|
205
|
+
tmp_logger.debug(f"Done. {message}")
|
|
206
|
+
|
|
207
|
+
return generate_response(success, message, data)
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
from typing import Dict
|
|
2
|
+
|
|
3
|
+
from pandacommon.pandalogger.LogWrapper import LogWrapper
|
|
4
|
+
from pandacommon.pandalogger.PandaLogger import PandaLogger
|
|
5
|
+
|
|
6
|
+
from pandaserver.api.v1.common import (
|
|
7
|
+
extract_primary_production_working_group,
|
|
8
|
+
extract_production_working_groups,
|
|
9
|
+
generate_response,
|
|
10
|
+
get_dn,
|
|
11
|
+
get_email_address,
|
|
12
|
+
get_fqan,
|
|
13
|
+
has_production_role,
|
|
14
|
+
request_validation,
|
|
15
|
+
)
|
|
16
|
+
from pandaserver.config import panda_config
|
|
17
|
+
from pandaserver.srvcore.CoreUtils import clean_user_id
|
|
18
|
+
from pandaserver.srvcore.panda_request import PandaRequest
|
|
19
|
+
|
|
20
|
+
_logger = PandaLogger().getLogger("api_system")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@request_validation(_logger, secure=True, request_method="GET")
|
|
24
|
+
def get_attributes(req: PandaRequest, **kwargs: dict) -> Dict:
|
|
25
|
+
"""
|
|
26
|
+
Get attributes
|
|
27
|
+
|
|
28
|
+
Gets all parameters and environment variables.
|
|
29
|
+
|
|
30
|
+
API details:
|
|
31
|
+
HTTP Method: GET
|
|
32
|
+
Path: /v1/system/get_attributes
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
req(PandaRequest): internally generated request object containing the env variables
|
|
36
|
+
**kwargs(dict): arbitrary keyword parameters that will be printed out
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
dict: The system response `{"success": success, "message": message, "data": data}`.
|
|
40
|
+
When successful, the message field contains a string with all the attributes.
|
|
41
|
+
"""
|
|
42
|
+
tmp_logger = LogWrapper(_logger, "get_attributes")
|
|
43
|
+
tmp_logger.debug("Start")
|
|
44
|
+
|
|
45
|
+
# Add the parameters
|
|
46
|
+
parameter_dictionary = {key: str(value) for key, value in sorted(kwargs.items())}
|
|
47
|
+
parameter_section = "===== param =====\n" + "\n".join(f"{key} = {value}" for key, value in parameter_dictionary.items())
|
|
48
|
+
|
|
49
|
+
# Add the environment variables
|
|
50
|
+
environment_dictionary = {key: str(req.subprocess_env[key]) for key in sorted(req.subprocess_env)}
|
|
51
|
+
environment_section = "\n====== env ======\n" + "\n".join(f"{key} : {value}" for key, value in environment_dictionary.items())
|
|
52
|
+
|
|
53
|
+
# Combine sections
|
|
54
|
+
text_representation = parameter_section + "\n" + environment_section + "\n"
|
|
55
|
+
|
|
56
|
+
# Combine data in dictionary form
|
|
57
|
+
combined_data = {"parameters": parameter_dictionary, "environment": environment_dictionary}
|
|
58
|
+
tmp_logger.debug("Done")
|
|
59
|
+
return generate_response(True, text_representation, combined_data)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@request_validation(_logger, secure=True, request_method="GET")
|
|
63
|
+
def get_voms_attributes(req: PandaRequest) -> Dict:
|
|
64
|
+
"""
|
|
65
|
+
Get VOMS attributes
|
|
66
|
+
|
|
67
|
+
Gets the VOMS attributes (i.e. the ones starting with GRST) in sorted order. Requires a secure connection.
|
|
68
|
+
|
|
69
|
+
API details:
|
|
70
|
+
HTTP Method: GET
|
|
71
|
+
Path: /v1/system/get_voms_attributes
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
req(PandaRequest): internally generated request object containing the env variables
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
dict: The system response with text representation and dictionary of attributes.
|
|
78
|
+
Example: `{"success": True, "message": "<formatted string>", "data": {"key": "value"}}`
|
|
79
|
+
"""
|
|
80
|
+
tmp_logger = LogWrapper(_logger, "get_voms_attributes")
|
|
81
|
+
tmp_logger.debug("Start")
|
|
82
|
+
|
|
83
|
+
# Iterate over all the environment variables, keep only the ones related to GRST credentials (GRST: Grid Security Technology)
|
|
84
|
+
attributes = {}
|
|
85
|
+
for tmp_key, tmp_value in req.subprocess_env.items():
|
|
86
|
+
if tmp_key.startswith("GRST_CRED_"):
|
|
87
|
+
attributes[tmp_key] = tmp_value
|
|
88
|
+
|
|
89
|
+
# Create a sorted text representation
|
|
90
|
+
text_representation = "\n".join(f"{key} : {value}" for key, value in sorted(attributes.items()))
|
|
91
|
+
|
|
92
|
+
tmp_logger.debug("Done")
|
|
93
|
+
return generate_response(True, text_representation, attributes)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@request_validation(_logger, secure=True, request_method="GET")
|
|
97
|
+
def get_user_attributes(req: PandaRequest) -> Dict:
|
|
98
|
+
"""
|
|
99
|
+
Get user attributes
|
|
100
|
+
|
|
101
|
+
Gets user attributes as seen by PanDA for debug purposes. Requires a secure connection.
|
|
102
|
+
|
|
103
|
+
API details:
|
|
104
|
+
HTTP Method: GET
|
|
105
|
+
Path: /v1/system/get_user_attributes
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
req(PandaRequest): internally generated request object containing the env variables
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
dict: The system response `{"success": success, "message": message, "data": data}`.
|
|
112
|
+
When successful, the message field contains a string with the user attributes,
|
|
113
|
+
and the data field contains the dictionary representation.
|
|
114
|
+
"""
|
|
115
|
+
tmp_logger = LogWrapper(_logger, "get_user_attributes")
|
|
116
|
+
tmp_logger.debug("Start")
|
|
117
|
+
|
|
118
|
+
# Raw user DN
|
|
119
|
+
user_raw = req.subprocess_env["SSL_CLIENT_S_DN"]
|
|
120
|
+
|
|
121
|
+
# Bare user DN
|
|
122
|
+
user_bare = get_dn(req)
|
|
123
|
+
|
|
124
|
+
# Clean user DN
|
|
125
|
+
user_clean = clean_user_id(user_raw)
|
|
126
|
+
|
|
127
|
+
# FQANs
|
|
128
|
+
fqans = get_fqan(req)
|
|
129
|
+
|
|
130
|
+
# Email address
|
|
131
|
+
email_address = get_email_address(user_clean, tmp_logger)
|
|
132
|
+
|
|
133
|
+
# Has production role
|
|
134
|
+
is_production_user = has_production_role(req)
|
|
135
|
+
|
|
136
|
+
# Production working groups
|
|
137
|
+
production_working_groups = extract_production_working_groups(fqans)
|
|
138
|
+
|
|
139
|
+
# Primary production working group
|
|
140
|
+
primary_working_group = extract_primary_production_working_group(fqans)
|
|
141
|
+
|
|
142
|
+
# Combine sections
|
|
143
|
+
text_representation = (
|
|
144
|
+
f"User DN (raw): {user_raw}\nUser DN (bare): {user_bare}\nUser DN (clean): {user_clean}\n"
|
|
145
|
+
f"Email address: {email_address}\n"
|
|
146
|
+
f"FQANs: {fqans}\nProduction user: {is_production_user}\n"
|
|
147
|
+
f"Production working groups: {production_working_groups}\nPrimary production working group: {primary_working_group}\n"
|
|
148
|
+
)
|
|
149
|
+
dictionary_representation = {
|
|
150
|
+
"user_dn_raw": user_raw,
|
|
151
|
+
"user_dn_clean": user_clean,
|
|
152
|
+
"fqans": fqans,
|
|
153
|
+
"is_production_user": is_production_user,
|
|
154
|
+
"production_working_groups": production_working_groups,
|
|
155
|
+
"primary_working_group": primary_working_group,
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
tmp_logger.debug(text_representation)
|
|
159
|
+
|
|
160
|
+
tmp_logger.debug("Done")
|
|
161
|
+
return generate_response(True, text_representation, dictionary_representation)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@request_validation(_logger, secure=False, request_method="GET")
|
|
165
|
+
def is_alive(req: PandaRequest) -> Dict:
|
|
166
|
+
"""
|
|
167
|
+
Is alive
|
|
168
|
+
|
|
169
|
+
Check if the server is alive. Basic function for the health check used in SLS monitoring.
|
|
170
|
+
|
|
171
|
+
API details:
|
|
172
|
+
HTTP Method: GET
|
|
173
|
+
Path: /v1/system/is_alive
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
req(PandaRequest): internally generated request object containing the env variables
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
dict: The system response with the name of the endpoint
|
|
180
|
+
Example: `{"success": True}`
|
|
181
|
+
"""
|
|
182
|
+
tmp_logger = LogWrapper(_logger, "is_alive")
|
|
183
|
+
tmp_logger.debug("Start")
|
|
184
|
+
tmp_logger.debug("Done")
|
|
185
|
+
|
|
186
|
+
return generate_response(True)
|