rucio 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 might be problematic. Click here for more details.
- rucio/alembicrevision.py +1 -1
- rucio/{daemons/c3po/collectors → cli}/__init__.py +1 -0
- rucio/cli/account.py +216 -0
- rucio-35.7.0.data/scripts/rucio → rucio/cli/bin_legacy/rucio.py +769 -486
- rucio-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/dumper/__init__.py +45 -38
- rucio/common/dumper/consistency.py +75 -30
- rucio/common/dumper/data_models.py +63 -19
- rucio/common/dumper/path_parsing.py +19 -8
- 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/core/account_limit.py +14 -12
- rucio/core/authentication.py +2 -2
- rucio/core/config.py +23 -42
- rucio/core/credential.py +14 -15
- rucio/core/did.py +5 -1
- rucio/core/did_meta_plugins/elasticsearch_meta.py +407 -0
- rucio/core/did_meta_plugins/filter_engine.py +62 -3
- rucio/core/did_meta_plugins/json_meta.py +2 -2
- rucio/core/did_meta_plugins/mongo_meta.py +43 -30
- rucio/core/did_meta_plugins/postgres_meta.py +75 -39
- rucio/core/identity.py +6 -5
- rucio/core/importer.py +4 -3
- rucio/core/lifetime_exception.py +2 -2
- rucio/core/lock.py +8 -7
- rucio/core/message.py +6 -0
- rucio/core/monitor.py +30 -29
- rucio/core/naming_convention.py +2 -2
- rucio/core/nongrid_trace.py +2 -2
- rucio/core/oidc.py +11 -9
- rucio/core/permission/__init__.py +79 -37
- rucio/core/permission/generic.py +1 -7
- rucio/core/permission/generic_multi_vo.py +1 -7
- rucio/core/quarantined_replica.py +4 -3
- rucio/core/replica.py +464 -139
- rucio/core/replica_sorter.py +55 -59
- rucio/core/request.py +34 -32
- rucio/core/rse.py +301 -97
- rucio/core/rse_counter.py +1 -2
- rucio/core/rse_expression_parser.py +7 -7
- rucio/core/rse_selector.py +9 -7
- rucio/core/rule.py +41 -40
- rucio/core/rule_grouping.py +42 -40
- rucio/core/scope.py +5 -4
- rucio/core/subscription.py +26 -28
- rucio/core/topology.py +11 -11
- rucio/core/trace.py +2 -2
- rucio/core/transfer.py +29 -15
- rucio/core/volatile_replica.py +4 -3
- rucio/daemons/atropos/atropos.py +1 -1
- rucio/daemons/auditor/__init__.py +2 -2
- rucio/daemons/auditor/srmdumps.py +6 -6
- rucio/daemons/automatix/automatix.py +32 -21
- rucio/daemons/badreplicas/necromancer.py +2 -2
- rucio/daemons/bb8/nuclei_background_rebalance.py +1 -1
- rucio/daemons/bb8/t2_background_rebalance.py +1 -1
- rucio/daemons/common.py +15 -25
- rucio/daemons/conveyor/finisher.py +2 -2
- rucio/daemons/conveyor/poller.py +18 -28
- rucio/daemons/conveyor/receiver.py +2 -2
- rucio/daemons/conveyor/stager.py +1 -0
- rucio/daemons/conveyor/submitter.py +3 -3
- rucio/daemons/hermes/hermes.py +91 -30
- rucio/daemons/judge/evaluator.py +2 -2
- rucio/daemons/oauthmanager/oauthmanager.py +3 -3
- rucio/daemons/reaper/dark_reaper.py +7 -3
- rucio/daemons/reaper/reaper.py +12 -16
- rucio/daemons/rsedecommissioner/config.py +1 -1
- rucio/daemons/rsedecommissioner/profiles/generic.py +5 -4
- rucio/daemons/rsedecommissioner/profiles/types.py +7 -6
- rucio/daemons/rsedecommissioner/rse_decommissioner.py +1 -1
- rucio/daemons/storage/consistency/actions.py +8 -6
- rucio/daemons/tracer/kronos.py +4 -4
- rucio/db/sqla/constants.py +5 -0
- rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +4 -4
- rucio/db/sqla/migrate_repo/versions/30d5206e9cad_increase_oauthrequest_redirect_msg_.py +37 -0
- rucio/db/sqla/models.py +157 -154
- rucio/db/sqla/session.py +58 -27
- rucio/db/sqla/types.py +2 -2
- rucio/db/sqla/util.py +2 -2
- rucio/gateway/account.py +18 -12
- rucio/gateway/account_limit.py +137 -60
- rucio/gateway/authentication.py +18 -12
- rucio/gateway/config.py +30 -20
- rucio/gateway/credential.py +9 -10
- rucio/gateway/did.py +70 -53
- rucio/gateway/dirac.py +6 -4
- rucio/gateway/exporter.py +3 -2
- rucio/gateway/heartbeat.py +6 -4
- rucio/gateway/identity.py +36 -51
- rucio/gateway/importer.py +3 -2
- rucio/gateway/lifetime_exception.py +3 -2
- rucio/gateway/meta_conventions.py +17 -6
- rucio/gateway/permission.py +4 -1
- rucio/gateway/quarantined_replica.py +3 -2
- rucio/gateway/replica.py +31 -22
- rucio/gateway/request.py +27 -18
- rucio/gateway/rse.py +69 -37
- rucio/gateway/rule.py +46 -26
- rucio/gateway/scope.py +3 -2
- rucio/gateway/subscription.py +14 -11
- rucio/gateway/vo.py +12 -8
- 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/tests/common.py +23 -13
- rucio/tests/common_server.py +26 -9
- rucio/transfertool/bittorrent.py +15 -14
- rucio/transfertool/bittorrent_driver.py +5 -7
- rucio/transfertool/bittorrent_driver_qbittorrent.py +9 -8
- rucio/transfertool/fts3.py +20 -16
- rucio/transfertool/mock.py +2 -3
- rucio/vcsversion.py +4 -4
- rucio/version.py +7 -0
- rucio/web/rest/flaskapi/v1/accounts.py +17 -3
- rucio/web/rest/flaskapi/v1/auth.py +5 -5
- rucio/web/rest/flaskapi/v1/credentials.py +3 -2
- rucio/web/rest/flaskapi/v1/dids.py +21 -15
- rucio/web/rest/flaskapi/v1/identities.py +33 -9
- rucio/web/rest/flaskapi/v1/redirect.py +5 -4
- rucio/web/rest/flaskapi/v1/replicas.py +12 -8
- rucio/web/rest/flaskapi/v1/rses.py +15 -4
- rucio/web/rest/flaskapi/v1/traces.py +56 -19
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/alembic.ini.template +1 -1
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/alembic_offline.ini.template +1 -1
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rucio.cfg.atlas.client.template +3 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rucio.cfg.template +3 -19
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rucio_multi_vo.cfg.template +1 -18
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/requirements.server.txt +97 -68
- rucio-37.0.0.data/scripts/rucio +133 -0
- rucio-37.0.0.data/scripts/rucio-admin +97 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-atropos +2 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-auditor +2 -1
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-automatix +2 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-cache-client +17 -10
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-receiver +1 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-kronos +1 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-minos +2 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-minos-temporary-expiration +2 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-necromancer +2 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-reaper +6 -6
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-transmogrifier +2 -2
- rucio-37.0.0.dist-info/METADATA +92 -0
- {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/RECORD +237 -243
- {rucio-35.7.0.dist-info → rucio-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/core/permission/atlas.py +0 -1348
- rucio/core/permission/belleii.py +0 -1077
- rucio/core/permission/escape.py +0 -1078
- rucio/daemons/c3po/algorithms/__init__.py +0 -13
- rucio/daemons/c3po/algorithms/simple.py +0 -134
- rucio/daemons/c3po/algorithms/t2_free_space.py +0 -128
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +0 -130
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +0 -294
- rucio/daemons/c3po/c3po.py +0 -371
- rucio/daemons/c3po/collectors/agis.py +0 -108
- rucio/daemons/c3po/collectors/free_space.py +0 -81
- rucio/daemons/c3po/collectors/jedi_did.py +0 -57
- rucio/daemons/c3po/collectors/mock_did.py +0 -51
- rucio/daemons/c3po/collectors/network_metrics.py +0 -71
- rucio/daemons/c3po/collectors/workload.py +0 -112
- rucio/daemons/c3po/utils/__init__.py +0 -13
- rucio/daemons/c3po/utils/dataset_cache.py +0 -50
- rucio/daemons/c3po/utils/expiring_dataset_cache.py +0 -56
- rucio/daemons/c3po/utils/expiring_list.py +0 -62
- rucio/daemons/c3po/utils/popularity.py +0 -85
- rucio/daemons/c3po/utils/timeseries.py +0 -89
- rucio/rse/protocols/gsiftp.py +0 -92
- rucio-35.7.0.data/scripts/rucio-c3po +0 -85
- rucio-35.7.0.dist-info/METADATA +0 -72
- /rucio/{daemons/c3po → cli/bin_legacy}/__init__.py +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/globus-config.yml.template +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/ldap.cfg.template +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/tools/bootstrap.py +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/tools/merge_rucio_configs.py +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/tools/reset_database.py +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-abacus-account +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-abacus-collection-replica +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-abacus-rse +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-bb8 +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-cache-consumer +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-finisher +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-poller +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-preparer +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-stager +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-submitter +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-throttler +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-dark-reaper +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-dumper +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-follower +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-hermes +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-cleaner +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-evaluator +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-injector +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-repairer +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-oauth-manager +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-replica-recoverer +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-rse-decommissioner +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-storage-consistency-actions +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-undertaker +0 -0
- {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/WHEEL +0 -0
- {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/licenses/LICENSE +0 -0
- {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/top_level.txt +0 -0
rucio/db/sqla/session.py
CHANGED
|
@@ -16,6 +16,7 @@ import copy
|
|
|
16
16
|
import logging
|
|
17
17
|
import os
|
|
18
18
|
import sys
|
|
19
|
+
from contextlib import contextmanager
|
|
19
20
|
from datetime import datetime, timedelta
|
|
20
21
|
from functools import update_wrapper
|
|
21
22
|
from inspect import getfullargspec, isgeneratorfunction
|
|
@@ -33,11 +34,12 @@ from rucio.common.config import config_get
|
|
|
33
34
|
from rucio.common.exception import DatabaseException, InputValidationError, RucioException
|
|
34
35
|
from rucio.common.extra import import_extras
|
|
35
36
|
from rucio.common.utils import retrying
|
|
37
|
+
from rucio.db.sqla.constants import DatabaseOperationType
|
|
36
38
|
|
|
37
39
|
EXTRA_MODULES = import_extras(['MySQLdb', 'pymysql'])
|
|
38
40
|
|
|
39
41
|
if TYPE_CHECKING:
|
|
40
|
-
from collections.abc import Callable
|
|
42
|
+
from collections.abc import Callable, Iterator
|
|
41
43
|
from typing import Optional, ParamSpec, TypeVar
|
|
42
44
|
|
|
43
45
|
from pymysql import Connection as MySQLConnection
|
|
@@ -49,7 +51,6 @@ if TYPE_CHECKING:
|
|
|
49
51
|
R = TypeVar('R')
|
|
50
52
|
CallableTypeVar = TypeVar('CallableTypeVar', bound='Callable[..., Any]')
|
|
51
53
|
|
|
52
|
-
|
|
53
54
|
try:
|
|
54
55
|
main_script = os.path.basename(sys.argv[0])
|
|
55
56
|
CURRENT_COMPONENT = main_script.split('-')[1]
|
|
@@ -71,6 +72,13 @@ _METADATA = MetaData(schema=DEFAULT_SCHEMA_NAME)
|
|
|
71
72
|
_MAKER, _ENGINE, _LOCK = None, None, Lock()
|
|
72
73
|
|
|
73
74
|
|
|
75
|
+
SQLA_CONFIG_POOLCLASS_MAPPING = {
|
|
76
|
+
'queuepool': QueuePool,
|
|
77
|
+
'singletonthreadpool': SingletonThreadPool,
|
|
78
|
+
'nullpool': NullPool,
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
74
82
|
class BASE(DeclarativeBase):
|
|
75
83
|
metadata = _METADATA
|
|
76
84
|
|
|
@@ -151,22 +159,20 @@ def mysql_convert_decimal_to_float(
|
|
|
151
159
|
|
|
152
160
|
def psql_convert_decimal_to_float(dbapi_conn, connection_rec) -> None:
|
|
153
161
|
"""
|
|
154
|
-
|
|
155
|
-
|
|
162
|
+
Configure the PostgreSQL connection to return numeric types as float instead of Decimal.
|
|
163
|
+
Psycopg3 provides this functionality through type adapters.
|
|
156
164
|
|
|
157
165
|
:param dbapi_conn: DBAPI connection
|
|
158
166
|
:param connection_rec: connection record
|
|
159
167
|
"""
|
|
160
|
-
|
|
161
168
|
try:
|
|
162
|
-
import
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
psycopg2.extensions.register_type(DEC2FLOAT)
|
|
169
|
+
import psycopg
|
|
170
|
+
# Register a global loader that converts numeric types to float
|
|
171
|
+
dbapi_conn.adapters.register_loader("numeric", psycopg.types.numeric.FloatLoader)
|
|
172
|
+
except ImportError:
|
|
173
|
+
raise RucioException('Trying to use PostgreSQL without psycopg installed!')
|
|
174
|
+
except Exception as error:
|
|
175
|
+
raise RucioException(f'Error setting up PostgreSQL Decimal to Float conversion: {str(error)}')
|
|
170
176
|
|
|
171
177
|
|
|
172
178
|
def my_on_connect(dbapi_con, connection_record) -> None:
|
|
@@ -189,12 +195,6 @@ def _get_engine_poolclass(poolclass: str) -> Pool:
|
|
|
189
195
|
:raises InputValidationError: if config value doesn't correspond to an SQLAlchemy Pool class.
|
|
190
196
|
"""
|
|
191
197
|
|
|
192
|
-
SQLA_CONFIG_POOLCLASS_MAPPING = {
|
|
193
|
-
'queuepool': QueuePool,
|
|
194
|
-
'singletonthreadpool': SingletonThreadPool,
|
|
195
|
-
'nullpool': NullPool,
|
|
196
|
-
}
|
|
197
|
-
|
|
198
198
|
poolclass = poolclass.lower()
|
|
199
199
|
|
|
200
200
|
if poolclass not in SQLA_CONFIG_POOLCLASS_MAPPING:
|
|
@@ -204,7 +204,7 @@ def _get_engine_poolclass(poolclass: str) -> Pool:
|
|
|
204
204
|
|
|
205
205
|
|
|
206
206
|
def get_engine() -> 'Engine':
|
|
207
|
-
""" Creates
|
|
207
|
+
""" Creates an engine to a specific database.
|
|
208
208
|
:returns: engine
|
|
209
209
|
"""
|
|
210
210
|
global _ENGINE
|
|
@@ -223,9 +223,7 @@ def get_engine() -> 'Engine':
|
|
|
223
223
|
params[param] = param_type(config_get(DATABASE_SECTION, param, check_config_table=False))
|
|
224
224
|
except:
|
|
225
225
|
pass
|
|
226
|
-
|
|
227
|
-
# if backing up from 2.0, need to remove future=True .
|
|
228
|
-
_ENGINE = create_engine(sql_connection, future=True, **params)
|
|
226
|
+
_ENGINE = create_engine(sql_connection, **params)
|
|
229
227
|
if 'mysql' in sql_connection:
|
|
230
228
|
event.listen(_ENGINE, 'checkout', mysql_ping_listener)
|
|
231
229
|
elif 'postgresql' in sql_connection:
|
|
@@ -261,6 +259,7 @@ def get_dump_engine(
|
|
|
261
259
|
print(statement.replace(')', ');\n'))
|
|
262
260
|
else:
|
|
263
261
|
print(statement)
|
|
262
|
+
|
|
264
263
|
sql_connection = config_get(DATABASE_SECTION, 'default', check_config_table=False)
|
|
265
264
|
|
|
266
265
|
engine = create_engine(sql_connection, echo=echo, strategy='mock', executor=dump)
|
|
@@ -276,8 +275,7 @@ def get_maker() -> sessionmaker:
|
|
|
276
275
|
if not _ENGINE:
|
|
277
276
|
raise RuntimeError("Could not form database engine.")
|
|
278
277
|
if not _MAKER:
|
|
279
|
-
|
|
280
|
-
_MAKER = sessionmaker(bind=_ENGINE, autocommit=False, autoflush=True, expire_on_commit=True, future=True)
|
|
278
|
+
_MAKER = sessionmaker(bind=_ENGINE, autocommit=False, autoflush=True, expire_on_commit=True)
|
|
281
279
|
return _MAKER
|
|
282
280
|
|
|
283
281
|
|
|
@@ -387,12 +385,14 @@ def read_session(function: "Callable[P, R]"):
|
|
|
387
385
|
This is useful if only SELECTs and the like are being done; anything involving
|
|
388
386
|
INSERTs, UPDATEs etc should use transactional_session.
|
|
389
387
|
'''
|
|
388
|
+
|
|
390
389
|
@retrying(retry_on_exception=retry_if_db_connection_error,
|
|
391
390
|
wait_fixed=500,
|
|
392
391
|
stop_max_attempt_number=2)
|
|
393
392
|
def new_funct(*args: "P.args", session: "Optional[Session]" = None, **kwargs): # pylint:disable=missing-kwoa
|
|
394
393
|
if isgeneratorfunction(function):
|
|
395
|
-
raise RucioException(
|
|
394
|
+
raise RucioException(
|
|
395
|
+
'read_session decorator should not be used with generator. Use stream_session instead.')
|
|
396
396
|
|
|
397
397
|
if not session:
|
|
398
398
|
session_scoped = get_session()
|
|
@@ -415,6 +415,7 @@ def read_session(function: "Callable[P, R]"):
|
|
|
415
415
|
return function(*args, session=session, **kwargs)
|
|
416
416
|
except Exception:
|
|
417
417
|
raise
|
|
418
|
+
|
|
418
419
|
return _update_session_wrapper(new_funct, function)
|
|
419
420
|
|
|
420
421
|
|
|
@@ -427,13 +428,15 @@ def stream_session(function: "Callable[P, R]"):
|
|
|
427
428
|
This is useful if only SELECTs and the like are being done; anything involving
|
|
428
429
|
INSERTs, UPDATEs etc should use transactional_session.
|
|
429
430
|
'''
|
|
431
|
+
|
|
430
432
|
@retrying(retry_on_exception=retry_if_db_connection_error,
|
|
431
433
|
wait_fixed=500,
|
|
432
434
|
stop_max_attempt_number=2)
|
|
433
435
|
def new_funct(*args: "P.args", session: "Optional[Session]" = None, **kwargs): # pylint:disable=missing-kwoa
|
|
434
436
|
|
|
435
437
|
if not isgeneratorfunction(function):
|
|
436
|
-
raise RucioException(
|
|
438
|
+
raise RucioException(
|
|
439
|
+
'stream_session decorator should be used only with generator. Use read_session instead.')
|
|
437
440
|
|
|
438
441
|
if not session:
|
|
439
442
|
session_scoped = get_session()
|
|
@@ -469,6 +472,7 @@ def transactional_session(function: "Callable[P, R]") -> 'Callable':
|
|
|
469
472
|
|
|
470
473
|
session is a sqlalchemy session, and you can get one calling get_session().
|
|
471
474
|
'''
|
|
475
|
+
|
|
472
476
|
def new_funct(
|
|
473
477
|
*args: "P.args",
|
|
474
478
|
session: "Optional[Session]" = None,
|
|
@@ -495,4 +499,31 @@ def transactional_session(function: "Callable[P, R]") -> 'Callable':
|
|
|
495
499
|
else:
|
|
496
500
|
result = function(*args, session=session, **kwargs)
|
|
497
501
|
return result
|
|
502
|
+
|
|
498
503
|
return _update_session_wrapper(new_funct, function)
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
@retrying(retry_on_exception=retry_if_db_connection_error,
|
|
507
|
+
wait_fixed=500,
|
|
508
|
+
stop_max_attempt_number=2)
|
|
509
|
+
@contextmanager
|
|
510
|
+
def db_session(operation: DatabaseOperationType) -> "Iterator[Session]":
|
|
511
|
+
session_scoped = get_session()
|
|
512
|
+
session = session_scoped()
|
|
513
|
+
session.begin()
|
|
514
|
+
|
|
515
|
+
try:
|
|
516
|
+
yield session
|
|
517
|
+
if operation is DatabaseOperationType.WRITE:
|
|
518
|
+
session.commit()
|
|
519
|
+
except TimeoutError as error:
|
|
520
|
+
session.rollback()
|
|
521
|
+
raise DatabaseException(str(error))
|
|
522
|
+
except DatabaseError as error:
|
|
523
|
+
session.rollback()
|
|
524
|
+
raise DatabaseException(str(error))
|
|
525
|
+
except Exception:
|
|
526
|
+
session.rollback()
|
|
527
|
+
raise
|
|
528
|
+
finally:
|
|
529
|
+
session_scoped.remove()
|
rucio/db/sqla/types.py
CHANGED
|
@@ -164,7 +164,7 @@ class InternalAccountString(TypeDecorator):
|
|
|
164
164
|
def process_result_value(self, value, dialect):
|
|
165
165
|
if value is None:
|
|
166
166
|
return value
|
|
167
|
-
return InternalAccount(value,
|
|
167
|
+
return InternalAccount(value, from_external=False)
|
|
168
168
|
|
|
169
169
|
def coerce_compared_value(self, op, value):
|
|
170
170
|
if op in (operators.like_op, operators.notlike_op):
|
|
@@ -197,7 +197,7 @@ class InternalScopeString(TypeDecorator):
|
|
|
197
197
|
def process_result_value(self, value, dialect):
|
|
198
198
|
if value is None:
|
|
199
199
|
return value
|
|
200
|
-
return InternalScope(value,
|
|
200
|
+
return InternalScope(value, from_external=False)
|
|
201
201
|
|
|
202
202
|
def coerce_compared_value(self, op, value):
|
|
203
203
|
if op in (operators.like_op, operators.notlike_op):
|
rucio/db/sqla/util.py
CHANGED
|
@@ -31,7 +31,7 @@ from sqlalchemy.sql.ddl import DropSchema
|
|
|
31
31
|
from sqlalchemy.sql.expression import select, text
|
|
32
32
|
|
|
33
33
|
from rucio import alembicrevision
|
|
34
|
-
from rucio.common.cache import
|
|
34
|
+
from rucio.common.cache import MemcacheRegion
|
|
35
35
|
from rucio.common.config import config_get, config_get_list
|
|
36
36
|
from rucio.common.schema import get_schema_value
|
|
37
37
|
from rucio.common.types import InternalAccount, LoggerFunction
|
|
@@ -50,7 +50,7 @@ if TYPE_CHECKING:
|
|
|
50
50
|
# TypeVar representing the DeclarativeObj class defined inside _create_temp_table
|
|
51
51
|
DeclarativeObj = TypeVar('DeclarativeObj')
|
|
52
52
|
|
|
53
|
-
REGION =
|
|
53
|
+
REGION = MemcacheRegion(expiration_time=600, memcached_expire_time=3660)
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
def build_database() -> None:
|
rucio/gateway/account.py
CHANGED
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from collections.abc import Iterator
|
|
16
15
|
from typing import TYPE_CHECKING, Any, Optional
|
|
17
16
|
|
|
18
17
|
import rucio.common.exception
|
|
@@ -27,6 +26,8 @@ from rucio.db.sqla.constants import AccountType
|
|
|
27
26
|
from rucio.db.sqla.session import read_session, stream_session, transactional_session
|
|
28
27
|
|
|
29
28
|
if TYPE_CHECKING:
|
|
29
|
+
from collections.abc import Iterator
|
|
30
|
+
|
|
30
31
|
from sqlalchemy.orm import Session
|
|
31
32
|
|
|
32
33
|
from rucio.common.types import AccountAttributesDict, IdentityDict, UsageDict
|
|
@@ -59,8 +60,9 @@ def add_account(
|
|
|
59
60
|
validate_schema(name='account', obj=account, vo=vo)
|
|
60
61
|
|
|
61
62
|
kwargs = {'account': account, 'type': type_}
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='add_account', kwargs=kwargs, session=session)
|
|
64
|
+
if not auth_result.allowed:
|
|
65
|
+
raise rucio.common.exception.AccessDenied('Account %s can not add account. %s' % (issuer, auth_result.message))
|
|
64
66
|
|
|
65
67
|
internal_account = InternalAccount(account, vo=vo)
|
|
66
68
|
|
|
@@ -85,8 +87,9 @@ def del_account(
|
|
|
85
87
|
|
|
86
88
|
"""
|
|
87
89
|
kwargs = {'account': account}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='del_account', kwargs=kwargs, session=session)
|
|
91
|
+
if not auth_result.allowed:
|
|
92
|
+
raise rucio.common.exception.AccessDenied('Account %s can not delete account. %s' % (issuer, auth_result.message))
|
|
90
93
|
|
|
91
94
|
internal_account = InternalAccount(account, vo=vo)
|
|
92
95
|
|
|
@@ -137,8 +140,9 @@ def update_account(
|
|
|
137
140
|
"""
|
|
138
141
|
validate_schema(name='account', obj=account, vo=vo)
|
|
139
142
|
kwargs = {}
|
|
140
|
-
|
|
141
|
-
|
|
143
|
+
auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='update_account', kwargs=kwargs, session=session)
|
|
144
|
+
if not auth_result.allowed:
|
|
145
|
+
raise rucio.common.exception.AccessDenied('Account %s can not change %s of the account. %s' % (issuer, key, auth_result.message))
|
|
142
146
|
|
|
143
147
|
internal_account = InternalAccount(account, vo=vo)
|
|
144
148
|
|
|
@@ -146,7 +150,7 @@ def update_account(
|
|
|
146
150
|
|
|
147
151
|
|
|
148
152
|
@stream_session
|
|
149
|
-
def list_accounts(filter_: Optional[dict[str, Any]] = None, vo: str = 'def', *, session: "Session") -> Iterator[dict[str, Any]]:
|
|
153
|
+
def list_accounts(filter_: Optional[dict[str, Any]] = None, vo: str = 'def', *, session: "Session") -> 'Iterator[dict[str, Any]]':
|
|
150
154
|
"""
|
|
151
155
|
Lists all the Rucio account names.
|
|
152
156
|
|
|
@@ -254,8 +258,9 @@ def add_account_attribute(
|
|
|
254
258
|
validate_schema(name='account_attribute', obj=value, vo=vo)
|
|
255
259
|
|
|
256
260
|
kwargs = {'account': account, 'key': key, 'value': value}
|
|
257
|
-
|
|
258
|
-
|
|
261
|
+
auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='add_attribute', kwargs=kwargs, session=session)
|
|
262
|
+
if not auth_result.allowed:
|
|
263
|
+
raise rucio.common.exception.AccessDenied('Account %s can not add attributes. %s' % (issuer, auth_result.message))
|
|
259
264
|
|
|
260
265
|
internal_account = InternalAccount(account, vo=vo)
|
|
261
266
|
|
|
@@ -281,8 +286,9 @@ def del_account_attribute(
|
|
|
281
286
|
:param session: The database session in use.
|
|
282
287
|
"""
|
|
283
288
|
kwargs = {'account': account, 'key': key}
|
|
284
|
-
|
|
285
|
-
|
|
289
|
+
auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='del_attribute', kwargs=kwargs, session=session)
|
|
290
|
+
if not auth_result.allowed:
|
|
291
|
+
raise rucio.common.exception.AccessDenied('Account %s can not delete attribute. %s' % (issuer, auth_result.message))
|
|
286
292
|
|
|
287
293
|
internal_account = InternalAccount(account, vo=vo)
|
|
288
294
|
|
rucio/gateway/account_limit.py
CHANGED
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from typing import TYPE_CHECKING
|
|
15
|
+
from typing import TYPE_CHECKING, Any, Union
|
|
16
16
|
|
|
17
17
|
import rucio.common.exception
|
|
18
18
|
import rucio.gateway.permission
|
|
19
|
-
from rucio.common.types import InternalAccount
|
|
19
|
+
from rucio.common.types import InternalAccount, RSEResolvedGlobalAccountLimitDict
|
|
20
20
|
from rucio.common.utils import gateway_update_return_dict
|
|
21
21
|
from rucio.core import account_limit as account_limit_core
|
|
22
22
|
from rucio.core.account import account_exists
|
|
@@ -28,7 +28,12 @@ if TYPE_CHECKING:
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
@read_session
|
|
31
|
-
def get_rse_account_usage(
|
|
31
|
+
def get_rse_account_usage(
|
|
32
|
+
rse: str,
|
|
33
|
+
vo: str = 'def',
|
|
34
|
+
*,
|
|
35
|
+
session: "Session"
|
|
36
|
+
) -> list[dict[str, Any]]:
|
|
32
37
|
"""
|
|
33
38
|
Returns the account limit and usage for all for all accounts on a RSE.
|
|
34
39
|
|
|
@@ -43,7 +48,12 @@ def get_rse_account_usage(rse, vo='def', *, session: "Session"):
|
|
|
43
48
|
|
|
44
49
|
|
|
45
50
|
@read_session
|
|
46
|
-
def get_local_account_limits(
|
|
51
|
+
def get_local_account_limits(
|
|
52
|
+
account: str,
|
|
53
|
+
vo: str = 'def',
|
|
54
|
+
*,
|
|
55
|
+
session: "Session"
|
|
56
|
+
) -> dict[str, Any]:
|
|
47
57
|
"""
|
|
48
58
|
Lists the limitation names/values for the specified account name.
|
|
49
59
|
|
|
@@ -56,16 +66,22 @@ def get_local_account_limits(account, vo='def', *, session: "Session"):
|
|
|
56
66
|
:returns: The account limits.
|
|
57
67
|
"""
|
|
58
68
|
|
|
59
|
-
|
|
69
|
+
internal_account = InternalAccount(account, vo=vo)
|
|
60
70
|
|
|
61
71
|
rse_instead_id = {}
|
|
62
|
-
for elem in account_limit_core.get_local_account_limits(account=
|
|
72
|
+
for elem in account_limit_core.get_local_account_limits(account=internal_account, session=session).items():
|
|
63
73
|
rse_instead_id[get_rse_name(rse_id=elem[0], session=session)] = elem[1]
|
|
64
74
|
return rse_instead_id
|
|
65
75
|
|
|
66
76
|
|
|
67
77
|
@read_session
|
|
68
|
-
def get_local_account_limit(
|
|
78
|
+
def get_local_account_limit(
|
|
79
|
+
account: str,
|
|
80
|
+
rse: str,
|
|
81
|
+
vo: str = 'def',
|
|
82
|
+
*,
|
|
83
|
+
session: "Session"
|
|
84
|
+
) -> dict[str, Union[int, float, None]]:
|
|
69
85
|
"""
|
|
70
86
|
Lists the limitation names/values for the specified account name and rse name.
|
|
71
87
|
|
|
@@ -79,14 +95,19 @@ def get_local_account_limit(account, rse, vo='def', *, session: "Session"):
|
|
|
79
95
|
:returns: The account limit.
|
|
80
96
|
"""
|
|
81
97
|
|
|
82
|
-
|
|
98
|
+
internal_account = InternalAccount(account, vo=vo)
|
|
83
99
|
|
|
84
100
|
rse_id = get_rse_id(rse=rse, vo=vo, session=session)
|
|
85
|
-
return {rse: account_limit_core.get_local_account_limit(account=
|
|
101
|
+
return {rse: account_limit_core.get_local_account_limit(account=internal_account, rse_id=rse_id, session=session)}
|
|
86
102
|
|
|
87
103
|
|
|
88
104
|
@read_session
|
|
89
|
-
def get_global_account_limits(
|
|
105
|
+
def get_global_account_limits(
|
|
106
|
+
account: str,
|
|
107
|
+
vo: str = 'def',
|
|
108
|
+
*,
|
|
109
|
+
session: "Session"
|
|
110
|
+
) -> dict[str, RSEResolvedGlobalAccountLimitDict]:
|
|
90
111
|
"""
|
|
91
112
|
Lists the limitation names/values for the specified account name.
|
|
92
113
|
|
|
@@ -99,15 +120,21 @@ def get_global_account_limits(account, vo='def', *, session: "Session"):
|
|
|
99
120
|
:returns: The account limits.
|
|
100
121
|
"""
|
|
101
122
|
if account:
|
|
102
|
-
|
|
123
|
+
internal_account = InternalAccount(account, vo=vo)
|
|
103
124
|
else:
|
|
104
|
-
|
|
125
|
+
internal_account = InternalAccount('*', vo=vo)
|
|
105
126
|
|
|
106
|
-
return account_limit_core.get_global_account_limits(account=
|
|
127
|
+
return account_limit_core.get_global_account_limits(account=internal_account, session=session)
|
|
107
128
|
|
|
108
129
|
|
|
109
130
|
@read_session
|
|
110
|
-
def get_global_account_limit(
|
|
131
|
+
def get_global_account_limit(
|
|
132
|
+
account: str,
|
|
133
|
+
rse_expression: str,
|
|
134
|
+
vo: str = 'def',
|
|
135
|
+
*,
|
|
136
|
+
session: "Session"
|
|
137
|
+
) -> dict[str, dict[str, RSEResolvedGlobalAccountLimitDict]]:
|
|
111
138
|
"""
|
|
112
139
|
Lists the limitation names/values for the specified account name and rse expression.
|
|
113
140
|
|
|
@@ -121,15 +148,23 @@ def get_global_account_limit(account, rse_expression, vo='def', *, session: "Ses
|
|
|
121
148
|
:returns: The account limit.
|
|
122
149
|
"""
|
|
123
150
|
|
|
124
|
-
|
|
151
|
+
internal_account = InternalAccount(account, vo=vo)
|
|
125
152
|
|
|
126
|
-
return {rse_expression: account_limit_core.get_global_account_limit(account=
|
|
153
|
+
return {rse_expression: account_limit_core.get_global_account_limit(account=internal_account, rse_expression=rse_expression, session=session)}
|
|
127
154
|
|
|
128
155
|
|
|
129
156
|
@transactional_session
|
|
130
|
-
def set_local_account_limit(
|
|
157
|
+
def set_local_account_limit(
|
|
158
|
+
account: str,
|
|
159
|
+
rse: str,
|
|
160
|
+
bytes_: int,
|
|
161
|
+
issuer: str,
|
|
162
|
+
vo: str = 'def',
|
|
163
|
+
*,
|
|
164
|
+
session: "Session"
|
|
165
|
+
) -> None:
|
|
131
166
|
"""
|
|
132
|
-
Set an account limit
|
|
167
|
+
Set an account limit.
|
|
133
168
|
|
|
134
169
|
:param account: The account name.
|
|
135
170
|
:param rse: The rse name.
|
|
@@ -141,19 +176,28 @@ def set_local_account_limit(account, rse, bytes_, issuer, vo='def', *, session:
|
|
|
141
176
|
rse_id = get_rse_id(rse=rse, vo=vo, session=session)
|
|
142
177
|
|
|
143
178
|
kwargs = {'account': account, 'rse': rse, 'rse_id': rse_id, 'bytes': bytes_}
|
|
144
|
-
|
|
145
|
-
|
|
179
|
+
auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='set_local_account_limit', kwargs=kwargs, session=session)
|
|
180
|
+
if not auth_result.allowed:
|
|
181
|
+
raise rucio.common.exception.AccessDenied('Account %s can not set account limits. %s' % (issuer, auth_result.message))
|
|
146
182
|
|
|
147
|
-
|
|
183
|
+
internal_account = InternalAccount(account, vo=vo)
|
|
148
184
|
|
|
149
|
-
if not account_exists(account=
|
|
150
|
-
raise rucio.common.exception.AccountNotFound('Account %s does not exist' % (
|
|
185
|
+
if not account_exists(account=internal_account, session=session):
|
|
186
|
+
raise rucio.common.exception.AccountNotFound('Account %s does not exist' % (internal_account))
|
|
151
187
|
|
|
152
|
-
account_limit_core.set_local_account_limit(account=
|
|
188
|
+
account_limit_core.set_local_account_limit(account=internal_account, rse_id=rse_id, bytes_=bytes_, session=session)
|
|
153
189
|
|
|
154
190
|
|
|
155
191
|
@transactional_session
|
|
156
|
-
def set_global_account_limit(
|
|
192
|
+
def set_global_account_limit(
|
|
193
|
+
account: str,
|
|
194
|
+
rse_expression: str,
|
|
195
|
+
bytes_: int,
|
|
196
|
+
issuer: str,
|
|
197
|
+
vo: str = 'def',
|
|
198
|
+
*,
|
|
199
|
+
session: "Session"
|
|
200
|
+
) -> None:
|
|
157
201
|
"""
|
|
158
202
|
Set a global account limit.
|
|
159
203
|
|
|
@@ -166,21 +210,29 @@ def set_global_account_limit(account, rse_expression, bytes_, issuer, vo='def',
|
|
|
166
210
|
"""
|
|
167
211
|
|
|
168
212
|
kwargs = {'account': account, 'rse_expression': rse_expression, 'bytes': bytes_}
|
|
169
|
-
|
|
170
|
-
|
|
213
|
+
auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='set_global_account_limit', kwargs=kwargs, session=session)
|
|
214
|
+
if not auth_result.allowed:
|
|
215
|
+
raise rucio.common.exception.AccessDenied('Account %s can not set account limits. %s' % (issuer, auth_result.message))
|
|
171
216
|
|
|
172
|
-
|
|
217
|
+
internal_account = InternalAccount(account, vo=vo)
|
|
173
218
|
|
|
174
|
-
if not account_exists(account=
|
|
175
|
-
raise rucio.common.exception.AccountNotFound('Account %s does not exist' % (
|
|
219
|
+
if not account_exists(account=internal_account, session=session):
|
|
220
|
+
raise rucio.common.exception.AccountNotFound('Account %s does not exist' % (internal_account))
|
|
176
221
|
|
|
177
|
-
account_limit_core.set_global_account_limit(account=
|
|
222
|
+
account_limit_core.set_global_account_limit(account=internal_account, rse_expression=rse_expression, bytes_=bytes_, session=session)
|
|
178
223
|
|
|
179
224
|
|
|
180
225
|
@transactional_session
|
|
181
|
-
def delete_local_account_limit(
|
|
226
|
+
def delete_local_account_limit(
|
|
227
|
+
account: str,
|
|
228
|
+
rse: str,
|
|
229
|
+
issuer: str,
|
|
230
|
+
vo: str = 'def',
|
|
231
|
+
*,
|
|
232
|
+
session: "Session"
|
|
233
|
+
) -> bool:
|
|
182
234
|
"""
|
|
183
|
-
Delete an account limit
|
|
235
|
+
Delete an account limit.
|
|
184
236
|
|
|
185
237
|
:param account: The account name.
|
|
186
238
|
:param rse: The rse name.
|
|
@@ -193,19 +245,27 @@ def delete_local_account_limit(account, rse, issuer, vo='def', *, session: "Sess
|
|
|
193
245
|
|
|
194
246
|
rse_id = get_rse_id(rse=rse, vo=vo, session=session)
|
|
195
247
|
kwargs = {'account': account, 'rse': rse, 'rse_id': rse_id}
|
|
196
|
-
|
|
197
|
-
|
|
248
|
+
auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='delete_local_account_limit', kwargs=kwargs, session=session)
|
|
249
|
+
if not auth_result.allowed:
|
|
250
|
+
raise rucio.common.exception.AccessDenied('Account %s can not delete account limits. %s' % (issuer, auth_result.message))
|
|
198
251
|
|
|
199
|
-
|
|
252
|
+
internal_account = InternalAccount(account, vo=vo)
|
|
200
253
|
|
|
201
|
-
if not account_exists(account=
|
|
202
|
-
raise rucio.common.exception.AccountNotFound('Account %s does not exist' % (
|
|
254
|
+
if not account_exists(account=internal_account, session=session):
|
|
255
|
+
raise rucio.common.exception.AccountNotFound('Account %s does not exist' % (internal_account))
|
|
203
256
|
|
|
204
|
-
return account_limit_core.delete_local_account_limit(account=
|
|
257
|
+
return account_limit_core.delete_local_account_limit(account=internal_account, rse_id=rse_id, session=session)
|
|
205
258
|
|
|
206
259
|
|
|
207
260
|
@transactional_session
|
|
208
|
-
def delete_global_account_limit(
|
|
261
|
+
def delete_global_account_limit(
|
|
262
|
+
account: str,
|
|
263
|
+
rse_expression: str,
|
|
264
|
+
issuer: str,
|
|
265
|
+
vo: str = 'def',
|
|
266
|
+
*,
|
|
267
|
+
session: "Session"
|
|
268
|
+
) -> bool:
|
|
209
269
|
"""
|
|
210
270
|
Delete a global account limit..
|
|
211
271
|
|
|
@@ -219,19 +279,27 @@ def delete_global_account_limit(account, rse_expression, issuer, vo='def', *, se
|
|
|
219
279
|
"""
|
|
220
280
|
|
|
221
281
|
kwargs = {'account': account, 'rse_expression': rse_expression}
|
|
222
|
-
|
|
223
|
-
|
|
282
|
+
auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='delete_global_account_limit', kwargs=kwargs, session=session)
|
|
283
|
+
if not auth_result.allowed:
|
|
284
|
+
raise rucio.common.exception.AccessDenied('Account %s can not delete global account limits. %s' % (issuer, auth_result.message))
|
|
224
285
|
|
|
225
|
-
|
|
286
|
+
internal_account = InternalAccount(account, vo=vo)
|
|
226
287
|
|
|
227
|
-
if not account_exists(account=
|
|
228
|
-
raise rucio.common.exception.AccountNotFound('Account %s does not exist' % (
|
|
288
|
+
if not account_exists(account=internal_account, session=session):
|
|
289
|
+
raise rucio.common.exception.AccountNotFound('Account %s does not exist' % (internal_account))
|
|
229
290
|
|
|
230
|
-
return account_limit_core.delete_global_account_limit(account=
|
|
291
|
+
return account_limit_core.delete_global_account_limit(account=internal_account, rse_expression=rse_expression, session=session)
|
|
231
292
|
|
|
232
293
|
|
|
233
294
|
@read_session
|
|
234
|
-
def get_local_account_usage(
|
|
295
|
+
def get_local_account_usage(
|
|
296
|
+
account: str,
|
|
297
|
+
rse: str,
|
|
298
|
+
issuer: str,
|
|
299
|
+
vo: str = 'def',
|
|
300
|
+
*,
|
|
301
|
+
session: "Session"
|
|
302
|
+
) -> list[dict[str, Any]]:
|
|
235
303
|
"""
|
|
236
304
|
Get the account usage and connect it with (if available) the account limits of the account.
|
|
237
305
|
|
|
@@ -249,19 +317,27 @@ def get_local_account_usage(account, rse, issuer, vo='def', *, session: "Session
|
|
|
249
317
|
if rse:
|
|
250
318
|
rse_id = get_rse_id(rse=rse, vo=vo, session=session)
|
|
251
319
|
kwargs = {'account': account, 'rse': rse, 'rse_id': rse_id}
|
|
252
|
-
|
|
253
|
-
|
|
320
|
+
auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='get_local_account_usage', kwargs=kwargs, session=session)
|
|
321
|
+
if not auth_result.allowed:
|
|
322
|
+
raise rucio.common.exception.AccessDenied('Account %s can not list account usage. %s' % (issuer, auth_result.message))
|
|
254
323
|
|
|
255
|
-
|
|
324
|
+
internal_account = InternalAccount(account, vo=vo)
|
|
256
325
|
|
|
257
|
-
if not account_exists(account=
|
|
258
|
-
raise rucio.common.exception.AccountNotFound('Account %s does not exist' % (
|
|
326
|
+
if not account_exists(account=internal_account, session=session):
|
|
327
|
+
raise rucio.common.exception.AccountNotFound('Account %s does not exist' % (internal_account))
|
|
259
328
|
|
|
260
|
-
return [gateway_update_return_dict(d, session=session) for d in account_limit_core.get_local_account_usage(account=
|
|
329
|
+
return [gateway_update_return_dict(d, session=session) for d in account_limit_core.get_local_account_usage(account=internal_account, rse_id=rse_id, session=session)]
|
|
261
330
|
|
|
262
331
|
|
|
263
332
|
@read_session
|
|
264
|
-
def get_global_account_usage(
|
|
333
|
+
def get_global_account_usage(
|
|
334
|
+
account: str,
|
|
335
|
+
rse_expression: str,
|
|
336
|
+
issuer: str,
|
|
337
|
+
vo: str = 'def',
|
|
338
|
+
*,
|
|
339
|
+
session: "Session"
|
|
340
|
+
) -> list[dict[str, Any]]:
|
|
265
341
|
"""
|
|
266
342
|
Get the account usage and connect it with (if available) the account limits of the account.
|
|
267
343
|
|
|
@@ -275,12 +351,13 @@ def get_global_account_usage(account, rse_expression, issuer, vo='def', *, sessi
|
|
|
275
351
|
"""
|
|
276
352
|
|
|
277
353
|
kwargs = {'account': account, 'rse_expression': rse_expression}
|
|
278
|
-
|
|
279
|
-
|
|
354
|
+
auth_result = rucio.gateway.permission.has_permission(issuer=issuer, vo=vo, action='get_global_account_usage', kwargs=kwargs, session=session)
|
|
355
|
+
if not auth_result.allowed:
|
|
356
|
+
raise rucio.common.exception.AccessDenied('Account %s can not list global account usage. %s' % (issuer, auth_result.message))
|
|
280
357
|
|
|
281
|
-
|
|
358
|
+
internal_account = InternalAccount(account, vo=vo)
|
|
282
359
|
|
|
283
|
-
if not account_exists(account=
|
|
284
|
-
raise rucio.common.exception.AccountNotFound('Account %s does not exist' % (
|
|
360
|
+
if not account_exists(account=internal_account, session=session):
|
|
361
|
+
raise rucio.common.exception.AccountNotFound('Account %s does not exist' % (internal_account))
|
|
285
362
|
|
|
286
|
-
return [gateway_update_return_dict(d, session=session) for d in account_limit_core.get_global_account_usage(account=
|
|
363
|
+
return [gateway_update_return_dict(d, session=session) for d in account_limit_core.get_global_account_usage(account=internal_account, rse_expression=rse_expression, session=session)]
|