From 363ff3d8ad4c4bf2b4bee790a9dd6f74f8ba5021 Mon Sep 17 00:00:00 2001 From: Alexander Rogovskiy Date: Thu, 26 Feb 2026 16:36:15 +0100 Subject: [PATCH] feat: add "remoteonly" value to the SE Access option It's the same as "remote", but prevents using the protocol in local context (e.g. to upload data from some site's WNs to the local SE). This may be useful for sites with different storage infrastructure for local and remote transfers. --- docs/source/AdministratorGuide/Resources/storage.rst | 3 ++- src/DIRAC/Resources/Storage/StorageElement.py | 5 +++++ src/DIRAC/Resources/Storage/StorageFactory.py | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/source/AdministratorGuide/Resources/storage.rst b/docs/source/AdministratorGuide/Resources/storage.rst index 0dc907bcdce..fcd2ad5799e 100644 --- a/docs/source/AdministratorGuide/Resources/storage.rst +++ b/docs/source/AdministratorGuide/Resources/storage.rst @@ -20,7 +20,7 @@ DIRAC provides an abstraction of a SE interface that allows to access different # The name of the DIRAC Plugin module to be used for implementation # of the access protocol PluginName = SRM2 - # Flag specifying the access type (local/remote) + # Flag specifying the access type (local/remote/remoteonly) Access = remote # Protocol name Protocol = srm @@ -50,6 +50,7 @@ Configuration options are: * ``UseCatalogURL``: default ``False``. If ``True``, use the url stored in the catalog instead of regenerating it * ``ChecksumType``: default ``ADLER32``. NOT ACTIVE ! * ``Alias``: when set to the name of another storage element, it instanciates the other SE instead. +* ``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. * ``ReadAccess``: default ``True``. Allowed for Read if no RSS enabled (:ref:`activateRSS`) * ``WriteAccess``: default ``True``. Allowed for Write if no RSS enabled * ``CheckAccess``: default ``True``. Allowed for Check if no RSS enabled diff --git a/src/DIRAC/Resources/Storage/StorageElement.py b/src/DIRAC/Resources/Storage/StorageElement.py index 621d58a2ab6..9a0b5f5e6ea 100755 --- a/src/DIRAC/Resources/Storage/StorageElement.py +++ b/src/DIRAC/Resources/Storage/StorageElement.py @@ -1153,6 +1153,7 @@ def __filterPlugins(self, methodName, protocols=None, inputProtocol=None): # Determine whether to use this storage object pluginParameters = plugin.getParameters() isProxyPlugin = pluginParameters.get("PluginName") == "Proxy" + isRemoteOnly = pluginParameters.get("Access", "").lower() == "remoteonly" if not pluginParameters: log.debug("Failed to get storage parameters.", f"{self.name} {protocolSection}") @@ -1167,6 +1168,10 @@ def __filterPlugins(self, methodName, protocols=None, inputProtocol=None): log.debug(f"Plugin {protocolSection} not allowed for {methodName}.") continue + # If protocol is remote only and the context is local, skip it. + if isRemoteOnly and localSE: + continue + # If we are attempting a putFile and we know the inputProtocol if methodName == "putFile" and inputProtocol: if inputProtocol not in pluginParameters["InputProtocols"]: diff --git a/src/DIRAC/Resources/Storage/StorageFactory.py b/src/DIRAC/Resources/Storage/StorageFactory.py index c440604bf70..86bae026dd4 100755 --- a/src/DIRAC/Resources/Storage/StorageFactory.py +++ b/src/DIRAC/Resources/Storage/StorageFactory.py @@ -333,14 +333,14 @@ def _getConfigStorageProtocols(self, storageName, derivedStorageName=None, seCon for protocolSectionName, protocolDict in self.protocols.items(): # Now update the local and remote protocol lists. # A warning will be given if the Access option is not set to local or remote. - if protocolDict["Access"].lower() == "remote": + if protocolDict["Access"].lower() in ("remote", "remoteonly"): self.remoteProtocolSections.append(protocolSectionName) elif protocolDict["Access"].lower() == "local": self.localProtocolSections.append(protocolSectionName) else: errStr = ( "StorageFactory.__getProtocolDetails: The 'Access' option \ - for %s:%s is neither 'local' or 'remote'." + for %s:%s is not 'local', 'remote' or 'remoteonly'." % (storageName, protocolSectionName) ) gLogger.warn(errStr)