rucio 35.7.0__py3-none-any.whl → 37.0.0rc2__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/stomp_utils.py +383 -119
- 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/cache/consumer.py +26 -90
- 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 +53 -123
- rucio/daemons/conveyor/stager.py +1 -0
- rucio/daemons/conveyor/submitter.py +3 -3
- rucio/daemons/hermes/hermes.py +129 -369
- 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 +117 -142
- 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.0rc2.data}/data/rucio/etc/alembic.ini.template +1 -1
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/data/rucio/etc/alembic_offline.ini.template +1 -1
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/data/rucio/etc/rucio.cfg.atlas.client.template +3 -2
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/data/rucio/etc/rucio.cfg.template +3 -19
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/data/rucio/etc/rucio_multi_vo.cfg.template +1 -18
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/data/rucio/requirements.server.txt +97 -68
- rucio-37.0.0rc2.data/scripts/rucio +133 -0
- rucio-37.0.0rc2.data/scripts/rucio-admin +97 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-atropos +2 -2
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-auditor +2 -1
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-automatix +2 -2
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-cache-client +17 -10
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-conveyor-receiver +1 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-kronos +1 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-minos +2 -2
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-minos-temporary-expiration +2 -2
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-necromancer +2 -2
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-reaper +6 -6
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-transmogrifier +2 -2
- rucio-37.0.0rc2.dist-info/METADATA +92 -0
- {rucio-35.7.0.dist-info → rucio-37.0.0rc2.dist-info}/RECORD +239 -245
- {rucio-35.7.0.dist-info → rucio-37.0.0rc2.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.0rc2.data}/data/rucio/etc/globus-config.yml.template +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/data/rucio/etc/ldap.cfg.template +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/data/rucio/tools/bootstrap.py +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/data/rucio/tools/merge_rucio_configs.py +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/data/rucio/tools/reset_database.py +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-abacus-account +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-abacus-collection-replica +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-abacus-rse +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-bb8 +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-cache-consumer +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-conveyor-finisher +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-conveyor-poller +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-conveyor-preparer +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-conveyor-stager +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-conveyor-submitter +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-conveyor-throttler +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-dark-reaper +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-dumper +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-follower +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-hermes +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-judge-cleaner +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-judge-evaluator +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-judge-injector +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-judge-repairer +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-oauth-manager +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-replica-recoverer +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-rse-decommissioner +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-storage-consistency-actions +0 -0
- {rucio-35.7.0.data → rucio-37.0.0rc2.data}/scripts/rucio-undertaker +0 -0
- {rucio-35.7.0.dist-info → rucio-37.0.0rc2.dist-info}/WHEEL +0 -0
- {rucio-35.7.0.dist-info → rucio-37.0.0rc2.dist-info}/licenses/LICENSE +0 -0
- {rucio-35.7.0.dist-info → rucio-37.0.0rc2.dist-info}/top_level.txt +0 -0
rucio/core/rse_counter.py
CHANGED
|
@@ -178,9 +178,8 @@ def fill_rse_counter_history_table(*, session: "Session"):
|
|
|
178
178
|
|
|
179
179
|
:param session: Database session in use.
|
|
180
180
|
"""
|
|
181
|
-
RSEUsageHistory = models.RSEUsageHistory
|
|
182
181
|
stmt = select(
|
|
183
182
|
models.RSEUsage
|
|
184
183
|
)
|
|
185
184
|
for usage in session.execute(stmt).scalars().all():
|
|
186
|
-
RSEUsageHistory(rse_id=usage['rse_id'], used=usage['used'], files=usage['files'], source=usage['source']).save(session=session)
|
|
185
|
+
models.RSEUsageHistory(rse_id=usage['rse_id'], used=usage['used'], files=usage['files'], source=usage['source']).save(session=session)
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
import abc
|
|
16
16
|
import re
|
|
17
17
|
from hashlib import sha256
|
|
18
|
-
from typing import TYPE_CHECKING
|
|
18
|
+
from typing import TYPE_CHECKING, Any
|
|
19
19
|
|
|
20
20
|
from dogpile.cache.api import NoValue
|
|
21
21
|
|
|
22
|
-
from rucio.common.cache import
|
|
22
|
+
from rucio.common.cache import MemcacheRegion
|
|
23
23
|
from rucio.common.exception import InvalidRSEExpression, RSEWriteBlocked
|
|
24
24
|
from rucio.core.rse import get_rse_attribute, get_rses_with_attribute, list_rses
|
|
25
25
|
from rucio.db.sqla.session import transactional_session
|
|
@@ -37,7 +37,7 @@ COMPLEMENT = r'(\\%s)' % (PRIMITIVE)
|
|
|
37
37
|
|
|
38
38
|
PATTERN = r'^%s(%s|%s|%s)*' % (PRIMITIVE, UNION, INTERSECTION, COMPLEMENT)
|
|
39
39
|
|
|
40
|
-
REGION =
|
|
40
|
+
REGION = MemcacheRegion(expiration_time=600)
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
@transactional_session
|
|
@@ -286,7 +286,7 @@ class RSEAttributeSmallerCheck(BaseExpressionElement):
|
|
|
286
286
|
"""
|
|
287
287
|
Inherited from :py:func:`BaseExpressionElement.resolve_elements`
|
|
288
288
|
"""
|
|
289
|
-
rse_list = get_rses_with_attribute(key=self.key, session=session)
|
|
289
|
+
rse_list: list[dict[str, Any]] = get_rses_with_attribute(key=self.key, session=session)
|
|
290
290
|
if not rse_list:
|
|
291
291
|
return (set(), {})
|
|
292
292
|
|
|
@@ -294,7 +294,7 @@ class RSEAttributeSmallerCheck(BaseExpressionElement):
|
|
|
294
294
|
rse_dict = {}
|
|
295
295
|
for rse in rse_list:
|
|
296
296
|
try:
|
|
297
|
-
if float(get_rse_attribute(rse['id'], self.key, session=session)) < float(self.value):
|
|
297
|
+
if float(get_rse_attribute(rse['id'], self.key, session=session)) < float(self.value): # type: ignore (get_rse_attribute could return None)
|
|
298
298
|
rse_dict[rse['id']] = rse
|
|
299
299
|
output.append(rse['id'])
|
|
300
300
|
except ValueError:
|
|
@@ -321,7 +321,7 @@ class RSEAttributeLargerCheck(BaseExpressionElement):
|
|
|
321
321
|
"""
|
|
322
322
|
Inherited from :py:func:`BaseExpressionElement.resolve_elements`
|
|
323
323
|
"""
|
|
324
|
-
rse_list = get_rses_with_attribute(key=self.key, session=session)
|
|
324
|
+
rse_list: list[dict[str, Any]] = get_rses_with_attribute(key=self.key, session=session)
|
|
325
325
|
if not rse_list:
|
|
326
326
|
return (set(), {})
|
|
327
327
|
|
|
@@ -329,7 +329,7 @@ class RSEAttributeLargerCheck(BaseExpressionElement):
|
|
|
329
329
|
rse_dict = {}
|
|
330
330
|
for rse in rse_list:
|
|
331
331
|
try:
|
|
332
|
-
if float(get_rse_attribute(rse['id'], self.key, session=session)) > float(self.value):
|
|
332
|
+
if float(get_rse_attribute(rse['id'], self.key, session=session)) > float(self.value): # type: ignore (get_rse_attribute could return None)
|
|
333
333
|
rse_dict[rse['id']] = rse
|
|
334
334
|
output.append(rse['id'])
|
|
335
335
|
except ValueError:
|
rucio/core/rse_selector.py
CHANGED
|
@@ -12,12 +12,10 @@
|
|
|
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 Iterable, Sequence
|
|
16
15
|
from random import shuffle, uniform
|
|
17
16
|
from typing import TYPE_CHECKING, Optional
|
|
18
17
|
|
|
19
18
|
from rucio.common.exception import InsufficientAccountLimit, InsufficientTargetRSEs, InvalidRuleWeight, RSEOverQuota
|
|
20
|
-
from rucio.common.types import InternalAccount
|
|
21
19
|
from rucio.core.account import get_all_rse_usages_per_account, get_usage, has_account_attribute
|
|
22
20
|
from rucio.core.account_limit import get_global_account_limits, get_local_account_limit
|
|
23
21
|
from rucio.core.rse import get_rse_limits, has_rse_attribute, list_rse_attributes
|
|
@@ -26,8 +24,12 @@ from rucio.core.rse_expression_parser import parse_expression
|
|
|
26
24
|
from rucio.db.sqla.session import read_session
|
|
27
25
|
|
|
28
26
|
if TYPE_CHECKING:
|
|
27
|
+
from collections.abc import Iterable, Sequence
|
|
28
|
+
|
|
29
29
|
from sqlalchemy.orm import Session
|
|
30
30
|
|
|
31
|
+
from rucio.common.types import InternalAccount
|
|
32
|
+
|
|
31
33
|
|
|
32
34
|
class RSESelector:
|
|
33
35
|
"""
|
|
@@ -138,9 +140,9 @@ class RSESelector:
|
|
|
138
140
|
def select_rse(
|
|
139
141
|
self,
|
|
140
142
|
size: int,
|
|
141
|
-
preferred_rse_ids: Iterable[str],
|
|
143
|
+
preferred_rse_ids: "Iterable[str]",
|
|
142
144
|
copies: int = 0,
|
|
143
|
-
blocklist: Optional[Sequence[str]] = None,
|
|
145
|
+
blocklist: Optional["Sequence[str]"] = None,
|
|
144
146
|
prioritize_order_over_weight: bool = False,
|
|
145
147
|
existing_rse_size: Optional[dict[str, int]] = None
|
|
146
148
|
) -> list[tuple[str, bool, bool]]:
|
|
@@ -258,13 +260,13 @@ class RSESelector:
|
|
|
258
260
|
@read_session
|
|
259
261
|
def resolve_rse_expression(
|
|
260
262
|
rse_expression: str,
|
|
261
|
-
account: InternalAccount,
|
|
263
|
+
account: "InternalAccount",
|
|
262
264
|
weight: Optional[int] = None,
|
|
263
265
|
copies: int = 1,
|
|
264
266
|
ignore_account_limit: bool = False,
|
|
265
267
|
size: int = 0,
|
|
266
|
-
preferred_rses: Optional[Iterable[str]] = None,
|
|
267
|
-
blocklist: Optional[Sequence[str]] = None,
|
|
268
|
+
preferred_rses: Optional["Iterable[str]"] = None,
|
|
269
|
+
blocklist: Optional["Sequence[str]"] = None,
|
|
268
270
|
prioritize_order_over_weight: bool = False,
|
|
269
271
|
existing_rse_size: Optional[dict[str, int]] = None,
|
|
270
272
|
*,
|
rucio/core/rule.py
CHANGED
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
|
|
15
15
|
import json
|
|
16
16
|
import logging
|
|
17
|
-
from collections.abc import Callable, Iterator, Sequence
|
|
18
17
|
from configparser import NoOptionError, NoSectionError
|
|
19
18
|
from copy import deepcopy
|
|
20
19
|
from datetime import datetime, timedelta
|
|
@@ -36,7 +35,7 @@ from sqlalchemy.sql.expression import and_, false, null, or_, true, tuple_
|
|
|
36
35
|
import rucio.core.did
|
|
37
36
|
import rucio.core.lock # import get_replica_locks, get_files_and_replica_locks_of_dataset
|
|
38
37
|
import rucio.core.replica # import get_and_lock_file_replicas, get_and_lock_file_replicas_for_dataset
|
|
39
|
-
from rucio.common.cache import
|
|
38
|
+
from rucio.common.cache import MemcacheRegion
|
|
40
39
|
from rucio.common.config import config_get
|
|
41
40
|
from rucio.common.constants import RseAttr
|
|
42
41
|
from rucio.common.exception import (
|
|
@@ -84,10 +83,12 @@ from rucio.db.sqla.constants import OBSOLETE, BadFilesStatus, DIDAvailability, D
|
|
|
84
83
|
from rucio.db.sqla.session import read_session, stream_session, transactional_session
|
|
85
84
|
|
|
86
85
|
if TYPE_CHECKING:
|
|
86
|
+
from collections.abc import Callable, Iterator, Sequence
|
|
87
|
+
|
|
87
88
|
from sqlalchemy.orm import Session
|
|
88
89
|
|
|
89
90
|
|
|
90
|
-
REGION =
|
|
91
|
+
REGION = MemcacheRegion(expiration_time=900)
|
|
91
92
|
METRICS = MetricManager(module=__name__)
|
|
92
93
|
AutoApproveT = TypeVar('AutoApproveT', bound='AutoApprove')
|
|
93
94
|
|
|
@@ -113,7 +114,7 @@ class AutoApprove(PolicyPackageAlgorithms):
|
|
|
113
114
|
return self.get_configured_algorithm()(self.rule, self.did, self.session)
|
|
114
115
|
|
|
115
116
|
@classmethod
|
|
116
|
-
def get_configured_algorithm(cls: type[AutoApproveT]) -> Callable[[models.ReplicationRule, models.DataIdentifier,
|
|
117
|
+
def get_configured_algorithm(cls: type[AutoApproveT]) -> "Callable[[models.ReplicationRule, models.DataIdentifier, Session], bool]":
|
|
117
118
|
"""
|
|
118
119
|
Get the configured auto-approve algorithm
|
|
119
120
|
"""
|
|
@@ -125,7 +126,7 @@ class AutoApprove(PolicyPackageAlgorithms):
|
|
|
125
126
|
return super()._get_one_algorithm(cls._algorithm_type, configured_algorithm)
|
|
126
127
|
|
|
127
128
|
@classmethod
|
|
128
|
-
def register(cls: type[AutoApproveT], name: str, fn_auto_approve: Callable[[models.ReplicationRule, models.DataIdentifier,
|
|
129
|
+
def register(cls: type[AutoApproveT], name: str, fn_auto_approve: "Callable[[models.ReplicationRule, models.DataIdentifier, Session], bool]") -> None:
|
|
129
130
|
"""
|
|
130
131
|
Register a new auto-approve algorithm
|
|
131
132
|
"""
|
|
@@ -163,7 +164,7 @@ class AutoApprove(PolicyPackageAlgorithms):
|
|
|
163
164
|
|
|
164
165
|
@transactional_session
|
|
165
166
|
def add_rule(
|
|
166
|
-
dids: Sequence[DIDDict],
|
|
167
|
+
dids: 'Sequence[DIDDict]',
|
|
167
168
|
account: InternalAccount,
|
|
168
169
|
copies: int,
|
|
169
170
|
rse_expression: str,
|
|
@@ -477,8 +478,8 @@ def add_rule(
|
|
|
477
478
|
|
|
478
479
|
@transactional_session
|
|
479
480
|
def add_rules(
|
|
480
|
-
dids: Sequence[DIDDict],
|
|
481
|
-
rules: Sequence[RuleDict],
|
|
481
|
+
dids: 'Sequence[DIDDict]',
|
|
482
|
+
rules: 'Sequence[RuleDict]',
|
|
482
483
|
*,
|
|
483
484
|
session: "Session",
|
|
484
485
|
logger: LoggerFunction = logging.log
|
|
@@ -954,7 +955,7 @@ def list_rules(
|
|
|
954
955
|
filters: Optional[dict[str, Any]] = None,
|
|
955
956
|
*,
|
|
956
957
|
session: "Session"
|
|
957
|
-
) -> Iterator[dict[str, Any]]:
|
|
958
|
+
) -> 'Iterator[dict[str, Any]]':
|
|
958
959
|
"""
|
|
959
960
|
List replication rules.
|
|
960
961
|
|
|
@@ -1021,7 +1022,7 @@ def list_rule_history(
|
|
|
1021
1022
|
rule_id: str,
|
|
1022
1023
|
*,
|
|
1023
1024
|
session: "Session"
|
|
1024
|
-
) -> Iterator[dict[str, Any]]:
|
|
1025
|
+
) -> 'Iterator[dict[str, Any]]':
|
|
1025
1026
|
"""
|
|
1026
1027
|
List the rule history of a rule.
|
|
1027
1028
|
|
|
@@ -1055,7 +1056,7 @@ def list_rule_full_history(
|
|
|
1055
1056
|
name: str,
|
|
1056
1057
|
*,
|
|
1057
1058
|
session: "Session"
|
|
1058
|
-
) -> Iterator[dict[str, Any]]:
|
|
1059
|
+
) -> 'Iterator[dict[str, Any]]':
|
|
1059
1060
|
"""
|
|
1060
1061
|
List the rule history of a DID.
|
|
1061
1062
|
|
|
@@ -1094,7 +1095,7 @@ def list_associated_rules_for_file(
|
|
|
1094
1095
|
name: str,
|
|
1095
1096
|
*,
|
|
1096
1097
|
session: "Session"
|
|
1097
|
-
) -> Iterator[dict[str, Any]]:
|
|
1098
|
+
) -> 'Iterator[dict[str, Any]]':
|
|
1098
1099
|
"""
|
|
1099
1100
|
List replication rules a file is affected from.
|
|
1100
1101
|
|
|
@@ -2110,7 +2111,7 @@ def get_updated_dids(
|
|
|
2110
2111
|
total_workers: int,
|
|
2111
2112
|
worker_number: int,
|
|
2112
2113
|
limit: int = 100,
|
|
2113
|
-
blocked_dids: Optional[Sequence[tuple[str, str]]] = None,
|
|
2114
|
+
blocked_dids: Optional['Sequence[tuple[str, str]]'] = None,
|
|
2114
2115
|
*,
|
|
2115
2116
|
session: "Session"
|
|
2116
2117
|
) -> list[tuple[str, InternalScope, str, DIDReEvaluation]]:
|
|
@@ -2196,7 +2197,7 @@ def get_expired_rules(
|
|
|
2196
2197
|
total_workers: int,
|
|
2197
2198
|
worker_number: int,
|
|
2198
2199
|
limit: int = 100,
|
|
2199
|
-
blocked_rules: Optional[Sequence[str]] = None,
|
|
2200
|
+
blocked_rules: Optional['Sequence[str]'] = None,
|
|
2200
2201
|
*,
|
|
2201
2202
|
session: "Session"
|
|
2202
2203
|
) -> list[tuple[str, str]]:
|
|
@@ -2246,7 +2247,7 @@ def get_injected_rules(
|
|
|
2246
2247
|
total_workers: int,
|
|
2247
2248
|
worker_number: int,
|
|
2248
2249
|
limit: int = 100,
|
|
2249
|
-
blocked_rules: Optional[Sequence[str]] = None,
|
|
2250
|
+
blocked_rules: Optional['Sequence[str]'] = None,
|
|
2250
2251
|
*,
|
|
2251
2252
|
session: "Session"
|
|
2252
2253
|
) -> list[str]:
|
|
@@ -2295,7 +2296,7 @@ def get_stuck_rules(
|
|
|
2295
2296
|
worker_number: int,
|
|
2296
2297
|
delta: int = 600,
|
|
2297
2298
|
limit: int = 10,
|
|
2298
|
-
blocked_rules: Optional[Sequence[str]] = None,
|
|
2299
|
+
blocked_rules: Optional['Sequence[str]'] = None,
|
|
2299
2300
|
*,
|
|
2300
2301
|
session: "Session"
|
|
2301
2302
|
) -> list[str]:
|
|
@@ -3152,7 +3153,7 @@ def list_rules_for_rse_decommissioning(
|
|
|
3152
3153
|
rse_id: str,
|
|
3153
3154
|
*,
|
|
3154
3155
|
session: "Session"
|
|
3155
|
-
) -> Iterator[dict[str, Any]]:
|
|
3156
|
+
) -> 'Iterator[dict[str, Any]]':
|
|
3156
3157
|
"""Return a generator of rules at the RSE that is being decommissioned.
|
|
3157
3158
|
|
|
3158
3159
|
Decommissioning of an RSE involves deleting or moving away all rules that are
|
|
@@ -3215,13 +3216,13 @@ def list_rules_for_rse_decommissioning(
|
|
|
3215
3216
|
|
|
3216
3217
|
@transactional_session
|
|
3217
3218
|
def __find_missing_locks_and_create_them(
|
|
3218
|
-
datasetfiles: Sequence[dict[str, Any]],
|
|
3219
|
-
locks: dict[tuple[InternalScope, str], Sequence[models.ReplicaLock]],
|
|
3220
|
-
replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
3221
|
-
source_replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
3219
|
+
datasetfiles: 'Sequence[dict[str, Any]]',
|
|
3220
|
+
locks: dict[tuple[InternalScope, str], 'Sequence[models.ReplicaLock]'],
|
|
3221
|
+
replicas: dict[tuple[InternalScope, str], 'Sequence[models.CollectionReplica]'],
|
|
3222
|
+
source_replicas: dict[tuple[InternalScope, str], 'Sequence[models.CollectionReplica]'],
|
|
3222
3223
|
rseselector: RSESelector,
|
|
3223
3224
|
rule: models.ReplicationRule,
|
|
3224
|
-
source_rses: Sequence[str],
|
|
3225
|
+
source_rses: 'Sequence[str]',
|
|
3225
3226
|
*,
|
|
3226
3227
|
session: "Session",
|
|
3227
3228
|
logger: LoggerFunction = logging.log
|
|
@@ -3273,7 +3274,7 @@ def __find_missing_locks_and_create_them(
|
|
|
3273
3274
|
|
|
3274
3275
|
@transactional_session
|
|
3275
3276
|
def __find_surplus_locks_and_remove_them(
|
|
3276
|
-
datasetfiles: Sequence[dict[str, Any]],
|
|
3277
|
+
datasetfiles: 'Sequence[dict[str, Any]]',
|
|
3277
3278
|
locks: dict[tuple[InternalScope, str], list[models.ReplicaLock]],
|
|
3278
3279
|
rule: models.ReplicationRule,
|
|
3279
3280
|
*,
|
|
@@ -3324,13 +3325,13 @@ def __find_surplus_locks_and_remove_them(
|
|
|
3324
3325
|
|
|
3325
3326
|
@transactional_session
|
|
3326
3327
|
def __find_stuck_locks_and_repair_them(
|
|
3327
|
-
datasetfiles: Sequence[dict[str, Any]],
|
|
3328
|
-
locks: dict[tuple[InternalScope, str], Sequence[models.ReplicaLock]],
|
|
3329
|
-
replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
3330
|
-
source_replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
3328
|
+
datasetfiles: 'Sequence[dict[str, Any]]',
|
|
3329
|
+
locks: dict[tuple[InternalScope, str], 'Sequence[models.ReplicaLock]'],
|
|
3330
|
+
replicas: dict[tuple[InternalScope, str], 'Sequence[models.CollectionReplica]'],
|
|
3331
|
+
source_replicas: dict[tuple[InternalScope, str], 'Sequence[models.CollectionReplica]'],
|
|
3331
3332
|
rseselector: RSESelector,
|
|
3332
3333
|
rule: models.ReplicationRule,
|
|
3333
|
-
source_rses: Sequence[str],
|
|
3334
|
+
source_rses: 'Sequence[str]',
|
|
3334
3335
|
*,
|
|
3335
3336
|
session: "Session",
|
|
3336
3337
|
logger: LoggerFunction = logging.log
|
|
@@ -3802,8 +3803,8 @@ def __evaluate_did_attach(
|
|
|
3802
3803
|
def __resolve_did_to_locks_and_replicas(
|
|
3803
3804
|
did: models.DataIdentifier,
|
|
3804
3805
|
nowait: bool = False,
|
|
3805
|
-
restrict_rses: Optional[Sequence[str]] = None,
|
|
3806
|
-
source_rses: Optional[Sequence[str]] = None,
|
|
3806
|
+
restrict_rses: Optional['Sequence[str]'] = None,
|
|
3807
|
+
source_rses: Optional['Sequence[str]'] = None,
|
|
3807
3808
|
only_stuck: bool = False,
|
|
3808
3809
|
*,
|
|
3809
3810
|
session: "Session"
|
|
@@ -3908,10 +3909,10 @@ def __resolve_did_to_locks_and_replicas(
|
|
|
3908
3909
|
|
|
3909
3910
|
@transactional_session
|
|
3910
3911
|
def __resolve_dids_to_locks_and_replicas(
|
|
3911
|
-
dids: Sequence[models.DataIdentifierAssociation],
|
|
3912
|
+
dids: 'Sequence[models.DataIdentifierAssociation]',
|
|
3912
3913
|
nowait: bool = False,
|
|
3913
|
-
restrict_rses: Optional[Sequence[str]] = None,
|
|
3914
|
-
source_rses: Optional[Sequence[str]] = None,
|
|
3914
|
+
restrict_rses: Optional['Sequence[str]'] = None,
|
|
3915
|
+
source_rses: Optional['Sequence[str]'] = None,
|
|
3915
3916
|
*,
|
|
3916
3917
|
session: "Session"
|
|
3917
3918
|
) -> tuple[list[dict[str, Any]],
|
|
@@ -4078,14 +4079,14 @@ def __resolve_dids_to_locks_and_replicas(
|
|
|
4078
4079
|
|
|
4079
4080
|
@transactional_session
|
|
4080
4081
|
def __create_locks_replicas_transfers(
|
|
4081
|
-
datasetfiles: Sequence[dict[str, Any]],
|
|
4082
|
-
locks: dict[tuple[InternalScope, str], Sequence[models.ReplicaLock]],
|
|
4083
|
-
replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
4084
|
-
source_replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
4082
|
+
datasetfiles: 'Sequence[dict[str, Any]]',
|
|
4083
|
+
locks: dict[tuple[InternalScope, str], 'Sequence[models.ReplicaLock]'],
|
|
4084
|
+
replicas: dict[tuple[InternalScope, str], 'Sequence[models.CollectionReplica]'],
|
|
4085
|
+
source_replicas: dict[tuple[InternalScope, str], 'Sequence[models.CollectionReplica]'],
|
|
4085
4086
|
rseselector: RSESelector,
|
|
4086
4087
|
rule: models.ReplicationRule,
|
|
4087
|
-
preferred_rse_ids: Optional[Sequence[str]] = None,
|
|
4088
|
-
source_rses: Optional[Sequence[str]] = None,
|
|
4088
|
+
preferred_rse_ids: Optional['Sequence[str]'] = None,
|
|
4089
|
+
source_rses: Optional['Sequence[str]'] = None,
|
|
4089
4090
|
*,
|
|
4090
4091
|
session: "Session",
|
|
4091
4092
|
logger: LoggerFunction = logging.log
|
|
@@ -4460,7 +4461,7 @@ def archive_localgroupdisk_datasets(
|
|
|
4460
4461
|
@read_session
|
|
4461
4462
|
def get_scratch_policy(
|
|
4462
4463
|
account: InternalAccount,
|
|
4463
|
-
rses: Sequence[dict[str, Any]],
|
|
4464
|
+
rses: 'Sequence[dict[str, Any]]',
|
|
4464
4465
|
lifetime: Optional[int],
|
|
4465
4466
|
*,
|
|
4466
4467
|
session: "Session"
|
rucio/core/rule_grouping.py
CHANGED
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import logging
|
|
16
|
-
from collections.abc import Sequence
|
|
17
16
|
from datetime import datetime
|
|
18
17
|
from typing import TYPE_CHECKING, Any, Optional
|
|
19
18
|
|
|
@@ -26,29 +25,32 @@ import rucio.core.replica
|
|
|
26
25
|
from rucio.common.config import config_get_int
|
|
27
26
|
from rucio.common.constants import RseAttr
|
|
28
27
|
from rucio.common.exception import InsufficientTargetRSEs
|
|
29
|
-
from rucio.common.types import InternalScope
|
|
30
28
|
from rucio.core import account_counter, rse_counter
|
|
31
29
|
from rucio.core import request as request_core
|
|
32
30
|
from rucio.core.rse import get_rse, get_rse_attribute, get_rse_name
|
|
33
|
-
from rucio.core.rse_selector import RSESelector
|
|
34
31
|
from rucio.db.sqla import models
|
|
35
32
|
from rucio.db.sqla.constants import OBSOLETE, DIDType, LockState, ReplicaState, RequestType, RuleGrouping
|
|
36
33
|
from rucio.db.sqla.session import transactional_session
|
|
37
34
|
|
|
38
35
|
if TYPE_CHECKING:
|
|
36
|
+
from collections.abc import Sequence
|
|
37
|
+
|
|
39
38
|
from sqlalchemy.orm import Session
|
|
40
39
|
|
|
40
|
+
from rucio.common.types import InternalScope
|
|
41
|
+
from rucio.core.rse_selector import RSESelector
|
|
42
|
+
|
|
41
43
|
|
|
42
44
|
@transactional_session
|
|
43
45
|
def apply_rule_grouping(
|
|
44
|
-
datasetfiles: Sequence[dict[str, Any]],
|
|
45
|
-
locks: dict[tuple[InternalScope, str], Sequence[models.ReplicaLock]],
|
|
46
|
-
replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
47
|
-
source_replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
48
|
-
rseselector: RSESelector,
|
|
46
|
+
datasetfiles: "Sequence[dict[str, Any]]",
|
|
47
|
+
locks: dict[tuple["InternalScope", str], "Sequence[models.ReplicaLock]"],
|
|
48
|
+
replicas: dict[tuple["InternalScope", str], "Sequence[models.CollectionReplica]"],
|
|
49
|
+
source_replicas: dict[tuple["InternalScope", str], "Sequence[models.CollectionReplica]"],
|
|
50
|
+
rseselector: "RSESelector",
|
|
49
51
|
rule: models.ReplicationRule,
|
|
50
|
-
preferred_rse_ids: Optional[Sequence[str]] = None,
|
|
51
|
-
source_rses: Optional[Sequence[str]] = None,
|
|
52
|
+
preferred_rse_ids: Optional["Sequence[str]"] = None,
|
|
53
|
+
source_rses: Optional["Sequence[str]"] = None,
|
|
52
54
|
*,
|
|
53
55
|
session: "Session"
|
|
54
56
|
) -> tuple[dict[str, list[dict[str, models.RSEFileAssociation]]],
|
|
@@ -116,12 +118,12 @@ def apply_rule_grouping(
|
|
|
116
118
|
|
|
117
119
|
@transactional_session
|
|
118
120
|
def repair_stuck_locks_and_apply_rule_grouping(
|
|
119
|
-
datasetfiles: Sequence[dict[str, Any]],
|
|
120
|
-
locks: dict[tuple[InternalScope, str], models.ReplicaLock],
|
|
121
|
-
replicas: dict[tuple[InternalScope, str], Any],
|
|
122
|
-
source_replicas: dict[tuple[InternalScope, str], Any],
|
|
123
|
-
rseselector: RSESelector, rule: models.ReplicationRule,
|
|
124
|
-
source_rses: Sequence[str],
|
|
121
|
+
datasetfiles: "Sequence[dict[str, Any]]",
|
|
122
|
+
locks: dict[tuple["InternalScope", str], models.ReplicaLock],
|
|
123
|
+
replicas: dict[tuple["InternalScope", str], Any],
|
|
124
|
+
source_replicas: dict[tuple["InternalScope", str], Any],
|
|
125
|
+
rseselector: "RSESelector", rule: models.ReplicationRule,
|
|
126
|
+
source_rses: "Sequence[str]",
|
|
125
127
|
*,
|
|
126
128
|
session: "Session"
|
|
127
129
|
) -> tuple[dict[str, list[dict[str, models.RSEFileAssociation]]],
|
|
@@ -228,14 +230,14 @@ def create_transfer_dict(dest_rse_id, request_type, scope, name, rule, lock=None
|
|
|
228
230
|
|
|
229
231
|
@transactional_session
|
|
230
232
|
def __apply_rule_to_files_none_grouping(
|
|
231
|
-
datasetfiles: Sequence[dict[str, Any]],
|
|
232
|
-
locks: dict[tuple[InternalScope, str], Sequence[models.ReplicaLock]],
|
|
233
|
-
replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
234
|
-
source_replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
235
|
-
rseselector: RSESelector,
|
|
233
|
+
datasetfiles: "Sequence[dict[str, Any]]",
|
|
234
|
+
locks: dict[tuple["InternalScope", str], "Sequence[models.ReplicaLock]"],
|
|
235
|
+
replicas: dict[tuple["InternalScope", str], "Sequence[models.CollectionReplica]"],
|
|
236
|
+
source_replicas: dict[tuple["InternalScope", str], "Sequence[models.CollectionReplica]"],
|
|
237
|
+
rseselector: "RSESelector",
|
|
236
238
|
rule: models.ReplicationRule,
|
|
237
|
-
preferred_rse_ids: Optional[Sequence[str]] = None,
|
|
238
|
-
source_rses: Optional[Sequence[str]] = None,
|
|
239
|
+
preferred_rse_ids: Optional["Sequence[str]"] = None,
|
|
240
|
+
source_rses: Optional["Sequence[str]"] = None,
|
|
239
241
|
*,
|
|
240
242
|
session: "Session"
|
|
241
243
|
) -> tuple[dict[str, list[dict[str, models.RSEFileAssociation]]],
|
|
@@ -329,14 +331,14 @@ def __apply_rule_to_files_none_grouping(
|
|
|
329
331
|
|
|
330
332
|
@transactional_session
|
|
331
333
|
def __apply_rule_to_files_all_grouping(
|
|
332
|
-
datasetfiles: Sequence[dict[str, Any]],
|
|
333
|
-
locks: dict[tuple[InternalScope, str], Sequence[models.ReplicaLock]],
|
|
334
|
-
replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
335
|
-
source_replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
336
|
-
rseselector: RSESelector,
|
|
334
|
+
datasetfiles: "Sequence[dict[str, Any]]",
|
|
335
|
+
locks: dict[tuple["InternalScope", str], "Sequence[models.ReplicaLock]"],
|
|
336
|
+
replicas: dict[tuple["InternalScope", str], "Sequence[models.CollectionReplica]"],
|
|
337
|
+
source_replicas: dict[tuple["InternalScope", str], "Sequence[models.CollectionReplica]"],
|
|
338
|
+
rseselector: "RSESelector",
|
|
337
339
|
rule: models.ReplicationRule,
|
|
338
|
-
preferred_rse_ids: Optional[Sequence[str]] = None,
|
|
339
|
-
source_rses: Optional[Sequence[str]] = None,
|
|
340
|
+
preferred_rse_ids: Optional["Sequence[str]"] = None,
|
|
341
|
+
source_rses: Optional["Sequence[str]"] = None,
|
|
340
342
|
*,
|
|
341
343
|
session: "Session"
|
|
342
344
|
) -> tuple[dict[str, list[dict[str, models.RSEFileAssociation]]],
|
|
@@ -480,14 +482,14 @@ def __apply_rule_to_files_all_grouping(
|
|
|
480
482
|
|
|
481
483
|
@transactional_session
|
|
482
484
|
def __apply_rule_to_files_dataset_grouping(
|
|
483
|
-
datasetfiles: Sequence[dict[str, Any]],
|
|
484
|
-
locks: dict[tuple[InternalScope, str], Sequence[models.ReplicaLock]],
|
|
485
|
-
replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
486
|
-
source_replicas: dict[tuple[InternalScope, str], Sequence[models.CollectionReplica]],
|
|
487
|
-
rseselector: RSESelector,
|
|
485
|
+
datasetfiles: "Sequence[dict[str, Any]]",
|
|
486
|
+
locks: dict[tuple["InternalScope", str], "Sequence[models.ReplicaLock]"],
|
|
487
|
+
replicas: dict[tuple["InternalScope", str], "Sequence[models.CollectionReplica]"],
|
|
488
|
+
source_replicas: dict[tuple["InternalScope", str], "Sequence[models.CollectionReplica]"],
|
|
489
|
+
rseselector: "RSESelector",
|
|
488
490
|
rule: models.ReplicationRule,
|
|
489
|
-
preferred_rse_ids: Optional[Sequence[str]] = None,
|
|
490
|
-
source_rses: Optional[Sequence[str]] = None,
|
|
491
|
+
preferred_rse_ids: Optional["Sequence[str]"] = None,
|
|
492
|
+
source_rses: Optional["Sequence[str]"] = None,
|
|
491
493
|
*,
|
|
492
494
|
session: "Session"
|
|
493
495
|
) -> tuple[dict[str, list[dict[str, models.RSEFileAssociation]]],
|
|
@@ -1446,7 +1448,7 @@ def apply_rule(did, rule, rses, source_rses, rseselector, *, session: "Session",
|
|
|
1446
1448
|
for ds_scope, ds_name in datasets:
|
|
1447
1449
|
ds = rucio.core.did.get_did(scope=ds_scope, name=ds_name, dynamic_depth=DIDType.FILE, session=session) # this will be retrieved again later on -> could be optimized
|
|
1448
1450
|
nbytes += ds['bytes']
|
|
1449
|
-
one_rse_coverage = rucio.core.replica.
|
|
1451
|
+
one_rse_coverage = rucio.core.replica.get_rse_coverage_of_dataset(scope=ds_scope, name=ds_name, session=session)
|
|
1450
1452
|
for rse_id, bytes_ in one_rse_coverage.items():
|
|
1451
1453
|
rse_coverage[rse_id] = bytes_ + rse_coverage.get(rse_id, 0)
|
|
1452
1454
|
|
|
@@ -1472,7 +1474,7 @@ def apply_rule(did, rule, rses, source_rses, rseselector, *, session: "Session",
|
|
|
1472
1474
|
|
|
1473
1475
|
if rule.grouping == RuleGrouping.DATASET:
|
|
1474
1476
|
# calculate target RSEs
|
|
1475
|
-
rse_coverage = rucio.core.replica.
|
|
1477
|
+
rse_coverage = rucio.core.replica.get_rse_coverage_of_dataset(scope=ds_scope, name=ds_name, session=session)
|
|
1476
1478
|
# prnt(rse_coverage)
|
|
1477
1479
|
preferred_rse_ids = [x[0] for x in sorted(rse_coverage.items(), key=lambda tup: tup[1], reverse=True)]
|
|
1478
1480
|
# prnt(preferred_rse_ids)
|
|
@@ -1531,7 +1533,7 @@ def apply_rule(did, rule, rses, source_rses, rseselector, *, session: "Session",
|
|
|
1531
1533
|
# prnt(rse_tuples)
|
|
1532
1534
|
# keep track of used RSEs
|
|
1533
1535
|
for rt in rse_tuples:
|
|
1534
|
-
if
|
|
1536
|
+
if rt[0] not in used_rse_ids:
|
|
1535
1537
|
used_rse_ids.append(rt[0])
|
|
1536
1538
|
|
|
1537
1539
|
for rse_id, staging_area, availability_write in rse_tuples:
|
rucio/core/scope.py
CHANGED
|
@@ -20,7 +20,6 @@ from sqlalchemy import and_, select
|
|
|
20
20
|
from sqlalchemy.exc import IntegrityError
|
|
21
21
|
|
|
22
22
|
from rucio.common.exception import AccountNotFound, Duplicate, RucioException, VONotFound
|
|
23
|
-
from rucio.common.types import InternalScope
|
|
24
23
|
from rucio.core.vo import vo_exists
|
|
25
24
|
from rucio.db.sqla import models
|
|
26
25
|
from rucio.db.sqla.constants import AccountStatus, ScopeStatus
|
|
@@ -29,6 +28,8 @@ from rucio.db.sqla.session import read_session, transactional_session
|
|
|
29
28
|
if TYPE_CHECKING:
|
|
30
29
|
from sqlalchemy.orm import Session
|
|
31
30
|
|
|
31
|
+
from rucio.common.types import InternalScope
|
|
32
|
+
|
|
32
33
|
|
|
33
34
|
@transactional_session
|
|
34
35
|
def add_scope(scope, account, *, session: "Session"):
|
|
@@ -69,7 +70,7 @@ def add_scope(scope, account, *, session: "Session"):
|
|
|
69
70
|
|
|
70
71
|
|
|
71
72
|
@read_session
|
|
72
|
-
def bulk_add_scopes(scopes, account,
|
|
73
|
+
def bulk_add_scopes(scopes, account, skip_existing=False, *, session: "Session"):
|
|
73
74
|
""" add a group of scopes, this call should not be exposed to users.
|
|
74
75
|
|
|
75
76
|
:param scopes: a list of scopes to be added.
|
|
@@ -81,12 +82,12 @@ def bulk_add_scopes(scopes, account, skipExisting=False, *, session: "Session"):
|
|
|
81
82
|
try:
|
|
82
83
|
add_scope(scope, account, session=session)
|
|
83
84
|
except Duplicate:
|
|
84
|
-
if not
|
|
85
|
+
if not skip_existing:
|
|
85
86
|
raise
|
|
86
87
|
|
|
87
88
|
|
|
88
89
|
@read_session
|
|
89
|
-
def list_scopes(filter_: Optional[dict[str, Any]] = None, *, session: "Session") -> list[InternalScope]:
|
|
90
|
+
def list_scopes(filter_: Optional[dict[str, Any]] = None, *, session: "Session") -> list["InternalScope"]:
|
|
90
91
|
"""
|
|
91
92
|
Lists all scopes.
|
|
92
93
|
:param filter_: Dictionary of attributes by which the input data should be filtered
|
rucio/core/subscription.py
CHANGED
|
@@ -81,7 +81,6 @@ def add_subscription(name: str,
|
|
|
81
81
|
except (NoOptionError, NoSectionError, RuntimeError):
|
|
82
82
|
keep_history = False
|
|
83
83
|
|
|
84
|
-
SubscriptionHistory = models.SubscriptionHistory
|
|
85
84
|
retroactive = bool(retroactive) # Force boolean type, necessary for strict SQL
|
|
86
85
|
state = SubscriptionState.ACTIVE
|
|
87
86
|
if retroactive:
|
|
@@ -99,18 +98,18 @@ def add_subscription(name: str,
|
|
|
99
98
|
retroactive=retroactive,
|
|
100
99
|
policyid=priority, comments=comments)
|
|
101
100
|
if keep_history:
|
|
102
|
-
subscription_history = SubscriptionHistory(id=new_subscription.id,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
101
|
+
subscription_history = models.SubscriptionHistory(id=new_subscription.id,
|
|
102
|
+
name=new_subscription.name,
|
|
103
|
+
filter=new_subscription.filter,
|
|
104
|
+
account=new_subscription.account,
|
|
105
|
+
replication_rules=new_subscription.replication_rules,
|
|
106
|
+
state=new_subscription.state,
|
|
107
|
+
lifetime=new_subscription.lifetime,
|
|
108
|
+
retroactive=new_subscription.retroactive,
|
|
109
|
+
policyid=new_subscription.policyid,
|
|
110
|
+
comments=new_subscription.comments,
|
|
111
|
+
created_at=datetime.datetime.utcnow(),
|
|
112
|
+
updated_at=datetime.datetime.utcnow())
|
|
114
113
|
try:
|
|
115
114
|
new_subscription.save(session=session)
|
|
116
115
|
if keep_history:
|
|
@@ -171,7 +170,6 @@ def update_subscription(name: str,
|
|
|
171
170
|
values['state'] = SubscriptionState.INACTIVE
|
|
172
171
|
values['expired_at'] = datetime.datetime.utcnow()
|
|
173
172
|
|
|
174
|
-
SubscriptionHistory = models.SubscriptionHistory
|
|
175
173
|
try:
|
|
176
174
|
stmt = select(
|
|
177
175
|
models.Subscription
|
|
@@ -191,20 +189,20 @@ def update_subscription(name: str,
|
|
|
191
189
|
|
|
192
190
|
subscription.update(values)
|
|
193
191
|
if keep_history and current_subscription_state != new_subscription_state:
|
|
194
|
-
subscription_history = SubscriptionHistory(id=subscription.id,
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
192
|
+
subscription_history = models.SubscriptionHistory(id=subscription.id,
|
|
193
|
+
name=subscription.name,
|
|
194
|
+
filter=subscription.filter,
|
|
195
|
+
account=subscription.account,
|
|
196
|
+
replication_rules=subscription.replication_rules,
|
|
197
|
+
state=subscription.state,
|
|
198
|
+
lifetime=subscription.lifetime,
|
|
199
|
+
retroactive=subscription.retroactive,
|
|
200
|
+
policyid=subscription.policyid,
|
|
201
|
+
comments=subscription.comments,
|
|
202
|
+
last_processed=subscription.last_processed,
|
|
203
|
+
expired_at=subscription.expired_at,
|
|
204
|
+
updated_at=datetime.datetime.utcnow(),
|
|
205
|
+
created_at=subscription.created_at)
|
|
208
206
|
subscription_history.save(session=session)
|
|
209
207
|
except NoResultFound:
|
|
210
208
|
raise SubscriptionNotFound(f"Subscription for account '{account}' named '{name}' not found")
|