rucio-clients 37.0.0rc1__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/__init__.py +17 -0
- rucio/alembicrevision.py +15 -0
- rucio/cli/__init__.py +14 -0
- rucio/cli/account.py +216 -0
- rucio/cli/bin_legacy/__init__.py +13 -0
- rucio/cli/bin_legacy/rucio.py +2825 -0
- rucio/cli/bin_legacy/rucio_admin.py +2500 -0
- 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/__init__.py +15 -0
- rucio/client/accountclient.py +432 -0
- rucio/client/accountlimitclient.py +183 -0
- rucio/client/baseclient.py +983 -0
- rucio/client/client.py +120 -0
- rucio/client/configclient.py +126 -0
- rucio/client/credentialclient.py +59 -0
- rucio/client/didclient.py +868 -0
- rucio/client/diracclient.py +56 -0
- rucio/client/downloadclient.py +1783 -0
- rucio/client/exportclient.py +44 -0
- rucio/client/fileclient.py +50 -0
- rucio/client/importclient.py +42 -0
- rucio/client/lifetimeclient.py +90 -0
- rucio/client/lockclient.py +109 -0
- rucio/client/metaconventionsclient.py +140 -0
- rucio/client/pingclient.py +44 -0
- rucio/client/replicaclient.py +452 -0
- rucio/client/requestclient.py +125 -0
- rucio/client/richclient.py +317 -0
- rucio/client/rseclient.py +746 -0
- rucio/client/ruleclient.py +294 -0
- rucio/client/scopeclient.py +90 -0
- rucio/client/subscriptionclient.py +173 -0
- rucio/client/touchclient.py +82 -0
- rucio/client/uploadclient.py +969 -0
- rucio/common/__init__.py +13 -0
- rucio/common/bittorrent.py +234 -0
- rucio/common/cache.py +111 -0
- rucio/common/checksum.py +168 -0
- rucio/common/client.py +122 -0
- rucio/common/config.py +788 -0
- rucio/common/constants.py +217 -0
- rucio/common/constraints.py +17 -0
- rucio/common/didtype.py +237 -0
- rucio/common/exception.py +1208 -0
- rucio/common/extra.py +31 -0
- rucio/common/logging.py +420 -0
- rucio/common/pcache.py +1409 -0
- rucio/common/plugins.py +185 -0
- rucio/common/policy.py +93 -0
- rucio/common/schema/__init__.py +200 -0
- rucio/common/schema/generic.py +416 -0
- rucio/common/schema/generic_multi_vo.py +395 -0
- rucio/common/stomp_utils.py +423 -0
- rucio/common/stopwatch.py +55 -0
- rucio/common/test_rucio_server.py +154 -0
- rucio/common/types.py +483 -0
- rucio/common/utils.py +1688 -0
- rucio/rse/__init__.py +96 -0
- rucio/rse/protocols/__init__.py +13 -0
- rucio/rse/protocols/bittorrent.py +194 -0
- rucio/rse/protocols/cache.py +111 -0
- rucio/rse/protocols/dummy.py +100 -0
- rucio/rse/protocols/gfal.py +708 -0
- rucio/rse/protocols/globus.py +243 -0
- rucio/rse/protocols/http_cache.py +82 -0
- rucio/rse/protocols/mock.py +123 -0
- rucio/rse/protocols/ngarc.py +209 -0
- rucio/rse/protocols/posix.py +250 -0
- rucio/rse/protocols/protocol.py +361 -0
- rucio/rse/protocols/rclone.py +365 -0
- rucio/rse/protocols/rfio.py +145 -0
- rucio/rse/protocols/srm.py +338 -0
- rucio/rse/protocols/ssh.py +414 -0
- rucio/rse/protocols/storm.py +195 -0
- rucio/rse/protocols/webdav.py +594 -0
- rucio/rse/protocols/xrootd.py +302 -0
- rucio/rse/rsemanager.py +881 -0
- rucio/rse/translation.py +260 -0
- rucio/vcsversion.py +11 -0
- rucio/version.py +45 -0
- rucio_clients-37.0.0rc1.data/data/etc/rse-accounts.cfg.template +25 -0
- rucio_clients-37.0.0rc1.data/data/etc/rucio.cfg.atlas.client.template +43 -0
- rucio_clients-37.0.0rc1.data/data/etc/rucio.cfg.template +241 -0
- rucio_clients-37.0.0rc1.data/data/requirements.client.txt +19 -0
- rucio_clients-37.0.0rc1.data/data/rucio_client/merge_rucio_configs.py +144 -0
- rucio_clients-37.0.0rc1.data/scripts/rucio +133 -0
- rucio_clients-37.0.0rc1.data/scripts/rucio-admin +97 -0
- rucio_clients-37.0.0rc1.dist-info/METADATA +54 -0
- rucio_clients-37.0.0rc1.dist-info/RECORD +104 -0
- rucio_clients-37.0.0rc1.dist-info/WHEEL +5 -0
- rucio_clients-37.0.0rc1.dist-info/licenses/AUTHORS.rst +100 -0
- rucio_clients-37.0.0rc1.dist-info/licenses/LICENSE +201 -0
- rucio_clients-37.0.0rc1.dist-info/top_level.txt +1 -0
rucio/cli/scope.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
import click
|
|
15
|
+
|
|
16
|
+
from rucio.cli.bin_legacy.rucio_admin import add_scope, list_scopes
|
|
17
|
+
from rucio.cli.utils import Arguments
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@click.group()
|
|
21
|
+
def scope():
|
|
22
|
+
"""Interact with scopes - a logical grouping of DIDs"""
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@scope.command("add")
|
|
26
|
+
@click.argument("scope-name")
|
|
27
|
+
@click.option("-a", "--account", help="Associated account", required=True)
|
|
28
|
+
@click.pass_context
|
|
29
|
+
def add_(ctx, account, scope_name):
|
|
30
|
+
"""Add a new scope with name [SCOPE-NAME]"""
|
|
31
|
+
args = Arguments({"scope": scope_name, "account": account})
|
|
32
|
+
add_scope(args, ctx.obj.client, ctx.obj.logger, ctx.obj.console, ctx.obj.spinner)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@scope.command("list")
|
|
36
|
+
@click.option("-a", "--account", help="Filter by associated account", required=False)
|
|
37
|
+
@click.pass_context
|
|
38
|
+
def list_(ctx, account):
|
|
39
|
+
"""List existing scopes"""
|
|
40
|
+
list_scopes(Arguments({"account": account}), ctx.obj.client, ctx.obj.logger, ctx.obj.console, ctx.obj.spinner)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
import click
|
|
15
|
+
|
|
16
|
+
from rucio.cli.bin_legacy.rucio_admin import add_subscription, list_subscriptions, reevaluate_did_for_subscription, update_subscription
|
|
17
|
+
from rucio.cli.utils import Arguments
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@click.group()
|
|
21
|
+
def subscription():
|
|
22
|
+
"The methods for automated and regular processing of some specific rules"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@subscription.command("show")
|
|
26
|
+
@click.option("-a", "--account", help="Account associated with the subscription")
|
|
27
|
+
@click.option("--long", default=False, is_flag=True, help="Show extended information about the subscription")
|
|
28
|
+
@click.argument("subscription-name")
|
|
29
|
+
@click.pass_context
|
|
30
|
+
def list_(ctx, subscription_name, account, long):
|
|
31
|
+
"""Show the attributes of a subscription [SUBSCRIPTION-NAME]"""
|
|
32
|
+
args = Arguments({"subs_account": account, "name": subscription_name, "long": long})
|
|
33
|
+
list_subscriptions(args, ctx.obj.client, ctx.obj.logger, ctx.obj.console, ctx.obj.spinner)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@subscription.command("update")
|
|
37
|
+
@click.argument("subscription-name")
|
|
38
|
+
@click.option("--filter", "did_filter", help='Json serializable DID filter (eg \'{"scope": ["tests"], "project": ["data12_8TeV"]}\')', required=True)
|
|
39
|
+
@click.option("--rule", help='List of replication rules (eg \'[{"activity": "Functional Tests", "copies": 2, "rse_expression": "tier=2", "lifetime": 3600, "weight": "mou"}]\')', required=True)
|
|
40
|
+
@click.option("--comment", help="Comments on subscription")
|
|
41
|
+
@click.option("--lifetime", type=int, help="Subscription lifetime (in days)")
|
|
42
|
+
@click.option("--account", help="Account name")
|
|
43
|
+
@click.option("--priority", help="The priority of the subscription")
|
|
44
|
+
@click.pass_context
|
|
45
|
+
def update(ctx, subscription_name, did_filter, rule, comment, lifetime, account, priority):
|
|
46
|
+
"""Update a subscription [SUBSCRIPTION-NAME] to have new properties"""
|
|
47
|
+
args = Arguments({"name": subscription_name, "filter": did_filter, "replication_rules": rule, "comments": comment, "lifetime": lifetime, "subs_account": account, "priority": priority})
|
|
48
|
+
update_subscription(args, ctx.obj.client, ctx.obj.logger, ctx.obj.console, ctx.obj.spinner)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@subscription.command("add")
|
|
52
|
+
@click.argument("subscription-name")
|
|
53
|
+
@click.option("--filter", "did_filter", help='Json serializable DID filter (eg \'{"scope": ["tests"], "project": ["data12_8TeV"]}\')', required=True)
|
|
54
|
+
@click.option("--rule", help='List of replication rules (eg \'[{"activity": "Functional Tests", "copies": 2, "rse_expression": "tier=2", "lifetime": 3600, "weight": "mou"}]\')', required=True)
|
|
55
|
+
@click.option("--comment", help="Comments on subscription")
|
|
56
|
+
@click.option("--lifetime", type=int, help="Subscription lifetime (in days)")
|
|
57
|
+
@click.option("--account", help="Account name")
|
|
58
|
+
@click.option("--priority", help="The priority of the subscription")
|
|
59
|
+
@click.pass_context
|
|
60
|
+
def add_(ctx, subscription_name, did_filter, rule, comment, lifetime, account, priority):
|
|
61
|
+
"""Create a new subscription with the name [SUBSCRIPTION-NAME]"""
|
|
62
|
+
args = Arguments({"name": subscription_name, "filter": did_filter, "replication_rules": rule, "comments": comment, "lifetime": lifetime, "subs_account": account, "priority": priority})
|
|
63
|
+
add_subscription(args, ctx.obj.client, ctx.obj.logger, ctx.obj.console, ctx.obj.spinner)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@subscription.command("touch")
|
|
67
|
+
@click.argument("dids", nargs=-1)
|
|
68
|
+
@click.pass_context
|
|
69
|
+
def touch(ctx, dids):
|
|
70
|
+
"""Reevaluate list of DIDs against all active subscriptions"""
|
|
71
|
+
# TODO make reeval accept dids as a list
|
|
72
|
+
dids = ",".join(dids)
|
|
73
|
+
reevaluate_did_for_subscription(Arguments({"dids": dids}), ctx.obj.client, ctx.obj.logger, ctx.obj.console, ctx.obj.spinner)
|
rucio/cli/upload.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
import click
|
|
15
|
+
|
|
16
|
+
from rucio.cli.bin_legacy.rucio import upload
|
|
17
|
+
from rucio.cli.utils import Arguments
|
|
18
|
+
from rucio.common.config import config_get_float
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@click.command("upload")
|
|
22
|
+
@click.argument("file-paths", nargs=-1)
|
|
23
|
+
@click.option("--rse", "--rse-name", help="Rucio Storage Element (RSE) name", required=True)
|
|
24
|
+
@click.option("--lifetime", type=int, help="Lifetime of the rule in seconds")
|
|
25
|
+
@click.option("--expiration-date", help="The date when the rule expires in UTC, format: <year>-<month>-<day>-<hour>:<minute>:<second>. E.g. 2022-10-20-20:00:00")
|
|
26
|
+
@click.option("--scope", help="Scope name.")
|
|
27
|
+
@click.option("--impl", type=click.Choice([]), help="Transfer protocol implementation to use (e.g: xrootd, gfal.NoRename, webdav, ssh.Rsync, rclone)")
|
|
28
|
+
# The --no-register option is hidden. This is pilot ONLY. Users should not use this. Will lead to unregistered data on storage!
|
|
29
|
+
@click.option("--no-register", is_flag=True, default=False, hidden=True)
|
|
30
|
+
@click.option("--register-after-upload", is_flag=True, default=False, help="Register the file _only_ after successful upload")
|
|
31
|
+
@click.option("--summary", is_flag=True, default=False, help="Create rucio_upload.json summary file")
|
|
32
|
+
@click.option("--guid", help="Manually specify the GUID for the file.")
|
|
33
|
+
@click.option("--protocol", help="Force the protocol to use")
|
|
34
|
+
@click.option("--pfn", help="Specify the exact PFN for the upload")
|
|
35
|
+
@click.option("--lfn", help="Specify the exact LFN for the upload")
|
|
36
|
+
@click.option("--transfer-timeout", type=float, default=config_get_float("upload", "transfer_timeout", False, 360), help="Transfer timeout (in seconds)")
|
|
37
|
+
@click.option("-r", "--recursive", is_flag=True, default=False, help="Convert recursively the folder structure into collections")
|
|
38
|
+
@click.pass_context
|
|
39
|
+
def upload_command(ctx, file_paths, rse, lifetime, expiration_date, scope, impl, no_register, register_after_upload, summary, guid, protocol, pfn, lfn, transfer_timeout, recursive):
|
|
40
|
+
"""Upload file(s) to a Rucio RSE"""
|
|
41
|
+
args = Arguments(
|
|
42
|
+
{
|
|
43
|
+
"args": file_paths,
|
|
44
|
+
"rse": rse,
|
|
45
|
+
"lifetime": lifetime,
|
|
46
|
+
"expiration_date": expiration_date,
|
|
47
|
+
"scope": scope,
|
|
48
|
+
"impl": impl,
|
|
49
|
+
"no_register": no_register,
|
|
50
|
+
"register_after_upload": register_after_upload,
|
|
51
|
+
"protocol": protocol,
|
|
52
|
+
"summary": summary,
|
|
53
|
+
"guid": guid,
|
|
54
|
+
"pfn": pfn,
|
|
55
|
+
"name": lfn,
|
|
56
|
+
"transfer_timeout": transfer_timeout,
|
|
57
|
+
"recursive": recursive,
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
upload(args, ctx.obj.client, ctx.obj.logger, ctx.obj.console, ctx.obj.spinner)
|
rucio/cli/utils.py
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
import errno
|
|
15
|
+
import logging
|
|
16
|
+
import os
|
|
17
|
+
import signal
|
|
18
|
+
import subprocess
|
|
19
|
+
import sys
|
|
20
|
+
import traceback
|
|
21
|
+
from configparser import NoOptionError, NoSectionError
|
|
22
|
+
from functools import wraps
|
|
23
|
+
|
|
24
|
+
from rucio.client.client import Client
|
|
25
|
+
from rucio.common.config import config_get
|
|
26
|
+
from rucio.common.exception import (
|
|
27
|
+
AccessDenied,
|
|
28
|
+
CannotAuthenticate,
|
|
29
|
+
DataIdentifierAlreadyExists,
|
|
30
|
+
DataIdentifierNotFound,
|
|
31
|
+
Duplicate,
|
|
32
|
+
DuplicateContent,
|
|
33
|
+
InvalidObject,
|
|
34
|
+
InvalidRSEExpression,
|
|
35
|
+
MissingDependency,
|
|
36
|
+
RSENotFound,
|
|
37
|
+
RucioException,
|
|
38
|
+
RuleNotFound,
|
|
39
|
+
UnsupportedOperation,
|
|
40
|
+
)
|
|
41
|
+
from rucio.common.utils import setup_logger
|
|
42
|
+
|
|
43
|
+
SUCCESS = 0
|
|
44
|
+
FAILURE = 1
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def exception_handler(function):
|
|
48
|
+
verbosity = ("-v" in sys.argv) or ("--verbose" in sys.argv)
|
|
49
|
+
logger = setup_logger(module_name=__name__, logger_name="user", verbose=verbosity)
|
|
50
|
+
|
|
51
|
+
@wraps(function)
|
|
52
|
+
def new_funct(*args, **kwargs):
|
|
53
|
+
try:
|
|
54
|
+
return function(*args, **kwargs)
|
|
55
|
+
except NotImplementedError as error:
|
|
56
|
+
logger.error(f"Cannot run that operation/command combination {error}")
|
|
57
|
+
return FAILURE
|
|
58
|
+
except InvalidObject as error:
|
|
59
|
+
logger.error(error)
|
|
60
|
+
return error.error_code
|
|
61
|
+
except DataIdentifierNotFound as error:
|
|
62
|
+
logger.error(error)
|
|
63
|
+
logger.debug("This means that the Data IDentifier you provided is not known by Rucio.")
|
|
64
|
+
return error.error_code
|
|
65
|
+
except AccessDenied as error:
|
|
66
|
+
logger.error(error)
|
|
67
|
+
logger.debug("This error is a permission issue. You cannot run this command with your account.")
|
|
68
|
+
return error.error_code
|
|
69
|
+
except DataIdentifierAlreadyExists as error:
|
|
70
|
+
logger.error(error)
|
|
71
|
+
logger.debug("This means that the Data IDentifier you try to add is already registered in Rucio.")
|
|
72
|
+
return error.error_code
|
|
73
|
+
except RSENotFound as error:
|
|
74
|
+
logger.error(error)
|
|
75
|
+
logger.debug("This means that the Rucio Storage Element you provided is not known by Rucio.")
|
|
76
|
+
return error.error_code
|
|
77
|
+
except InvalidRSEExpression as error:
|
|
78
|
+
logger.error(error)
|
|
79
|
+
logger.debug("This means the RSE expression you provided is not syntactically correct.")
|
|
80
|
+
return error.error_code
|
|
81
|
+
except DuplicateContent as error:
|
|
82
|
+
logger.error(error)
|
|
83
|
+
logger.debug("This means that the DID you want to attach is already in the target DID.")
|
|
84
|
+
return error.error_code
|
|
85
|
+
except Duplicate as error:
|
|
86
|
+
logger.error(error)
|
|
87
|
+
logger.debug("This means that you are trying to add something that already exists.")
|
|
88
|
+
return error.error_code
|
|
89
|
+
except TypeError as error:
|
|
90
|
+
logger.error(error)
|
|
91
|
+
logger.debug("This means the parameter you passed has a wrong type.")
|
|
92
|
+
return FAILURE
|
|
93
|
+
except RuleNotFound as error:
|
|
94
|
+
logger.error(error)
|
|
95
|
+
logger.debug("This means the rule you specified does not exist.")
|
|
96
|
+
return error.error_code
|
|
97
|
+
except UnsupportedOperation as error:
|
|
98
|
+
logger.error(error)
|
|
99
|
+
logger.debug("This means you cannot change the status of the DID.")
|
|
100
|
+
return error.error_code
|
|
101
|
+
except MissingDependency as error:
|
|
102
|
+
logger.error(error)
|
|
103
|
+
logger.debug("This means one dependency is missing.")
|
|
104
|
+
return error.error_code
|
|
105
|
+
except KeyError as error:
|
|
106
|
+
if "x-rucio-auth-token" in str(error):
|
|
107
|
+
used_account = None
|
|
108
|
+
try: # get the configured account from the configuration file
|
|
109
|
+
used_account = "%s (from rucio.cfg)" % config_get("client", "account")
|
|
110
|
+
except Exception:
|
|
111
|
+
pass
|
|
112
|
+
try: # are we overriden by the environment?
|
|
113
|
+
used_account = "%s (from RUCIO_ACCOUNT)" % os.environ["RUCIO_ACCOUNT"]
|
|
114
|
+
except Exception:
|
|
115
|
+
pass
|
|
116
|
+
logger.error("Specified account %s does not have an associated identity." % used_account)
|
|
117
|
+
|
|
118
|
+
else:
|
|
119
|
+
logger.debug(traceback.format_exc())
|
|
120
|
+
contact = config_get("policy", "support", raise_exception=False)
|
|
121
|
+
support = ("Please follow up with all relevant information at: " + contact) if contact else ""
|
|
122
|
+
logger.error("\nThe object is missing this property: %s\n" 'This should never happen. Please rerun the last command with the "-v" option to gather more information.\n' "%s" % (str(error), support))
|
|
123
|
+
return FAILURE
|
|
124
|
+
except RucioException as error:
|
|
125
|
+
logger.error(error)
|
|
126
|
+
return error.error_code
|
|
127
|
+
except Exception as error:
|
|
128
|
+
if isinstance(error, IOError) and getattr(error, "errno", None) == errno.EPIPE:
|
|
129
|
+
# Ignore Broken Pipe
|
|
130
|
+
# While in python3 we can directly catch 'BrokenPipeError', in python2 it doesn't exist.
|
|
131
|
+
|
|
132
|
+
# Python flushes standard streams on exit; redirect remaining output
|
|
133
|
+
# to devnull to avoid another BrokenPipeError at shutdown
|
|
134
|
+
devnull = os.open(os.devnull, os.O_WRONLY)
|
|
135
|
+
os.dup2(devnull, sys.stdout.fileno())
|
|
136
|
+
return SUCCESS
|
|
137
|
+
logger.debug(traceback.format_exc())
|
|
138
|
+
logger.error(error)
|
|
139
|
+
contact = config_get("policy", "support", raise_exception=False)
|
|
140
|
+
support = ("If it's a problem concerning your experiment or if you're unsure what to do, please follow up at: %s\n" % contact) if contact else ""
|
|
141
|
+
contact = config_get("policy", "support_rucio", default="https://github.com/rucio/rucio/issues")
|
|
142
|
+
support += "If you're sure there is a problem with Rucio itself, please follow up at: " + contact
|
|
143
|
+
logger.error("\nRucio exited with an unexpected/unknown error.\n" 'Please rerun the last command with the "-v" option to gather more information.\n' "%s" % support)
|
|
144
|
+
return FAILURE
|
|
145
|
+
|
|
146
|
+
return new_funct
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def get_client(args, logger):
|
|
150
|
+
"""
|
|
151
|
+
Returns a new client object.
|
|
152
|
+
"""
|
|
153
|
+
if hasattr(args, "config") and (args.config is not None):
|
|
154
|
+
os.environ["RUCIO_CONFIG"] = args.config
|
|
155
|
+
|
|
156
|
+
if logger is None:
|
|
157
|
+
logger = setup_logger(module_name=__name__, logger_name="user", verbose=args.verbose)
|
|
158
|
+
|
|
159
|
+
if not args.auth_strategy:
|
|
160
|
+
if "RUCIO_AUTH_TYPE" in os.environ:
|
|
161
|
+
auth_type = os.environ["RUCIO_AUTH_TYPE"].lower()
|
|
162
|
+
else:
|
|
163
|
+
try:
|
|
164
|
+
auth_type = config_get("client", "auth_type").lower()
|
|
165
|
+
except (NoOptionError, NoSectionError):
|
|
166
|
+
logger.error("Cannot get AUTH_TYPE")
|
|
167
|
+
sys.exit(1)
|
|
168
|
+
else:
|
|
169
|
+
auth_type = args.auth_strategy.lower()
|
|
170
|
+
|
|
171
|
+
if auth_type in ["userpass", "saml"] and args.username is not None and args.password is not None:
|
|
172
|
+
creds = {"username": args.username, "password": args.password}
|
|
173
|
+
elif auth_type == "oidc":
|
|
174
|
+
if args.oidc_issuer:
|
|
175
|
+
args.oidc_issuer = args.oidc_issuer.lower()
|
|
176
|
+
creds = {
|
|
177
|
+
"oidc_auto": args.oidc_auto,
|
|
178
|
+
"oidc_scope": args.oidc_scope,
|
|
179
|
+
"oidc_audience": args.oidc_audience,
|
|
180
|
+
"oidc_polling": args.oidc_polling,
|
|
181
|
+
"oidc_refresh_lifetime": args.oidc_refresh_lifetime,
|
|
182
|
+
"oidc_issuer": args.oidc_issuer,
|
|
183
|
+
"oidc_username": args.oidc_username,
|
|
184
|
+
"oidc_password": args.oidc_password,
|
|
185
|
+
}
|
|
186
|
+
elif auth_type == "x509":
|
|
187
|
+
creds = {"client_cert": args.certificate, "client_key": args.client_key}
|
|
188
|
+
else:
|
|
189
|
+
creds = None
|
|
190
|
+
|
|
191
|
+
try:
|
|
192
|
+
client = Client(rucio_host=args.host, auth_host=args.auth_host, account=args.issuer, auth_type=auth_type, creds=creds, ca_cert=args.ca_certificate, timeout=args.timeout, user_agent=args.user_agent, vo=args.vo, logger=logger)
|
|
193
|
+
except CannotAuthenticate as error:
|
|
194
|
+
logger.error(error)
|
|
195
|
+
if "alert certificate expired" in str(error):
|
|
196
|
+
logger.error("The server certificate expired.")
|
|
197
|
+
elif auth_type.lower() == "x509_proxy":
|
|
198
|
+
logger.error("Please verify that your proxy is still valid and renew it if needed.")
|
|
199
|
+
sys.exit(1)
|
|
200
|
+
return client
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def signal_handler(sig, frame, logger):
|
|
204
|
+
logger.warning("You pressed Ctrl+C! Exiting gracefully")
|
|
205
|
+
child_processes = subprocess.Popen("ps -o pid --ppid %s --noheaders" % os.getpid(), shell=True, stdout=subprocess.PIPE)
|
|
206
|
+
child_processes = child_processes.stdout.read() # type: ignore
|
|
207
|
+
for pid in child_processes.split("\n")[:-1]: # type: ignore
|
|
208
|
+
try:
|
|
209
|
+
os.kill(int(pid), signal.SIGTERM)
|
|
210
|
+
except Exception:
|
|
211
|
+
print("Cannot kill child process")
|
|
212
|
+
sys.exit(1)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def setup_gfal2_logger():
|
|
216
|
+
gfal2_logger = logging.getLogger("gfal2")
|
|
217
|
+
gfal2_logger.setLevel(logging.CRITICAL)
|
|
218
|
+
gfal2_logger.addHandler(logging.StreamHandler())
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class Arguments(dict):
|
|
222
|
+
"""dot.notation access to dictionary attributes"""
|
|
223
|
+
|
|
224
|
+
__getattr__ = dict.get
|
|
225
|
+
__setattr__ = dict.__setitem__
|
|
226
|
+
__delattr__ = dict.__delitem__
|
rucio/client/__init__.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Copyright European Organization for Nuclear Research (CERN) since 2012
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from .client import Client # noqa: F401
|