Skip to content

Commit e21716d

Browse files
authored
Merge pull request #7104 from aldbr/rel-v8r0_FIX_MultiVOProxyRenewal
[8.0] fix: MultiVO proxy renewal in AREXCE
2 parents 08451d4 + d1ebe08 commit e21716d

File tree

1 file changed

+89
-42
lines changed

1 file changed

+89
-42
lines changed

src/DIRAC/Resources/Computing/AREXComputingElement.py

Lines changed: 89 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ def __init__(self, ceUniqueID):
4646
self.restVersion = "1.0"
4747
# Time left before proxy renewal: 3 hours is a good default
4848
self.proxyTimeLeftBeforeRenewal = 10800
49-
# Current delegation ID, generated/fetched in submitJob(), renewed in getJobStatus()
50-
self._delegationID = None
5149
# Timeout
5250
self.timeout = 5.0
5351
# Request session
@@ -187,6 +185,10 @@ def _checkSession(self):
187185
self.headers.pop("Authorization", None)
188186

189187
# Get a proxy: still mandatory, even if tokens are used to authenticate
188+
if not self.proxy:
189+
self.log.error("Proxy not set")
190+
return S_ERROR("Proxy not set")
191+
190192
result = self._prepareProxy()
191193
if not result["OK"]:
192194
self.log.error("Failed to set up proxy", result["Message"])
@@ -198,7 +200,7 @@ def _checkSession(self):
198200
return S_OK()
199201

200202
# Attach the proxy to the session, only if the token is unavailable
201-
self.session.cert = Locations.getProxyLocation()
203+
self.session.cert = os.environ["X509_USER_PROXY"]
202204
return S_OK()
203205

204206
#############################################################################
@@ -241,15 +243,8 @@ def __uploadCertificate(self, delegationID, csrContent):
241243
headers = {"Content-Type": "x-pem-file"}
242244
query = self._urlJoin(os.path.join("delegations", delegationID))
243245

244-
# Get a proxy and sign the CSR
245-
proxy = X509Chain()
246-
proxyFile = Locations.getProxyLocation()
247-
if not proxyFile:
248-
return S_ERROR(f"No proxy available")
249-
result = proxy.loadProxyFromFile(proxyFile)
250-
if not result["OK"]:
251-
return S_ERROR(f"Can't load {proxyFile}: {result['Message']}")
252-
result = proxy.generateChainFromRequestString(csrContent)
246+
# Sign the CSR
247+
result = self.proxy.generateChainFromRequestString(csrContent)
253248
if not result["OK"]:
254249
self.log.error("Problem with the Certificate Signing Request:", result["Message"])
255250
return S_ERROR("Problem with the Certificate Signing Request")
@@ -322,6 +317,32 @@ def _getDelegationIDs(self):
322317
delegationIDs = [delegationContent["id"] for delegationContent in delegations]
323318
return S_OK(delegationIDs)
324319

320+
def _getProxyFromDelegationID(self, delegationID):
321+
"""Get proxy stored within the delegation
322+
323+
:param str delegationID: delegation ID
324+
"""
325+
query = self._urlJoin(os.path.join("delegations", delegationID))
326+
params = {"action": "get"}
327+
328+
# Submit the POST request to get the delegation
329+
result = self._request("post", query, params=params)
330+
if not result["OK"]:
331+
self.log.error("Issue while interacting with the delegations.", result["Message"])
332+
return S_ERROR("Issue while interacting with the delegations")
333+
response = result["Value"]
334+
335+
proxyContent = response.text
336+
proxy = X509Chain()
337+
result = proxy.loadChainFromString(proxyContent)
338+
if not result["OK"]:
339+
self.log.error(
340+
"Issue while trying to load proxy content from delegation", f"{delegationID}: {result['Message']}"
341+
)
342+
return S_ERROR("Issue while trying to load proxy content from delegation")
343+
344+
return S_OK(proxy)
345+
325346
#############################################################################
326347

327348
def _getArcJobID(self, executableFile, inputs, outputs, delegation):
@@ -406,18 +427,33 @@ def submitJob(self, executableFile, proxy, numberOfJobs=1, inputs=None, outputs=
406427
if not result["OK"]:
407428
self.log.error("Could not get delegation IDs.", result["Message"])
408429
return S_ERROR("Could not get delegation IDs")
409-
410430
delegationIDs = result["Value"]
411-
if not delegationIDs:
431+
432+
# Get the delegationID which corresponds to the DIRAC group of the proxy if it exists
433+
currentDelegationID = None
434+
proxyGroup = self.proxy.getDIRACGroup()
435+
for delegationID in delegationIDs:
436+
# Get the proxy attached to the delegationID
437+
result = self._getProxyFromDelegationID(delegationID)
438+
if not result["OK"]:
439+
return result
440+
proxy = result["Value"]
441+
442+
if proxy.getDIRACGroup() != proxyGroup:
443+
continue
444+
445+
# If we are here, we have found the right delegationID to use
446+
currentDelegationID = delegationID
447+
448+
if not currentDelegationID:
412449
# No existing delegation, we need to prepare one
413450
result = self._prepareDelegation()
414451
if not result["OK"]:
415452
self.log.warn("Could not get a new delegation", f"for CE {self.ceHost}")
416453
return S_ERROR("Could not get a new delegation")
417-
self._delegationID = result["Value"]
418-
else:
419-
self._delegationID = delegationIDs[0]
420-
delegation = f"\n(delegationid={self._delegationID})"
454+
currentDelegationID = result["Value"]
455+
456+
delegation = f"\n(delegationid={currentDelegationID})"
421457

422458
if not inputs:
423459
inputs = []
@@ -562,10 +598,14 @@ def getCEStatus(self):
562598
self.log.error("Cannot get CE Status", result["Message"])
563599
return result
564600

565-
# Try to find out which VO we are running for.
601+
# Find out which VO we are running for.
566602
# Essential now for REST interface.
567-
res = getVOfromProxyGroup()
568-
vo = res["Value"] if res["OK"] else ""
603+
result = getVOfromProxyGroup()
604+
if not result["OK"]:
605+
return result
606+
if not result["Value"]:
607+
return S_ERROR("Could not get VO value from the proxy group")
608+
vo = result["Value"]
569609

570610
# Prepare the command
571611
params = {"schema": "glue2"}
@@ -599,33 +639,36 @@ def getCEStatus(self):
599639

600640
#############################################################################
601641

602-
def _renewDelegation(self):
603-
"""Renew the delegations"""
642+
def _renewDelegation(self, delegationID):
643+
"""Renew the delegation
644+
645+
:params delegationID: delegation ID to renew
646+
"""
604647
# Prepare the command
605648
params = {"action": "get"}
606-
query = self._urlJoin(os.path.join("delegations", self._delegationID))
649+
query = self._urlJoin(os.path.join("delegations", delegationID))
607650

608651
# Submit the POST request to get the proxy
609652
result = self._request("post", query, params=params)
610653
if not result["OK"]:
611-
self.log.error("Could not get a proxy for", f"delegation {self._delegationID}: {result['Message']}")
612-
return S_ERROR(f"Could not get a proxy for delegation {self._delegationID}")
654+
self.log.error("Could not get a proxy for", f"delegation {delegationID}: {result['Message']}")
655+
return S_ERROR(f"Could not get a proxy for delegation {delegationID}")
613656
response = result["Value"]
614657

615658
proxy = X509Chain()
616659
result = proxy.loadChainFromString(response.text)
617660
if not result["OK"]:
618-
self.log.error("Could not load proxy for", f"delegation {self._delegationID}: {result['Message']}")
619-
return S_ERROR(f"Could not load proxy for delegation {self._delegationID}")
661+
self.log.error("Could not load proxy for", f"delegation {delegationID}: {result['Message']}")
662+
return S_ERROR(f"Could not load proxy for delegation {delegationID}")
620663

621664
# Now test and renew the proxy
622665
result = proxy.getRemainingSecs()
623666
if not result["OK"]:
624667
self.log.error(
625668
"Could not get remaining time from the proxy for",
626-
f"delegation {self._delegationID}: {result['Message']}",
669+
f"delegation {delegationID}: {result['Message']}",
627670
)
628-
return S_ERROR(f"Could not get remaining time from the proxy for delegation {self._delegationID}")
671+
return S_ERROR(f"Could not get remaining time from the proxy for delegation {delegationID}")
629672
timeLeft = result["Value"]
630673

631674
if timeLeft >= self.proxyTimeLeftBeforeRenewal:
@@ -634,31 +677,31 @@ def _renewDelegation(self):
634677

635678
self.log.verbose(
636679
"Renewing delegation",
637-
f"{self._delegationID} whose proxy expires at {timeLeft}",
680+
f"{delegationID} whose proxy expires at {timeLeft}",
638681
)
639682
# Proxy needs to be renewed - try to renew it
640683
# First, get a new CSR from the delegation
641684
params = {"action": "renew"}
642-
query = self._urlJoin(os.path.join("delegations", self._delegationID))
685+
query = self._urlJoin(os.path.join("delegations", delegationID))
643686
result = self._request("post", query, params=params)
644687
if not result["OK"]:
645688
self.log.error(
646689
"Proxy not renewed, failed to get CSR",
647-
f"for delegation {self._delegationID}",
690+
f"for delegation {delegationID}",
648691
)
649-
return S_ERROR(f"Proxy not renewed, failed to get CSR for delegation {self._delegationID}")
692+
return S_ERROR(f"Proxy not renewed, failed to get CSR for delegation {delegationID}")
650693
response = result["Value"]
651694

652695
# Then, sign and upload the certificate
653-
result = self.__uploadCertificate(self._delegationID, response.text)
696+
result = self.__uploadCertificate(delegationID, response.text)
654697
if not result["OK"]:
655698
self.log.error(
656699
"Proxy not renewed, failed to send renewed proxy",
657-
f"delegation {self._delegationID}: {result['Message']}",
700+
f"delegation {delegationID}: {result['Message']}",
658701
)
659-
return S_ERROR(f"Proxy not renewed, failed to send renewed proxy for delegation {self._delegationID}")
702+
return S_ERROR(f"Proxy not renewed, failed to send renewed proxy for delegation {delegationID}")
660703

661-
self.log.verbose("Proxy successfully renewed", f"for delegation {self._delegationID}")
704+
self.log.verbose("Proxy successfully renewed", f"for delegation {delegationID}")
662705

663706
return S_OK()
664707

@@ -714,12 +757,16 @@ def getJobStatus(self, jobIDList):
714757
jobsToCancel.append(arcJob["id"])
715758
self.log.debug(f"Killing held job {jobID}")
716759

717-
# Renew delegation to renew the proxies of the jobs
718-
if self._delegationID:
719-
result = self._renewDelegation()
760+
# Renew delegations to renew the proxies of the jobs
761+
result = self._getDelegationIDs()
762+
if not result["OK"]:
763+
return result
764+
delegationIDs = result["Value"]
765+
for delegationID in delegationIDs:
766+
result = self._renewDelegation(delegationID)
720767
if not result["OK"]:
721768
# Only log here as we still want to return statuses
722-
self.log.warn("Failed to renew delegation", f"{self._delegationID}: {result['Message']}")
769+
self.log.warn("Failed to renew delegation", f"{delegationID}: {result['Message']}")
723770

724771
# Kill held jobs
725772
if jobsToCancel:

0 commit comments

Comments
 (0)