Skip to content

Commit c379267

Browse files
authored
Merge pull request #8291 from alex-rg/add_remoteonly_access_option
[9.1] support "remoteonly" value for the Access protocol parameter
2 parents 497d619 + 1b643d9 commit c379267

File tree

3 files changed

+40
-10
lines changed

3 files changed

+40
-10
lines changed

docs/source/AdministratorGuide/Resources/storage.rst

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ DIRAC provides an abstraction of a SE interface that allows to access different
2020
# The name of the DIRAC Plugin module to be used for implementation
2121
# of the access protocol
2222
PluginName = SRM2
23-
# Flag specifying the access type (local/remote)
23+
# Flag specifying the access type (local/remote/remoteonly)
2424
Access = remote
2525
# Protocol name
2626
Protocol = srm
@@ -50,6 +50,7 @@ Configuration options are:
5050
* ``UseCatalogURL``: default ``False``. If ``True``, use the url stored in the catalog instead of regenerating it
5151
* ``ChecksumType``: default ``ADLER32``. NOT ACTIVE !
5252
* ``Alias``: when set to the name of another storage element, it instanciates the other SE instead.
53+
* ``Access``: Can be ``local``, ``remote`` or ``remoteonly``. Options specify that the protocol can be used in local (e.g. upload from a WN to local SE), remote+local or remote context.
5354
* ``ReadAccess``: default ``True``. Allowed for Read if no RSS enabled (:ref:`activateRSS`)
5455
* ``WriteAccess``: default ``True``. Allowed for Write if no RSS enabled
5556
* ``CheckAccess``: default ``True``. Allowed for Check if no RSS enabled
@@ -221,7 +222,7 @@ There are also a set of plugins based on the `gfal2 libraries <https://dmc-docs.
221222

222223
Default plugin options:
223224

224-
* ``Access``: ``Remote`` or ``Local``. If ``Local``, then this protocol can be used only if we are running at the site to which the SE is associated. Typically, if a site mounts the storage as NFS, the ``file`` protocol can be used.
225+
* ``Access``: ``Remote``, ``Local`` or ``RemoteOnly``. If ``Local``, then this protocol can be used only if we are running at the site to which the SE is associated. Typically, if a site mounts the storage as NFS, the ``file`` protocol can be used. If ``RemoteOnly``, this protocol is not used when running at the site. For example, if you need to use a different hostname within the site than from outside.
225226
* InputProtocols/OutputProtocols: a given plugin normally contain a hard coded list of protocol it is able to generate or accept as input. There are however seldom cases (like SRM) where the site configuration may change these lists. These options are here to accomodate for that case.
226227

227228
GRIDFTP Optimisation
@@ -317,6 +318,32 @@ You need to define a protocol section with SRM, specifying that a ``file`` URL c
317318
}
318319

319320

321+
RemoteOnly protocol definition
322+
------------------------------
323+
324+
Some sites may want you to have a different endpoint when running on the worker node than when transfering files via FTS. Or they recommend a protocol remotely only. This is possible with the ``RemoteOnly`` only option::
325+
326+
327+
HTTPsConfig
328+
{
329+
Host = webdav.fromoutside.ac.uk
330+
Port = 1094
331+
PluginName = Echo
332+
Protocol = https
333+
Path = lhcb:mydata
334+
Access = remoteonly
335+
}
336+
HTTPsConfigLocal
337+
{
338+
Host = inner-webdav-gateway..ac.uk
339+
Port = 1095
340+
PluginName = Echo
341+
Protocol = https
342+
Path = lhcb:mydata
343+
Access = local
344+
}
345+
346+
320347

321348
.. _multiProtocol:
322349

src/DIRAC/Resources/Storage/StorageElement.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,7 +1092,6 @@ def __filterPlugins(self, methodName, protocols=None, inputProtocol=None):
10921092
Returns:
10931093
list: list of storage plugins
10941094
"""
1095-
10961095
log = self.log.getSubLogger("__filterPlugins")
10971096
log.debug(f"Filtering plugins for {methodName} (protocol = {protocols} ; inputProtocol = {inputProtocol})")
10981097

@@ -1104,6 +1103,8 @@ def __filterPlugins(self, methodName, protocols=None, inputProtocol=None):
11041103
potentialProtocols = []
11051104
allowedProtocols = []
11061105

1106+
localSE = self.__isLocalSE()["Value"]
1107+
11071108
if methodName in self.readMethods + self.checkMethods:
11081109
allowedProtocols = self.localAccessProtocolList
11091110
elif methodName in self.stageMethods:
@@ -1125,12 +1126,12 @@ def __filterPlugins(self, methodName, protocols=None, inputProtocol=None):
11251126
pluginsToUse = list(self.storages.values())
11261127

11271128
# The closest list for "OK" methods is the AccessProtocol preference, so we sort based on that
1128-
1129+
# note: False < True, so to have local plugin first IF we are in a localSE, we use the remoteProtocol list
11291130
pluginsToUse = sorted(
11301131
pluginsToUse,
11311132
key=lambda x: (
11321133
getIndexInList(x.protocolParameters["Protocol"], self.localAccessProtocolList),
1133-
x.protocolSectionName in self.remoteProtocolSections,
1134+
x.protocolSectionName in (self.remoteProtocolSections if localSE else self.localAccessProtocolList),
11341135
),
11351136
)
11361137

@@ -1147,12 +1148,11 @@ def __filterPlugins(self, methodName, protocols=None, inputProtocol=None):
11471148

11481149
log.debug(f"Potential protocols {potentialProtocols}")
11491150

1150-
localSE = self.__isLocalSE()["Value"]
1151-
11521151
for protocolSection, plugin in self.storages.items():
11531152
# Determine whether to use this storage object
11541153
pluginParameters = plugin.getParameters()
11551154
isProxyPlugin = pluginParameters.get("PluginName") == "Proxy"
1155+
isRemoteOnly = pluginParameters.get("Access", "").lower() == "remoteonly"
11561156

11571157
if not pluginParameters:
11581158
log.debug("Failed to get storage parameters.", f"{self.name} {protocolSection}")
@@ -1167,6 +1167,10 @@ def __filterPlugins(self, methodName, protocols=None, inputProtocol=None):
11671167
log.debug(f"Plugin {protocolSection} not allowed for {methodName}.")
11681168
continue
11691169

1170+
# If protocol is remote only and the context is local, skip it.
1171+
if isRemoteOnly and localSE:
1172+
continue
1173+
11701174
# If we are attempting a putFile and we know the inputProtocol
11711175
if methodName == "putFile" and inputProtocol:
11721176
if inputProtocol not in pluginParameters["InputProtocols"]:
@@ -1188,7 +1192,6 @@ def __filterPlugins(self, methodName, protocols=None, inputProtocol=None):
11881192
)
11891193

11901194
log.debug(f"Plugins to be used for {methodName}: {[p.protocolSectionName for p in pluginsToUse]}")
1191-
11921195
return pluginsToUse
11931196

11941197
def __executeMethod(self, lfn, *args, **kwargs):

src/DIRAC/Resources/Storage/StorageFactory.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,14 +333,14 @@ def _getConfigStorageProtocols(self, storageName, derivedStorageName=None, seCon
333333
for protocolSectionName, protocolDict in self.protocols.items():
334334
# Now update the local and remote protocol lists.
335335
# A warning will be given if the Access option is not set to local or remote.
336-
if protocolDict["Access"].lower() == "remote":
336+
if protocolDict["Access"].lower() in ("remote", "remoteonly"):
337337
self.remoteProtocolSections.append(protocolSectionName)
338338
elif protocolDict["Access"].lower() == "local":
339339
self.localProtocolSections.append(protocolSectionName)
340340
else:
341341
errStr = (
342342
"StorageFactory.__getProtocolDetails: The 'Access' option \
343-
for %s:%s is neither 'local' or 'remote'."
343+
for %s:%s is not 'local', 'remote' or 'remoteonly'."
344344
% (storageName, protocolSectionName)
345345
)
346346
gLogger.warn(errStr)

0 commit comments

Comments
 (0)