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,232 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
from pandaserver.srvcore.CoreUtils import NonJsonObjectEncoder, as_python_object
|
|
5
|
+
from pandaserver.taskbuffer.JobSpec import JobSpec
|
|
6
|
+
|
|
7
|
+
# list of prod source label for pilot tests
|
|
8
|
+
list_ptest_prod_sources = ["ptest", "rc_test", "rc_test2", "rc_alrb"]
|
|
9
|
+
|
|
10
|
+
# mapping with prodsourcelabels that belong to analysis and production
|
|
11
|
+
analy_sources = ["user", "panda"]
|
|
12
|
+
prod_sources = ["managed", "prod_test"]
|
|
13
|
+
neutral_sources = ["install"] + list_ptest_prod_sources
|
|
14
|
+
|
|
15
|
+
ANALY_PS = "user"
|
|
16
|
+
PROD_PS = "managed"
|
|
17
|
+
|
|
18
|
+
ANALY_TASKTYPE = "anal"
|
|
19
|
+
PROD_TASKTYPE = "prod"
|
|
20
|
+
|
|
21
|
+
MEMORY_COMPENSATION = 0.9
|
|
22
|
+
|
|
23
|
+
job_labels = [ANALY_PS, PROD_PS]
|
|
24
|
+
|
|
25
|
+
# priority of tasks to jumbo over others
|
|
26
|
+
priorityTasksToJumpOver = 1500
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def translate_prodsourcelabel_to_jobtype(queue_type, prodsourcelabel):
|
|
30
|
+
if prodsourcelabel in analy_sources:
|
|
31
|
+
return ANALY_PS
|
|
32
|
+
|
|
33
|
+
if prodsourcelabel in prod_sources:
|
|
34
|
+
return PROD_PS
|
|
35
|
+
|
|
36
|
+
if prodsourcelabel in neutral_sources:
|
|
37
|
+
if queue_type == "unified" or queue_type == "production":
|
|
38
|
+
return PROD_PS
|
|
39
|
+
if queue_type == "analysis":
|
|
40
|
+
return ANALY_PS
|
|
41
|
+
|
|
42
|
+
# currently unmapped
|
|
43
|
+
return prodsourcelabel
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def translate_tasktype_to_jobtype(task_type):
|
|
47
|
+
# any unrecognized tasktype will be defaulted to production
|
|
48
|
+
if task_type == ANALY_TASKTYPE:
|
|
49
|
+
return ANALY_PS
|
|
50
|
+
else:
|
|
51
|
+
return PROD_PS
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# get core count
|
|
55
|
+
def getCoreCount(actualCoreCount, defCoreCount, jobMetrics):
|
|
56
|
+
coreCount = 1
|
|
57
|
+
try:
|
|
58
|
+
if actualCoreCount is not None:
|
|
59
|
+
coreCount = actualCoreCount
|
|
60
|
+
else:
|
|
61
|
+
tmpMatch = None
|
|
62
|
+
if jobMetrics is not None:
|
|
63
|
+
# extract coreCount
|
|
64
|
+
tmpMatch = re.search("coreCount=(\d+)", jobMetrics)
|
|
65
|
+
if tmpMatch is not None:
|
|
66
|
+
coreCount = int(tmpMatch.group(1))
|
|
67
|
+
else:
|
|
68
|
+
# use jobdef
|
|
69
|
+
if defCoreCount not in [None, 0]:
|
|
70
|
+
coreCount = defCoreCount
|
|
71
|
+
except Exception:
|
|
72
|
+
pass
|
|
73
|
+
return coreCount
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# get HS06sec
|
|
77
|
+
def getHS06sec(startTime, endTime, corePower, coreCount, baseWalltime=0, cpuEfficiency=100):
|
|
78
|
+
try:
|
|
79
|
+
# no scaling
|
|
80
|
+
if cpuEfficiency == 0:
|
|
81
|
+
return 0
|
|
82
|
+
# get execution time
|
|
83
|
+
tmpTimeDelta = endTime - startTime
|
|
84
|
+
tmpVal = tmpTimeDelta.seconds + tmpTimeDelta.days * 24 * 3600
|
|
85
|
+
if tmpVal <= baseWalltime:
|
|
86
|
+
return 0
|
|
87
|
+
hs06sec = float(tmpVal - baseWalltime) * corePower * coreCount * float(cpuEfficiency) / 100.0
|
|
88
|
+
return hs06sec
|
|
89
|
+
except Exception:
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def get_job_co2(start_time, end_time, core_count, energy_emissions, watts_per_core):
|
|
94
|
+
energy_emissions_by_ts = {}
|
|
95
|
+
for entry in energy_emissions:
|
|
96
|
+
aux_timestamp, region, value = entry
|
|
97
|
+
energy_emissions_by_ts[aux_timestamp] = {"value": value}
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
timestamps = sorted([entry[0] for entry in energy_emissions])
|
|
101
|
+
|
|
102
|
+
started = False
|
|
103
|
+
ended = False
|
|
104
|
+
i = 0
|
|
105
|
+
|
|
106
|
+
g_co2_job = 0
|
|
107
|
+
|
|
108
|
+
for timestamp in timestamps:
|
|
109
|
+
try:
|
|
110
|
+
if start_time < timestamps[i + 1] and not started:
|
|
111
|
+
started = True
|
|
112
|
+
except IndexError:
|
|
113
|
+
pass
|
|
114
|
+
|
|
115
|
+
if end_time < timestamp and not ended:
|
|
116
|
+
ended = True
|
|
117
|
+
|
|
118
|
+
if started and not ended or i == len(timestamps) - 1:
|
|
119
|
+
bottom = max(start_time, timestamp)
|
|
120
|
+
try:
|
|
121
|
+
top = min(end_time, timestamps[i + 1])
|
|
122
|
+
except IndexError:
|
|
123
|
+
top = end_time
|
|
124
|
+
|
|
125
|
+
g_co2_perkWh = energy_emissions_by_ts[timestamp]["value"]
|
|
126
|
+
|
|
127
|
+
duration = max((top - bottom).total_seconds(), 0)
|
|
128
|
+
g_co2_job = g_co2_job + (duration * g_co2_perkWh * core_count * watts_per_core / 3600 / 1000)
|
|
129
|
+
|
|
130
|
+
if ended:
|
|
131
|
+
break
|
|
132
|
+
|
|
133
|
+
i = i + 1
|
|
134
|
+
|
|
135
|
+
return g_co2_job
|
|
136
|
+
|
|
137
|
+
except Exception:
|
|
138
|
+
return None
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
# parse string for number of standby jobs
|
|
142
|
+
def parseNumStandby(catchall):
|
|
143
|
+
retMap = {}
|
|
144
|
+
if catchall is not None:
|
|
145
|
+
for tmpItem in catchall.split(","):
|
|
146
|
+
tmpMatch = re.search("^nStandby=(.+)", tmpItem)
|
|
147
|
+
if tmpMatch is None:
|
|
148
|
+
continue
|
|
149
|
+
for tmpSubStr in tmpMatch.group(1).split("|"):
|
|
150
|
+
if len(tmpSubStr.split(":")) != 3:
|
|
151
|
+
continue
|
|
152
|
+
sw_id, resource_type, num = tmpSubStr.split(":")
|
|
153
|
+
try:
|
|
154
|
+
sw_id = int(sw_id)
|
|
155
|
+
except Exception:
|
|
156
|
+
pass
|
|
157
|
+
if sw_id not in retMap:
|
|
158
|
+
retMap[sw_id] = {}
|
|
159
|
+
if num == "":
|
|
160
|
+
num = 0
|
|
161
|
+
else:
|
|
162
|
+
num = int(num)
|
|
163
|
+
retMap[sw_id][resource_type] = num
|
|
164
|
+
break
|
|
165
|
+
return retMap
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
# compensate memory count to prevent jobs with ramCount close to the HIMEM border from going to HIMEM PQs
|
|
169
|
+
def compensate_ram_count(ram_count):
|
|
170
|
+
if ram_count in ("NULL", None):
|
|
171
|
+
return None
|
|
172
|
+
ram_count = int(ram_count * MEMORY_COMPENSATION)
|
|
173
|
+
return ram_count
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
# undo the memory count compensation
|
|
177
|
+
def decompensate_ram_count(ram_count):
|
|
178
|
+
if ram_count in ("NULL", None):
|
|
179
|
+
return None
|
|
180
|
+
ram_count = int(ram_count / MEMORY_COMPENSATION)
|
|
181
|
+
return ram_count
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
# dump jobs to serialized json
|
|
185
|
+
def dump_jobs_json(jobs):
|
|
186
|
+
state_objects = []
|
|
187
|
+
for job_spec in jobs:
|
|
188
|
+
state_objects.append(job_spec.dump_to_json_serializable())
|
|
189
|
+
return json.dumps(state_objects, cls=NonJsonObjectEncoder)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
# load serialized json to jobs
|
|
193
|
+
def load_jobs_json(state):
|
|
194
|
+
state_objects = json.loads(state, object_hook=as_python_object)
|
|
195
|
+
jobs = []
|
|
196
|
+
for job_state in state_objects:
|
|
197
|
+
job_spec = JobSpec()
|
|
198
|
+
job_spec.load_from_json_serializable(job_state)
|
|
199
|
+
jobs.append(job_spec)
|
|
200
|
+
return jobs
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
# get resource type for a job
|
|
204
|
+
def get_resource_type_job(resource_map: list, job_spec: JobSpec) -> str:
|
|
205
|
+
"""
|
|
206
|
+
Get the resource type for a job based on the job's resource type and the list of resource types.
|
|
207
|
+
:param resource_map: The list of resource types.
|
|
208
|
+
:param job_spec: The job.
|
|
209
|
+
:return: The resource type.
|
|
210
|
+
"""
|
|
211
|
+
for resource_spec in resource_map:
|
|
212
|
+
if resource_spec.match_job(job_spec):
|
|
213
|
+
return resource_spec.resource_name
|
|
214
|
+
return "Undefined"
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
# get min ram count for job
|
|
218
|
+
def getJobMinRamCount(taskSpec, inputChunk, siteSpec, coreCount):
|
|
219
|
+
minRamCount = inputChunk.getMaxRamCount()
|
|
220
|
+
if inputChunk.isMerging:
|
|
221
|
+
minRamUnit = "MB"
|
|
222
|
+
else:
|
|
223
|
+
minRamUnit = taskSpec.ramUnit
|
|
224
|
+
if minRamUnit in [None, "", "NULL"]:
|
|
225
|
+
minRamUnit = "MB"
|
|
226
|
+
if taskSpec.ramPerCore():
|
|
227
|
+
minRamCount *= coreCount
|
|
228
|
+
minRamCount += taskSpec.baseRamCount
|
|
229
|
+
minRamUnit = re.sub("PerCore.*$", "", minRamUnit)
|
|
230
|
+
# round up with chunks
|
|
231
|
+
minRamCount = compensate_ram_count(minRamCount)
|
|
232
|
+
return minRamCount, minRamUnit
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""
|
|
2
|
+
nucleus specification
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import re
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class NucleusSpec(object):
|
|
10
|
+
# constructor
|
|
11
|
+
def __init__(self, name):
|
|
12
|
+
self.name = name
|
|
13
|
+
self.allPandaSites = []
|
|
14
|
+
self.allDdmEndPoints = {}
|
|
15
|
+
self.all_ddm_endpoints_in = {}
|
|
16
|
+
self.state = None
|
|
17
|
+
self.bareNucleus = None
|
|
18
|
+
self.secondaryNucleus = None
|
|
19
|
+
self.nucleus = True
|
|
20
|
+
self.default_ddm_endpoint_out = None
|
|
21
|
+
|
|
22
|
+
# add
|
|
23
|
+
def add(self, siteName, ddmSpecDict, ddmSpecDictForInput=None):
|
|
24
|
+
if siteName not in self.allPandaSites:
|
|
25
|
+
self.allPandaSites.append(siteName)
|
|
26
|
+
# add local endpoints
|
|
27
|
+
for scope in ddmSpecDict:
|
|
28
|
+
ddmSpec = ddmSpecDict[scope]
|
|
29
|
+
for localEndPoint in ddmSpec.getLocalEndPoints():
|
|
30
|
+
if localEndPoint not in self.allDdmEndPoints:
|
|
31
|
+
self.allDdmEndPoints[localEndPoint] = ddmSpec.getEndPoint(localEndPoint)
|
|
32
|
+
if ddmSpecDictForInput is not None:
|
|
33
|
+
# add endpoints
|
|
34
|
+
for scope in ddmSpecDictForInput:
|
|
35
|
+
ddmSpec = ddmSpecDictForInput[scope]
|
|
36
|
+
for localEndPoint in ddmSpec.getAllEndPoints():
|
|
37
|
+
if localEndPoint not in self.all_ddm_endpoints_in:
|
|
38
|
+
self.all_ddm_endpoints_in[localEndPoint] = ddmSpec.getEndPoint(localEndPoint)
|
|
39
|
+
|
|
40
|
+
# check if associated panda site
|
|
41
|
+
def isAssociatedPandaSite(self, siteName):
|
|
42
|
+
return siteName in self.allPandaSites
|
|
43
|
+
|
|
44
|
+
# check if associated DDM endpoint
|
|
45
|
+
def isAssociatedEndpoint(self, endPoint):
|
|
46
|
+
return endPoint in self.allDdmEndPoints
|
|
47
|
+
|
|
48
|
+
# check if associated endpoint for input
|
|
49
|
+
def is_associated_for_input(self, endpoint):
|
|
50
|
+
return endpoint in self.all_ddm_endpoints_in
|
|
51
|
+
|
|
52
|
+
# get associated DDM endpoint
|
|
53
|
+
def getEndpoint(self, endpoint):
|
|
54
|
+
try:
|
|
55
|
+
if endpoint in self.allDdmEndPoints:
|
|
56
|
+
return self.allDdmEndPoints[endpoint]
|
|
57
|
+
return self.all_ddm_endpoints_in[endpoint]
|
|
58
|
+
except Exception:
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
def getAssociatedEndpoint(self, pattern):
|
|
62
|
+
pattern = pattern.split("/")[-1]
|
|
63
|
+
if pattern.startswith("dst:"):
|
|
64
|
+
pattern = pattern.split(":")[-1]
|
|
65
|
+
|
|
66
|
+
if pattern in self.allDdmEndPoints:
|
|
67
|
+
return self.allDdmEndPoints[pattern]
|
|
68
|
+
|
|
69
|
+
for endpoint_name in self.allDdmEndPoints:
|
|
70
|
+
if re.search(pattern, endpoint_name) is not None:
|
|
71
|
+
return self.allDdmEndPoints[endpoint_name]
|
|
72
|
+
|
|
73
|
+
pattern_without_vo = re.sub("ATLAS", "", pattern)
|
|
74
|
+
|
|
75
|
+
if self.allDdmEndPoints[endpoint_name]["type"] == pattern_without_vo:
|
|
76
|
+
return self.allDdmEndPoints[endpoint_name]
|
|
77
|
+
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
# get one panda site
|
|
81
|
+
def getOnePandaSite(self):
|
|
82
|
+
if len(self.allPandaSites) > 0:
|
|
83
|
+
return self.allPandaSites[0]
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
# set bare nucleus mode
|
|
87
|
+
def set_bare_nucleus_mode(self, mode):
|
|
88
|
+
self.bareNucleus = mode
|
|
89
|
+
|
|
90
|
+
# get bare nucleus mode
|
|
91
|
+
def get_bare_nucleus_mode(self):
|
|
92
|
+
return self.bareNucleus
|
|
93
|
+
|
|
94
|
+
# set secondary nucleus
|
|
95
|
+
def set_secondary_nucleus(self, nucleus):
|
|
96
|
+
self.secondaryNucleus = nucleus
|
|
97
|
+
|
|
98
|
+
# get secondary nucleus
|
|
99
|
+
def get_secondary_nucleus(self):
|
|
100
|
+
return self.secondaryNucleus
|
|
101
|
+
|
|
102
|
+
# set satellite
|
|
103
|
+
def set_satellite(self):
|
|
104
|
+
self.nucleus = False
|
|
105
|
+
|
|
106
|
+
# check if nucleus
|
|
107
|
+
def is_nucleus(self):
|
|
108
|
+
return self.nucleus
|
|
109
|
+
|
|
110
|
+
# set default endpoint for output
|
|
111
|
+
def set_default_endpoint_out(self, rse):
|
|
112
|
+
self.default_ddm_endpoint_out = rse
|
|
113
|
+
|
|
114
|
+
# get default endpoint for output
|
|
115
|
+
def get_default_endpoint_out(self):
|
|
116
|
+
return self.getEndpoint(self.default_ddm_endpoint_out)
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"""
|
|
2
|
+
proxy for database connection
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import atexit
|
|
7
|
+
import logging
|
|
8
|
+
import warnings
|
|
9
|
+
|
|
10
|
+
from pandacommon.pandalogger.PandaLogger import PandaLogger
|
|
11
|
+
|
|
12
|
+
from pandaserver.config import panda_config
|
|
13
|
+
from pandaserver.taskbuffer.db_proxy_mods import (
|
|
14
|
+
data_carousel_module,
|
|
15
|
+
entity_module,
|
|
16
|
+
job_complex_module,
|
|
17
|
+
job_standalone_module,
|
|
18
|
+
metrics_module,
|
|
19
|
+
misc_standalone_module,
|
|
20
|
+
task_complex_module,
|
|
21
|
+
task_event_module,
|
|
22
|
+
task_standalone_module,
|
|
23
|
+
task_utils_module,
|
|
24
|
+
worker_module,
|
|
25
|
+
workflow_module,
|
|
26
|
+
)
|
|
27
|
+
from pandaserver.taskbuffer.WrappedCursor import WrappedCursor
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
import idds.common.constants
|
|
31
|
+
import idds.common.utils
|
|
32
|
+
from idds.client.client import Client as iDDS_Client
|
|
33
|
+
except ImportError:
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
if panda_config.backend == "oracle":
|
|
37
|
+
import oracledb
|
|
38
|
+
|
|
39
|
+
from . import wrapped_oracle_conn
|
|
40
|
+
|
|
41
|
+
oracledb.init_oracle_client()
|
|
42
|
+
|
|
43
|
+
elif panda_config.backend == "postgres":
|
|
44
|
+
import psycopg2 as psycopg
|
|
45
|
+
|
|
46
|
+
from . import WrappedPostgresConn
|
|
47
|
+
|
|
48
|
+
else:
|
|
49
|
+
import MySQLdb
|
|
50
|
+
|
|
51
|
+
warnings.filterwarnings("ignore")
|
|
52
|
+
|
|
53
|
+
# logger
|
|
54
|
+
_logger = PandaLogger().getLogger("DBProxy")
|
|
55
|
+
_loggerFiltered = PandaLogger().getLogger("DBProxyFiltered")
|
|
56
|
+
|
|
57
|
+
# add handlers
|
|
58
|
+
for handler in _loggerFiltered.handlers:
|
|
59
|
+
handler.setLevel(logging.INFO)
|
|
60
|
+
_logger.addHandler(handler)
|
|
61
|
+
_loggerFiltered.removeHandler(handler)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# proxy
|
|
65
|
+
class DBProxy(
|
|
66
|
+
entity_module.EntityModule,
|
|
67
|
+
metrics_module.MetricsModule,
|
|
68
|
+
worker_module.WorkerModule,
|
|
69
|
+
data_carousel_module.DataCarouselModule,
|
|
70
|
+
task_event_module.TaskEventModule,
|
|
71
|
+
job_complex_module.JobComplexModule,
|
|
72
|
+
job_standalone_module.JobStandaloneModule,
|
|
73
|
+
misc_standalone_module.MiscStandaloneModule,
|
|
74
|
+
task_complex_module.TaskComplexModule,
|
|
75
|
+
task_standalone_module.TaskStandaloneModule,
|
|
76
|
+
task_utils_module.TaskUtilsModule,
|
|
77
|
+
workflow_module.WorkflowModule,
|
|
78
|
+
):
|
|
79
|
+
# constructor
|
|
80
|
+
def __init__(self, useOtherError=False):
|
|
81
|
+
# init modules
|
|
82
|
+
super().__init__(_logger)
|
|
83
|
+
# connection object
|
|
84
|
+
self.conn = None
|
|
85
|
+
# cursor object
|
|
86
|
+
self.cur = None
|
|
87
|
+
|
|
88
|
+
# use special error codes for reconnection in querySQL
|
|
89
|
+
self.useOtherError = useOtherError
|
|
90
|
+
|
|
91
|
+
# set composite modules. use self to share a single database connection
|
|
92
|
+
self.add_composite_module("entity", self)
|
|
93
|
+
self.add_composite_module("metrics", self)
|
|
94
|
+
self.add_composite_module("worker", self)
|
|
95
|
+
self.add_composite_module("task_event", self)
|
|
96
|
+
self.add_composite_module("task_utils", self)
|
|
97
|
+
self.add_composite_module("job_complex", self)
|
|
98
|
+
|
|
99
|
+
# connect to DB
|
|
100
|
+
def connect(
|
|
101
|
+
self,
|
|
102
|
+
dbhost=panda_config.dbhost,
|
|
103
|
+
dbpasswd=panda_config.dbpasswd,
|
|
104
|
+
dbuser=panda_config.dbuser,
|
|
105
|
+
dbname=panda_config.dbname,
|
|
106
|
+
dbtimeout=panda_config.dbtimeout,
|
|
107
|
+
reconnect=False,
|
|
108
|
+
dbport=panda_config.dbport,
|
|
109
|
+
):
|
|
110
|
+
_logger.debug(f"connect : re={reconnect}")
|
|
111
|
+
# keep parameters for reconnect
|
|
112
|
+
if not reconnect:
|
|
113
|
+
self.dbhost = dbhost
|
|
114
|
+
self.dbpasswd = dbpasswd
|
|
115
|
+
self.dbuser = dbuser
|
|
116
|
+
self.dbname = dbname
|
|
117
|
+
self.dbtimeout = dbtimeout
|
|
118
|
+
self.dbport = dbport
|
|
119
|
+
# close old connection
|
|
120
|
+
if reconnect:
|
|
121
|
+
_logger.debug("closing old connection")
|
|
122
|
+
try:
|
|
123
|
+
self.conn.close()
|
|
124
|
+
except Exception:
|
|
125
|
+
_logger.debug("failed to close old connection")
|
|
126
|
+
# connect
|
|
127
|
+
try:
|
|
128
|
+
if self.backend == "oracle":
|
|
129
|
+
conn = oracledb.connect(dsn=self.dbhost, user=self.dbuser, password=self.dbpasswd)
|
|
130
|
+
|
|
131
|
+
def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
|
|
132
|
+
if defaultType == oracledb.CLOB:
|
|
133
|
+
return cursor.var(oracledb.LONG_STRING, arraysize=cursor.arraysize)
|
|
134
|
+
|
|
135
|
+
conn.outputtypehandler = OutputTypeHandler
|
|
136
|
+
self.conn = wrapped_oracle_conn.WrappedOracleConn(conn)
|
|
137
|
+
|
|
138
|
+
elif self.backend == "postgres":
|
|
139
|
+
dsn = {"dbname": self.dbname, "user": self.dbuser, "keepalives_idle": 30, "keepalives_interval": 30, "keepalives": 1}
|
|
140
|
+
if self.dbpasswd:
|
|
141
|
+
dsn["password"] = self.dbpasswd
|
|
142
|
+
if self.dbhost:
|
|
143
|
+
dsn["host"] = self.dbhost
|
|
144
|
+
if self.dbport:
|
|
145
|
+
dsn["port"] = self.dbport
|
|
146
|
+
conn = psycopg.connect(**dsn)
|
|
147
|
+
self.conn = WrappedPostgresConn.WrappedPostgresConn(conn)
|
|
148
|
+
else:
|
|
149
|
+
self.conn = MySQLdb.connect(
|
|
150
|
+
host=self.dbhost,
|
|
151
|
+
db=self.dbname,
|
|
152
|
+
port=self.dbport,
|
|
153
|
+
connect_timeout=self.dbtimeout,
|
|
154
|
+
user=self.dbuser,
|
|
155
|
+
passwd=self.dbpasswd,
|
|
156
|
+
charset="utf8",
|
|
157
|
+
)
|
|
158
|
+
self.cur = WrappedCursor(self.conn)
|
|
159
|
+
try:
|
|
160
|
+
# use SQL dumper
|
|
161
|
+
if panda_config.dump_sql:
|
|
162
|
+
from pandaserver.taskbuffer.SQLDumper import SQLDumper
|
|
163
|
+
|
|
164
|
+
self.cur = SQLDumper(self.cur)
|
|
165
|
+
except Exception:
|
|
166
|
+
pass
|
|
167
|
+
self.hostname = self.cur.initialize()
|
|
168
|
+
if not reconnect:
|
|
169
|
+
atexit.register(self.close_connection)
|
|
170
|
+
_logger.debug(f"connect : re={reconnect} ready")
|
|
171
|
+
return True
|
|
172
|
+
except Exception as e:
|
|
173
|
+
_logger.error(f"connect : {str(e)}")
|
|
174
|
+
return False
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Minimum schema version required for the panda-server to work properly.
|
|
3
|
+
Please always keep this version number up to date.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from pandacommon.pandalogger.PandaLogger import PandaLogger
|
|
7
|
+
|
|
8
|
+
# logger
|
|
9
|
+
_logger = PandaLogger().getLogger("DBSchema")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PandaDBSchemaInfo:
|
|
13
|
+
schema_version = None
|
|
14
|
+
|
|
15
|
+
def method(self):
|
|
16
|
+
schema_version = "0.1.1"
|
|
17
|
+
_logger.debug(f"PanDA schema version required for Server is : {schema_version}")
|
|
18
|
+
return schema_version
|