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.

Files changed (104) hide show
  1. rucio/__init__.py +17 -0
  2. rucio/alembicrevision.py +15 -0
  3. rucio/cli/__init__.py +14 -0
  4. rucio/cli/account.py +216 -0
  5. rucio/cli/bin_legacy/__init__.py +13 -0
  6. rucio/cli/bin_legacy/rucio.py +2825 -0
  7. rucio/cli/bin_legacy/rucio_admin.py +2500 -0
  8. rucio/cli/command.py +272 -0
  9. rucio/cli/config.py +72 -0
  10. rucio/cli/did.py +191 -0
  11. rucio/cli/download.py +128 -0
  12. rucio/cli/lifetime_exception.py +33 -0
  13. rucio/cli/replica.py +162 -0
  14. rucio/cli/rse.py +293 -0
  15. rucio/cli/rule.py +158 -0
  16. rucio/cli/scope.py +40 -0
  17. rucio/cli/subscription.py +73 -0
  18. rucio/cli/upload.py +60 -0
  19. rucio/cli/utils.py +226 -0
  20. rucio/client/__init__.py +15 -0
  21. rucio/client/accountclient.py +432 -0
  22. rucio/client/accountlimitclient.py +183 -0
  23. rucio/client/baseclient.py +983 -0
  24. rucio/client/client.py +120 -0
  25. rucio/client/configclient.py +126 -0
  26. rucio/client/credentialclient.py +59 -0
  27. rucio/client/didclient.py +868 -0
  28. rucio/client/diracclient.py +56 -0
  29. rucio/client/downloadclient.py +1783 -0
  30. rucio/client/exportclient.py +44 -0
  31. rucio/client/fileclient.py +50 -0
  32. rucio/client/importclient.py +42 -0
  33. rucio/client/lifetimeclient.py +90 -0
  34. rucio/client/lockclient.py +109 -0
  35. rucio/client/metaconventionsclient.py +140 -0
  36. rucio/client/pingclient.py +44 -0
  37. rucio/client/replicaclient.py +452 -0
  38. rucio/client/requestclient.py +125 -0
  39. rucio/client/richclient.py +317 -0
  40. rucio/client/rseclient.py +746 -0
  41. rucio/client/ruleclient.py +294 -0
  42. rucio/client/scopeclient.py +90 -0
  43. rucio/client/subscriptionclient.py +173 -0
  44. rucio/client/touchclient.py +82 -0
  45. rucio/client/uploadclient.py +969 -0
  46. rucio/common/__init__.py +13 -0
  47. rucio/common/bittorrent.py +234 -0
  48. rucio/common/cache.py +111 -0
  49. rucio/common/checksum.py +168 -0
  50. rucio/common/client.py +122 -0
  51. rucio/common/config.py +788 -0
  52. rucio/common/constants.py +217 -0
  53. rucio/common/constraints.py +17 -0
  54. rucio/common/didtype.py +237 -0
  55. rucio/common/exception.py +1208 -0
  56. rucio/common/extra.py +31 -0
  57. rucio/common/logging.py +420 -0
  58. rucio/common/pcache.py +1409 -0
  59. rucio/common/plugins.py +185 -0
  60. rucio/common/policy.py +93 -0
  61. rucio/common/schema/__init__.py +200 -0
  62. rucio/common/schema/generic.py +416 -0
  63. rucio/common/schema/generic_multi_vo.py +395 -0
  64. rucio/common/stomp_utils.py +423 -0
  65. rucio/common/stopwatch.py +55 -0
  66. rucio/common/test_rucio_server.py +154 -0
  67. rucio/common/types.py +483 -0
  68. rucio/common/utils.py +1688 -0
  69. rucio/rse/__init__.py +96 -0
  70. rucio/rse/protocols/__init__.py +13 -0
  71. rucio/rse/protocols/bittorrent.py +194 -0
  72. rucio/rse/protocols/cache.py +111 -0
  73. rucio/rse/protocols/dummy.py +100 -0
  74. rucio/rse/protocols/gfal.py +708 -0
  75. rucio/rse/protocols/globus.py +243 -0
  76. rucio/rse/protocols/http_cache.py +82 -0
  77. rucio/rse/protocols/mock.py +123 -0
  78. rucio/rse/protocols/ngarc.py +209 -0
  79. rucio/rse/protocols/posix.py +250 -0
  80. rucio/rse/protocols/protocol.py +361 -0
  81. rucio/rse/protocols/rclone.py +365 -0
  82. rucio/rse/protocols/rfio.py +145 -0
  83. rucio/rse/protocols/srm.py +338 -0
  84. rucio/rse/protocols/ssh.py +414 -0
  85. rucio/rse/protocols/storm.py +195 -0
  86. rucio/rse/protocols/webdav.py +594 -0
  87. rucio/rse/protocols/xrootd.py +302 -0
  88. rucio/rse/rsemanager.py +881 -0
  89. rucio/rse/translation.py +260 -0
  90. rucio/vcsversion.py +11 -0
  91. rucio/version.py +45 -0
  92. rucio_clients-37.0.0rc1.data/data/etc/rse-accounts.cfg.template +25 -0
  93. rucio_clients-37.0.0rc1.data/data/etc/rucio.cfg.atlas.client.template +43 -0
  94. rucio_clients-37.0.0rc1.data/data/etc/rucio.cfg.template +241 -0
  95. rucio_clients-37.0.0rc1.data/data/requirements.client.txt +19 -0
  96. rucio_clients-37.0.0rc1.data/data/rucio_client/merge_rucio_configs.py +144 -0
  97. rucio_clients-37.0.0rc1.data/scripts/rucio +133 -0
  98. rucio_clients-37.0.0rc1.data/scripts/rucio-admin +97 -0
  99. rucio_clients-37.0.0rc1.dist-info/METADATA +54 -0
  100. rucio_clients-37.0.0rc1.dist-info/RECORD +104 -0
  101. rucio_clients-37.0.0rc1.dist-info/WHEEL +5 -0
  102. rucio_clients-37.0.0rc1.dist-info/licenses/AUTHORS.rst +100 -0
  103. rucio_clients-37.0.0rc1.dist-info/licenses/LICENSE +201 -0
  104. 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__
@@ -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