Skip to content

Commit 288d60b

Browse files
committed
Conflicts resolved with rel-v7r2
2 parents 5159f14 + 94165d8 commit 288d60b

File tree

57 files changed

+1211
-1018
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1211
-1018
lines changed

.github/workflows/basic-python3.yml

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,7 @@ jobs:
1919
# TODO These three tests fail on Python 3:
2020
# * `test_BaseType_Unicode` and `test_nestedStructure` fail due to
2121
# DISET's string and unicode types being poorly defined
22-
# * `testLockedClass` deadlocks frequently due to the use of
23-
# self.__processThread._Thread__stop(). Officially "threads
24-
# cannot be destroyed, stopped, suspended, resumed, or
25-
# interrupted" so the code should be rewritten to follow the
26-
# supported alternative: "If you want your threads to stop
27-
# gracefully, make them non-daemonic and use a suitable
28-
# signalling mechanism such as an Event."
29-
- pytest --runslow -k 'not test_BaseType_Unicode and not test_nestedStructure and not testLockedClass'
22+
- pytest --runslow -k 'not test_BaseType_Unicode and not test_nestedStructure'
3023
- pylint -E src/
3124

3225
steps:

dirac.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,8 @@ Operations
665665
FTS3
666666
{
667667
ServerPolicy = Random # http://dirac.readthedocs.io/en/latest/AdministratorGuide/Systems/DataManagement/fts.html#ftsserver-policy
668+
# Plugin to alter default TPC selection list
669+
FTS3Plugin = Default # http://dirac.readthedocs.io/en/latest/AdministratorGuide/Systems/DataManagement/fts.html#fts3-plugins
668670
}
669671
}
670672
}

docs/source/AdministratorGuide/Resources/storage.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,11 @@ External services like FTS requires pair of URLs to perform third party copy.
307307
This is implemented using the same logic as described above. There is however an extra step: once the common protocols between 2 SEs have been filtered, an extra loop filter is done to make sure that the selected protocol can be used as read from the source and as write to the destination. Finally, the URLs which are returned are not necessarily the url of the common protocol, but are the native urls of the plugin that can accept/generate the common protocol. For example, if the common protocol is gsiftp but one of the SE has only an SRM plugin, then you will get an srm URL (which is compatible with gsiftp).
308308

309309

310+
.. versionadded:: v7r1p37
311+
The FTS3Agent can now use plugins to influence the list of TPC protocols used. See :ref:`fts3`
312+
313+
314+
310315
Protocol matrix
311316
^^^^^^^^^^^^^^^
312317

docs/source/AdministratorGuide/Systems/DataManagement/fts3.rst

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Operations configuration
5050

5151
* DataManagement/FTSVersion: FTS2/FTS3. Set it to FTS3...
5252
* DataManagement/FTSPlacement/FTS3/ServerPolicy: Policy to choose the FTS server see `FTSServer policy`_.
53+
* DataManagement/FTSPlacement/FTS3/FTS3Plugin: Plugin to alter the behavior of the FTS3Agent
5354

5455

5556
======================
@@ -92,11 +93,11 @@ The RMS will create one FTS3TransferOperation per RMS Operation, and one FTS3Fil
9293
The grouping into jobs is done following this logic:
9394
* Group by target SE
9495
* Group by source SE. If not specified, we take the active replicas as returned by the DataManager
95-
* Since their might be several possible source SE, we need to pick one only. The choice is to select the SE where there is the most files of the operation present. This increases the likely hood to pick a good old Tier1
96+
* Since there might be several possible source SEs, we need to pick one only. By default, the choice is random, but this can be changed (see FTS3Plugins)
9697
* Divide all that according to the maximum number of files we want per job
9798

9899
Once the FTS jobs have been executed, and all the operation is completed, the callback takes place. The callback consists in fetching the RMS request which submitted the FTS3Operation, update the status of the RMS files, and insert a Registration Operation.
99-
Note that since the multiple targets are grouped in a single RMS operation, failing to transfer one file t one destination will result in the failure of the Operation. However, there is one Registration operation per target, and hence correctly transferred files will be registered.
100+
Note that since the multiple targets are grouped in a single RMS operation, failing to transfer one file to one destination will result in the failure of the Operation. However, there is one Registration operation per target, and hence correctly transferred files will be registered.
100101

101102
====================
102103
FTS3StagingOperation
@@ -170,3 +171,13 @@ States from the FTS3Job::
170171
The status of the FTS3Jobs and FTSFiles are updated every time we monitor the matching job.
171172

172173
The FTS3Operation goes to Processed when all the files are in a final state, and to Finished when the callback has been called successfully
174+
175+
176+
FTS3 Plugins
177+
------------
178+
179+
.. versionadded:: v7r1p37
180+
The ``FTS3Plugin`` option
181+
182+
183+
The ``FTS3Plugin`` option allows one to specify a plugin to alter some default choices made by the FTS3 system. These choices concern the list of third party protocols used, as well as the selection of a source storage element. This can be useful if you want to implement a matrix-like selection of protocols, or if some links require specific protocols, etc. The plugins must be placed in :py:mod:`DIRAC.DataManagementSystem.private.FTS3Plugins`. The default behaviors, as well as the documentation on how to implement your own plugin can be found in :py:mod:`DIRAC.DataManagementSystem.private.FTS3Plugins.DefaultFTS3Plugin`

docs/source/DeveloperGuide/AddingNewComponents/DevelopingCommands/index.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ which will set the interpreter directive to the python on the environment.
3737

3838
**2.** The next is the documentation line which is describing the command. This same documentation line will be used also the command help information available with the *-h* command switch.
3939

40-
**3.** The majority of the code should be contained with a function, often called ``main`` though this is not required. This function should be wrapped with the ``@DiracScript()`` decorator to allow the DIRAC plugin mechanism to override the script with the function from the highest priority extension.
40+
**3.** The majority of the code should be contained with a function, often called ``main`` though this is not required. This function should be wrapped with the ``@DIRACScript()`` decorator to allow the DIRAC plugin mechanism to override the script with the function from the highest priority extension.
4141

4242
.. code-block:: python
4343
@@ -46,8 +46,8 @@ which will set the interpreter directive to the python on the environment.
4646
from DIRAC.Interfaces.API.DIRAC import DIRAC
4747
from DIRAC import gLogger
4848
49-
@DiracScript()
50-
def main()
49+
@DIRACScript()
50+
def main():
5151
# Do stuff
5252
5353
if __name__ == "__main__":

environment-py3.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ dependencies:
99
# Temporary workarounds
1010
- astroid !=2.5 # https://github.com/PyCQA/astroid/issues/903
1111
# runtime
12-
- python =3.8
12+
- python =3.9
1313
- pip
1414
- boto3
1515
- certifi

release.notes

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,32 @@ CHANGE: (#4937) removed StatesMonitoringAgent (use StatesAccountingAgent agent i
1717
*tests
1818
CHANGE: (#5046) don't use mail in the self generated certificates
1919

20+
[v7r2p3]
21+
22+
FIX: Fixes from v7r054 and v7r1p37
23+
FIX: (#5088) Fix various Python 3.9 deprecations
24+
25+
*Core
26+
FIX: (#5095) Avoid KeyError when calling parseCommandLine
27+
28+
*Framework
29+
CHANGE: (#5092) Use String(64) for DIRACVersion column in InstalledComponentsDB.HostLogging
30+
CHANGE: (#5098) in the run files created by ComponentInstaller, execute directly the deployed scripts
31+
32+
*WMS
33+
NEW: (#5073) JobManager service now exposes a "RemoveJob" RPC call
34+
NEW: (#5073) implementing bulk indexing for jobs parameters
35+
CHANGE: (#5073) JobCleaningAgent will not remove those jobs that, while marked "DELETED", have still Operations to do in RMS
36+
37+
*RequestManagement
38+
FIX: (#5091) Ensure BLOB columns are always passed bytes data
39+
40+
*Resources
41+
CHANGE: (#5050) StompMQConnector uses a single connection
42+
43+
*tests
44+
NEW: (#5086) Integration tests can be re-ran locally without re-installing the entire setup
45+
2046
[v7r2p2]
2147

2248
FIX: Fixes from v7r053 and v7r1p36
@@ -154,6 +180,11 @@ NEW: (#4910) --runslow option on unit tests to allow faster local tests
154180
NEW: (#4938) added a helloworld test for the (yet to be implemented) cloud testing in certification
155181
CHANGE: (#4968) Change the defaults for tests (to MySQL 8 and ES 7)
156182

183+
[v7r1p37]
184+
185+
*DataManagement
186+
NEW: (#5096) FTS3 plugins to alter TPC and source SE preferences
187+
157188
[v7r1p36]
158189

159190
*DMS
@@ -769,6 +800,16 @@ FIX: (#4551) align ProxyDB test to current changes
769800
NEW: (#4289) Document how to run integration tests in docker
770801
NEW: (#4551) add DNProperties description to Registry/Users subsection
771802

803+
[v7r0p54]
804+
805+
*Core
806+
FIX: (#5087) Undefined variable error when RabbitMQAdmin fails to connect
807+
808+
*CS
809+
FIX: (#5090) VOMS2CSSynchronizer: add email information about a user joining groups for an additional VO, fix for #5037
810+
FIX: (#5090) VOMS2CSSynchronizer: When a user leaves a second VO, only the membership in these groups is removed
811+
CHANGE: (#5090) VOMS2CSSynchronizer: If email of user is known, do not replace it with None
812+
772813
[v7r0p53]
773814

774815
*Interface

src/DIRAC/ConfigurationSystem/Agent/VOMS2CSAgent.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ def execute(self):
180180
mailMsg += result['Message']
181181
if self.dryRun:
182182
self.log.info("Dry Run: mail won't be sent")
183+
self.log.info(mailMsg)
183184
else:
184185
NotificationClient().sendMail(self.am_getOption('MailTo', voAdminMail),
185186
"VOMS2CSAgent run log", mailMsg,

src/DIRAC/ConfigurationSystem/Client/VOMS2CSSynchronizer.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -316,9 +316,11 @@ def syncCSWithVOMS(self):
316316
modified = False
317317
suspendedInVOMS = self.vomsUserDict[dn]['suspended'] or self.vomsUserDict[dn]['certSuspended']
318318
suspendedVOList = getUserOption(diracName, 'Suspended', [])
319+
knownEmail = getUserOption(diracName, 'Email', None)
319320
userDict = {"DN": dn,
320321
"CA": self.vomsUserDict[dn]['CA'],
321-
"Email": self.vomsUserDict[dn].get('mail', self.vomsUserDict[dn].get('emailAddress'))}
322+
"Email": self.vomsUserDict[dn].get('mail', self.vomsUserDict[dn].get('emailAddress')) or knownEmail,
323+
}
322324

323325
# Set Suspended status for the user for this particular VO
324326
if suspendedInVOMS and self.vo not in suspendedVOList:
@@ -376,7 +378,12 @@ def syncCSWithVOMS(self):
376378
if groups['OK']:
377379
self.log.info('Found groups for user %s %s' % (diracName, groups['Value']))
378380
userDict['Groups'] = list(set(groups['Value'] + keepGroups))
381+
addedGroups = list(set(userDict['Groups']) - set(groups['Value']))
379382
modified = True
383+
message = "\n Modified user %s:\n" % diracName
384+
message += " Added to group(s) %s\n" % ','.join(addedGroups)
385+
self.adminMsgs['Info'].append(message)
386+
380387

381388
# Check if something changed before asking CSAPI to modify
382389
if diracName in diracUserDict:
@@ -415,15 +422,37 @@ def syncCSWithVOMS(self):
415422
for user in diracUserDict:
416423
dnSet = set(fromChar(diracUserDict[user]['DN']))
417424
if not dnSet.intersection(set(self.vomsUserDict)) and user not in nonVOUserDict:
418-
for group in diracUserDict[user]['Groups']:
419-
if group not in noVOMSGroups:
420-
oldUsers.add(user)
425+
existingGroups = diracUserDict.get(user, {}).get('Groups', [])
426+
nonVOGroups = list(set(existingGroups) - set(diracVOMSMapping))
427+
removedGroups = list(set(existingGroups) - set(nonVOGroups))
428+
if removedGroups:
429+
self.log.info("Checking user for deletion", "%s: %s" % (user, existingGroups))
430+
self.log.info("User has groups in other VOs", "%s: %s" % (user, nonVOGroups))
431+
userDict = diracUserDict[user]
432+
userDict['Groups'] = nonVOGroups
433+
if self.autoModifyUsers:
434+
result = self.csapi.modifyUser(user, userDict)
435+
if result['OK'] and result['Value']:
436+
self.log.info("Modified user %s: %s" % (user, str(userDict)))
437+
self.voChanged = True
438+
message = "\n Modified user %s:\n" % user
439+
modMsg = " Removed from group(s) %s\n" % ','.join(removedGroups)
440+
self.adminMsgs['Info'].append(message + modMsg)
441+
resultDict['ModifiedUsers'].append(user)
442+
continue
443+
if not any(group in noVOMSGroups for group in existingGroups):
444+
oldUsers.add(user)
421445

422446
# Check for obsoleted DNs
423447
for user in diracUserDict:
424448
dnSet = set(fromChar(diracUserDict[user]['DN']))
425449
for dn in dnSet:
426450
if dn in obsoletedDNs and user not in oldUsers:
451+
existingGroups = diracUserDict.get(user, {}).get('Groups', [])
452+
nonVOGroups = list(set(existingGroups) - set(diracVOMSMapping))
453+
if nonVOGroups:
454+
self.log.verbose("User has groups in other VOs", "%s: %s" % (user, nonVOGroups))
455+
continue
427456
self.log.verbose("Modified user %s: dropped DN %s" % (user, dn))
428457
if self.autoModifyUsers:
429458
userDict = diracUserDict[user]
@@ -453,7 +482,7 @@ def syncCSWithVOMS(self):
453482
else:
454483
self.adminMsgs['Info'].append('The following users to be checked for deletion:\n\t%s' %
455484
"\n\t".join(sorted(oldUsers)))
456-
self.log.info('The following users to be checked for deletion: %s' % str(oldUsers))
485+
self.log.info('The following users to be checked for deletion:', "\n\t".join(sorted(oldUsers)))
457486

458487
resultDict['CSAPI'] = self.csapi
459488
resultDict['AdminMessages'] = self.adminMsgs

src/DIRAC/Core/Base/Script.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,10 @@ def parseCommandLine(script=False, ignoreErrors=False, initializeMonitor=False):
6060

6161
# Read and parse the script __doc__ to create a draft help message
6262
if not gIsAlreadySetUsageMsg:
63-
localCfg.setUsageMessage(inspect.currentframe().f_back.f_globals['__doc__'])
63+
try:
64+
localCfg.setUsageMessage(inspect.currentframe().f_back.f_globals['__doc__'])
65+
except KeyError:
66+
pass
6467
gIsAlreadySetUsageMsg = True
6568

6669
if gIsAlreadyInitialized:
@@ -134,7 +137,10 @@ def addDefaultOptionValue(option, value):
134137
def setUsageMessage(usageMessage):
135138
global gIsAlreadySetUsageMsg
136139
gIsAlreadySetUsageMsg = True
137-
localCfg.setUsageMessage(inspect.currentframe().f_back.f_globals['__doc__'])
140+
try:
141+
localCfg.setUsageMessage(inspect.currentframe().f_back.f_globals['__doc__'])
142+
except KeyError:
143+
pass
138144
localCfg.setUsageMessage(usageMessage)
139145

140146

0 commit comments

Comments
 (0)