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,221 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import glob
|
|
3
|
+
import os
|
|
4
|
+
import re
|
|
5
|
+
import sys
|
|
6
|
+
import threading
|
|
7
|
+
import time
|
|
8
|
+
import traceback
|
|
9
|
+
|
|
10
|
+
from pandacommon.pandalogger.LogWrapper import LogWrapper
|
|
11
|
+
from pandacommon.pandalogger.PandaLogger import PandaLogger
|
|
12
|
+
from pandacommon.pandautils.PandaUtils import naive_utcnow
|
|
13
|
+
from pandacommon.pandautils.thread_utils import GenericThread
|
|
14
|
+
|
|
15
|
+
import pandaserver.taskbuffer.ErrorCode
|
|
16
|
+
import pandaserver.userinterface.Client as Client
|
|
17
|
+
from pandaserver.brokerage.SiteMapper import SiteMapper
|
|
18
|
+
from pandaserver.config import panda_config
|
|
19
|
+
from pandaserver.srvcore.CoreUtils import commands_get_status_output
|
|
20
|
+
|
|
21
|
+
# logger
|
|
22
|
+
_logger = PandaLogger().getLogger("add_sub")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# main
|
|
26
|
+
def main(argv=tuple(), tbuf=None, **kwargs):
|
|
27
|
+
tmp_log = LogWrapper(_logger, None)
|
|
28
|
+
requester_id = GenericThread().get_full_id(__name__, sys.modules[__name__].__file__)
|
|
29
|
+
|
|
30
|
+
tmp_log.debug("===================== start =====================")
|
|
31
|
+
|
|
32
|
+
# current minute
|
|
33
|
+
current_minute = naive_utcnow().minute
|
|
34
|
+
|
|
35
|
+
# instantiate TB
|
|
36
|
+
if tbuf is None:
|
|
37
|
+
from pandaserver.taskbuffer.TaskBuffer import taskBuffer
|
|
38
|
+
|
|
39
|
+
taskBuffer.init(
|
|
40
|
+
panda_config.dbhost,
|
|
41
|
+
panda_config.dbpasswd,
|
|
42
|
+
nDBConnection=1,
|
|
43
|
+
useTimeout=True,
|
|
44
|
+
requester=requester_id,
|
|
45
|
+
)
|
|
46
|
+
else:
|
|
47
|
+
taskBuffer = tbuf
|
|
48
|
+
|
|
49
|
+
# instantiate sitemapper
|
|
50
|
+
aSiteMapper = SiteMapper(taskBuffer)
|
|
51
|
+
|
|
52
|
+
# count # of getJob/updateJob in dispatcher's log
|
|
53
|
+
try:
|
|
54
|
+
# don't update when logrotate is running
|
|
55
|
+
timeNow = naive_utcnow()
|
|
56
|
+
logRotateTime = timeNow.replace(hour=3, minute=2, second=0, microsecond=0)
|
|
57
|
+
if (timeNow > logRotateTime and (timeNow - logRotateTime) < datetime.timedelta(minutes=5)) or (
|
|
58
|
+
logRotateTime > timeNow and (logRotateTime - timeNow) < datetime.timedelta(minutes=5)
|
|
59
|
+
):
|
|
60
|
+
tmp_log.debug("skip pilotCounts session for logrotate")
|
|
61
|
+
else:
|
|
62
|
+
# log filename
|
|
63
|
+
dispLogName = f"{panda_config.logdir}/panda-PilotRequests.log"
|
|
64
|
+
# time limit
|
|
65
|
+
timeLimit = naive_utcnow() - datetime.timedelta(hours=3)
|
|
66
|
+
timeLimitS = naive_utcnow() - datetime.timedelta(hours=1)
|
|
67
|
+
# check if tgz is required
|
|
68
|
+
com = f"head -1 {dispLogName}"
|
|
69
|
+
lostat, loout = commands_get_status_output(com)
|
|
70
|
+
useLogTgz = True
|
|
71
|
+
if lostat == 0:
|
|
72
|
+
match = re.search("^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}", loout)
|
|
73
|
+
if match is not None:
|
|
74
|
+
startTime = datetime.datetime(*time.strptime(match.group(0), "%Y-%m-%d %H:%M:%S")[:6])
|
|
75
|
+
# current log contains all info
|
|
76
|
+
if startTime < timeLimit:
|
|
77
|
+
useLogTgz = False
|
|
78
|
+
# log files
|
|
79
|
+
dispLogNameList = [dispLogName]
|
|
80
|
+
if useLogTgz:
|
|
81
|
+
today = datetime.date.today()
|
|
82
|
+
dispLogNameList.append(f"{dispLogName}-{today.strftime('%Y%m%d')}.gz")
|
|
83
|
+
# delete tmp
|
|
84
|
+
commands_get_status_output(f"rm -f {dispLogName}.tmp-*")
|
|
85
|
+
# tmp name
|
|
86
|
+
tmp_logName = f"{dispLogName}.tmp-{naive_utcnow().strftime('%Y-%m-%d-%H-%M-%S')}"
|
|
87
|
+
# loop over all files
|
|
88
|
+
pilotCounts = {}
|
|
89
|
+
pilotCountsS = {}
|
|
90
|
+
for tmpDispLogName in dispLogNameList:
|
|
91
|
+
# expand or copy
|
|
92
|
+
if tmpDispLogName.endswith(".gz"):
|
|
93
|
+
com = f"gunzip -c {tmpDispLogName} > {tmp_logName}"
|
|
94
|
+
else:
|
|
95
|
+
com = f"cp {tmpDispLogName} {tmp_logName}"
|
|
96
|
+
lostat, loout = commands_get_status_output(com)
|
|
97
|
+
if lostat != 0:
|
|
98
|
+
errMsg = f"failed to expand/copy {tmpDispLogName} with : {loout}"
|
|
99
|
+
raise RuntimeError(errMsg)
|
|
100
|
+
# search string
|
|
101
|
+
sStr = "^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}).*"
|
|
102
|
+
sStr += "method=(.+),site=(.+),node=(.+),type=(.+)"
|
|
103
|
+
# read
|
|
104
|
+
logFH = open(tmp_logName)
|
|
105
|
+
for line in logFH:
|
|
106
|
+
# check format
|
|
107
|
+
match = re.search(sStr, line)
|
|
108
|
+
if match is not None:
|
|
109
|
+
# check timerange
|
|
110
|
+
timeStamp = datetime.datetime(*time.strptime(match.group(1), "%Y-%m-%d %H:%M:%S")[:6])
|
|
111
|
+
if timeStamp < timeLimit:
|
|
112
|
+
continue
|
|
113
|
+
tmpMethod = match.group(2)
|
|
114
|
+
tmpSite = match.group(3)
|
|
115
|
+
tmpNode = match.group(4)
|
|
116
|
+
|
|
117
|
+
# protection against corrupted entries from pilot,
|
|
118
|
+
# e.g. pilot reading site json from cvmfs while it was being updated
|
|
119
|
+
if tmpSite not in aSiteMapper.siteSpecList:
|
|
120
|
+
continue
|
|
121
|
+
# sum
|
|
122
|
+
pilotCounts.setdefault(tmpSite, {})
|
|
123
|
+
pilotCounts[tmpSite].setdefault(tmpMethod, {})
|
|
124
|
+
pilotCounts[tmpSite][tmpMethod].setdefault(tmpNode, 0)
|
|
125
|
+
pilotCounts[tmpSite][tmpMethod][tmpNode] += 1
|
|
126
|
+
# short
|
|
127
|
+
if timeStamp > timeLimitS:
|
|
128
|
+
if tmpSite not in pilotCountsS:
|
|
129
|
+
pilotCountsS[tmpSite] = dict()
|
|
130
|
+
if tmpMethod not in pilotCountsS[tmpSite]:
|
|
131
|
+
pilotCountsS[tmpSite][tmpMethod] = dict()
|
|
132
|
+
if tmpNode not in pilotCountsS[tmpSite][tmpMethod]:
|
|
133
|
+
pilotCountsS[tmpSite][tmpMethod][tmpNode] = 0
|
|
134
|
+
pilotCountsS[tmpSite][tmpMethod][tmpNode] += 1
|
|
135
|
+
# close
|
|
136
|
+
logFH.close()
|
|
137
|
+
# delete tmp
|
|
138
|
+
commands_get_status_output(f"rm {tmp_logName}")
|
|
139
|
+
# update
|
|
140
|
+
hostID = panda_config.pserverhost.split(".")[0]
|
|
141
|
+
tmp_log.debug("pilotCounts session")
|
|
142
|
+
retPC = taskBuffer.updateSiteData(hostID, pilotCounts, interval=3)
|
|
143
|
+
tmp_log.debug(retPC)
|
|
144
|
+
retPC = taskBuffer.updateSiteData(hostID, pilotCountsS, interval=1)
|
|
145
|
+
tmp_log.debug(retPC)
|
|
146
|
+
except Exception:
|
|
147
|
+
errType, errValue = sys.exc_info()[:2]
|
|
148
|
+
tmp_log.error(f"updateJob/getJob : {errType} {errValue}")
|
|
149
|
+
|
|
150
|
+
# nRunning
|
|
151
|
+
tmp_log.debug("nRunning session")
|
|
152
|
+
try:
|
|
153
|
+
if (current_minute / panda_config.nrun_interval) % panda_config.nrun_hosts == panda_config.nrun_snum:
|
|
154
|
+
retNR = taskBuffer.insertnRunningInSiteData()
|
|
155
|
+
tmp_log.debug(retNR)
|
|
156
|
+
except Exception:
|
|
157
|
+
errType, errValue = sys.exc_info()[:2]
|
|
158
|
+
tmp_log.error(f"nRunning : {errType} {errValue}")
|
|
159
|
+
|
|
160
|
+
# session for co-jumbo jobs
|
|
161
|
+
tmp_log.debug("co-jumbo session")
|
|
162
|
+
try:
|
|
163
|
+
ret = taskBuffer.getCoJumboJobsToBeFinished(30, 0, 1000)
|
|
164
|
+
if ret is None:
|
|
165
|
+
tmp_log.debug("failed to get co-jumbo jobs to finish")
|
|
166
|
+
else:
|
|
167
|
+
coJumboA, coJumboD, coJumboTokill = ret
|
|
168
|
+
tmp_log.debug(f"finish {len(coJumboA)} co-jumbo jobs in Active")
|
|
169
|
+
if len(coJumboA) > 0:
|
|
170
|
+
jobSpecs = taskBuffer.peekJobs(
|
|
171
|
+
coJumboA,
|
|
172
|
+
fromDefined=False,
|
|
173
|
+
fromActive=True,
|
|
174
|
+
fromArchived=False,
|
|
175
|
+
fromWaiting=False,
|
|
176
|
+
)
|
|
177
|
+
for jobSpec in jobSpecs:
|
|
178
|
+
fileCheckInJEDI = taskBuffer.checkInputFileStatusInJEDI(jobSpec)
|
|
179
|
+
if not fileCheckInJEDI:
|
|
180
|
+
jobSpec.jobStatus = "closed"
|
|
181
|
+
jobSpec.jobSubStatus = "cojumbo_wrong"
|
|
182
|
+
jobSpec.taskBufferErrorCode = pandaserver.taskbuffer.ErrorCode.EC_EventServiceInconsistentIn
|
|
183
|
+
taskBuffer.archiveJobs([jobSpec], False)
|
|
184
|
+
tmp_log.debug(f"finish {len(coJumboD)} co-jumbo jobs in Defined")
|
|
185
|
+
if len(coJumboD) > 0:
|
|
186
|
+
jobSpecs = taskBuffer.peekJobs(
|
|
187
|
+
coJumboD,
|
|
188
|
+
fromDefined=True,
|
|
189
|
+
fromActive=False,
|
|
190
|
+
fromArchived=False,
|
|
191
|
+
fromWaiting=False,
|
|
192
|
+
)
|
|
193
|
+
for jobSpec in jobSpecs:
|
|
194
|
+
fileCheckInJEDI = taskBuffer.checkInputFileStatusInJEDI(jobSpec)
|
|
195
|
+
if not fileCheckInJEDI:
|
|
196
|
+
jobSpec.jobStatus = "closed"
|
|
197
|
+
jobSpec.jobSubStatus = "cojumbo_wrong"
|
|
198
|
+
jobSpec.taskBufferErrorCode = pandaserver.taskbuffer.ErrorCode.EC_EventServiceInconsistentIn
|
|
199
|
+
taskBuffer.archiveJobs([jobSpec], True)
|
|
200
|
+
if len(coJumboTokill) > 0:
|
|
201
|
+
jediJobs = list(coJumboTokill)
|
|
202
|
+
nJob = 100
|
|
203
|
+
iJob = 0
|
|
204
|
+
while iJob < len(jediJobs):
|
|
205
|
+
tmp_log.debug(f" killing {str(jediJobs[iJob:iJob + nJob])}")
|
|
206
|
+
Client.kill_jobs(jediJobs[iJob : iJob + nJob], 51, keepUnmerged=True)
|
|
207
|
+
iJob += nJob
|
|
208
|
+
except Exception:
|
|
209
|
+
errStr = traceback.format_exc()
|
|
210
|
+
tmp_log.error(errStr)
|
|
211
|
+
|
|
212
|
+
# stop taskBuffer if created inside this script
|
|
213
|
+
if tbuf is None:
|
|
214
|
+
taskBuffer.cleanup(requester=requester_id)
|
|
215
|
+
|
|
216
|
+
tmp_log.debug("===================== end =====================")
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
# run
|
|
220
|
+
if __name__ == "__main__":
|
|
221
|
+
main(argv=sys.argv)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import traceback
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from pandacommon.pandalogger.PandaLogger import PandaLogger
|
|
7
|
+
|
|
8
|
+
from pandaserver.config import panda_config
|
|
9
|
+
|
|
10
|
+
# logger
|
|
11
|
+
_logger = PandaLogger().getLogger("cache_pilot_config")
|
|
12
|
+
|
|
13
|
+
# list of source files to be copied
|
|
14
|
+
source_file_list = [
|
|
15
|
+
"/cvmfs/atlas.cern.ch/repo/sw/PandaPilot/tar/pilot2.tar.gz",
|
|
16
|
+
"/cvmfs/atlas.cern.ch/repo/sw/PandaPilot/tar/pilot3.tar.gz",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
# default destination directory
|
|
20
|
+
default_dest_dir = getattr(panda_config, "pilot_cache_dir", "/var/cache/pandaserver/pilot")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def main(argv=tuple(), tbuf=None, **kwargs):
|
|
24
|
+
_logger.debug("start")
|
|
25
|
+
try:
|
|
26
|
+
# ensure the destination directory
|
|
27
|
+
dest_dir_path = Path(default_dest_dir)
|
|
28
|
+
try:
|
|
29
|
+
dest_dir_path.mkdir(mode=0o755, exist_ok=True)
|
|
30
|
+
except Exception as e:
|
|
31
|
+
_logger.error(f"failed to mkdir {dest_dir_path}: {e}")
|
|
32
|
+
# copy
|
|
33
|
+
for source_file in source_file_list:
|
|
34
|
+
if not os.path.exists(source_file):
|
|
35
|
+
_logger.warning(f"source file {source_file} does not exist, skipped")
|
|
36
|
+
continue
|
|
37
|
+
dest_file_path = shutil.copy(source_file, dest_dir_path)
|
|
38
|
+
_logger.debug(f"copied {source_file} to {dest_file_path}")
|
|
39
|
+
except Exception as e:
|
|
40
|
+
err_str = traceback.format_exc()
|
|
41
|
+
_logger.error(f"failed to copy files: {err_str}")
|
|
42
|
+
# done
|
|
43
|
+
_logger.debug("done")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
if __name__ == "__main__":
|
|
47
|
+
main()
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
#! /usr/bin/env python
|
|
2
|
+
#
|
|
3
|
+
# Dump schedconfig on a per-queue basis into cache files
|
|
4
|
+
#
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import os
|
|
9
|
+
import shutil
|
|
10
|
+
import sys
|
|
11
|
+
import traceback
|
|
12
|
+
from argparse import ArgumentParser
|
|
13
|
+
from copy import deepcopy
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
from pandacommon.pandalogger.PandaLogger import PandaLogger
|
|
17
|
+
from pandacommon.pandautils.thread_utils import GenericThread
|
|
18
|
+
|
|
19
|
+
from pandaserver.config import panda_config
|
|
20
|
+
|
|
21
|
+
# logger
|
|
22
|
+
_logger = PandaLogger().getLogger("cache_schedconfig")
|
|
23
|
+
|
|
24
|
+
# default destination directory
|
|
25
|
+
default_dest_dir = getattr(panda_config, "schedconfig_cache_dir", "/var/cache/pandaserver/schedconfig")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class cacheSchedConfig:
|
|
29
|
+
"""
|
|
30
|
+
Class to dump schedconfig on a per-queue basis into cache files
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, tbuf):
|
|
34
|
+
self.tbuf = tbuf
|
|
35
|
+
self.queueData = None
|
|
36
|
+
self.cloudStatus = None
|
|
37
|
+
# Define this here, but could be more flexible...
|
|
38
|
+
self.queueDataFields = {
|
|
39
|
+
# Note that json dumps always use sort_keys=True; for pilot format
|
|
40
|
+
# the order defined here is respected
|
|
41
|
+
"pilot": [
|
|
42
|
+
"appdir",
|
|
43
|
+
"allowdirectaccess",
|
|
44
|
+
"cloud",
|
|
45
|
+
"datadir",
|
|
46
|
+
"dq2url",
|
|
47
|
+
"copytool",
|
|
48
|
+
"copytoolin",
|
|
49
|
+
"copysetup",
|
|
50
|
+
"copysetupin",
|
|
51
|
+
"ddm",
|
|
52
|
+
"se",
|
|
53
|
+
"sepath",
|
|
54
|
+
"seprodpath",
|
|
55
|
+
"envsetup",
|
|
56
|
+
"envsetupin",
|
|
57
|
+
"region",
|
|
58
|
+
"copyprefix",
|
|
59
|
+
"copyprefixin",
|
|
60
|
+
"lfcpath",
|
|
61
|
+
"lfcprodpath",
|
|
62
|
+
"lfchost",
|
|
63
|
+
"lfcregister",
|
|
64
|
+
"sein",
|
|
65
|
+
"wntmpdir",
|
|
66
|
+
"proxy",
|
|
67
|
+
"retry",
|
|
68
|
+
"recoverdir",
|
|
69
|
+
"space",
|
|
70
|
+
"memory",
|
|
71
|
+
"cmtconfig",
|
|
72
|
+
"status",
|
|
73
|
+
"setokens",
|
|
74
|
+
"glexec",
|
|
75
|
+
"seopt",
|
|
76
|
+
"gatekeeper",
|
|
77
|
+
"pcache",
|
|
78
|
+
"maxinputsize",
|
|
79
|
+
"timefloor",
|
|
80
|
+
"corecount",
|
|
81
|
+
"faxredirector",
|
|
82
|
+
"allowfax",
|
|
83
|
+
"maxtime",
|
|
84
|
+
"maxwdir",
|
|
85
|
+
],
|
|
86
|
+
"factory": [
|
|
87
|
+
"site",
|
|
88
|
+
"siteid",
|
|
89
|
+
"nickname",
|
|
90
|
+
"cloud",
|
|
91
|
+
"status",
|
|
92
|
+
"jdl",
|
|
93
|
+
"queue",
|
|
94
|
+
"localqueue",
|
|
95
|
+
"nqueue",
|
|
96
|
+
"environ",
|
|
97
|
+
"proxy",
|
|
98
|
+
"glexec",
|
|
99
|
+
"depthboost",
|
|
100
|
+
"idlepilotsupression",
|
|
101
|
+
"pilotlimit",
|
|
102
|
+
"transferringlimit",
|
|
103
|
+
"memory",
|
|
104
|
+
"maxtime",
|
|
105
|
+
"system",
|
|
106
|
+
"fairsharepolicy",
|
|
107
|
+
"autosetup_pre",
|
|
108
|
+
"autosetup_post",
|
|
109
|
+
],
|
|
110
|
+
# None is magic here and really means "all"
|
|
111
|
+
"all": None,
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
def query_column_sql(self, sql, varMap=None, arraySize=100):
|
|
115
|
+
res = self.tbuf.querySQL(sql, varMap, arraySize=arraySize)
|
|
116
|
+
retList = []
|
|
117
|
+
for (
|
|
118
|
+
panda_queue,
|
|
119
|
+
data,
|
|
120
|
+
) in res:
|
|
121
|
+
if isinstance(data, str):
|
|
122
|
+
dictData = json.loads(data)
|
|
123
|
+
elif isinstance(data, dict):
|
|
124
|
+
dictData = data
|
|
125
|
+
else:
|
|
126
|
+
dictData = json.loads(data.read())
|
|
127
|
+
dictData["siteid"] = panda_queue
|
|
128
|
+
retList.append(dictData)
|
|
129
|
+
return retList
|
|
130
|
+
|
|
131
|
+
def getQueueData(self, site=None, queue=None):
|
|
132
|
+
# Dump schedconfig in a single query (it's not very big)
|
|
133
|
+
varDict = {}
|
|
134
|
+
sql = f"SELECT panda_queue, data from {panda_config.schemaPANDA}.SCHEDCONFIG_JSON"
|
|
135
|
+
if site:
|
|
136
|
+
sql += " where panda_queue=:site"
|
|
137
|
+
varDict[":site"] = site
|
|
138
|
+
self.queueData = self.query_column_sql(sql, varDict)
|
|
139
|
+
elif queue:
|
|
140
|
+
sql += " where panda_queue=:queue"
|
|
141
|
+
varDict[":queue"] = queue
|
|
142
|
+
self.queueData = self.query_column_sql(sql, varDict)
|
|
143
|
+
else:
|
|
144
|
+
self.queueData = self.query_column_sql(sql)
|
|
145
|
+
|
|
146
|
+
def dumpSingleQueue(self, queueDict, dest="/tmp", outputSet="all", format="txt"):
|
|
147
|
+
try:
|
|
148
|
+
file = os.path.join(dest, queueDict["nickname"] + "." + outputSet + "." + format)
|
|
149
|
+
output = open(file, "w")
|
|
150
|
+
outputFields = self.queueDataFields[outputSet]
|
|
151
|
+
if outputFields is None:
|
|
152
|
+
outputFields = queueDict.keys()
|
|
153
|
+
if format == "txt":
|
|
154
|
+
for outputField in outputFields:
|
|
155
|
+
output.write(outputField + "=" + str(queueDict[outputField]))
|
|
156
|
+
if format == "pilot":
|
|
157
|
+
outputStr = ""
|
|
158
|
+
for outputField in outputFields:
|
|
159
|
+
if outputField in queueDict and queueDict[outputField]:
|
|
160
|
+
outputStr += outputField + "=" + str(queueDict[outputField]) + "|"
|
|
161
|
+
else:
|
|
162
|
+
outputStr += outputField + "=|"
|
|
163
|
+
output.write(outputStr[:-1])
|
|
164
|
+
if format == "json":
|
|
165
|
+
dumpMe = {}
|
|
166
|
+
for outputField in outputFields:
|
|
167
|
+
if outputField in queueDict:
|
|
168
|
+
val = queueDict[outputField]
|
|
169
|
+
else:
|
|
170
|
+
val = ""
|
|
171
|
+
dumpMe[outputField] = val
|
|
172
|
+
json.dump(self.queueDictPythonise(dumpMe), output, sort_keys=True, indent=4)
|
|
173
|
+
output.close()
|
|
174
|
+
# a copy of the file, when makes sense, with filename based on siteid
|
|
175
|
+
newfile = os.path.join(dest, queueDict["siteid"] + "." + outputSet + "." + format)
|
|
176
|
+
if newfile != file:
|
|
177
|
+
shutil.copy(file, newfile)
|
|
178
|
+
except Exception:
|
|
179
|
+
raise
|
|
180
|
+
|
|
181
|
+
def queueDictPythonise(self, queueDict, deepCopy=True):
|
|
182
|
+
"""Turn queue dictionary with SQL text fields into a more stuctured python representation"""
|
|
183
|
+
if deepCopy:
|
|
184
|
+
structDict = deepcopy(queueDict)
|
|
185
|
+
else:
|
|
186
|
+
structDict = queueDict
|
|
187
|
+
|
|
188
|
+
if "releases" in structDict and structDict["releases"] is not None:
|
|
189
|
+
if isinstance(structDict["releases"], str):
|
|
190
|
+
structDict["releases"] = structDict["releases"].split("|")
|
|
191
|
+
|
|
192
|
+
for timeKey in "lastmod", "tspace":
|
|
193
|
+
if timeKey in structDict:
|
|
194
|
+
structDict[timeKey] = structDict[timeKey].isoformat()
|
|
195
|
+
return structDict
|
|
196
|
+
|
|
197
|
+
def dumpAllSchedConfig(self, queueArray=None, dest="/tmp"):
|
|
198
|
+
"""Dumps all of schedconfig into a single json file - allows clients to retrieve a
|
|
199
|
+
machine readable version of schedconfig efficiently"""
|
|
200
|
+
file = os.path.join(dest, "schedconfig.all.json")
|
|
201
|
+
if queueArray is None:
|
|
202
|
+
queueArray = self.queueData
|
|
203
|
+
output = open(file, "w")
|
|
204
|
+
dumpMe = {}
|
|
205
|
+
for queueDict in queueArray:
|
|
206
|
+
dumpMe[queueDict["nickname"]] = {}
|
|
207
|
+
for k in queueDict:
|
|
208
|
+
v = queueDict[k]
|
|
209
|
+
dumpMe[queueDict["nickname"]][k] = v
|
|
210
|
+
dumpMe[queueDict["nickname"]] = self.queueDictPythonise(dumpMe[queueDict["nickname"]])
|
|
211
|
+
json.dump(dumpMe, output, sort_keys=True, indent=4)
|
|
212
|
+
self.dump_pilot_gdp_config(dest)
|
|
213
|
+
|
|
214
|
+
def dump_pilot_gdp_config(self, dest="/tmp"):
|
|
215
|
+
app = "pilot"
|
|
216
|
+
dump_me = {}
|
|
217
|
+
sql = f"SELECT key, component, vo from {panda_config.schemaPANDA}.config where app=:app"
|
|
218
|
+
r = self.tbuf.querySQL(sql, {":app": app})
|
|
219
|
+
for key, component, vo in r:
|
|
220
|
+
dump_me.setdefault(vo, {})
|
|
221
|
+
value = self.tbuf.getConfigValue(component, key, app, vo)
|
|
222
|
+
dump_me[vo][key] = value
|
|
223
|
+
# dump
|
|
224
|
+
_logger.debug(f"pilot GDP config: {str(dump_me)}")
|
|
225
|
+
with open(os.path.join(dest, "pilot_gdp_config.json"), "w") as f:
|
|
226
|
+
json.dump(dump_me, f, sort_keys=True, indent=4)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def main(argv=tuple(), tbuf=None, **kwargs):
|
|
230
|
+
_logger.debug("start")
|
|
231
|
+
try:
|
|
232
|
+
# parse arguments
|
|
233
|
+
parser = ArgumentParser()
|
|
234
|
+
parser.add_argument(
|
|
235
|
+
"-o",
|
|
236
|
+
"--output",
|
|
237
|
+
dest="dirname",
|
|
238
|
+
default=default_dest_dir,
|
|
239
|
+
help="write cache outputs to DIR",
|
|
240
|
+
metavar="DIR",
|
|
241
|
+
)
|
|
242
|
+
args = parser.parse_args(list(argv)[1:])
|
|
243
|
+
# ensure destination directory
|
|
244
|
+
dest_dir_path = Path(args.dirname)
|
|
245
|
+
dest_dir_path.mkdir(mode=0o755, exist_ok=True)
|
|
246
|
+
# instantiate TB
|
|
247
|
+
requester_id = GenericThread().get_full_id(__name__, sys.modules[__name__].__file__)
|
|
248
|
+
if tbuf is None:
|
|
249
|
+
from pandaserver.taskbuffer.TaskBuffer import taskBuffer
|
|
250
|
+
|
|
251
|
+
taskBuffer.init(
|
|
252
|
+
panda_config.dbhost,
|
|
253
|
+
panda_config.dbpasswd,
|
|
254
|
+
nDBConnection=1,
|
|
255
|
+
useTimeout=True,
|
|
256
|
+
requester=requester_id,
|
|
257
|
+
)
|
|
258
|
+
else:
|
|
259
|
+
taskBuffer = tbuf
|
|
260
|
+
|
|
261
|
+
# initialize
|
|
262
|
+
cacher = cacheSchedConfig(tbuf=taskBuffer)
|
|
263
|
+
cacher.getQueueData()
|
|
264
|
+
|
|
265
|
+
# dump
|
|
266
|
+
for queue in cacher.queueData:
|
|
267
|
+
cacher.dumpSingleQueue(queue, dest=args.dirname, outputSet="pilot", format="pilot")
|
|
268
|
+
cacher.dumpSingleQueue(queue, dest=args.dirname, outputSet="pilot", format="json")
|
|
269
|
+
cacher.dumpSingleQueue(queue, dest=args.dirname, outputSet="all", format="json")
|
|
270
|
+
cacher.dumpSingleQueue(queue, dest=args.dirname, outputSet="factory", format="json")
|
|
271
|
+
_logger.debug("dumped json files for each queue")
|
|
272
|
+
# Big dumper
|
|
273
|
+
cacher.dumpAllSchedConfig(dest=args.dirname)
|
|
274
|
+
_logger.debug("dumped schedconfig.all.json")
|
|
275
|
+
# stop taskBuffer if created inside this script
|
|
276
|
+
if tbuf is None:
|
|
277
|
+
taskBuffer.cleanup(requester=requester_id)
|
|
278
|
+
except Exception as e:
|
|
279
|
+
err_str = traceback.format_exc()
|
|
280
|
+
_logger.error(f"failed to copy files: {err_str}")
|
|
281
|
+
# done
|
|
282
|
+
_logger.debug("done")
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
if __name__ == "__main__":
|
|
286
|
+
main(argv=sys.argv)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
from pandacommon.pandalogger import logger_utils
|
|
5
|
+
from pandacommon.pandautils.thread_utils import GenericThread
|
|
6
|
+
from pandaserver.config import panda_config
|
|
7
|
+
from pandaserver.configurator import Carbon as carbon_module
|
|
8
|
+
from pandaserver.configurator.Carbon import CarbonEmissions
|
|
9
|
+
|
|
10
|
+
# logger
|
|
11
|
+
base_logger = carbon_module._logger
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# main
|
|
15
|
+
def main(argv=tuple(), tbuf=None, **kwargs):
|
|
16
|
+
requester_id = GenericThread().get_full_id(__name__, sys.modules[__name__].__file__)
|
|
17
|
+
|
|
18
|
+
# instantiate TB
|
|
19
|
+
if tbuf is None:
|
|
20
|
+
from pandaserver.taskbuffer.TaskBuffer import taskBuffer
|
|
21
|
+
|
|
22
|
+
taskBuffer.init(
|
|
23
|
+
panda_config.dbhost,
|
|
24
|
+
panda_config.dbpasswd,
|
|
25
|
+
nDBConnection=1,
|
|
26
|
+
useTimeout=True,
|
|
27
|
+
requester=requester_id,
|
|
28
|
+
)
|
|
29
|
+
else:
|
|
30
|
+
taskBuffer = tbuf
|
|
31
|
+
|
|
32
|
+
# If no argument, call the basic configurator
|
|
33
|
+
if len(argv) == 1:
|
|
34
|
+
_logger = logger_utils.make_logger(base_logger, "Carbon")
|
|
35
|
+
t1 = time.time()
|
|
36
|
+
carbon_emissions = CarbonEmissions(taskBuffer=taskBuffer)
|
|
37
|
+
carbon_emissions.run()
|
|
38
|
+
t2 = time.time()
|
|
39
|
+
_logger.debug(f"Carbon run took {t2 - t1}s")
|
|
40
|
+
|
|
41
|
+
else:
|
|
42
|
+
base_logger.error("Carbon module being called with wrong arguments. Use no arguments")
|
|
43
|
+
|
|
44
|
+
# stop taskBuffer if created inside this script
|
|
45
|
+
if tbuf is None:
|
|
46
|
+
taskBuffer.cleanup(requester=requester_id)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
if __name__ == "__main__":
|
|
50
|
+
main(argv=sys.argv)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
from pandacommon.pandalogger import logger_utils
|
|
5
|
+
from pandacommon.pandautils.thread_utils import GenericThread
|
|
6
|
+
from pandaserver.config import panda_config
|
|
7
|
+
from pandaserver.configurator import Configurator as configurator_module
|
|
8
|
+
from pandaserver.configurator.Configurator import (
|
|
9
|
+
Configurator,
|
|
10
|
+
NetworkConfigurator,
|
|
11
|
+
SchedconfigJsonDumper,
|
|
12
|
+
SWTagsDumper,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
# logger
|
|
16
|
+
base_logger = configurator_module._logger
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# main
|
|
20
|
+
def main(argv=tuple(), tbuf=None, **kwargs):
|
|
21
|
+
requester_id = GenericThread().get_full_id(__name__, sys.modules[__name__].__file__)
|
|
22
|
+
|
|
23
|
+
# instantiate TB
|
|
24
|
+
if tbuf is None:
|
|
25
|
+
from pandaserver.taskbuffer.TaskBuffer import taskBuffer
|
|
26
|
+
|
|
27
|
+
taskBuffer.init(
|
|
28
|
+
panda_config.dbhost,
|
|
29
|
+
panda_config.dbpasswd,
|
|
30
|
+
nDBConnection=1,
|
|
31
|
+
useTimeout=True,
|
|
32
|
+
requester=requester_id,
|
|
33
|
+
)
|
|
34
|
+
else:
|
|
35
|
+
taskBuffer = tbuf
|
|
36
|
+
|
|
37
|
+
# If no argument, call the basic configurator
|
|
38
|
+
if len(argv) == 1:
|
|
39
|
+
_logger = logger_utils.make_logger(base_logger, "Configurator")
|
|
40
|
+
t1 = time.time()
|
|
41
|
+
configurator = Configurator(taskBuffer=taskBuffer, log_stream=_logger)
|
|
42
|
+
|
|
43
|
+
if not configurator.retrieve_data():
|
|
44
|
+
_logger.error("Data was not retrieved correctly")
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
if not configurator.run():
|
|
48
|
+
_logger.error("Configurator loop FAILED")
|
|
49
|
+
t2 = time.time()
|
|
50
|
+
_logger.debug(f"Configurator run took {t2 - t1}s")
|
|
51
|
+
|
|
52
|
+
# If --network argument, call the network configurator
|
|
53
|
+
elif len(argv) == 2 and argv[1].lower() == "--network":
|
|
54
|
+
_logger = logger_utils.make_logger(base_logger, "NetworkConfigurator")
|
|
55
|
+
t1 = time.time()
|
|
56
|
+
network_configurator = NetworkConfigurator(taskBuffer=taskBuffer, log_stream=_logger)
|
|
57
|
+
if not network_configurator.retrieve_data():
|
|
58
|
+
_logger.error("Data was not retrieved correctly")
|
|
59
|
+
return
|
|
60
|
+
if not network_configurator.run():
|
|
61
|
+
_logger.error("Configurator loop FAILED")
|
|
62
|
+
t2 = time.time()
|
|
63
|
+
_logger.debug(f" run took {t2 - t1}s")
|
|
64
|
+
|
|
65
|
+
# If --json_dump
|
|
66
|
+
elif len(argv) == 2 and argv[1].lower() == "--json_dump":
|
|
67
|
+
_logger = logger_utils.make_logger(base_logger, "SchedconfigJsonDumper")
|
|
68
|
+
t1 = time.time()
|
|
69
|
+
json_dumper = SchedconfigJsonDumper(taskBuffer=taskBuffer, log_stream=_logger)
|
|
70
|
+
out_msg = json_dumper.run()
|
|
71
|
+
_logger.debug(f"Json_dumper finished with {out_msg}")
|
|
72
|
+
t2 = time.time()
|
|
73
|
+
_logger.debug(f" run took {t2 - t1}s")
|
|
74
|
+
|
|
75
|
+
# If --sw_tags
|
|
76
|
+
elif len(argv) == 2 and argv[1].lower() == "--sw_tags":
|
|
77
|
+
_logger = logger_utils.make_logger(base_logger, "SWTagsDumper")
|
|
78
|
+
t1 = time.time()
|
|
79
|
+
sw_tag_collector = SWTagsDumper(taskBuffer=taskBuffer, log_stream=_logger)
|
|
80
|
+
out_msg = sw_tag_collector.run()
|
|
81
|
+
_logger.debug(f"sw_tag_collector finished with {out_msg}")
|
|
82
|
+
t2 = time.time()
|
|
83
|
+
_logger.debug(f" run took {t2 - t1}s")
|
|
84
|
+
|
|
85
|
+
else:
|
|
86
|
+
base_logger.error("Configurator being called with wrong arguments. Use either no arguments or --network or --json_dump")
|
|
87
|
+
|
|
88
|
+
# stop taskBuffer if created inside this script
|
|
89
|
+
if tbuf is None:
|
|
90
|
+
taskBuffer.cleanup(requester=requester_id)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
if __name__ == "__main__":
|
|
94
|
+
main(argv=sys.argv)
|