rucio-clients 35.7.0__py3-none-any.whl → 37.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rucio-clients might be problematic. Click here for more details.
- rucio/alembicrevision.py +1 -1
- rucio/cli/__init__.py +14 -0
- rucio/cli/account.py +216 -0
- rucio/cli/bin_legacy/__init__.py +13 -0
- rucio_clients-35.7.0.data/scripts/rucio → rucio/cli/bin_legacy/rucio.py +769 -486
- rucio_clients-35.7.0.data/scripts/rucio-admin → rucio/cli/bin_legacy/rucio_admin.py +476 -423
- rucio/cli/command.py +272 -0
- rucio/cli/config.py +72 -0
- rucio/cli/did.py +191 -0
- rucio/cli/download.py +128 -0
- rucio/cli/lifetime_exception.py +33 -0
- rucio/cli/replica.py +162 -0
- rucio/cli/rse.py +293 -0
- rucio/cli/rule.py +158 -0
- rucio/cli/scope.py +40 -0
- rucio/cli/subscription.py +73 -0
- rucio/cli/upload.py +60 -0
- rucio/cli/utils.py +226 -0
- rucio/client/accountclient.py +0 -1
- rucio/client/baseclient.py +33 -24
- rucio/client/client.py +45 -1
- rucio/client/didclient.py +5 -3
- rucio/client/downloadclient.py +6 -8
- rucio/client/replicaclient.py +0 -2
- rucio/client/richclient.py +317 -0
- rucio/client/rseclient.py +4 -4
- rucio/client/uploadclient.py +26 -12
- rucio/common/bittorrent.py +234 -0
- rucio/common/cache.py +66 -29
- rucio/common/checksum.py +168 -0
- rucio/common/client.py +122 -0
- rucio/common/config.py +22 -35
- rucio/common/constants.py +61 -3
- rucio/common/didtype.py +72 -24
- rucio/common/exception.py +65 -8
- rucio/common/extra.py +5 -10
- rucio/common/logging.py +13 -13
- rucio/common/pcache.py +8 -7
- rucio/common/plugins.py +59 -27
- rucio/common/policy.py +12 -3
- rucio/common/schema/__init__.py +84 -34
- rucio/common/schema/generic.py +0 -17
- rucio/common/schema/generic_multi_vo.py +0 -17
- rucio/common/test_rucio_server.py +12 -6
- rucio/common/types.py +132 -52
- rucio/common/utils.py +93 -643
- rucio/rse/__init__.py +3 -3
- rucio/rse/protocols/bittorrent.py +11 -1
- rucio/rse/protocols/cache.py +0 -11
- rucio/rse/protocols/dummy.py +0 -11
- rucio/rse/protocols/gfal.py +14 -9
- rucio/rse/protocols/globus.py +1 -1
- rucio/rse/protocols/http_cache.py +1 -1
- rucio/rse/protocols/posix.py +2 -2
- rucio/rse/protocols/protocol.py +84 -317
- rucio/rse/protocols/rclone.py +2 -1
- rucio/rse/protocols/rfio.py +10 -1
- rucio/rse/protocols/ssh.py +2 -1
- rucio/rse/protocols/storm.py +2 -13
- rucio/rse/protocols/webdav.py +74 -30
- rucio/rse/protocols/xrootd.py +2 -1
- rucio/rse/rsemanager.py +170 -53
- rucio/rse/translation.py +260 -0
- rucio/vcsversion.py +4 -4
- rucio/version.py +7 -0
- {rucio_clients-35.7.0.data → rucio_clients-37.0.0.data}/data/etc/rucio.cfg.atlas.client.template +3 -2
- {rucio_clients-35.7.0.data → rucio_clients-37.0.0.data}/data/etc/rucio.cfg.template +3 -19
- {rucio_clients-35.7.0.data → rucio_clients-37.0.0.data}/data/requirements.client.txt +11 -7
- rucio_clients-37.0.0.data/scripts/rucio +133 -0
- rucio_clients-37.0.0.data/scripts/rucio-admin +97 -0
- {rucio_clients-35.7.0.dist-info → rucio_clients-37.0.0.dist-info}/METADATA +18 -14
- rucio_clients-37.0.0.dist-info/RECORD +104 -0
- {rucio_clients-35.7.0.dist-info → rucio_clients-37.0.0.dist-info}/licenses/AUTHORS.rst +3 -0
- rucio/common/schema/atlas.py +0 -413
- rucio/common/schema/belleii.py +0 -408
- rucio/common/schema/domatpc.py +0 -401
- rucio/common/schema/escape.py +0 -426
- rucio/common/schema/icecube.py +0 -406
- rucio/rse/protocols/gsiftp.py +0 -92
- rucio_clients-35.7.0.dist-info/RECORD +0 -88
- {rucio_clients-35.7.0.data → rucio_clients-37.0.0.data}/data/etc/rse-accounts.cfg.template +0 -0
- {rucio_clients-35.7.0.data → rucio_clients-37.0.0.data}/data/rucio_client/merge_rucio_configs.py +0 -0
- {rucio_clients-35.7.0.dist-info → rucio_clients-37.0.0.dist-info}/WHEEL +0 -0
- {rucio_clients-35.7.0.dist-info → rucio_clients-37.0.0.dist-info}/licenses/LICENSE +0 -0
- {rucio_clients-35.7.0.dist-info → rucio_clients-37.0.0.dist-info}/top_level.txt +0 -0
rucio/common/pcache.py
CHANGED
|
@@ -44,6 +44,8 @@ DEBUG, INFO, WARN, ERROR = "DEBUG", "INFO ", "WARN ", "ERROR"
|
|
|
44
44
|
# filename for locking
|
|
45
45
|
LOCK_NAME = ".LOCK"
|
|
46
46
|
|
|
47
|
+
MAXFD = 1024
|
|
48
|
+
|
|
47
49
|
# Session ID
|
|
48
50
|
sessid = "%s.%s" % (int(time.time()), os.getpid())
|
|
49
51
|
|
|
@@ -131,7 +133,7 @@ def unitize(x: int) -> str:
|
|
|
131
133
|
|
|
132
134
|
class Pcache:
|
|
133
135
|
|
|
134
|
-
def
|
|
136
|
+
def usage(self) -> None:
|
|
135
137
|
msg = """Usage: %s [flags] copy_prog [copy_flags] input output""" % self.progname
|
|
136
138
|
sys.stderr.write("%s\n" % msg) # py3, py2
|
|
137
139
|
# print>>sys.stderr, " flags are: "
|
|
@@ -227,7 +229,7 @@ class Pcache:
|
|
|
227
229
|
# TODO: move checksum/size validation from lsm to pcache
|
|
228
230
|
except getopt.GetoptError as err:
|
|
229
231
|
sys.stderr.write("%s\n" % str(err))
|
|
230
|
-
self.
|
|
232
|
+
self.usage()
|
|
231
233
|
self.fail(100)
|
|
232
234
|
|
|
233
235
|
for opt, arg in opts:
|
|
@@ -356,7 +358,7 @@ class Pcache:
|
|
|
356
358
|
|
|
357
359
|
# Fail on extra args
|
|
358
360
|
if not self.scratch_dir:
|
|
359
|
-
self.
|
|
361
|
+
self.usage()
|
|
360
362
|
self.fail(100)
|
|
361
363
|
|
|
362
364
|
# hardcoded pcache dir
|
|
@@ -417,7 +419,7 @@ class Pcache:
|
|
|
417
419
|
|
|
418
420
|
# Fail on extra args
|
|
419
421
|
if not scratch_dir:
|
|
420
|
-
self.
|
|
422
|
+
self.usage()
|
|
421
423
|
self.fail(100)
|
|
422
424
|
|
|
423
425
|
# If the source is lfn:, execute original command, no further action
|
|
@@ -491,7 +493,7 @@ class Pcache:
|
|
|
491
493
|
|
|
492
494
|
# Must have a list of arguments
|
|
493
495
|
if (self.parse_args(args[1:])):
|
|
494
|
-
self.
|
|
496
|
+
self.usage()
|
|
495
497
|
self.fail(100)
|
|
496
498
|
|
|
497
499
|
# Cache dir may have been wiped
|
|
@@ -522,7 +524,7 @@ class Pcache:
|
|
|
522
524
|
|
|
523
525
|
# Fail on extra args
|
|
524
526
|
if (len(self.args) < 3):
|
|
525
|
-
self.
|
|
527
|
+
self.usage()
|
|
526
528
|
self.fail(100)
|
|
527
529
|
|
|
528
530
|
self.copy_util = self.args[0]
|
|
@@ -1059,7 +1061,6 @@ class Pcache:
|
|
|
1059
1061
|
os.dup2(n, i)
|
|
1060
1062
|
os.dup2(n, o)
|
|
1061
1063
|
os.dup2(n, e)
|
|
1062
|
-
MAXFD = 1024
|
|
1063
1064
|
try:
|
|
1064
1065
|
import resource # Resource usage information.
|
|
1065
1066
|
maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
|
rucio/common/plugins.py
CHANGED
|
@@ -13,25 +13,73 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import importlib
|
|
16
|
+
import logging
|
|
16
17
|
import os
|
|
17
|
-
from collections.abc import Callable
|
|
18
18
|
from configparser import NoOptionError, NoSectionError
|
|
19
|
-
from typing import Any, TypeVar
|
|
19
|
+
from typing import TYPE_CHECKING, Any, TypeVar
|
|
20
|
+
|
|
21
|
+
from packaging.specifiers import SpecifierSet
|
|
20
22
|
|
|
21
23
|
from rucio.common import config
|
|
22
|
-
from rucio.common.
|
|
24
|
+
from rucio.common.client import get_client_vo, is_client
|
|
25
|
+
from rucio.common.exception import InvalidAlgorithmName, PolicyPackageIsNotVersioned, PolicyPackageVersionError
|
|
26
|
+
from rucio.version import current_version
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from collections.abc import Callable
|
|
30
|
+
|
|
31
|
+
from rucio.common.types import LoggerFunction
|
|
23
32
|
|
|
24
33
|
PolicyPackageAlgorithmsT = TypeVar('PolicyPackageAlgorithmsT', bound='PolicyPackageAlgorithms')
|
|
25
34
|
|
|
26
35
|
|
|
36
|
+
def check_policy_package_version(package: str, logger: 'LoggerFunction' = logging.log) -> None:
|
|
37
|
+
|
|
38
|
+
'''
|
|
39
|
+
Checks that the Rucio version supported by the policy package is compatible
|
|
40
|
+
with this version. Raises an exception if not.
|
|
41
|
+
:param package: the fully qualified name of the policy package
|
|
42
|
+
'''
|
|
43
|
+
try:
|
|
44
|
+
supported_versionset = _get_supported_versions_from_policy_package(package)
|
|
45
|
+
except ImportError:
|
|
46
|
+
logger(logging.DEBUG, 'Policy package %s not found' % package)
|
|
47
|
+
return
|
|
48
|
+
except PolicyPackageIsNotVersioned:
|
|
49
|
+
logger(logging.DEBUG, 'Policy package %s does not include information about which Rucio versions it supports' % package)
|
|
50
|
+
return
|
|
51
|
+
|
|
52
|
+
rucio_version = current_version()
|
|
53
|
+
if rucio_version not in supported_versionset:
|
|
54
|
+
raise PolicyPackageVersionError(rucio_version=rucio_version, supported_versionset=str(supported_versionset), package=package)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _get_supported_versions_from_policy_package(package: str) -> SpecifierSet:
|
|
58
|
+
try:
|
|
59
|
+
module = importlib.import_module(package)
|
|
60
|
+
except ImportError as e:
|
|
61
|
+
raise e
|
|
62
|
+
|
|
63
|
+
if not hasattr(module, 'SUPPORTED_VERSION'):
|
|
64
|
+
raise PolicyPackageIsNotVersioned(package)
|
|
65
|
+
|
|
66
|
+
supported_versionset = module.SUPPORTED_VERSION
|
|
67
|
+
|
|
68
|
+
if isinstance(supported_versionset, list):
|
|
69
|
+
supported_versionset = ','.join(supported_versionset)
|
|
70
|
+
|
|
71
|
+
return SpecifierSet(supported_versionset)
|
|
72
|
+
|
|
73
|
+
|
|
27
74
|
class PolicyPackageAlgorithms:
|
|
28
75
|
"""
|
|
29
76
|
Base class for Rucio Policy Package Algorithms
|
|
30
77
|
|
|
31
|
-
ALGORITHMS is
|
|
32
|
-
|
|
78
|
+
ALGORITHMS is a dict where:
|
|
79
|
+
- the key is the algorithm type
|
|
80
|
+
- the value is a dictionary of algorithm names and their callables
|
|
33
81
|
"""
|
|
34
|
-
_ALGORITHMS: dict[str, dict[str, Callable[..., Any]]] = {}
|
|
82
|
+
_ALGORITHMS: dict[str, dict[str, 'Callable[..., Any]']] = {}
|
|
35
83
|
_loaded_policy_modules = False
|
|
36
84
|
|
|
37
85
|
def __init__(self) -> None:
|
|
@@ -40,14 +88,14 @@ class PolicyPackageAlgorithms:
|
|
|
40
88
|
self._loaded_policy_modules = True
|
|
41
89
|
|
|
42
90
|
@classmethod
|
|
43
|
-
def _get_one_algorithm(cls: type[PolicyPackageAlgorithmsT], algorithm_type: str, name: str) -> Callable[..., Any]:
|
|
91
|
+
def _get_one_algorithm(cls: type[PolicyPackageAlgorithmsT], algorithm_type: str, name: str) -> 'Callable[..., Any]':
|
|
44
92
|
"""
|
|
45
93
|
Get the algorithm from the dictionary of algorithms
|
|
46
94
|
"""
|
|
47
95
|
return cls._ALGORITHMS[algorithm_type][name]
|
|
48
96
|
|
|
49
97
|
@classmethod
|
|
50
|
-
def _get_algorithms(cls: type[PolicyPackageAlgorithmsT], algorithm_type: str) -> dict[str, Callable[..., Any]]:
|
|
98
|
+
def _get_algorithms(cls: type[PolicyPackageAlgorithmsT], algorithm_type: str) -> dict[str, 'Callable[..., Any]']:
|
|
51
99
|
"""
|
|
52
100
|
Get the dictionary of algorithms for a given type
|
|
53
101
|
"""
|
|
@@ -56,7 +104,7 @@ class PolicyPackageAlgorithms:
|
|
|
56
104
|
@classmethod
|
|
57
105
|
def _register(
|
|
58
106
|
cls: type[PolicyPackageAlgorithmsT],
|
|
59
|
-
algorithm_type: str, algorithm_dict: dict[str, Callable[..., Any]]) -> None:
|
|
107
|
+
algorithm_type: str, algorithm_dict: dict[str, 'Callable[..., Any]']) -> None:
|
|
60
108
|
"""
|
|
61
109
|
Provided a dictionary of callable function,
|
|
62
110
|
and the associated algorithm type,
|
|
@@ -90,24 +138,9 @@ class PolicyPackageAlgorithms:
|
|
|
90
138
|
# single policy package
|
|
91
139
|
cls._try_importing_policy()
|
|
92
140
|
else:
|
|
93
|
-
# determine whether on client or server
|
|
94
|
-
client = False
|
|
95
|
-
if 'RUCIO_CLIENT_MODE' not in os.environ:
|
|
96
|
-
if not config.config_has_section('database') and config.config_has_section('client'):
|
|
97
|
-
client = True
|
|
98
|
-
else:
|
|
99
|
-
if os.environ['RUCIO_CLIENT_MODE']:
|
|
100
|
-
client = True
|
|
101
|
-
|
|
102
141
|
# on client, only register algorithms for selected VO
|
|
103
|
-
if
|
|
104
|
-
|
|
105
|
-
vo = os.environ['RUCIO_VO']
|
|
106
|
-
else:
|
|
107
|
-
try:
|
|
108
|
-
vo = str(config.config_get('client', 'vo'))
|
|
109
|
-
except (NoOptionError, NoSectionError):
|
|
110
|
-
vo = 'def'
|
|
142
|
+
if is_client():
|
|
143
|
+
vo = get_client_vo()
|
|
111
144
|
cls._try_importing_policy(vo)
|
|
112
145
|
# on server, list all VOs and register their algorithms
|
|
113
146
|
else:
|
|
@@ -121,7 +154,6 @@ class PolicyPackageAlgorithms:
|
|
|
121
154
|
def _try_importing_policy(cls: type[PolicyPackageAlgorithmsT], vo: str = "") -> None:
|
|
122
155
|
try:
|
|
123
156
|
# import from utils here to avoid circular import
|
|
124
|
-
from rucio.common.utils import check_policy_package_version
|
|
125
157
|
|
|
126
158
|
env_name = 'RUCIO_POLICY_PACKAGE' + ('' if not vo else '_' + vo.upper())
|
|
127
159
|
package = getattr(os.environ, env_name, "")
|
rucio/common/policy.py
CHANGED
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import json
|
|
16
|
+
import logging
|
|
16
17
|
import os
|
|
17
18
|
from configparser import NoOptionError, NoSectionError
|
|
18
19
|
from functools import wraps
|
|
19
|
-
from typing import Any
|
|
20
|
+
from typing import TYPE_CHECKING, Any
|
|
20
21
|
|
|
21
22
|
from dogpile.cache import make_region
|
|
22
23
|
from dogpile.cache.api import NoValue
|
|
@@ -24,17 +25,25 @@ from dogpile.cache.api import NoValue
|
|
|
24
25
|
from rucio.common.config import config_get
|
|
25
26
|
from rucio.common.exception import UndefinedPolicy
|
|
26
27
|
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from rucio.common.types import LoggerFunction
|
|
30
|
+
|
|
27
31
|
REGION = make_region().configure('dogpile.cache.memory',
|
|
28
32
|
expiration_time=900)
|
|
29
33
|
|
|
30
34
|
|
|
31
|
-
def get_policy() -> str:
|
|
35
|
+
def get_policy(logger: 'LoggerFunction' = logging.log) -> str:
|
|
32
36
|
policy = REGION.get('policy')
|
|
33
37
|
if isinstance(policy, NoValue):
|
|
34
38
|
try:
|
|
35
39
|
policy = config_get('policy', 'permission')
|
|
36
40
|
except (NoOptionError, NoSectionError):
|
|
37
|
-
|
|
41
|
+
try:
|
|
42
|
+
policy = config_get('permission', 'policy')
|
|
43
|
+
except (NoOptionError, NoSectionError):
|
|
44
|
+
policy = 'def'
|
|
45
|
+
logger(logging.WARNING, "Policy not specified, falling back to 'def'")
|
|
46
|
+
policy = os.environ.get('POLICY', policy)
|
|
38
47
|
REGION.set('policy', policy)
|
|
39
48
|
return policy
|
|
40
49
|
|
rucio/common/schema/__init__.py
CHANGED
|
@@ -12,103 +12,153 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
import functools
|
|
15
16
|
import importlib
|
|
17
|
+
import logging
|
|
16
18
|
from configparser import NoOptionError, NoSectionError
|
|
17
19
|
from os import environ
|
|
18
20
|
from typing import TYPE_CHECKING, Any
|
|
19
21
|
|
|
22
|
+
from jsonschema import ValidationError, validate
|
|
23
|
+
|
|
20
24
|
from rucio.common import config, exception
|
|
21
|
-
from rucio.common.
|
|
25
|
+
from rucio.common.plugins import check_policy_package_version
|
|
22
26
|
|
|
23
27
|
if TYPE_CHECKING:
|
|
24
28
|
from types import ModuleType
|
|
25
29
|
|
|
30
|
+
LOGGER = logging.getLogger('policy')
|
|
31
|
+
|
|
26
32
|
# dictionary of schema modules for each VO
|
|
27
33
|
schema_modules: dict[str, "ModuleType"] = {}
|
|
28
34
|
|
|
29
35
|
# list of unique SCOPE_NAME_REGEXP values from all schemas
|
|
30
36
|
scope_name_regexps: list[str] = []
|
|
31
37
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
|
|
39
|
+
# cached function to check for multivo
|
|
40
|
+
@functools.cache
|
|
41
|
+
def _is_multivo():
|
|
42
|
+
try:
|
|
43
|
+
return config.config_get_bool('common', 'multi_vo', check_config_table=False)
|
|
44
|
+
except (NoOptionError, NoSectionError):
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# cached function to get generic schema module
|
|
49
|
+
@functools.cache
|
|
50
|
+
def _get_generic_schema_module():
|
|
51
|
+
generic_fallback = 'generic_multi_vo' if _is_multivo() else 'generic'
|
|
52
|
+
return importlib.import_module('rucio.common.schema.' + generic_fallback)
|
|
53
|
+
|
|
36
54
|
|
|
37
55
|
# multi-VO version loads schema per-VO on demand
|
|
38
56
|
# we can't get a list of VOs here because the database might not
|
|
39
57
|
# be available as this is imported during the bootstrapping process
|
|
40
|
-
if not
|
|
58
|
+
if not _is_multivo():
|
|
41
59
|
GENERIC_FALLBACK = 'generic'
|
|
42
60
|
|
|
43
61
|
if config.config_has_section('policy'):
|
|
44
62
|
try:
|
|
45
63
|
if 'RUCIO_POLICY_PACKAGE' in environ:
|
|
46
|
-
|
|
64
|
+
policy = environ['RUCIO_POLICY_PACKAGE']
|
|
47
65
|
else:
|
|
48
|
-
|
|
49
|
-
check_policy_package_version(
|
|
50
|
-
|
|
66
|
+
policy = config.config_get('policy', 'package', check_config_table=False)
|
|
67
|
+
check_policy_package_version(policy)
|
|
68
|
+
policy = policy + ".schema"
|
|
51
69
|
except (NoOptionError, NoSectionError):
|
|
52
70
|
# fall back to old system for now
|
|
53
71
|
try:
|
|
54
|
-
|
|
72
|
+
policy = config.config_get('policy', 'schema', check_config_table=False)
|
|
55
73
|
except (NoOptionError, NoSectionError):
|
|
56
|
-
|
|
57
|
-
|
|
74
|
+
policy = GENERIC_FALLBACK
|
|
75
|
+
policy = 'rucio.common.schema.' + policy.lower()
|
|
58
76
|
else:
|
|
59
|
-
|
|
77
|
+
policy = 'rucio.common.schema.' + GENERIC_FALLBACK.lower()
|
|
60
78
|
|
|
61
79
|
try:
|
|
62
|
-
module = importlib.import_module(
|
|
80
|
+
module = importlib.import_module(policy)
|
|
63
81
|
except ModuleNotFoundError:
|
|
64
|
-
|
|
82
|
+
# if policy package does not contain schema module, load fallback module instead
|
|
83
|
+
# this allows a policy package to omit modules that do not need customisation
|
|
84
|
+
try:
|
|
85
|
+
LOGGER.warning('Unable to load schema module %s from policy package, falling back to %s'
|
|
86
|
+
% (policy, GENERIC_FALLBACK))
|
|
87
|
+
policy = 'rucio.common.schema.' + GENERIC_FALLBACK.lower()
|
|
88
|
+
module = importlib.import_module(policy)
|
|
89
|
+
except ModuleNotFoundError:
|
|
90
|
+
raise exception.PolicyPackageNotFound(policy)
|
|
91
|
+
except ImportError:
|
|
92
|
+
raise exception.ErrorLoadingPolicyPackage(policy)
|
|
65
93
|
except ImportError:
|
|
66
|
-
raise exception.ErrorLoadingPolicyPackage(
|
|
94
|
+
raise exception.ErrorLoadingPolicyPackage(policy)
|
|
67
95
|
|
|
68
96
|
schema_modules["def"] = module
|
|
69
|
-
|
|
97
|
+
if hasattr(module, 'SCOPE_NAME_REGEXP'):
|
|
98
|
+
scope_name_regexps.append(module.SCOPE_NAME_REGEXP)
|
|
70
99
|
|
|
71
100
|
|
|
72
101
|
def load_schema_for_vo(vo: str) -> None:
|
|
73
|
-
|
|
102
|
+
generic_fallback = 'generic_multi_vo'
|
|
74
103
|
if config.config_has_section('policy'):
|
|
75
104
|
try:
|
|
76
105
|
env_name = 'RUCIO_POLICY_PACKAGE_' + vo.upper()
|
|
77
106
|
if env_name in environ:
|
|
78
|
-
|
|
107
|
+
policy = environ[env_name]
|
|
79
108
|
else:
|
|
80
|
-
|
|
81
|
-
check_policy_package_version(
|
|
82
|
-
|
|
109
|
+
policy = config.config_get('policy', 'package-' + vo, check_config_table=False)
|
|
110
|
+
check_policy_package_version(policy)
|
|
111
|
+
policy = policy + ".schema"
|
|
83
112
|
except (NoOptionError, NoSectionError):
|
|
84
113
|
# fall back to old system for now
|
|
85
114
|
try:
|
|
86
|
-
|
|
115
|
+
policy = config.config_get('policy', 'schema', check_config_table=False)
|
|
87
116
|
except (NoOptionError, NoSectionError):
|
|
88
|
-
|
|
89
|
-
|
|
117
|
+
policy = generic_fallback
|
|
118
|
+
policy = 'rucio.common.schema.' + policy.lower()
|
|
90
119
|
else:
|
|
91
|
-
|
|
120
|
+
policy = 'rucio.common.schema.' + generic_fallback.lower()
|
|
92
121
|
|
|
93
122
|
try:
|
|
94
|
-
module = importlib.import_module(
|
|
123
|
+
module = importlib.import_module(policy)
|
|
95
124
|
except ModuleNotFoundError:
|
|
96
|
-
|
|
125
|
+
# if policy package does not contain schema module, load fallback module instead
|
|
126
|
+
# this allows a policy package to omit modules that do not need customisation
|
|
127
|
+
try:
|
|
128
|
+
LOGGER.warning('Unable to load schema module %s from policy package, falling back to %s'
|
|
129
|
+
% (policy, generic_fallback))
|
|
130
|
+
policy = 'rucio.common.schema.' + generic_fallback.lower()
|
|
131
|
+
module = importlib.import_module(policy)
|
|
132
|
+
except ModuleNotFoundError:
|
|
133
|
+
raise exception.PolicyPackageNotFound(policy)
|
|
134
|
+
except ImportError:
|
|
135
|
+
raise exception.ErrorLoadingPolicyPackage(policy)
|
|
97
136
|
except ImportError:
|
|
98
|
-
raise exception.ErrorLoadingPolicyPackage(
|
|
137
|
+
raise exception.ErrorLoadingPolicyPackage(policy)
|
|
99
138
|
|
|
100
139
|
schema_modules[vo] = module
|
|
101
140
|
|
|
102
141
|
|
|
103
142
|
def validate_schema(name: str, obj: Any, vo: str = 'def') -> None:
|
|
104
|
-
if
|
|
105
|
-
|
|
106
|
-
|
|
143
|
+
if obj:
|
|
144
|
+
if vo not in schema_modules:
|
|
145
|
+
load_schema_for_vo(vo)
|
|
146
|
+
if hasattr(schema_modules[vo], 'SCHEMAS') and name in schema_modules[vo].SCHEMAS:
|
|
147
|
+
schema = schema_modules[vo].SCHEMAS.get(name, {})
|
|
148
|
+
else:
|
|
149
|
+
# if schema not available in VO module, fall back to generic module
|
|
150
|
+
schema = _get_generic_schema_module().SCHEMAS.get(name, {})
|
|
151
|
+
try:
|
|
152
|
+
validate(obj, schema)
|
|
153
|
+
except ValidationError as error: # NOQA: F841
|
|
154
|
+
raise exception.InvalidObject(f'Problem validating {name}: {error}')
|
|
107
155
|
|
|
108
156
|
|
|
109
157
|
def get_schema_value(key: str, vo: str = 'def') -> Any:
|
|
110
158
|
if vo not in schema_modules:
|
|
111
159
|
load_schema_for_vo(vo)
|
|
160
|
+
if not hasattr(schema_modules[vo], key):
|
|
161
|
+
return getattr(_get_generic_schema_module(), key)
|
|
112
162
|
return getattr(schema_modules[vo], key)
|
|
113
163
|
|
|
114
164
|
|
|
@@ -120,7 +170,7 @@ def get_scope_name_regexps() -> list[str]:
|
|
|
120
170
|
from rucio.core.vo import list_vos
|
|
121
171
|
vos = list_vos()
|
|
122
172
|
for vo in vos:
|
|
123
|
-
if
|
|
173
|
+
if vo['vo'] not in schema_modules:
|
|
124
174
|
load_schema_for_vo(vo['vo'])
|
|
125
175
|
scope_name_regexp = schema_modules[vo['vo']].SCOPE_NAME_REGEXP
|
|
126
176
|
if scope_name_regexp not in scope_name_regexps:
|
rucio/common/schema/generic.py
CHANGED
|
@@ -12,9 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from jsonschema import ValidationError, validate
|
|
16
|
-
|
|
17
|
-
from rucio.common.exception import InvalidObject
|
|
18
15
|
|
|
19
16
|
ACCOUNT_LENGTH = 25
|
|
20
17
|
|
|
@@ -417,17 +414,3 @@ SCHEMAS = {'account': ACCOUNT,
|
|
|
417
414
|
'cache_delete_replicas': CACHE_DELETE_REPLICAS,
|
|
418
415
|
'account_attribute': ACCOUNT_ATTRIBUTE,
|
|
419
416
|
'import': IMPORT}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
def validate_schema(name, obj):
|
|
423
|
-
"""
|
|
424
|
-
Validate object against json schema
|
|
425
|
-
|
|
426
|
-
:param name: The json schema name.
|
|
427
|
-
:param obj: The object to validate.
|
|
428
|
-
"""
|
|
429
|
-
try:
|
|
430
|
-
if obj:
|
|
431
|
-
validate(obj, SCHEMAS.get(name, {}))
|
|
432
|
-
except ValidationError as error: # NOQA, pylint: disable=W0612
|
|
433
|
-
raise InvalidObject(f'Problem validating {name}: {error}')
|
|
@@ -12,9 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from jsonschema import ValidationError, validate
|
|
16
|
-
|
|
17
|
-
from rucio.common.exception import InvalidObject
|
|
18
15
|
|
|
19
16
|
ACCOUNT_LENGTH = 29
|
|
20
17
|
|
|
@@ -396,17 +393,3 @@ SCHEMAS = {'account': ACCOUNT,
|
|
|
396
393
|
'account_attribute': ACCOUNT_ATTRIBUTE,
|
|
397
394
|
'import': IMPORT,
|
|
398
395
|
'vo': VO}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
def validate_schema(name, obj):
|
|
402
|
-
"""
|
|
403
|
-
Validate object against json schema
|
|
404
|
-
|
|
405
|
-
:param name: The json schema name.
|
|
406
|
-
:param obj: The object to validate.
|
|
407
|
-
"""
|
|
408
|
-
try:
|
|
409
|
-
if obj:
|
|
410
|
-
validate(obj, SCHEMAS.get(name, {}))
|
|
411
|
-
except ValidationError as error: # NOQA, pylint: disable=W0612
|
|
412
|
-
raise InvalidObject(f'Problem validating {name}: {error}')
|
|
@@ -36,27 +36,33 @@ def get_scope_and_rses():
|
|
|
36
36
|
|
|
37
37
|
:return: A tuple (scope, rses) for the rucio client where scope is mock/test and rses is a list or (None, [None]) if no suitable rse exists.
|
|
38
38
|
"""
|
|
39
|
-
cmd = "rucio list
|
|
39
|
+
cmd = "rucio rse list 'test_container_xrd=True'"
|
|
40
40
|
print(cmd)
|
|
41
41
|
exitcode, out, err = execute(cmd)
|
|
42
42
|
print(out, err)
|
|
43
43
|
rses = out.split()
|
|
44
44
|
if len(rses) == 0:
|
|
45
45
|
return None, [None]
|
|
46
|
-
|
|
46
|
+
|
|
47
|
+
scope = 'test'
|
|
48
|
+
account = 'root'
|
|
49
|
+
cmd = f"rucio scope add {scope} --account {account}"
|
|
50
|
+
_, out, err = execute(cmd)
|
|
51
|
+
print(out, err)
|
|
52
|
+
return scope, rses
|
|
47
53
|
|
|
48
54
|
|
|
49
55
|
def delete_rules(did):
|
|
50
56
|
# get the rules for the file
|
|
51
57
|
print('Deleting rules')
|
|
52
|
-
cmd = "rucio list
|
|
58
|
+
cmd = "rucio rule list {0} | grep {0} | cut -f1 -d\\ ".format(did)
|
|
53
59
|
print(cmd)
|
|
54
60
|
exitcode, out, err = execute(cmd)
|
|
55
61
|
print(out, err)
|
|
56
62
|
rules = out.split()
|
|
57
63
|
# delete the rules for the file
|
|
58
64
|
for rule in rules:
|
|
59
|
-
cmd = "rucio
|
|
65
|
+
cmd = "rucio rule remove {0}".format(rule)
|
|
60
66
|
print(cmd)
|
|
61
67
|
exitcode, out, err = execute(cmd)
|
|
62
68
|
|
|
@@ -112,7 +118,7 @@ class TestRucioServer(unittest.TestCase):
|
|
|
112
118
|
self.assertEqual(exitcode, 0)
|
|
113
119
|
|
|
114
120
|
# List the files
|
|
115
|
-
cmd = 'rucio list
|
|
121
|
+
cmd = 'rucio did content list --did {0}:{1}'.format(self.scope, tmp_dsn)
|
|
116
122
|
print(self.marker + cmd)
|
|
117
123
|
exitcode, out, err = execute(cmd)
|
|
118
124
|
print(out)
|
|
@@ -120,7 +126,7 @@ class TestRucioServer(unittest.TestCase):
|
|
|
120
126
|
self.assertEqual(exitcode, 0)
|
|
121
127
|
|
|
122
128
|
# List the replicas
|
|
123
|
-
cmd = 'rucio list
|
|
129
|
+
cmd = 'rucio replica list file {0}:{1}'.format(self.scope, tmp_dsn)
|
|
124
130
|
print(self.marker + cmd)
|
|
125
131
|
exitcode, out, err = execute(cmd)
|
|
126
132
|
print(out)
|