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,405 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import functools
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
import socket
|
|
6
|
+
import sys
|
|
7
|
+
import traceback
|
|
8
|
+
from zlib import adler32
|
|
9
|
+
|
|
10
|
+
from pandacommon.pandalogger import logger_utils
|
|
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
|
+
from pandaserver.config import panda_config
|
|
16
|
+
from pandaserver.daemons.scripts.metric_collector import MetricsDB
|
|
17
|
+
|
|
18
|
+
# logger
|
|
19
|
+
main_logger = PandaLogger().getLogger("task_evaluator")
|
|
20
|
+
|
|
21
|
+
# dry run
|
|
22
|
+
DRY_RUN = False
|
|
23
|
+
|
|
24
|
+
# list of metrics in FetchData to fetch data and update to DB. Format: (metric, period_minutes)
|
|
25
|
+
metric_list = [
|
|
26
|
+
("analy_task_eval", 10),
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
# constant maps
|
|
30
|
+
# class_value_rank_map = {1: 'A_sites', 0: 'B_sites', -1: 'C_sites'}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class TaskEvaluationDB(object):
|
|
34
|
+
"""
|
|
35
|
+
Proxy to access the task_evaluation table in DB
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def __init__(self, tbuf):
|
|
39
|
+
self.tbuf = tbuf
|
|
40
|
+
|
|
41
|
+
def _decor(method):
|
|
42
|
+
def _decorator(_method, *args, **kwargs):
|
|
43
|
+
@functools.wraps(_method)
|
|
44
|
+
def _wrapped_method(self, *args, **kwargs):
|
|
45
|
+
try:
|
|
46
|
+
_method(self, *args, **kwargs)
|
|
47
|
+
except Exception as exc:
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
return _wrapped_method
|
|
51
|
+
|
|
52
|
+
return _decorator(method)
|
|
53
|
+
|
|
54
|
+
def update(self, metric, entity_dict):
|
|
55
|
+
tmp_log = logger_utils.make_logger(main_logger, "TaskEvaluationDB.update")
|
|
56
|
+
tmp_log.debug(f"start metric={metric}")
|
|
57
|
+
# sql
|
|
58
|
+
sql_query_taskid = """SELECT jediTaskID """ """FROM ATLAS_PANDA.Task_Evaluation """ """WHERE metric = :metric """
|
|
59
|
+
sql_update = (
|
|
60
|
+
"""UPDATE ATLAS_PANDA.Task_Evaluation SET """
|
|
61
|
+
"""value_json = :patch_value_json, """
|
|
62
|
+
"""timestamp = :timestamp """
|
|
63
|
+
"""WHERE jediTaskID=:taskID AND metric=:metric """
|
|
64
|
+
)
|
|
65
|
+
sql_insert = """INSERT INTO ATLAS_PANDA.Task_Evaluation """ """VALUES ( """ """:taskID, :metric, :patch_value_json, :timestamp """ """) """
|
|
66
|
+
# now
|
|
67
|
+
now_time = naive_utcnow()
|
|
68
|
+
# get existing taskID list
|
|
69
|
+
res = self.tbuf.querySQL(sql_query_taskid, {":metric": metric})
|
|
70
|
+
existing_taskID_list = [taskID for (taskID,) in res]
|
|
71
|
+
# var map template
|
|
72
|
+
varMap_template = {
|
|
73
|
+
":taskID": None,
|
|
74
|
+
":metric": metric,
|
|
75
|
+
":timestamp": now_time,
|
|
76
|
+
":patch_value_json": None,
|
|
77
|
+
}
|
|
78
|
+
# make var map lists
|
|
79
|
+
update_varMap_list = []
|
|
80
|
+
insert_varMap_list = []
|
|
81
|
+
for taskID, v in entity_dict.items():
|
|
82
|
+
# values to json string
|
|
83
|
+
try:
|
|
84
|
+
patch_value_json = json.dumps(v)
|
|
85
|
+
except Exception:
|
|
86
|
+
tmp_log.error(traceback.format_exc() + " " + str(v))
|
|
87
|
+
return
|
|
88
|
+
# update varMap
|
|
89
|
+
varMap = varMap_template.copy()
|
|
90
|
+
varMap[":taskID"] = taskID
|
|
91
|
+
varMap[":patch_value_json"] = patch_value_json
|
|
92
|
+
# append to the list
|
|
93
|
+
if taskID in existing_taskID_list:
|
|
94
|
+
update_varMap_list.append(varMap)
|
|
95
|
+
else:
|
|
96
|
+
insert_varMap_list.append(varMap)
|
|
97
|
+
# update
|
|
98
|
+
n_row = self.tbuf.executemanySQL(sql_update, update_varMap_list)
|
|
99
|
+
if n_row < len(update_varMap_list):
|
|
100
|
+
tmp_log.warning(f"only {n_row}/{len(update_varMap_list)} rows updated for metric={metric}")
|
|
101
|
+
else:
|
|
102
|
+
tmp_log.debug(f"updated {len(update_varMap_list)} rows for metric={metric}")
|
|
103
|
+
# insert
|
|
104
|
+
n_row = self.tbuf.executemanySQL(sql_insert, insert_varMap_list)
|
|
105
|
+
if n_row is None:
|
|
106
|
+
# try to insert one by one
|
|
107
|
+
n_row = 0
|
|
108
|
+
for varMap in insert_varMap_list:
|
|
109
|
+
res = self.tbuf.querySQL(sql_insert, varMap)
|
|
110
|
+
try:
|
|
111
|
+
n_row += res
|
|
112
|
+
except TypeError:
|
|
113
|
+
pass
|
|
114
|
+
if n_row < len(insert_varMap_list):
|
|
115
|
+
tmp_log.warning(f"only {n_row}/{len(insert_varMap_list)} rows inserted for metric={metric}")
|
|
116
|
+
else:
|
|
117
|
+
tmp_log.debug(f"inserted {len(insert_varMap_list)} rows for metric={metric}")
|
|
118
|
+
# done
|
|
119
|
+
tmp_log.debug(f"done metric={metric}")
|
|
120
|
+
|
|
121
|
+
def get_metrics(self, metric, fresher_than_minutes_ago=120):
|
|
122
|
+
tmp_log = logger_utils.make_logger(main_logger, "TaskEvaluationDB.update")
|
|
123
|
+
tmp_log.debug(f"start metric={metric}")
|
|
124
|
+
# sql
|
|
125
|
+
sql_query = (
|
|
126
|
+
"""SELECT jediTaskID, value_json """ """FROM ATLAS_PANDA.Task_Evaluation """ """WHERE metric = :metric """ """AND timestamp >= :min_timestamp """
|
|
127
|
+
)
|
|
128
|
+
# now
|
|
129
|
+
now_time = naive_utcnow()
|
|
130
|
+
# var map
|
|
131
|
+
varMap = {
|
|
132
|
+
":metric": metric,
|
|
133
|
+
":min_timestamp": now_time - datetime.timedelta(minutes=fresher_than_minutes_ago),
|
|
134
|
+
}
|
|
135
|
+
# query
|
|
136
|
+
res = self.tbuf.querySQL(sql_query, varMap)
|
|
137
|
+
if res is None:
|
|
138
|
+
tmp_log.warning(f"failed to query metric={metric}")
|
|
139
|
+
return
|
|
140
|
+
# return map
|
|
141
|
+
ret_map = {}
|
|
142
|
+
for taskID, value_json in res:
|
|
143
|
+
try:
|
|
144
|
+
value_dict = json.loads(value_json)
|
|
145
|
+
except Exception:
|
|
146
|
+
tmp_log.error(traceback.format_exc() + " " + str(taskID) + str(value_json))
|
|
147
|
+
else:
|
|
148
|
+
ret_map[taskID] = value_dict
|
|
149
|
+
# return
|
|
150
|
+
return ret_map
|
|
151
|
+
|
|
152
|
+
def clean_up(self, metric, fresher_than_minutes_ago=120):
|
|
153
|
+
tmp_log = logger_utils.make_logger(main_logger, "TaskEvaluationDB.clean_up")
|
|
154
|
+
tmp_log.debug(f"start metric={metric}")
|
|
155
|
+
# sql
|
|
156
|
+
sql_delete_terminated_tasks = (
|
|
157
|
+
"DELETE "
|
|
158
|
+
"FROM ATLAS_PANDA.Task_Evaluation te "
|
|
159
|
+
"WHERE te.jediTaskID IN ( "
|
|
160
|
+
"SELECT jt.jediTaskID "
|
|
161
|
+
"FROM ATLAS_PANDA.JEDI_Tasks jt, ATLAS_PANDA.Task_Evaluation tez "
|
|
162
|
+
"WHERE tez.jediTaskID = jt.jediTaskID "
|
|
163
|
+
"AND jt.status IN ('done', 'finished', 'failed', 'broken', 'aborted', 'exhausted') "
|
|
164
|
+
") "
|
|
165
|
+
"AND te.metric = :metric "
|
|
166
|
+
"AND te.timestamp <= :max_timestamp "
|
|
167
|
+
)
|
|
168
|
+
# now
|
|
169
|
+
now_time = naive_utcnow()
|
|
170
|
+
# var map
|
|
171
|
+
varMap = {
|
|
172
|
+
":metric": metric,
|
|
173
|
+
":max_timestamp": now_time - datetime.timedelta(minutes=fresher_than_minutes_ago),
|
|
174
|
+
}
|
|
175
|
+
# clean up
|
|
176
|
+
n_row = self.tbuf.querySQL(sql_delete_terminated_tasks, varMap)
|
|
177
|
+
tmp_log.debug(f"cleaned up {n_row} rows for metric={metric}")
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class FetchData(object):
|
|
181
|
+
"""
|
|
182
|
+
methods to fetch or evaluate data values to store
|
|
183
|
+
"""
|
|
184
|
+
|
|
185
|
+
def __init__(self, tbuf):
|
|
186
|
+
self.tbuf = tbuf
|
|
187
|
+
# initialize stored data
|
|
188
|
+
self.gshare_status = None
|
|
189
|
+
|
|
190
|
+
def analy_task_eval(self):
|
|
191
|
+
tmp_log = logger_utils.make_logger(main_logger, "FetchData")
|
|
192
|
+
# sql
|
|
193
|
+
sql_get_active_tasks = (
|
|
194
|
+
"SELECT jt.jediTaskID, jt.userName, jt.gshare "
|
|
195
|
+
"FROM ATLAS_PANDA.JEDI_Tasks jt, ATLAS_PANDA.JEDI_AUX_Status_MinTaskID asm "
|
|
196
|
+
"WHERE jt.taskType = 'anal' AND jt.prodSourceLabel = 'user' "
|
|
197
|
+
"AND jt.status=asm.status AND jt.jediTaskID >= asm.min_jediTaskID "
|
|
198
|
+
"AND jt.status IN ('scouting', 'scouted', 'running', 'pending', 'throttled') "
|
|
199
|
+
"AND jt.userName NOT IN ('gangarbt') "
|
|
200
|
+
"AND jt.modificationTime >= CURRENT_DATE - 30 "
|
|
201
|
+
)
|
|
202
|
+
sql_get_task_dsinfo = (
|
|
203
|
+
"SELECT ds.jediTaskID, SUM(ds.nFiles), SUM(ds.nFilesFinished), SUM(ds.nFilesFailed) "
|
|
204
|
+
"FROM ATLAS_PANDA.JEDI_Datasets ds "
|
|
205
|
+
"WHERE ds.jediTaskID = :taskID "
|
|
206
|
+
"AND ds.type IN ('input', 'pseudo_input') "
|
|
207
|
+
"AND ds.masterID IS NULL "
|
|
208
|
+
"GROUP BY ds.jediTaskID "
|
|
209
|
+
)
|
|
210
|
+
sql_get_task_n_jobs = (
|
|
211
|
+
"SELECT COUNT(*) FROM ( "
|
|
212
|
+
"SELECT DISTINCT c.PandaID "
|
|
213
|
+
"FROM ATLAS_PANDA.JEDI_Datasets ds, ATLAS_PANDA.JEDI_Dataset_Contents c "
|
|
214
|
+
"WHERE c.jediTaskID=ds.jediTaskID AND c.datasetID=ds.datasetID "
|
|
215
|
+
"AND ds.jediTaskID=:taskID AND ds.masterID IS NULL "
|
|
216
|
+
"AND ds.type IN ('input', 'pseudo_input') "
|
|
217
|
+
") "
|
|
218
|
+
)
|
|
219
|
+
try:
|
|
220
|
+
# initialize
|
|
221
|
+
# tmp_site_dict = dict()
|
|
222
|
+
task_dict = dict()
|
|
223
|
+
# now time
|
|
224
|
+
now_time = naive_utcnow()
|
|
225
|
+
# MetricsDB
|
|
226
|
+
mdb = MetricsDB(self.tbuf)
|
|
227
|
+
# get user evaluation
|
|
228
|
+
ue_dict = mdb.get_metrics("analy_user_eval", "neither", fresher_than_minutes_ago=20)
|
|
229
|
+
# get active tasks
|
|
230
|
+
varMap = {}
|
|
231
|
+
active_tasks_list = self.tbuf.querySQL(sql_get_active_tasks, varMap)
|
|
232
|
+
taskID_list = [task[0] for task in active_tasks_list]
|
|
233
|
+
n_tot_tasks = len(active_tasks_list)
|
|
234
|
+
tmp_log.debug(f"got total {n_tot_tasks} tasks")
|
|
235
|
+
# counter
|
|
236
|
+
cc = 0
|
|
237
|
+
n_tasks_dict = {
|
|
238
|
+
2: 0,
|
|
239
|
+
1: 0,
|
|
240
|
+
0: 0,
|
|
241
|
+
-1: 0,
|
|
242
|
+
}
|
|
243
|
+
# loop over tasks
|
|
244
|
+
for taskID, user, gshare in active_tasks_list:
|
|
245
|
+
# initialize
|
|
246
|
+
task_class = 1
|
|
247
|
+
n_files_total = 0
|
|
248
|
+
n_files_finished = 0
|
|
249
|
+
n_files_failed = 0
|
|
250
|
+
n_files_remaining = 0
|
|
251
|
+
pct_finished = 0
|
|
252
|
+
pct_failed = 0
|
|
253
|
+
n_jobs = 0
|
|
254
|
+
n_jobs_remaining = 0
|
|
255
|
+
# get dataset info of each task
|
|
256
|
+
varMap = {":taskID": taskID}
|
|
257
|
+
dsinfo_list = self.tbuf.querySQL(sql_get_task_dsinfo, varMap)
|
|
258
|
+
dsinfo_dict = {
|
|
259
|
+
tup[0]: {
|
|
260
|
+
"nFiles": tup[1],
|
|
261
|
+
"nFilesFinished": tup[2],
|
|
262
|
+
"nFilesFailed": tup[3],
|
|
263
|
+
}
|
|
264
|
+
for tup in dsinfo_list
|
|
265
|
+
}
|
|
266
|
+
# get n jobs of each task
|
|
267
|
+
tmp_res = self.tbuf.querySQL(sql_get_task_n_jobs, varMap)
|
|
268
|
+
for obj in tmp_res:
|
|
269
|
+
(n_jobs,) = obj
|
|
270
|
+
dsinfo_dict.setdefault(taskID, {})
|
|
271
|
+
dsinfo_dict[taskID]["nJobs"] = n_jobs
|
|
272
|
+
break
|
|
273
|
+
# get task proceeding progress
|
|
274
|
+
ds_info = dsinfo_dict.get(taskID)
|
|
275
|
+
if ds_info is not None:
|
|
276
|
+
n_files_total = ds_info.get("nFiles", 0)
|
|
277
|
+
n_files_finished = ds_info.get("nFilesFinished", 0)
|
|
278
|
+
n_files_failed = ds_info.get("nFilesFailed", 0)
|
|
279
|
+
n_files_remaining = max(n_files_total - n_files_finished - n_files_failed, 0)
|
|
280
|
+
n_jobs = ds_info.get("nJobs", 0)
|
|
281
|
+
if n_files_total > 0:
|
|
282
|
+
pct_finished = n_files_finished * 100 / n_files_total
|
|
283
|
+
pct_failed = n_files_failed * 100 / n_files_total
|
|
284
|
+
n_jobs_remaining = int(n_jobs * n_files_remaining / n_files_total)
|
|
285
|
+
# classify
|
|
286
|
+
if gshare == "Express Analysis":
|
|
287
|
+
# Express Analysis tasks always in class S
|
|
288
|
+
task_class = 2
|
|
289
|
+
else:
|
|
290
|
+
# parameters
|
|
291
|
+
progress_to_boost_A = self.tbuf.getConfigValue("analy_eval", "PROGRESS_TO_BOOST_A", default=90)
|
|
292
|
+
progress_to_boost_B = self.tbuf.getConfigValue("analy_eval", "PROGRESS_TO_BOOST_B", default=95)
|
|
293
|
+
max_rem_jobs_to_boost_A = self.tbuf.getConfigValue("analy_eval", "MAX_REM_JOBS_TO_BOOST_A", default=500)
|
|
294
|
+
max_rem_jobs_to_boost_B = self.tbuf.getConfigValue("analy_eval", "MAX_REM_JOBS_TO_BOOST_B", default=200)
|
|
295
|
+
# check usage of the user
|
|
296
|
+
usage_dict = ue_dict.get(user)
|
|
297
|
+
if usage_dict is None:
|
|
298
|
+
continue
|
|
299
|
+
if usage_dict["rem_slots_A"] <= 0:
|
|
300
|
+
if usage_dict["rem_slots_B"] <= 0:
|
|
301
|
+
task_class = -1
|
|
302
|
+
else:
|
|
303
|
+
task_class = 0
|
|
304
|
+
# boost for nearly done tasks
|
|
305
|
+
if task_class == 1 and pct_finished >= progress_to_boost_A and n_jobs_remaining > 0 and n_jobs_remaining <= max_rem_jobs_to_boost_A:
|
|
306
|
+
# almost done A-tasks, to boost
|
|
307
|
+
task_class = 2
|
|
308
|
+
elif task_class == 0 and pct_finished >= progress_to_boost_B and n_jobs_remaining > 0 and n_jobs_remaining <= max_rem_jobs_to_boost_B:
|
|
309
|
+
# almost done B-tasks, to boost
|
|
310
|
+
task_class = 2
|
|
311
|
+
# fill in task class
|
|
312
|
+
task_dict[taskID] = {
|
|
313
|
+
"task_id": taskID,
|
|
314
|
+
"user": user,
|
|
315
|
+
"gshare": gshare,
|
|
316
|
+
"n_files_total": n_files_total,
|
|
317
|
+
"n_files_finished": n_files_finished,
|
|
318
|
+
"n_files_failed": n_files_failed,
|
|
319
|
+
"pct_finished": pct_finished,
|
|
320
|
+
"pct_failed": pct_failed,
|
|
321
|
+
"class": task_class,
|
|
322
|
+
}
|
|
323
|
+
# counter
|
|
324
|
+
cc += 1
|
|
325
|
+
if cc % 5000 == 0:
|
|
326
|
+
tmp_log.debug(f"evaluated {cc:6d} tasks")
|
|
327
|
+
n_tasks_dict[task_class] += 1
|
|
328
|
+
tmp_log.debug(f"evaluated {cc:6d} tasks in total (S:{n_tasks_dict[2]}, A:{n_tasks_dict[1]}, B:{n_tasks_dict[0]}, C:{n_tasks_dict[-1]})")
|
|
329
|
+
# return
|
|
330
|
+
# tmp_log.debug('{}'.format(str([ v for v in task_dict.values() if v['class'] != 1 ])[:3000]))
|
|
331
|
+
tmp_log.debug("done")
|
|
332
|
+
return task_dict
|
|
333
|
+
except Exception:
|
|
334
|
+
tmp_log.error(traceback.format_exc())
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
# main
|
|
338
|
+
def main(tbuf=None, **kwargs):
|
|
339
|
+
# instantiate TB
|
|
340
|
+
if tbuf is None:
|
|
341
|
+
from pandaserver.taskbuffer.TaskBuffer import taskBuffer
|
|
342
|
+
|
|
343
|
+
requester_id = GenericThread().get_full_id(__name__, sys.modules[__name__].__file__)
|
|
344
|
+
taskBuffer.init(
|
|
345
|
+
panda_config.dbhost,
|
|
346
|
+
panda_config.dbpasswd,
|
|
347
|
+
nDBConnection=1,
|
|
348
|
+
useTimeout=True,
|
|
349
|
+
requester=requester_id,
|
|
350
|
+
)
|
|
351
|
+
else:
|
|
352
|
+
taskBuffer = tbuf
|
|
353
|
+
# pid
|
|
354
|
+
my_pid = os.getpid()
|
|
355
|
+
my_full_pid = f"{socket.getfqdn().split('.')[0]}-{os.getpgrp()}-{my_pid}"
|
|
356
|
+
# go
|
|
357
|
+
if DRY_RUN:
|
|
358
|
+
# dry run, regardless of lock, not update DB
|
|
359
|
+
fetcher = FetchData(taskBuffer)
|
|
360
|
+
# loop over all fetch data methods to run and update to DB
|
|
361
|
+
for metric_name, period in metric_list:
|
|
362
|
+
main_logger.debug(f"(dry-run) start {metric_name}")
|
|
363
|
+
# fetch data and update DB
|
|
364
|
+
the_method = getattr(fetcher, metric_name)
|
|
365
|
+
fetched_data = the_method()
|
|
366
|
+
if fetched_data is None:
|
|
367
|
+
main_logger.warning(f"(dry-run) {metric_name} got no valid data")
|
|
368
|
+
continue
|
|
369
|
+
main_logger.debug(f"(dry-run) done {metric_name}")
|
|
370
|
+
else:
|
|
371
|
+
# real run, will update DB
|
|
372
|
+
# instantiate
|
|
373
|
+
tedb = TaskEvaluationDB(taskBuffer)
|
|
374
|
+
fetcher = FetchData(taskBuffer)
|
|
375
|
+
# loop over all fetch data methods to run and update to DB
|
|
376
|
+
for metric_name, period in metric_list:
|
|
377
|
+
# metric lock
|
|
378
|
+
lock_component_name = f"pandaTaskEval.{metric_name:.30}.{adler32(metric_name.encode('utf-8')):0x}"
|
|
379
|
+
# try to get lock
|
|
380
|
+
got_lock = taskBuffer.lockProcess_PANDA(component=lock_component_name, pid=my_full_pid, time_limit=period)
|
|
381
|
+
if got_lock:
|
|
382
|
+
main_logger.debug(f"got lock of {metric_name}")
|
|
383
|
+
else:
|
|
384
|
+
main_logger.debug(f"{metric_name} locked by other process; skipped...")
|
|
385
|
+
continue
|
|
386
|
+
main_logger.debug(f"start {metric_name}")
|
|
387
|
+
# clean up
|
|
388
|
+
tedb.clean_up(metric=metric_name, fresher_than_minutes_ago=120)
|
|
389
|
+
main_logger.debug(f"cleaned up {metric_name}")
|
|
390
|
+
# fetch data and update DB
|
|
391
|
+
the_method = getattr(fetcher, metric_name)
|
|
392
|
+
fetched_data = the_method()
|
|
393
|
+
if fetched_data is None:
|
|
394
|
+
main_logger.warning(f"{metric_name} got no valid data")
|
|
395
|
+
continue
|
|
396
|
+
tedb.update(metric=metric_name, entity_dict=fetched_data)
|
|
397
|
+
main_logger.debug(f"done {metric_name}")
|
|
398
|
+
# stop taskBuffer if created inside this script
|
|
399
|
+
if tbuf is None:
|
|
400
|
+
taskBuffer.cleanup(requester=requester_id)
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
# run
|
|
404
|
+
if __name__ == "__main__":
|
|
405
|
+
main()
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import glob
|
|
3
|
+
import optparse
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
from pandacommon.pandautils.PandaUtils import naive_utcnow
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# main
|
|
11
|
+
def main(argv=tuple(), **kwargs):
|
|
12
|
+
# options
|
|
13
|
+
optP = optparse.OptionParser(conflict_handler="resolve")
|
|
14
|
+
optP.add_option(
|
|
15
|
+
"-t",
|
|
16
|
+
action="store_const",
|
|
17
|
+
const=True,
|
|
18
|
+
dest="test",
|
|
19
|
+
default=False,
|
|
20
|
+
help="test mode",
|
|
21
|
+
)
|
|
22
|
+
optP.add_option(
|
|
23
|
+
"-h",
|
|
24
|
+
action="store",
|
|
25
|
+
type="int",
|
|
26
|
+
dest="limit",
|
|
27
|
+
default=12,
|
|
28
|
+
help="time limit in hour",
|
|
29
|
+
)
|
|
30
|
+
options, args = optP.parse_args(args=argv[1:])
|
|
31
|
+
|
|
32
|
+
# patterns of tmp files
|
|
33
|
+
tmpPatts = ["/tmp/tmp*", "/tmp/atlpan/tmp*", "/tmp/pansrv/tmp*"]
|
|
34
|
+
|
|
35
|
+
# limit
|
|
36
|
+
timeLimit = naive_utcnow() - datetime.timedelta(hours=options.limit)
|
|
37
|
+
|
|
38
|
+
# loop over all pattern
|
|
39
|
+
for tmpPatt in tmpPatts:
|
|
40
|
+
tmpFiles = glob.glob(tmpPatt)
|
|
41
|
+
# loop over all files
|
|
42
|
+
for tmpFile in tmpFiles:
|
|
43
|
+
try:
|
|
44
|
+
print(f"INFO: tmpfile -> {tmpFile}")
|
|
45
|
+
# only file
|
|
46
|
+
if not os.path.isfile(tmpFile):
|
|
47
|
+
continue
|
|
48
|
+
# not symlink
|
|
49
|
+
if os.path.islink(tmpFile):
|
|
50
|
+
continue
|
|
51
|
+
# writable
|
|
52
|
+
if not os.access(tmpFile, os.W_OK):
|
|
53
|
+
continue
|
|
54
|
+
# check time stamp
|
|
55
|
+
timeStamp = os.path.getmtime(tmpFile)
|
|
56
|
+
timeStamp = datetime.datetime.fromtimestamp(timeStamp)
|
|
57
|
+
if timeStamp > timeLimit:
|
|
58
|
+
continue
|
|
59
|
+
# remove
|
|
60
|
+
print(f"INFO: remove {tmpFile}")
|
|
61
|
+
if not options.test:
|
|
62
|
+
os.remove(tmpFile)
|
|
63
|
+
except Exception:
|
|
64
|
+
errType, errValue = sys.exc_info()[:2]
|
|
65
|
+
print(f"ERROR: failed with {errType}:{errValue}")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# run
|
|
69
|
+
if __name__ == "__main__":
|
|
70
|
+
main(argv=sys.argv)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import time
|
|
3
|
+
import traceback
|
|
4
|
+
|
|
5
|
+
from pandacommon.pandalogger.PandaLogger import PandaLogger
|
|
6
|
+
from pandacommon.pandautils.thread_utils import GenericThread
|
|
7
|
+
from pandaserver.config import panda_config
|
|
8
|
+
from pandaserver.taskbuffer.Utils import create_shards
|
|
9
|
+
|
|
10
|
+
# logger
|
|
11
|
+
_logger = PandaLogger().getLogger("worker_sync")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def translate_status_to_command(pilot_status):
|
|
15
|
+
if pilot_status == "running":
|
|
16
|
+
return "SYNC_WORKERS_ACTIVATE"
|
|
17
|
+
if pilot_status == "finished":
|
|
18
|
+
return "SYNC_WORKERS_KILL"
|
|
19
|
+
return None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class WorkerSync(object):
|
|
23
|
+
def __init__(self, tbuf):
|
|
24
|
+
self._logger = _logger
|
|
25
|
+
self.tbuf = tbuf
|
|
26
|
+
return
|
|
27
|
+
|
|
28
|
+
def run(self):
|
|
29
|
+
"""
|
|
30
|
+
Identifies workers with stale harvester states and newer pilot states
|
|
31
|
+
:return:
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
# timing
|
|
35
|
+
time_start = time.time()
|
|
36
|
+
self._logger.debug("Start.")
|
|
37
|
+
|
|
38
|
+
# variables for the harvester command
|
|
39
|
+
status = "new"
|
|
40
|
+
ack_requested = False
|
|
41
|
+
lock_interval = None
|
|
42
|
+
com_interval = None
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
stale_workers_per_harvester = self.tbuf.get_workers_to_synchronize()
|
|
46
|
+
for harvester_id in stale_workers_per_harvester:
|
|
47
|
+
for pilot_status in stale_workers_per_harvester[harvester_id]:
|
|
48
|
+
command = translate_status_to_command(pilot_status)
|
|
49
|
+
if command:
|
|
50
|
+
workers = stale_workers_per_harvester[harvester_id][pilot_status]
|
|
51
|
+
for worker_shard in create_shards(workers, 100):
|
|
52
|
+
self._logger.debug(f"Processing harvester_id={harvester_id} pilot_status={pilot_status}. Workers to update: {worker_shard}")
|
|
53
|
+
self.tbuf.commandToHarvester(
|
|
54
|
+
harvester_id,
|
|
55
|
+
command,
|
|
56
|
+
ack_requested,
|
|
57
|
+
status,
|
|
58
|
+
lock_interval,
|
|
59
|
+
com_interval,
|
|
60
|
+
worker_shard,
|
|
61
|
+
)
|
|
62
|
+
except Exception:
|
|
63
|
+
self._logger.error(traceback.format_exc())
|
|
64
|
+
|
|
65
|
+
# timing
|
|
66
|
+
time_stop = time.time()
|
|
67
|
+
self._logger.debug(f"Done. Worker sync took: {time_stop - time_start} s")
|
|
68
|
+
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# main
|
|
73
|
+
def main(tbuf=None, **kwargs):
|
|
74
|
+
# instantiate TB
|
|
75
|
+
if tbuf is None:
|
|
76
|
+
from pandaserver.taskbuffer.TaskBuffer import taskBuffer
|
|
77
|
+
|
|
78
|
+
requester_id = GenericThread().get_full_id(__name__, sys.modules[__name__].__file__)
|
|
79
|
+
taskBuffer.init(
|
|
80
|
+
panda_config.dbhost,
|
|
81
|
+
panda_config.dbpasswd,
|
|
82
|
+
nDBConnection=1,
|
|
83
|
+
useTimeout=True,
|
|
84
|
+
requester=requester_id,
|
|
85
|
+
)
|
|
86
|
+
else:
|
|
87
|
+
taskBuffer = tbuf
|
|
88
|
+
# run
|
|
89
|
+
WorkerSync(tbuf=taskBuffer).run()
|
|
90
|
+
# stop taskBuffer if created inside this script
|
|
91
|
+
if tbuf is None:
|
|
92
|
+
taskBuffer.cleanup(requester=requester_id)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# run
|
|
96
|
+
if __name__ == "__main__":
|
|
97
|
+
main()
|