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/topology.py
CHANGED
|
@@ -17,7 +17,6 @@ import itertools
|
|
|
17
17
|
import logging
|
|
18
18
|
import threading
|
|
19
19
|
import weakref
|
|
20
|
-
from collections.abc import Callable, Iterable, Iterator
|
|
21
20
|
from decimal import Decimal
|
|
22
21
|
from typing import TYPE_CHECKING, Any, Generic, Optional, TypeVar, Union, cast
|
|
23
22
|
|
|
@@ -38,6 +37,7 @@ TE = TypeVar("TE", bound="Edge")
|
|
|
38
37
|
ExpiringObjectCacheNewObject = TypeVar("ExpiringObjectCacheNewObject")
|
|
39
38
|
|
|
40
39
|
if TYPE_CHECKING:
|
|
40
|
+
from collections.abc import Callable, Iterable, Iterator
|
|
41
41
|
from typing import Protocol
|
|
42
42
|
|
|
43
43
|
from sqlalchemy.orm import Session
|
|
@@ -63,7 +63,7 @@ INF = float('inf')
|
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
class Node(RseData):
|
|
66
|
-
def __init__(self, rse_id: str):
|
|
66
|
+
def __init__(self, rse_id: str) -> None:
|
|
67
67
|
super().__init__(rse_id)
|
|
68
68
|
|
|
69
69
|
self.in_edges = weakref.WeakKeyDictionary()
|
|
@@ -75,7 +75,7 @@ class Node(RseData):
|
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
class Edge(Generic[TN]):
|
|
78
|
-
def __init__(self, src_node: TN, dst_node: TN):
|
|
78
|
+
def __init__(self, src_node: TN, dst_node: TN) -> None:
|
|
79
79
|
self._src_node = weakref.ref(src_node)
|
|
80
80
|
self._dst_node = weakref.ref(dst_node)
|
|
81
81
|
|
|
@@ -123,11 +123,11 @@ class Topology(RseCollection, Generic[TN, TE]):
|
|
|
123
123
|
"""
|
|
124
124
|
def __init__(
|
|
125
125
|
self,
|
|
126
|
-
rse_ids: Optional[Iterable[str]] = None,
|
|
126
|
+
rse_ids: Optional["Iterable[str]"] = None,
|
|
127
127
|
ignore_availability: bool = False,
|
|
128
128
|
node_cls: type[TN] = Node,
|
|
129
129
|
edge_cls: type[TE] = Edge,
|
|
130
|
-
):
|
|
130
|
+
) -> None:
|
|
131
131
|
super().__init__(rse_ids=rse_ids, rse_data_cls=node_cls)
|
|
132
132
|
self._edge_cls = edge_cls
|
|
133
133
|
self._edges: dict[tuple[TN, TN], TE] = {}
|
|
@@ -284,7 +284,7 @@ class Topology(RseCollection, Generic[TN, TE]):
|
|
|
284
284
|
@read_session
|
|
285
285
|
def search_shortest_paths(
|
|
286
286
|
self,
|
|
287
|
-
src_nodes: Iterable[TN],
|
|
287
|
+
src_nodes: "Iterable[TN]",
|
|
288
288
|
dst_node: TN,
|
|
289
289
|
operation_src: str,
|
|
290
290
|
operation_dest: str,
|
|
@@ -310,7 +310,7 @@ class Topology(RseCollection, Generic[TN, TE]):
|
|
|
310
310
|
class _NodeStateProvider:
|
|
311
311
|
_hop_penalty = self._hop_penalty
|
|
312
312
|
|
|
313
|
-
def __init__(self, node: TN):
|
|
313
|
+
def __init__(self, node: TN) -> None:
|
|
314
314
|
self.enabled: bool = True
|
|
315
315
|
self.cost: _Number = 0
|
|
316
316
|
if node != dst_node:
|
|
@@ -322,7 +322,7 @@ class Topology(RseCollection, Generic[TN, TE]):
|
|
|
322
322
|
scheme_missmatch_found = {}
|
|
323
323
|
|
|
324
324
|
class _EdgeStateProvider:
|
|
325
|
-
def __init__(self, edge: TE):
|
|
325
|
+
def __init__(self, edge: TE) -> None:
|
|
326
326
|
self.edge = edge
|
|
327
327
|
self.chosen_scheme = {}
|
|
328
328
|
|
|
@@ -358,7 +358,7 @@ class Topology(RseCollection, Generic[TN, TE]):
|
|
|
358
358
|
node_state_provider=_NodeStateProvider,
|
|
359
359
|
edge_state_provider=_EdgeStateProvider):
|
|
360
360
|
nh_node = edge_to_next_hop.dst_node
|
|
361
|
-
edge_state = cast(_EdgeStateProvider, edge_state)
|
|
361
|
+
edge_state = cast("_EdgeStateProvider", edge_state)
|
|
362
362
|
hop = {
|
|
363
363
|
'source_rse': node,
|
|
364
364
|
'dest_rse': nh_node,
|
|
@@ -433,8 +433,8 @@ class ExpiringObjectCache(Generic[ExpiringObjectCacheNewObject]):
|
|
|
433
433
|
def __init__(
|
|
434
434
|
self,
|
|
435
435
|
ttl: int,
|
|
436
|
-
new_obj_fnc: Callable[[], ExpiringObjectCacheNewObject]
|
|
437
|
-
):
|
|
436
|
+
new_obj_fnc: "Callable[[], ExpiringObjectCacheNewObject]"
|
|
437
|
+
) -> None:
|
|
438
438
|
self._lock = threading.Lock()
|
|
439
439
|
self._object: Optional[ExpiringObjectCacheNewObject] = None
|
|
440
440
|
self._creation_time: Optional[datetime.datetime] = None
|
rucio/core/trace.py
CHANGED
|
@@ -26,7 +26,7 @@ from typing import TYPE_CHECKING, Any, Union, overload
|
|
|
26
26
|
import stomp
|
|
27
27
|
from jsonschema import Draft7Validator, ValidationError, validate
|
|
28
28
|
|
|
29
|
-
from rucio.common.config import config_get, config_get_int
|
|
29
|
+
from rucio.common.config import config_get, config_get_int, config_get_list
|
|
30
30
|
from rucio.common.exception import InvalidObject, TraceValidationSchemaNotFound
|
|
31
31
|
from rucio.common.logging import rucio_log_formatter
|
|
32
32
|
from rucio.common.schema.generic import TIME_ENTRY, UUID, IPv4orIPv6
|
|
@@ -70,7 +70,7 @@ ROTATING_LOGGER.addHandler(ROTATING_HANDLER)
|
|
|
70
70
|
|
|
71
71
|
BROKERS_ALIAS, BROKERS_RESOLVED = [], []
|
|
72
72
|
try:
|
|
73
|
-
BROKERS_ALIAS =
|
|
73
|
+
BROKERS_ALIAS = config_get_list('trace', 'brokers')
|
|
74
74
|
except:
|
|
75
75
|
raise Exception('Could not load brokers from configuration')
|
|
76
76
|
|
rucio/core/transfer.py
CHANGED
|
@@ -38,7 +38,6 @@ from rucio.core import request as request_core
|
|
|
38
38
|
from rucio.core.account import list_accounts
|
|
39
39
|
from rucio.core.monitor import MetricManager
|
|
40
40
|
from rucio.core.request import DirectTransfer, RequestSource, RequestWithSources, TransferDestination, transition_request_state
|
|
41
|
-
from rucio.core.rse import RseData
|
|
42
41
|
from rucio.core.rse_expression_parser import parse_expression
|
|
43
42
|
from rucio.db.sqla import models
|
|
44
43
|
from rucio.db.sqla.constants import DIDType, RequestState, RequestType, TransferLimitDirection
|
|
@@ -48,7 +47,6 @@ from rucio.transfertool.bittorrent import BittorrentTransfertool
|
|
|
48
47
|
from rucio.transfertool.fts3 import FTS3Transfertool
|
|
49
48
|
from rucio.transfertool.globus import GlobusTransferTool
|
|
50
49
|
from rucio.transfertool.mock import MockTransfertool
|
|
51
|
-
from rucio.transfertool.transfertool import TransferStatusReport, Transfertool
|
|
52
50
|
|
|
53
51
|
if TYPE_CHECKING:
|
|
54
52
|
from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence
|
|
@@ -56,9 +54,11 @@ if TYPE_CHECKING:
|
|
|
56
54
|
|
|
57
55
|
from sqlalchemy.orm import Session
|
|
58
56
|
|
|
59
|
-
from rucio.common.types import InternalAccount
|
|
57
|
+
from rucio.common.types import InternalAccount, LFNDict
|
|
58
|
+
from rucio.core.rse import RseData
|
|
60
59
|
from rucio.core.topology import Topology
|
|
61
60
|
from rucio.rse.protocols.protocol import RSEProtocol
|
|
61
|
+
from rucio.transfertool.transfertool import TransferStatusReport, Transfertool
|
|
62
62
|
|
|
63
63
|
LoggerFunction = Callable[..., Any]
|
|
64
64
|
|
|
@@ -90,7 +90,7 @@ class ProtocolFactory:
|
|
|
90
90
|
def __init__(self):
|
|
91
91
|
self.protocols = {}
|
|
92
92
|
|
|
93
|
-
def protocol(self, rse: RseData, scheme: "Optional[str]", operation: str):
|
|
93
|
+
def protocol(self, rse: 'RseData', scheme: "Optional[str]", operation: str):
|
|
94
94
|
protocol_key = '%s_%s_%s' % (operation, rse.id, scheme)
|
|
95
95
|
protocol = self.protocols.get(protocol_key)
|
|
96
96
|
if not protocol:
|
|
@@ -210,7 +210,12 @@ class DirectTransferImplementation(DirectTransfer):
|
|
|
210
210
|
# Compute the source URL
|
|
211
211
|
source_sign_url = src.rse.attributes.get(RseAttr.SIGN_URL, None)
|
|
212
212
|
dest_sign_url = dst.rse.attributes.get(RseAttr.SIGN_URL, None)
|
|
213
|
-
|
|
213
|
+
lfn: "LFNDict" = {
|
|
214
|
+
'scope': rws.scope.external, # type: ignore (scope.external might be None)
|
|
215
|
+
'name': rws.name,
|
|
216
|
+
'path': src.file_path
|
|
217
|
+
}
|
|
218
|
+
source_url = list(protocol.lfns2pfns(lfns=lfn).values())[0]
|
|
214
219
|
source_url = cls.__rewrite_source_url(source_url, source_sign_url=source_sign_url, dest_sign_url=dest_sign_url, source_scheme=src.scheme)
|
|
215
220
|
return source_url
|
|
216
221
|
|
|
@@ -223,7 +228,11 @@ class DirectTransferImplementation(DirectTransfer):
|
|
|
223
228
|
protocol = protocol_factory.protocol(dst.rse, dst.scheme, operation)
|
|
224
229
|
|
|
225
230
|
if dst.rse.info['deterministic']:
|
|
226
|
-
|
|
231
|
+
lfn: "LFNDict" = {
|
|
232
|
+
'scope': rws.scope.external, # type: ignore (scope.external might be None)
|
|
233
|
+
'name': rws.name
|
|
234
|
+
}
|
|
235
|
+
dest_url = list(protocol.lfns2pfns(lfns=lfn).values())[0]
|
|
227
236
|
else:
|
|
228
237
|
# compute dest url in case of non deterministic
|
|
229
238
|
# naming convention, etc.
|
|
@@ -236,7 +245,12 @@ class DirectTransferImplementation(DirectTransfer):
|
|
|
236
245
|
if rws.retry_count or rws.activity == 'Recovery':
|
|
237
246
|
dest_path = '%s_%i' % (dest_path, int(time.time()))
|
|
238
247
|
|
|
239
|
-
|
|
248
|
+
lfn: "LFNDict" = {
|
|
249
|
+
'scope': rws.scope.external, # type: ignore (scope.external might be None)
|
|
250
|
+
'name': rws.name,
|
|
251
|
+
'path': dest_path
|
|
252
|
+
}
|
|
253
|
+
dest_url = list(protocol.lfns2pfns(lfns=lfn).values())[0]
|
|
240
254
|
|
|
241
255
|
dest_sign_url = dst.rse.attributes.get(RseAttr.SIGN_URL, None)
|
|
242
256
|
dest_url = cls.__rewrite_dest_url(dest_url, dest_sign_url=dest_sign_url)
|
|
@@ -498,7 +512,7 @@ def set_transfers_state(
|
|
|
498
512
|
|
|
499
513
|
@transactional_session
|
|
500
514
|
def update_transfer_state(
|
|
501
|
-
tt_status_report: TransferStatusReport,
|
|
515
|
+
tt_status_report: 'TransferStatusReport',
|
|
502
516
|
stats_manager: request_core.TransferStatsManager,
|
|
503
517
|
*,
|
|
504
518
|
session: "Session",
|
|
@@ -744,7 +758,7 @@ def _create_stagein_definitions(
|
|
|
744
758
|
"""
|
|
745
759
|
transfers_by_source = {
|
|
746
760
|
source.rse: [
|
|
747
|
-
cast(DirectTransfer, StageinTransferImplementation(
|
|
761
|
+
cast('DirectTransfer', StageinTransferImplementation(
|
|
748
762
|
source=RequestSource(
|
|
749
763
|
rse=source.rse,
|
|
750
764
|
file_path=source.file_path,
|
|
@@ -973,7 +987,7 @@ class EnforceSourceRSEExpression(SourceFilterStrategy):
|
|
|
973
987
|
return self._RankingContext(self, rws, allowed_source_rses)
|
|
974
988
|
|
|
975
989
|
def apply(self, ctx: RequestRankingContext, source: RequestSource) -> "Optional[int | _SkipSource]":
|
|
976
|
-
ctx = cast(EnforceSourceRSEExpression._RankingContext, ctx)
|
|
990
|
+
ctx = cast('EnforceSourceRSEExpression._RankingContext', ctx)
|
|
977
991
|
if ctx.allowed_source_rses is not None and source.rse.id not in ctx.allowed_source_rses:
|
|
978
992
|
return SKIP_SOURCE
|
|
979
993
|
|
|
@@ -1049,7 +1063,7 @@ class PathDistance(SourceRankingStrategy):
|
|
|
1049
1063
|
return PathDistance._RankingContext(self, rws, paths_for_rws)
|
|
1050
1064
|
|
|
1051
1065
|
def apply(self, ctx: RequestRankingContext, source: RequestSource) -> "Optional[int | _SkipSource]":
|
|
1052
|
-
path = cast(PathDistance._RankingContext, ctx).paths_for_rws.get(source.rse)
|
|
1066
|
+
path = cast('PathDistance._RankingContext', ctx).paths_for_rws.get(source.rse)
|
|
1053
1067
|
if not path:
|
|
1054
1068
|
return SKIP_SOURCE
|
|
1055
1069
|
return path[0].src.distance
|
|
@@ -1057,7 +1071,7 @@ class PathDistance(SourceRankingStrategy):
|
|
|
1057
1071
|
|
|
1058
1072
|
class PreferSingleHop(PathDistance):
|
|
1059
1073
|
def apply(self, ctx: RequestRankingContext, source: RequestSource) -> "Optional[int | _SkipSource]":
|
|
1060
|
-
path = cast(PathDistance._RankingContext, ctx).paths_for_rws.get(source.rse)
|
|
1074
|
+
path = cast('PathDistance._RankingContext', ctx).paths_for_rws.get(source.rse)
|
|
1061
1075
|
if not path:
|
|
1062
1076
|
return SKIP_SOURCE
|
|
1063
1077
|
return int(len(path) > 1)
|
|
@@ -1097,7 +1111,7 @@ class FailureRate(SourceRankingStrategy):
|
|
|
1097
1111
|
self.source_stats.setdefault(stat['src_rse_id'], self._FailureRateStat()).incorporate_stat(stat)
|
|
1098
1112
|
|
|
1099
1113
|
def apply(self, ctx: RequestRankingContext, source: RequestSource) -> "Optional[int | _SkipSource]":
|
|
1100
|
-
failure_rate = cast(FailureRate, ctx.strategy).source_stats.get(source.rse.id, self._FailureRateStat()).get_failure_rate()
|
|
1114
|
+
failure_rate = cast('FailureRate', ctx.strategy).source_stats.get(source.rse.id, self._FailureRateStat()).get_failure_rate()
|
|
1101
1115
|
return failure_rate
|
|
1102
1116
|
|
|
1103
1117
|
|
|
@@ -1105,7 +1119,7 @@ class SkipSchemeMissmatch(PathDistance):
|
|
|
1105
1119
|
filter_only = True
|
|
1106
1120
|
|
|
1107
1121
|
def apply(self, ctx: RequestRankingContext, source: RequestSource) -> "Optional[int | _SkipSource]":
|
|
1108
|
-
path = cast(PathDistance._RankingContext, ctx).paths_for_rws.get(source.rse)
|
|
1122
|
+
path = cast('PathDistance._RankingContext', ctx).paths_for_rws.get(source.rse)
|
|
1109
1123
|
# path == None means that there is no path;
|
|
1110
1124
|
# path == [] means that a path exists (according to distances) but cannot be used (scheme mismatch)
|
|
1111
1125
|
if path is not None and not path:
|
|
@@ -1117,7 +1131,7 @@ class SkipIntermediateTape(PathDistance):
|
|
|
1117
1131
|
|
|
1118
1132
|
def apply(self, ctx: RequestRankingContext, source: RequestSource) -> "Optional[int | _SkipSource]":
|
|
1119
1133
|
# Discard multihop transfers which contain a tape source as an intermediate hop
|
|
1120
|
-
path = cast(PathDistance._RankingContext, ctx).paths_for_rws.get(source.rse)
|
|
1134
|
+
path = cast('PathDistance._RankingContext', ctx).paths_for_rws.get(source.rse)
|
|
1121
1135
|
if path and any(transfer.src.rse.is_tape_or_staging_required() for transfer in path[1:]):
|
|
1122
1136
|
return SKIP_SOURCE
|
|
1123
1137
|
|
rucio/core/volatile_replica.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 Iterable
|
|
16
15
|
from datetime import datetime
|
|
17
16
|
from typing import TYPE_CHECKING, Any
|
|
18
17
|
|
|
@@ -26,11 +25,13 @@ from rucio.db.sqla.constants import ReplicaState
|
|
|
26
25
|
from rucio.db.sqla.session import transactional_session
|
|
27
26
|
|
|
28
27
|
if TYPE_CHECKING:
|
|
28
|
+
from collections.abc import Iterable
|
|
29
|
+
|
|
29
30
|
from sqlalchemy.orm import Session
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
@transactional_session
|
|
33
|
-
def add_volatile_replicas(rse_id: str, replicas: Iterable[dict[str, Any]], *, session: "Session") -> None:
|
|
34
|
+
def add_volatile_replicas(rse_id: str, replicas: "Iterable[dict[str, Any]]", *, session: "Session") -> None:
|
|
34
35
|
"""
|
|
35
36
|
Bulk add volatile replicas.
|
|
36
37
|
|
|
@@ -112,7 +113,7 @@ def add_volatile_replicas(rse_id: str, replicas: Iterable[dict[str, Any]], *, se
|
|
|
112
113
|
|
|
113
114
|
|
|
114
115
|
@transactional_session
|
|
115
|
-
def delete_volatile_replicas(rse_id: str, replicas: Iterable[dict[str, Any]], *, session: "Session") -> None:
|
|
116
|
+
def delete_volatile_replicas(rse_id: str, replicas: "Iterable[dict[str, Any]]", *, session: "Session") -> None:
|
|
116
117
|
"""
|
|
117
118
|
Bulk delete volatile replicas.
|
|
118
119
|
|
rucio/daemons/atropos/atropos.py
CHANGED
|
@@ -16,9 +16,9 @@ import bz2
|
|
|
16
16
|
import glob
|
|
17
17
|
import logging
|
|
18
18
|
import os
|
|
19
|
-
import queue as Queue
|
|
20
19
|
import select
|
|
21
20
|
from datetime import datetime, timedelta
|
|
21
|
+
from queue import Empty as EmptyQueue
|
|
22
22
|
from typing import TYPE_CHECKING, Optional
|
|
23
23
|
|
|
24
24
|
from rucio.common import config
|
|
@@ -238,7 +238,7 @@ def check(
|
|
|
238
238
|
while not terminate.is_set():
|
|
239
239
|
try:
|
|
240
240
|
rse, attempts = queue.get(timeout=30)
|
|
241
|
-
except
|
|
241
|
+
except EmptyQueue:
|
|
242
242
|
continue
|
|
243
243
|
start = datetime.now()
|
|
244
244
|
try:
|
|
@@ -12,15 +12,15 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
import configparser as ConfigParser
|
|
16
15
|
import datetime
|
|
17
16
|
import glob
|
|
18
17
|
import hashlib
|
|
19
|
-
import html.parser as HTMLParser
|
|
20
18
|
import logging
|
|
21
19
|
import operator
|
|
22
20
|
import os
|
|
23
21
|
import re
|
|
22
|
+
from configparser import RawConfigParser
|
|
23
|
+
from html.parser import HTMLParser
|
|
24
24
|
from typing import IO, TYPE_CHECKING, Any, Optional
|
|
25
25
|
|
|
26
26
|
import gfal2
|
|
@@ -49,7 +49,7 @@ __DUMPERCONFIGDIRS = list(
|
|
|
49
49
|
OBJECTSTORE_NUM_TRIES = 30
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
class Parser(
|
|
52
|
+
class Parser(RawConfigParser):
|
|
53
53
|
'''
|
|
54
54
|
RawConfigParser subclass that doesn't modify the the name of the options
|
|
55
55
|
and removes any quotes around the string values.
|
|
@@ -137,7 +137,7 @@ def gfal_links(base_url: str) -> list[str]:
|
|
|
137
137
|
return ['/'.join((base_url, f)) for f in ctxt.listdir(str(base_url))]
|
|
138
138
|
|
|
139
139
|
|
|
140
|
-
class _LinkCollector(HTMLParser
|
|
140
|
+
class _LinkCollector(HTMLParser):
|
|
141
141
|
def __init__(self):
|
|
142
142
|
super(_LinkCollector, self).__init__()
|
|
143
143
|
self.links = []
|
|
@@ -244,7 +244,7 @@ def parse_configuration(conf_dirs: Optional[list[str]] = None) -> Parser:
|
|
|
244
244
|
|
|
245
245
|
def download_rse_dump(
|
|
246
246
|
rse: str,
|
|
247
|
-
configuration:
|
|
247
|
+
configuration: RawConfigParser,
|
|
248
248
|
date: Optional[datetime.datetime] = None,
|
|
249
249
|
destdir: str = DUMPS_CACHE_DIR
|
|
250
250
|
) -> tuple[str, datetime.datetime]:
|
|
@@ -331,7 +331,7 @@ def download_rse_dump(
|
|
|
331
331
|
|
|
332
332
|
def generate_url(
|
|
333
333
|
rse: str,
|
|
334
|
-
config:
|
|
334
|
+
config: RawConfigParser
|
|
335
335
|
) -> tuple[str, str]:
|
|
336
336
|
'''
|
|
337
337
|
:param rse: Name of the endpoint.
|
|
@@ -28,7 +28,7 @@ import rucio.db.sqla.util
|
|
|
28
28
|
from rucio.client import Client
|
|
29
29
|
from rucio.client.uploadclient import UploadClient
|
|
30
30
|
from rucio.common import exception
|
|
31
|
-
from rucio.common.config import config_get, config_get_bool, config_get_int
|
|
31
|
+
from rucio.common.config import config_get, config_get_bool, config_get_int, config_get_list
|
|
32
32
|
from rucio.common.logging import setup_logging
|
|
33
33
|
from rucio.common.stopwatch import Stopwatch
|
|
34
34
|
from rucio.common.types import InternalScope, LoggerFunction
|
|
@@ -149,18 +149,14 @@ def run_once(heartbeat_handler: HeartbeatHandler, inputfile: str, **_kwargs) ->
|
|
|
149
149
|
|
|
150
150
|
_, _, logger = heartbeat_handler.live()
|
|
151
151
|
try:
|
|
152
|
-
rses =
|
|
153
|
-
s.strip() for s in config_get("automatix", "rses").split(",")
|
|
154
|
-
] # TODO use config_get_list
|
|
152
|
+
rses = config_get_list("automatix", "rses")
|
|
155
153
|
except (NoOptionError, NoSectionError, RuntimeError):
|
|
156
154
|
logging.log(
|
|
157
155
|
logging.ERROR,
|
|
158
156
|
"Option rses not found in automatix section. Trying the legacy sites option",
|
|
159
157
|
)
|
|
160
158
|
try:
|
|
161
|
-
rses =
|
|
162
|
-
s.strip() for s in config_get("automatix", "sites").split(",")
|
|
163
|
-
] # TODO use config_get_list
|
|
159
|
+
rses = config_get_list("automatix", "sites")
|
|
164
160
|
logging.log(
|
|
165
161
|
logging.WARNING,
|
|
166
162
|
"Option sites found in automatix section. This option will be deprecated soon. Please update your config to use rses.",
|
|
@@ -190,6 +186,8 @@ def run_once(heartbeat_handler: HeartbeatHandler, inputfile: str, **_kwargs) ->
|
|
|
190
186
|
logger(logging.DEBUG, "Probabilities %s", probabilities)
|
|
191
187
|
|
|
192
188
|
cycle_stopwatch = Stopwatch()
|
|
189
|
+
successes = []
|
|
190
|
+
failures = []
|
|
193
191
|
for rse in rses:
|
|
194
192
|
stopwatch = Stopwatch()
|
|
195
193
|
_, _, logger = heartbeat_handler.live()
|
|
@@ -239,24 +237,37 @@ def run_once(heartbeat_handler: HeartbeatHandler, inputfile: str, **_kwargs) ->
|
|
|
239
237
|
file_["dataset_meta"]["lifetime"] = dataset_lifetime
|
|
240
238
|
files.append(file_)
|
|
241
239
|
logger(logging.INFO, "Upload %s:%s to %s", scope, dsn, rse)
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
240
|
+
try:
|
|
241
|
+
upload_client = UploadClient(client)
|
|
242
|
+
ret = upload_client.upload(files)
|
|
243
|
+
if ret == 0:
|
|
244
|
+
logger(logging.INFO, "%s successfully registered on %s", dsn, rse)
|
|
245
|
+
METRICS.counter(name="addnewdataset.done").inc()
|
|
246
|
+
METRICS.counter(name="addnewfile.done").inc(nbfiles)
|
|
247
|
+
METRICS.timer(name='datasetinjection').observe(stopwatch.elapsed)
|
|
248
|
+
successes.append(rse)
|
|
249
|
+
else:
|
|
250
|
+
logger(logging.INFO, "Error uploading files")
|
|
251
|
+
failures.append(rse)
|
|
252
|
+
except Exception as error:
|
|
253
|
+
logger(logging.ERROR, "Error uploading files on %s: %s", rse, str(error))
|
|
254
|
+
failures.append(rse)
|
|
255
|
+
finally:
|
|
256
|
+
for physical_fname in physical_fnames:
|
|
257
|
+
remove(physical_fname)
|
|
258
|
+
rmdir(tmpdir)
|
|
254
259
|
logger(
|
|
255
260
|
logging.INFO,
|
|
256
|
-
"It took %f seconds to upload
|
|
261
|
+
"It took %f seconds to upload datasets on %s RSEs: %s",
|
|
257
262
|
cycle_stopwatch.elapsed,
|
|
258
|
-
|
|
263
|
+
len(successes),
|
|
264
|
+
str(successes),
|
|
259
265
|
)
|
|
266
|
+
if failures:
|
|
267
|
+
logger(
|
|
268
|
+
logging.WARNING,
|
|
269
|
+
"Datasets could not be uploaded on %s RSEs: %s", len(failures), str(failures),
|
|
270
|
+
)
|
|
260
271
|
return True
|
|
261
272
|
|
|
262
273
|
|
|
@@ -25,7 +25,7 @@ from sqlalchemy.exc import DatabaseError
|
|
|
25
25
|
|
|
26
26
|
import rucio.db.sqla.util
|
|
27
27
|
from rucio.common import exception
|
|
28
|
-
from rucio.common.cache import
|
|
28
|
+
from rucio.common.cache import MemcacheRegion
|
|
29
29
|
from rucio.common.config import config_get_int
|
|
30
30
|
from rucio.common.exception import DatabaseException
|
|
31
31
|
from rucio.common.logging import setup_logging
|
|
@@ -41,7 +41,7 @@ if TYPE_CHECKING:
|
|
|
41
41
|
|
|
42
42
|
graceful_stop = threading.Event()
|
|
43
43
|
METRICS = MetricManager(module=__name__)
|
|
44
|
-
REGION =
|
|
44
|
+
REGION = MemcacheRegion(expiration_time=config_get_int('necromancer', 'cache_time', False, 600))
|
|
45
45
|
DAEMON_NAME = 'necromancer'
|
|
46
46
|
|
|
47
47
|
|
|
@@ -61,7 +61,7 @@ total_total = 0
|
|
|
61
61
|
global_ratio = float(0)
|
|
62
62
|
for rse in rses:
|
|
63
63
|
site_name = get_rse_attribute(rse['id'], RseAttr.SITE)
|
|
64
|
-
rse['groupdisk'] = group_space(site_name)
|
|
64
|
+
rse['groupdisk'] = group_space(site_name) # type: ignore (site_name could be None)
|
|
65
65
|
rse['primary'] = get_rse_usage(rse_id=rse['id'], source='rucio')[0]['used'] - get_rse_usage(rse_id=rse['id'], source='expired')[0]['used']
|
|
66
66
|
rse['primary'] += rse['groupdisk']
|
|
67
67
|
rse['secondary'] = get_rse_usage(rse_id=rse['id'], source='expired')[0]['used']
|
|
@@ -61,7 +61,7 @@ total_total = 0
|
|
|
61
61
|
global_ratio = float(0)
|
|
62
62
|
for rse in rses:
|
|
63
63
|
site_name = get_rse_attribute(rse['id'], RseAttr.SITE)
|
|
64
|
-
rse['groupdisk'] = group_space(site_name)
|
|
64
|
+
rse['groupdisk'] = group_space(site_name) # type: ignore (site_name could be None)
|
|
65
65
|
rse['primary'] = get_rse_usage(rse_id=rse['id'], source='rucio')[0]['used'] - get_rse_usage(rse_id=rse['id'], source='expired')[0]['used']
|
|
66
66
|
rse['primary'] += rse['groupdisk']
|
|
67
67
|
rse['secondary'] = get_rse_usage(rse_id=rse['id'], source='expired')[0]['used']
|