Skip to content

Commit 95e2e33

Browse files
committed
fix: Refactor the PilotLoggingAgent - download proxies at initialisation (adress #7249)
1 parent c0e5f42 commit 95e2e33

File tree

1 file changed

+58
-27
lines changed

1 file changed

+58
-27
lines changed

src/DIRAC/WorkloadManagementSystem/Agent/PilotLoggingAgent.py

Lines changed: 58 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@
1212
# # imports
1313
import os
1414
import time
15+
import tempfile
1516
from DIRAC import S_OK, S_ERROR, gConfig
1617
from DIRAC.ConfigurationSystem.Client.Helpers.Operations import Operations
1718
from DIRAC.ConfigurationSystem.Client.Helpers.Registry import getVOs
1819
from DIRAC.Core.Base.AgentModule import AgentModule
19-
from DIRAC.Core.Utilities.Proxy import executeWithUserProxy
20+
from DIRAC.Core.Utilities.Proxy import executeWithoutServerCertificate
21+
from DIRAC.Core.Utilities.Proxy import getProxy
2022
from DIRAC.DataManagementSystem.Client.DataManager import DataManager
23+
from DIRAC.ConfigurationSystem.Client.Helpers.Registry import getVOMSAttributeForGroup, getDNForUsername
2124
from DIRAC.WorkloadManagementSystem.Client.TornadoPilotLoggingClient import TornadoPilotLoggingClient
2225

2326

@@ -36,9 +39,8 @@ def __init__(self, *args, **kwargs):
3639
def initialize(self):
3740
"""
3841
agent's initialisation. Use this agent's CS information to:
39-
Determine what Defaults/Shifter shifter proxy to use.,
40-
get the target SE name from the CS.
41-
Obtain log file location from Tornado.
42+
Determine VOs with remote logging enabled,
43+
Determine what Defaults/Shifter shifter proxy to use., download the proxies.
4244
4345
:param self: self reference
4446
"""
@@ -52,25 +54,17 @@ def initialize(self):
5254

5355
if isinstance(self.voList, str):
5456
self.voList = [self.voList]
57+
# download shifter proxies for enabled VOs:
58+
self.proxyDict = {}
5559

56-
return S_OK()
57-
58-
def execute(self):
59-
"""
60-
Execute one agent cycle. Upload log files to the SE and register them in the DFC.
61-
Use a shifter proxy dynamically loaded for every VO
62-
63-
:param self: self reference
64-
"""
65-
voRes = {}
6660
for vo in self.voList:
67-
self.opsHelper = Operations(vo=vo)
61+
opsHelper = Operations(vo=vo)
6862
# is remote pilot logging enabled for the VO ?
69-
pilotLogging = self.opsHelper.getValue("/Pilot/RemoteLogging", False)
63+
pilotLogging = opsHelper.getValue("/Pilot/RemoteLogging", False)
7064
if pilotLogging:
71-
res = self.opsHelper.getOptionsDict("Shifter/DataManager")
65+
res = opsHelper.getOptionsDict("Shifter/DataManager")
7266
if not res["OK"]:
73-
voRes[vo] = "No shifter defined - skipped"
67+
# voRes[vo] = "No shifter defined - skipped"
7468
self.log.error(f"No shifter defined for VO: {vo} - skipping ...")
7569
continue
7670

@@ -80,36 +74,73 @@ def execute(self):
8074
self.log.error(
8175
f"No proxy user or group defined for pilot: VO: {vo}, User: {proxyUser}, Group: {proxyGroup}"
8276
)
83-
voRes[vo] = "No proxy user or group defined - skipped"
8477
continue
8578

8679
self.log.info(f"Proxy used for pilot logging: VO: {vo}, User: {proxyUser}, Group: {proxyGroup}")
87-
res = self.executeForVO( # pylint: disable=unexpected-keyword-arg
88-
vo, proxyUserName=proxyUser, proxyUserGroup=proxyGroup
89-
)
90-
if not res["OK"]:
91-
voRes[vo] = res["Message"]
80+
# download a proxy and save a filename for future use:
81+
result = getDNForUsername(proxyUser)
82+
if not result["OK"]:
83+
self.log.error(f"Could not obtain a DN of user {proxyUser} for VO {vo}, skipped")
84+
continue
85+
userDNs = result["Value"] # a same user may have more than one DN
86+
fd, filename = tempfile.mkstemp(prefix=vo + "__")
87+
os.close(fd)
88+
vomsAttr = getVOMSAttributeForGroup(proxyGroup)
89+
result = getProxy(userDNs, proxyGroup, vomsAttr=vomsAttr, proxyFilePath=filename)
90+
91+
if not result["OK"]:
92+
self.log.error(
93+
f"Could not download a proxy for DN {userDNs}, group {proxyGroup} for VO {vo}, skipped"
94+
)
95+
return result
96+
self.proxyDict[vo] = result["Value"]
97+
98+
return S_OK()
99+
100+
def execute(self):
101+
"""
102+
Execute one agent cycle. Upload log files to the SE and register them in the DFC.
103+
Consider only VOs we have proxies for.
104+
105+
:param self: self reference
106+
"""
107+
voRes = {}
108+
self.log.verbose(f"VOs configured for remote logging: {list(self.proxyDict.keys())}")
109+
originalUserProxy = os.environ.get("X509_USER_PROXY")
110+
for vo, proxy in self.proxyDict.items():
111+
os.environ["X509_USER_PROXY"] = proxy
112+
res = self.executeForVO(vo)
113+
if not res["OK"]:
114+
voRes[vo] = res["Message"]
115+
# restore the original proxy:
116+
if originalUserProxy:
117+
os.environ["X509_USER_PROXY"] = originalUserProxy
118+
else:
119+
os.environ.pop("X509_USER_PROXY", None)
120+
92121
if voRes:
93122
for key, value in voRes.items():
94123
self.log.error(f"Error for {key} vo; message: {value}")
95124
voRes.update(S_ERROR("Agent cycle for some VO finished with errors"))
96125
return voRes
126+
97127
return S_OK()
98128

99-
@executeWithUserProxy
129+
@executeWithoutServerCertificate
100130
def executeForVO(self, vo):
101131
"""
102132
Execute one agent cycle for a VO. It obtains VO-specific configuration pilot options from the CS:
103133
UploadPath - the path where the VO wants to upload pilot logs. It has to start with a VO name (/vo/path).
104134
UploadSE - Storage element where the logs will be kept.
105135
106-
:param str vo: vo enabled for remote pilot logging
136+
:param str vo: vo enabled for remote pilot logging (and a successfully downloaded proxy for the VO)
107137
:return: S_OK or S_ERROR
108138
:rtype: dict
109139
"""
110140

111141
self.log.info(f"Pilot files upload cycle started for VO: {vo}")
112-
res = self.opsHelper.getOptionsDict("Pilot")
142+
opsHelper = Operations(vo=vo)
143+
res = opsHelper.getOptionsDict("Pilot")
113144
if not res["OK"]:
114145
return S_ERROR(f"No pilot section for {vo} vo")
115146
pilotOptions = res["Value"]

0 commit comments

Comments
 (0)