Skip to content

Commit a86cf3e

Browse files
authored
Merge pull request #8297 from chaen/v9.0_fix_excludeStaticList
fix (PilotSync): Remove not only the MasterCS but also its aliases
2 parents 9c79ff5 + f20b817 commit a86cf3e

File tree

2 files changed

+73
-9
lines changed

2 files changed

+73
-9
lines changed

src/DIRAC/WorkloadManagementSystem/Agent/PilotSyncAgent.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
""" This agent syncs CS and pilot files to a web server of your choice
1+
"""This agent syncs CS and pilot files to a web server of your choice
22
33
.. literalinclude:: ../ConfigTemplate.cfg
44
:start-after: ##BEGIN PilotSyncAgent
@@ -7,6 +7,7 @@
77
:caption: PilotsSyncAgent options
88
99
"""
10+
1011
import os
1112
import json
1213
import shutil
@@ -38,8 +39,8 @@ def initialize(self):
3839
self.workingDirectory = self.am_getOption("WorkDirectory")
3940
self.saveDir = self.am_getOption("SaveDirectory", self.saveDir)
4041
self.uploadLocations = self.am_getOption("UploadLocations", self.uploadLocations)
41-
includeMasterCS = self.am_getOption("IncludeMasterCS", self.includeMasterCS)
42-
if isinstance(includeMasterCS, str) and includeMasterCS.lower() in ["n", "no", "false"]:
42+
self.includeMasterCS = self.am_getOption("IncludeMasterCS", self.includeMasterCS)
43+
if isinstance(self.includeMasterCS, str) and self.includeMasterCS.lower() in ["n", "no", "false"]:
4344
self.includeMasterCS = False
4445

4546
self.certAndKeyLocation = getHostCertificateAndKeyLocation()

src/DIRAC/WorkloadManagementSystem/Utilities/PilotCStoJSONSynchronizer.py

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
""" CStoJSONSynchronizer
2-
Module that keeps the pilot parameters file synchronized with the information
3-
in the Operations/Pilot section of the CS. If there are additions in the CS,
4-
these are incorporated to the file.
5-
The module uploads to a web server the latest version of the pilot scripts.
1+
"""CStoJSONSynchronizer
2+
Module that keeps the pilot parameters file synchronized with the information
3+
in the Operations/Pilot section of the CS. If there are additions in the CS,
4+
these are incorporated to the file.
5+
The module uploads to a web server the latest version of the pilot scripts.
66
"""
7+
78
import datetime
89
import glob
910
import os
@@ -19,6 +20,67 @@
1920
from DIRAC.ConfigurationSystem.Client.Helpers.Path import cfgPath
2021
from DIRAC.Core.Utilities.ReturnValues import DOKReturnType, DReturnType
2122

23+
import socket
24+
from urllib.parse import urlparse
25+
26+
27+
def exclude_master_cs_aliases(urls: list[str], master_cs_url: str) -> list[str]:
28+
"""
29+
Excludes URLs that are DNS aliases of the given MasterCS server URL.
30+
31+
This function resolves the IP addresses of the MasterCS server and each URL in the input list.
32+
It returns a new list containing only those URLs whose hostnames do not resolve to any of the
33+
MasterCS server's IP addresses, effectively excluding all DNS aliases of the MasterCS server.
34+
35+
Args:
36+
urls (list[str]): A list of URLs to filter. Each URL should be a string in a valid URL format.
37+
master_cs_url (str): The reference URL (e.g., MasterCS server URL) whose DNS aliases are to be excluded.
38+
39+
Returns:
40+
list[str]: A new list of URLs with all aliases of the MasterCS server removed.
41+
If the MasterCS hostname cannot be resolved, the original list is returned unchanged.
42+
43+
Example:
44+
>>> urls = [
45+
... 'dips://lbvobox303.cern.ch:9135/Configuration/Server',
46+
... 'dips://ccwlcglhcb02.in2p3.fr:9135/Configuration/Server',
47+
... 'dips://lbvobox302.cern.ch:9135/Configuration/Server',
48+
... ]
49+
>>> master_cs_url = "dips://mastercs.cern.ch:9135/Configuration/Server"
50+
>>> exclude_master_cs_aliases(urls, master_cs_url)
51+
['dips://ccwlcglhcb02.in2p3.fr:9135/Configuration/Server']
52+
53+
Notes:
54+
- If the MasterCS hostname cannot be resolved, the function returns the original list.
55+
- If a hostname in the input list cannot be resolved, it is included in the result.
56+
- The comparison is based on IP addresses, not hostnames.
57+
"""
58+
master_cs_hostname = urlparse(master_cs_url).hostname
59+
if not master_cs_hostname:
60+
return urls
61+
62+
# Resolve IP addresses for the MasterCS hostname
63+
try:
64+
master_cs_ips = set(socket.gethostbyname_ex(master_cs_hostname)[2])
65+
except socket.gaierror:
66+
return urls
67+
68+
# Function to get IPs for a hostname
69+
def get_ips(hostname):
70+
try:
71+
return set(socket.gethostbyname_ex(hostname)[2])
72+
except socket.gaierror:
73+
return set()
74+
75+
filtered_urls = []
76+
for url in urls:
77+
hostname = urlparse(url).hostname
78+
ips = get_ips(hostname)
79+
if not ips & master_cs_ips:
80+
filtered_urls.append(url)
81+
82+
return filtered_urls
83+
2284

2385
class PilotCStoJSONSynchronizer:
2486
"""
@@ -151,7 +213,8 @@ def getCSDict(self, includeMasterCS: bool = True) -> DReturnType[Any]:
151213
configurationServers = gConfig.getServersList()
152214
if not includeMasterCS:
153215
masterCS = gConfigurationData.getMasterServer()
154-
configurationServers = list(set(configurationServers) - {masterCS})
216+
configurationServers = exclude_master_cs_aliases(configurationServers, masterCS)
217+
155218
pilotDict["ConfigurationServers"] = configurationServers
156219

157220
self.log.debug("Got pilotDict", str(pilotDict))

0 commit comments

Comments
 (0)