rucio 37.6.0__py3-none-any.whl → 37.7.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/cli/bin_legacy/rucio.py +40 -21
- rucio/cli/rule.py +9 -5
- rucio/client/baseclient.py +4 -3
- rucio/client/downloadclient.py +2 -1
- rucio/client/exportclient.py +45 -4
- rucio/client/pingclient.py +35 -4
- rucio/client/touchclient.py +2 -1
- rucio/client/uploadclient.py +3 -2
- rucio/common/cache.py +1 -2
- rucio/common/client.py +4 -30
- rucio/common/config.py +26 -1
- rucio/common/constants.py +3 -1
- rucio/common/plugins.py +2 -2
- rucio/common/policy.py +3 -2
- rucio/common/schema/__init__.py +4 -3
- rucio/common/types.py +7 -5
- rucio/core/account.py +2 -1
- rucio/core/account_limit.py +3 -2
- rucio/core/did.py +8 -7
- rucio/core/dirac.py +2 -1
- rucio/core/distance.py +2 -1
- rucio/core/exporter.py +3 -2
- rucio/core/importer.py +5 -5
- rucio/core/permission/__init__.py +2 -1
- rucio/core/replica.py +5 -5
- rucio/core/request.py +2 -2
- rucio/core/rse.py +7 -7
- rucio/core/rule.py +8 -8
- rucio/core/transfer.py +2 -2
- rucio/core/vo.py +2 -1
- rucio/daemons/atropos/atropos.py +2 -1
- rucio/daemons/automatix/automatix.py +5 -5
- rucio/daemons/badreplicas/minos.py +3 -2
- rucio/daemons/bb8/bb8.py +2 -1
- rucio/daemons/bb8/nuclei_background_rebalance.py +2 -2
- rucio/daemons/conveyor/common.py +3 -3
- rucio/daemons/conveyor/submitter.py +2 -1
- rucio/daemons/hermes/hermes.py +27 -6
- rucio/daemons/reaper/dark_reaper.py +5 -4
- rucio/daemons/reaper/reaper.py +7 -7
- rucio/daemons/replicarecoverer/suspicious_replica_recoverer.py +3 -3
- rucio/daemons/tracer/kronos.py +3 -2
- rucio/daemons/transmogrifier/transmogrifier.py +70 -68
- rucio/daemons/undertaker/undertaker.py +2 -1
- rucio/db/sqla/models.py +2 -2
- rucio/db/sqla/util.py +3 -2
- rucio/gateway/account.py +13 -12
- rucio/gateway/account_limit.py +90 -116
- rucio/gateway/authentication.py +9 -8
- rucio/gateway/config.py +11 -10
- rucio/gateway/credential.py +2 -1
- rucio/gateway/did.py +32 -32
- rucio/gateway/dirac.py +2 -1
- rucio/gateway/exporter.py +2 -1
- rucio/gateway/heartbeat.py +3 -2
- rucio/gateway/identity.py +4 -3
- rucio/gateway/importer.py +2 -1
- rucio/gateway/lifetime_exception.py +4 -3
- rucio/gateway/lock.py +6 -5
- rucio/gateway/meta_conventions.py +3 -2
- rucio/gateway/permission.py +2 -1
- rucio/gateway/quarantined_replica.py +2 -1
- rucio/gateway/replica.py +18 -18
- rucio/gateway/request.py +10 -10
- rucio/gateway/rse.py +27 -26
- rucio/gateway/rule.py +12 -11
- rucio/gateway/scope.py +4 -3
- rucio/gateway/subscription.py +7 -6
- rucio/gateway/vo.py +5 -4
- rucio/rse/__init__.py +7 -6
- rucio/rse/rsemanager.py +5 -4
- rucio/rse/translation.py +2 -2
- rucio/tests/common.py +2 -1
- rucio/vcsversion.py +3 -3
- rucio/web/rest/flaskapi/v1/accountlimits.py +5 -5
- rucio/web/rest/flaskapi/v1/archives.py +2 -1
- rucio/web/rest/flaskapi/v1/common.py +4 -3
- rucio/web/rest/flaskapi/v1/dids.py +205 -154
- {rucio-37.6.0.dist-info → rucio-37.7.0.dist-info}/METADATA +1 -1
- {rucio-37.6.0.dist-info → rucio-37.7.0.dist-info}/RECORD +139 -139
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/etc/alembic.ini.template +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/etc/alembic_offline.ini.template +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/etc/globus-config.yml.template +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/etc/ldap.cfg.template +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/etc/rucio.cfg.atlas.client.template +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/etc/rucio.cfg.template +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/etc/rucio_multi_vo.cfg.template +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/requirements.server.txt +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/tools/bootstrap.py +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/tools/merge_rucio_configs.py +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/data/rucio/tools/reset_database.py +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-abacus-account +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-abacus-collection-replica +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-abacus-rse +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-admin +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-atropos +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-auditor +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-automatix +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-bb8 +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-cache-client +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-cache-consumer +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-conveyor-finisher +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-conveyor-poller +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-conveyor-preparer +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-conveyor-receiver +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-conveyor-stager +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-conveyor-submitter +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-conveyor-throttler +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-dark-reaper +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-dumper +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-follower +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-hermes +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-judge-cleaner +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-judge-evaluator +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-judge-injector +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-judge-repairer +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-kronos +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-minos +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-minos-temporary-expiration +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-necromancer +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-oauth-manager +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-reaper +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-replica-recoverer +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-rse-decommissioner +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-storage-consistency-actions +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-transmogrifier +0 -0
- {rucio-37.6.0.data → rucio-37.7.0.data}/scripts/rucio-undertaker +0 -0
- {rucio-37.6.0.dist-info → rucio-37.7.0.dist-info}/WHEEL +0 -0
- {rucio-37.6.0.dist-info → rucio-37.7.0.dist-info}/licenses/AUTHORS.rst +0 -0
- {rucio-37.6.0.dist-info → rucio-37.7.0.dist-info}/licenses/LICENSE +0 -0
- {rucio-37.6.0.dist-info → rucio-37.7.0.dist-info}/top_level.txt +0 -0
|
@@ -29,6 +29,7 @@ import rucio.core.rse as rse_core
|
|
|
29
29
|
import rucio.db.sqla.util
|
|
30
30
|
from rucio.common import exception
|
|
31
31
|
from rucio.common.config import config_get_bool
|
|
32
|
+
from rucio.common.constants import DEFAULT_VO
|
|
32
33
|
from rucio.common.exception import ResourceTemporaryUnavailable, RSEAccessDenied, RSENotFound, ServiceUnavailable, SourceNotFound, VONotFound
|
|
33
34
|
from rucio.common.logging import setup_logging
|
|
34
35
|
from rucio.core.message import add_message
|
|
@@ -145,7 +146,7 @@ def run_once(
|
|
|
145
146
|
'url': pfn,
|
|
146
147
|
'duration': duration,
|
|
147
148
|
'protocol': prot.attributes['scheme']}
|
|
148
|
-
if replica['scope'].vo !=
|
|
149
|
+
if replica['scope'].vo != DEFAULT_VO:
|
|
149
150
|
payload['vo'] = replica['scope'].vo
|
|
150
151
|
add_message('deletion-done', payload)
|
|
151
152
|
deleted_replicas.append(replica)
|
|
@@ -167,7 +168,7 @@ def run_once(
|
|
|
167
168
|
'url': pfn,
|
|
168
169
|
'reason': str(error),
|
|
169
170
|
'protocol': prot.attributes['scheme']}
|
|
170
|
-
if replica['scope'].vo !=
|
|
171
|
+
if replica['scope'].vo != DEFAULT_VO:
|
|
171
172
|
payload['vo'] = replica['scope'].vo
|
|
172
173
|
add_message('deletion-failed', payload)
|
|
173
174
|
|
|
@@ -215,7 +216,7 @@ def run(
|
|
|
215
216
|
:param exclude_rses: RSE expression to exclude RSEs from the Reaper.
|
|
216
217
|
:param include_rses: RSE expression to include RSEs.
|
|
217
218
|
:param vos: VOs on which to look for RSEs. Only used in multi-VO mode.
|
|
218
|
-
If None, we either use all VOs if run from
|
|
219
|
+
If None, we either use all VOs if run from DEFAULT_VO, or the current VO otherwise.
|
|
219
220
|
"""
|
|
220
221
|
rses = rses or []
|
|
221
222
|
setup_logging(process_name=DAEMON_NAME)
|
|
@@ -229,7 +230,7 @@ def run(
|
|
|
229
230
|
if not multi_vo:
|
|
230
231
|
if vos:
|
|
231
232
|
logging.warning('Ignoring argument vos, this is only applicable in a multi-VO setup.')
|
|
232
|
-
vos = [
|
|
233
|
+
vos = [DEFAULT_VO]
|
|
233
234
|
else:
|
|
234
235
|
if vos:
|
|
235
236
|
invalid = set(vos) - set([v['vo'] for v in list_vos()])
|
rucio/daemons/reaper/reaper.py
CHANGED
|
@@ -35,7 +35,7 @@ from sqlalchemy.exc import DatabaseError, IntegrityError
|
|
|
35
35
|
import rucio.db.sqla.util
|
|
36
36
|
from rucio.common.cache import MemcacheRegion
|
|
37
37
|
from rucio.common.config import config_get_bool, config_get_int
|
|
38
|
-
from rucio.common.constants import RseAttr
|
|
38
|
+
from rucio.common.constants import RseAttr, DEFAULT_VO
|
|
39
39
|
from rucio.common.exception import DatabaseException, ReplicaNotFound, ReplicaUnAvailable, ResourceTemporaryUnavailable, RSEAccessDenied, RSENotFound, RSEProtocolNotSupported, ServiceUnavailable, SourceNotFound, VONotFound
|
|
40
40
|
from rucio.common.logging import setup_logging
|
|
41
41
|
from rucio.common.stopwatch import Stopwatch
|
|
@@ -81,7 +81,7 @@ def get_rses_to_process(
|
|
|
81
81
|
:param exclude_rses: RSE expression to exclude RSEs from the Reaper.
|
|
82
82
|
:param include_rses: RSE expression to include RSEs.
|
|
83
83
|
:param vos: VOs on which to look for RSEs. Only used in multi-VO mode.
|
|
84
|
-
If None, we either use all VOs if run from
|
|
84
|
+
If None, we either use all VOs if run from DEFAULT_VO
|
|
85
85
|
|
|
86
86
|
:returns: A list of RSEs to process
|
|
87
87
|
"""
|
|
@@ -89,7 +89,7 @@ def get_rses_to_process(
|
|
|
89
89
|
if not multi_vo:
|
|
90
90
|
if vos:
|
|
91
91
|
logging.log(logging.WARNING, 'Ignoring argument vos, this is only applicable in a multi-VO setup.')
|
|
92
|
-
vos = [
|
|
92
|
+
vos = [DEFAULT_VO]
|
|
93
93
|
else:
|
|
94
94
|
if vos:
|
|
95
95
|
invalid = set(vos) - set([v['vo'] for v in list_vos()])
|
|
@@ -156,7 +156,7 @@ def delete_from_storage(heartbeat_handler, hb_payload, replicas, prot, rse_info,
|
|
|
156
156
|
'protocol': prot.attributes['scheme'],
|
|
157
157
|
'datatype': replica['datatype']}
|
|
158
158
|
try:
|
|
159
|
-
if replica['scope'].vo !=
|
|
159
|
+
if replica['scope'].vo != DEFAULT_VO:
|
|
160
160
|
deletion_dict['vo'] = replica['scope'].vo
|
|
161
161
|
logger(logging.DEBUG, 'Deletion ATTEMPT of %s:%s as %s on %s', replica['scope'], replica['name'], replica['pfn'], rse_name)
|
|
162
162
|
# For STAGING RSEs, no physical deletion
|
|
@@ -232,7 +232,7 @@ def delete_from_storage(heartbeat_handler, hb_payload, replicas, prot, rse_info,
|
|
|
232
232
|
'url': replica['pfn'],
|
|
233
233
|
'reason': str(error),
|
|
234
234
|
'protocol': prot.attributes['scheme']}
|
|
235
|
-
if replica['scope'].vo !=
|
|
235
|
+
if replica['scope'].vo != DEFAULT_VO:
|
|
236
236
|
payload['vo'] = replica['scope'].vo
|
|
237
237
|
add_message('deletion-failed', payload)
|
|
238
238
|
logger(logging.INFO, 'Cannot connect to %s. RSE will be temporarily excluded.', rse_name)
|
|
@@ -400,7 +400,7 @@ def reaper(
|
|
|
400
400
|
:param include_rses: RSE expression to include RSEs.
|
|
401
401
|
:param exclude_rses: RSE expression to exclude RSEs from the Reaper.
|
|
402
402
|
:param vos: VOs on which to look for RSEs. Only used in multi-VO mode.
|
|
403
|
-
If None, we either use all VOs if run from
|
|
403
|
+
If None, we either use all VOs if run from DEFAULT_VO, or the current VO otherwise.
|
|
404
404
|
:param chunk_size: The size of chunk for deletion.
|
|
405
405
|
:param once: If True, only runs one iteration of the main loop.
|
|
406
406
|
:param greedy: If True, delete right away replicas with tombstone.
|
|
@@ -703,7 +703,7 @@ def run(
|
|
|
703
703
|
:param exclude_rses: RSE expression to exclude RSEs from the Reaper.
|
|
704
704
|
:param include_rses: RSE expression to include RSEs.
|
|
705
705
|
:param vos: VOs on which to look for RSEs. Only used in multi-VO mode.
|
|
706
|
-
If None, we either use all VOs if run from
|
|
706
|
+
If None, we either use all VOs if run from DEFAULT_VO,
|
|
707
707
|
or the current VO otherwise.
|
|
708
708
|
:param delay_seconds: The delay to query replicas in BEING_DELETED state.
|
|
709
709
|
:param sleep_time: Time between two cycles.
|
|
@@ -31,7 +31,7 @@ from typing import TYPE_CHECKING, Any, Optional
|
|
|
31
31
|
|
|
32
32
|
import rucio.db.sqla.util
|
|
33
33
|
from rucio.common.config import config_get, config_get_bool
|
|
34
|
-
from rucio.common.constants import SuspiciousAvailability
|
|
34
|
+
from rucio.common.constants import DEFAULT_VO, SuspiciousAvailability
|
|
35
35
|
from rucio.common.exception import DatabaseException, DuplicateRule, VONotFound
|
|
36
36
|
from rucio.common.logging import setup_logging
|
|
37
37
|
from rucio.common.types import InternalAccount, LoggerFunction
|
|
@@ -145,7 +145,7 @@ def declare_suspicious_replicas_bad(
|
|
|
145
145
|
:param nattempts: The minimum number of appearances in the bad_replica DB table
|
|
146
146
|
in order to appear in the resulting list of replicas for recovery.
|
|
147
147
|
:param vos: VOs on which to look for RSEs. Only used in multi-VO mode.
|
|
148
|
-
If empty, we either use all VOs if run from
|
|
148
|
+
If empty, we either use all VOs if run from DEFAULT_VO,
|
|
149
149
|
:param limit_suspicious_files_on_rse: Maximum number of suspicious replicas on an RSE before that RSE
|
|
150
150
|
is considered problematic and the suspicious replicas on that RSE
|
|
151
151
|
are labeled as 'TEMPORARY_UNAVAILABLE'.
|
|
@@ -182,7 +182,7 @@ def run_once(heartbeat_handler: Any, younger_than: int, nattempts: int, vos: "Op
|
|
|
182
182
|
if not multi_vo:
|
|
183
183
|
if vos:
|
|
184
184
|
logger(logging.WARNING, 'Ignoring argument vos, this is only applicable in a multi-VO setup.')
|
|
185
|
-
vos = [
|
|
185
|
+
vos = [DEFAULT_VO]
|
|
186
186
|
else:
|
|
187
187
|
if vos:
|
|
188
188
|
invalid = set(vos) - set([v['vo'] for v in list_vos()])
|
rucio/daemons/tracer/kronos.py
CHANGED
|
@@ -30,6 +30,7 @@ from typing import TYPE_CHECKING, Optional
|
|
|
30
30
|
|
|
31
31
|
import rucio.db.sqla.util
|
|
32
32
|
from rucio.common.config import config_get, config_get_bool, config_get_int, config_get_list
|
|
33
|
+
from rucio.common.constants import DEFAULT_VO
|
|
33
34
|
from rucio.common.exception import DatabaseException, RSENotFound
|
|
34
35
|
from rucio.common.logging import setup_logging
|
|
35
36
|
from rucio.common.stomp_utils import StompConnectionManager
|
|
@@ -143,7 +144,7 @@ class AMQConsumer:
|
|
|
143
144
|
rses = []
|
|
144
145
|
for report in self.__reports:
|
|
145
146
|
if 'vo' not in report:
|
|
146
|
-
report['vo'] =
|
|
147
|
+
report['vo'] = DEFAULT_VO
|
|
147
148
|
|
|
148
149
|
try:
|
|
149
150
|
# Identify suspicious files
|
|
@@ -299,7 +300,7 @@ class AMQConsumer:
|
|
|
299
300
|
'usrdn': 'someuser',
|
|
300
301
|
'clientState': 'DONE',
|
|
301
302
|
'eventVersion': replica['eventVersion']}
|
|
302
|
-
if replica['scope'].vo !=
|
|
303
|
+
if replica['scope'].vo != DEFAULT_VO:
|
|
303
304
|
resubmit['vo'] = replica['scope'].vo
|
|
304
305
|
self.__conn.send(body=jdumps(resubmit), destination=self.__queue, headers={'appversion': 'rucio', 'resubmitted': '1'})
|
|
305
306
|
METRICS.counter('sent_resubmitted').inc()
|
|
@@ -124,7 +124,7 @@ def __split_rule_select_rses(
|
|
|
124
124
|
weight: int,
|
|
125
125
|
rse_expression: str,
|
|
126
126
|
copies: int,
|
|
127
|
-
|
|
127
|
+
blocklisted_rse_ids: list,
|
|
128
128
|
logger: LoggerFunction,
|
|
129
129
|
) -> tuple[list, bool, bool]:
|
|
130
130
|
"""
|
|
@@ -138,7 +138,7 @@ def __split_rule_select_rses(
|
|
|
138
138
|
:param weight: The weight of the rule.
|
|
139
139
|
:param rse_expression: The RSE expression of the rule.
|
|
140
140
|
:param copies: The number of copies.
|
|
141
|
-
:param
|
|
141
|
+
:param blocklisted_rse_ids: The list of blocklisted rse_ids.
|
|
142
142
|
:param logger: The logger.
|
|
143
143
|
:return: A tuple with list selected_rses, and 2 booleans create_rule, wont_reevaluate.
|
|
144
144
|
"""
|
|
@@ -172,7 +172,7 @@ def __split_rule_select_rses(
|
|
|
172
172
|
copies=copies,
|
|
173
173
|
size=0,
|
|
174
174
|
preferred_rses=preferred_rses,
|
|
175
|
-
blocklist=
|
|
175
|
+
blocklist=blocklisted_rse_ids,
|
|
176
176
|
)
|
|
177
177
|
wont_reevaluate = True
|
|
178
178
|
break
|
|
@@ -184,26 +184,22 @@ def __split_rule_select_rses(
|
|
|
184
184
|
) as error:
|
|
185
185
|
logger(
|
|
186
186
|
logging.WARNING,
|
|
187
|
-
'Problem getting RSEs for subscription "%s" for account %s : %s. %s'
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
'Try including blocklisted sites' if attempt == 0 else 'Skipping rule creation.'
|
|
193
|
-
),
|
|
187
|
+
'Problem getting RSEs for subscription "%s" for account %s : %s. %s',
|
|
188
|
+
subscription_name,
|
|
189
|
+
account,
|
|
190
|
+
str(error),
|
|
191
|
+
'Try including blocklisted sites' if attempt == 0 else 'Skipping rule creation.'
|
|
194
192
|
)
|
|
195
193
|
# Now including the blocklisted sites
|
|
196
|
-
|
|
194
|
+
blocklisted_rse_ids = []
|
|
197
195
|
METRICS.counter(name="addnewrule.errortype.{exception}").labels(exception=str(error.__class__.__name__)).inc()
|
|
198
196
|
wont_reevaluate = True
|
|
199
197
|
except Exception as error:
|
|
200
198
|
logger(
|
|
201
199
|
logging.ERROR,
|
|
202
|
-
"Problem resolving RSE expression %s : %s"
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
str(error),
|
|
206
|
-
)
|
|
200
|
+
"Problem resolving RSE expression %s : %s",
|
|
201
|
+
rse_expression,
|
|
202
|
+
str(error),
|
|
207
203
|
)
|
|
208
204
|
if len(preferred_rses) - len(preferred_unmatched) >= copies:
|
|
209
205
|
create_rule = False
|
|
@@ -242,6 +238,7 @@ def get_subscriptions(logger: LoggerFunction = logging.log) -> list[dict]:
|
|
|
242
238
|
break
|
|
243
239
|
if rule.get("copies") == "*":
|
|
244
240
|
rule["copies"] = len(list_rses_from_expression)
|
|
241
|
+
rule["wildcard"] = True
|
|
245
242
|
overwrite_rules = True
|
|
246
243
|
if skip_sub:
|
|
247
244
|
continue
|
|
@@ -272,7 +269,7 @@ def get_subscriptions(logger: LoggerFunction = logging.log) -> list[dict]:
|
|
|
272
269
|
subscriptions.extend(sub_dict[priority])
|
|
273
270
|
logger(logging.INFO, "%i active subscriptions", len(subscriptions))
|
|
274
271
|
except SubscriptionNotFound as error:
|
|
275
|
-
logger(logging.WARNING, "No subscriptions defined: %s"
|
|
272
|
+
logger(logging.WARNING, "No subscriptions defined: %s", (str(error)))
|
|
276
273
|
return []
|
|
277
274
|
except TypeError as error:
|
|
278
275
|
logger(
|
|
@@ -307,7 +304,7 @@ def __is_matching_subscription(
|
|
|
307
304
|
try:
|
|
308
305
|
filter_string = loads(subscription["filter"])
|
|
309
306
|
except ValueError as error:
|
|
310
|
-
logging.error("%s : Subscription will be skipped"
|
|
307
|
+
logging.error("%s : Subscription will be skipped", error)
|
|
311
308
|
return False
|
|
312
309
|
# Loop over the keys of filter_string for subscription
|
|
313
310
|
for key in filter_string:
|
|
@@ -399,7 +396,7 @@ def select_algorithm(
|
|
|
399
396
|
selected_rses = {}
|
|
400
397
|
for rule_id in rule_ids:
|
|
401
398
|
rule = get_rule(rule_id)
|
|
402
|
-
logging.
|
|
399
|
+
logger(logging.DEBUG, "In select_algorithm, %s", str(rule))
|
|
403
400
|
rse = rule["rse_expression"]
|
|
404
401
|
vo = rule["account"].vo
|
|
405
402
|
if rse_exists(rse, vo=vo):
|
|
@@ -439,7 +436,7 @@ def select_algorithm(
|
|
|
439
436
|
weight=rule.get("weight"),
|
|
440
437
|
rse_expression=rse_expression,
|
|
441
438
|
copies=rule.get('copies'),
|
|
442
|
-
|
|
439
|
+
blocklisted_rse_ids=params['blocklisted_rse_ids'],
|
|
443
440
|
logger=logger,
|
|
444
441
|
)
|
|
445
442
|
dict_selected_rses = {}
|
|
@@ -487,7 +484,8 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
|
|
|
487
484
|
|
|
488
485
|
worker_number, total_workers, logger = heartbeat_handler.live()
|
|
489
486
|
stopwatch = Stopwatch()
|
|
490
|
-
|
|
487
|
+
block_listed = {rse['rse']: rse["id"] for rse in list_rses({"availability_write": False})}
|
|
488
|
+
blocklisted_rse_ids = list(block_listed.values())
|
|
491
489
|
identifiers = []
|
|
492
490
|
# List all the active subscriptions
|
|
493
491
|
subscriptions = get_subscriptions(logger=logger)
|
|
@@ -535,6 +533,7 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
|
|
|
535
533
|
# Get all the rule and subscription parameters
|
|
536
534
|
rule_dict = __get_rule_dict(rule_dict, subscription)
|
|
537
535
|
weight = rule_dict.get("weight", None)
|
|
536
|
+
ignore_availability = rule_dict.get("ignore_availability", False)
|
|
538
537
|
source_replica_expression = rule_dict.get(
|
|
539
538
|
"source_replica_expression", None
|
|
540
539
|
)
|
|
@@ -551,7 +550,7 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
|
|
|
551
550
|
params['rse_expression'] = rule_dict.get("rse_expression")
|
|
552
551
|
params['subscription_id'] = subscription["id"]
|
|
553
552
|
params['subscription_name'] = subscription["name"]
|
|
554
|
-
params['
|
|
553
|
+
params['blocklisted_rse_ids'] = blocklisted_rse_ids
|
|
555
554
|
if rule_dict.get("associated_site_idx", None):
|
|
556
555
|
params["associated_site_idx"] = rule_dict.get(
|
|
557
556
|
"associated_site_idx", None
|
|
@@ -583,7 +582,7 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
|
|
|
583
582
|
weight=weight,
|
|
584
583
|
rse_expression=rule_dict.get("rse_expression"),
|
|
585
584
|
copies=copies,
|
|
586
|
-
|
|
585
|
+
blocklisted_rse_ids=blocklisted_rse_ids,
|
|
587
586
|
logger=logger,
|
|
588
587
|
)
|
|
589
588
|
copies = 1
|
|
@@ -595,20 +594,26 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
|
|
|
595
594
|
nb_rule = 0
|
|
596
595
|
# Try to create the rule
|
|
597
596
|
logger(logging.DEBUG, 'selected_rses : %s' % selected_rses)
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
source_replica_expression
|
|
603
|
-
|
|
604
|
-
None,
|
|
605
|
-
)
|
|
606
|
-
weight = selected_rses[rse].get("weight", None)
|
|
607
|
-
logger(
|
|
608
|
-
logging.INFO,
|
|
609
|
-
"Will insert one rule for %s:%s on %s"
|
|
610
|
-
% (did["scope"], did["name"], rse),
|
|
597
|
+
for rse in selected_rses:
|
|
598
|
+
if isinstance(selected_rses, dict):
|
|
599
|
+
# selected_rses is a dictionary only when split_rule is True or for chained subscriptions
|
|
600
|
+
source_replica_expression = selected_rses[rse].get(
|
|
601
|
+
"source_replica_expression",
|
|
602
|
+
None,
|
|
611
603
|
)
|
|
604
|
+
weight = selected_rses[rse].get("weight", None)
|
|
605
|
+
logger(
|
|
606
|
+
logging.INFO,
|
|
607
|
+
"Will insert one rule for %s:%s on %s",
|
|
608
|
+
did["scope"], did["name"], rse,
|
|
609
|
+
)
|
|
610
|
+
if rse in block_listed and rule_dict.get("wildcard"):
|
|
611
|
+
if ignore_availability:
|
|
612
|
+
logger(logging.WARNING, "RSE %s is unavailable, but wildcard number of copies is used with ignore_availability option. Creating a rule", rse)
|
|
613
|
+
else:
|
|
614
|
+
logger(logging.INFO, "RSE %s is unavailable and wildcard number of copies is used. Skipping rule creation", rse)
|
|
615
|
+
continue
|
|
616
|
+
try:
|
|
612
617
|
rule_ids = add_rule(
|
|
613
618
|
dids=[
|
|
614
619
|
{
|
|
@@ -627,9 +632,7 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
|
|
|
627
632
|
source_replica_expression=source_replica_expression,
|
|
628
633
|
activity=rule_dict.get("activity"),
|
|
629
634
|
purge_replicas=rule_dict.get("purge_replicas", False),
|
|
630
|
-
ignore_availability=
|
|
631
|
-
"ignore_availability", None
|
|
632
|
-
),
|
|
635
|
+
ignore_availability=ignore_availability,
|
|
633
636
|
comment=rule_dict.get("comment"),
|
|
634
637
|
delay_injection=rule_dict.get("delay_injection"),
|
|
635
638
|
)
|
|
@@ -640,41 +643,40 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
|
|
|
640
643
|
if split_rule:
|
|
641
644
|
success = True
|
|
642
645
|
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
646
|
+
except (
|
|
647
|
+
InvalidReplicationRule,
|
|
648
|
+
InvalidRuleWeight,
|
|
649
|
+
InvalidRSEExpression,
|
|
650
|
+
StagingAreaRuleRequiresLifetime,
|
|
651
|
+
DuplicateRule,
|
|
652
|
+
) as error:
|
|
653
|
+
# Errors that won't be retried
|
|
654
|
+
success = True
|
|
655
|
+
logger(logging.ERROR, str(error))
|
|
656
|
+
METRICS.counter("addnewrule.errortype.{exception}").labels(exception=str(error.__class__.__name__)).inc()
|
|
657
|
+
except Exception:
|
|
658
|
+
# Errors that will be retried
|
|
659
|
+
METRICS.counter("addnewrule.errortype.{exception}").labels(exception="unknown").inc()
|
|
660
|
+
logger(logging.ERROR, "Unexpected error", exc_info=True)
|
|
661
|
+
|
|
662
|
+
METRICS.counter("addnewrule.done").inc(nb_rule)
|
|
663
|
+
METRICS.counter("addnewrule.activity.{activity}").labels(activity="".join(rule_dict.get("activity").split())).inc(nb_rule)
|
|
664
|
+
success = True
|
|
661
665
|
|
|
662
666
|
did_success = did_success and success
|
|
663
667
|
if not success:
|
|
664
668
|
logger(
|
|
665
669
|
logging.ERROR,
|
|
666
|
-
"Rule for %s:%s on %s cannot be inserted"
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
rule_dict.get("rse_expression"),
|
|
671
|
-
),
|
|
670
|
+
"Rule for %s:%s on %s cannot be inserted",
|
|
671
|
+
did["scope"],
|
|
672
|
+
did["name"],
|
|
673
|
+
rule_dict.get("rse_expression"),
|
|
672
674
|
)
|
|
673
675
|
else:
|
|
674
676
|
logger(
|
|
675
677
|
logging.INFO,
|
|
676
|
-
"%s rule(s) inserted in %f seconds"
|
|
677
|
-
|
|
678
|
+
"%s rule(s) inserted in %f seconds",
|
|
679
|
+
str(nb_rule), time.time() - stime,
|
|
678
680
|
)
|
|
679
681
|
|
|
680
682
|
if did_success:
|
|
@@ -697,7 +699,7 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
|
|
|
697
699
|
flag_stopwatch = Stopwatch()
|
|
698
700
|
for identifier in chunks(identifiers, 100):
|
|
699
701
|
set_new_dids(identifier, None)
|
|
700
|
-
logger(logging.DEBUG, "Time to set the new flag : %f"
|
|
702
|
+
logger(logging.DEBUG, "Time to set the new flag : %f", flag_stopwatch.elapsed)
|
|
701
703
|
|
|
702
704
|
stopwatch.stop()
|
|
703
705
|
|
|
@@ -709,9 +711,9 @@ def run_once(heartbeat_handler: "HeartbeatHandler", bulk: int, **_kwargs) -> boo
|
|
|
709
711
|
)
|
|
710
712
|
logger(
|
|
711
713
|
logging.INFO,
|
|
712
|
-
"It took %f seconds to process %i DIDs"
|
|
714
|
+
"It took %f seconds to process %i DIDs", stopwatch.elapsed, len(identifiers),
|
|
713
715
|
)
|
|
714
|
-
logger(logging.DEBUG, "DIDs processed : %s"
|
|
716
|
+
logger(logging.DEBUG, "DIDs processed : %s", str(identifiers))
|
|
715
717
|
METRICS.counter(name="transmogrifier.job.done").inc(1)
|
|
716
718
|
METRICS.timer("job.duration").observe(stopwatch.elapsed)
|
|
717
719
|
must_sleep = True
|
|
@@ -29,6 +29,7 @@ from typing import TYPE_CHECKING
|
|
|
29
29
|
from sqlalchemy.exc import DatabaseError
|
|
30
30
|
|
|
31
31
|
import rucio.db.sqla.util
|
|
32
|
+
from rucio.common.constants import DEFAULT_VO
|
|
32
33
|
from rucio.common.exception import DatabaseException, RuleNotFound, UnsupportedOperation
|
|
33
34
|
from rucio.common.logging import setup_logging
|
|
34
35
|
from rucio.common.types import InternalAccount
|
|
@@ -90,7 +91,7 @@ def run_once(paused_dids: dict[tuple, datetime], chunk_size: int, heartbeat_hand
|
|
|
90
91
|
_, _, logger = heartbeat_handler.live()
|
|
91
92
|
try:
|
|
92
93
|
logger(logging.INFO, 'Receive %s dids to delete', len(chunk))
|
|
93
|
-
delete_dids(dids=chunk, account=InternalAccount('root', vo=
|
|
94
|
+
delete_dids(dids=chunk, account=InternalAccount('root', vo=DEFAULT_VO), expire_rules=True)
|
|
94
95
|
logger(logging.INFO, 'Delete %s dids', len(chunk))
|
|
95
96
|
METRICS.counter(name='undertaker.delete_dids').inc(len(chunk))
|
|
96
97
|
except RuleNotFound as error:
|
rucio/db/sqla/models.py
CHANGED
|
@@ -29,7 +29,7 @@ from sqlalchemy.types import LargeBinary
|
|
|
29
29
|
# and it must be renamed to avoid conflicts with the policy package schema modules
|
|
30
30
|
from rucio.common import schema as common_schema
|
|
31
31
|
from rucio.common import utils
|
|
32
|
-
from rucio.common.constants import TransferLimitDirection
|
|
32
|
+
from rucio.common.constants import DEFAULT_VO, TransferLimitDirection
|
|
33
33
|
from rucio.common.types import InternalAccount, InternalScope # noqa: TCH001 (types are needed by SQLAlchemy)
|
|
34
34
|
from rucio.db.sqla.constants import (
|
|
35
35
|
AccountStatus,
|
|
@@ -776,7 +776,7 @@ class RSE(BASE, SoftModelBase):
|
|
|
776
776
|
__tablename__ = 'rses'
|
|
777
777
|
id: Mapped[str] = mapped_column(GUID(), default=utils.generate_uuid)
|
|
778
778
|
rse: Mapped[str] = mapped_column(String(255))
|
|
779
|
-
vo: Mapped[str] = mapped_column(String(3), nullable=False, server_default=
|
|
779
|
+
vo: Mapped[str] = mapped_column(String(3), nullable=False, server_default=DEFAULT_VO)
|
|
780
780
|
rse_type: Mapped[RSEType] = mapped_column(Enum(RSEType, name='RSES_TYPE_CHK',
|
|
781
781
|
create_constraint=True,
|
|
782
782
|
values_callable=lambda obj: [e.value for e in obj]),
|
rucio/db/sqla/util.py
CHANGED
|
@@ -33,6 +33,7 @@ from sqlalchemy.sql.expression import select, text
|
|
|
33
33
|
from rucio import alembicrevision
|
|
34
34
|
from rucio.common.cache import MemcacheRegion
|
|
35
35
|
from rucio.common.config import config_get, config_get_list
|
|
36
|
+
from rucio.common.constants import DEFAULT_VO
|
|
36
37
|
from rucio.common.schema import get_schema_value
|
|
37
38
|
from rucio.common.types import InternalAccount, LoggerFunction
|
|
38
39
|
from rucio.common.utils import generate_uuid
|
|
@@ -136,7 +137,7 @@ def create_base_vo() -> None:
|
|
|
136
137
|
|
|
137
138
|
session_scoped = get_session()
|
|
138
139
|
|
|
139
|
-
vo = models.VO(vo=
|
|
140
|
+
vo = models.VO(vo=DEFAULT_VO, description='Default base VO', email='N/A')
|
|
140
141
|
with session_scoped() as s:
|
|
141
142
|
with s.begin():
|
|
142
143
|
s.add_all([vo])
|
|
@@ -172,7 +173,7 @@ def create_root_account() -> None:
|
|
|
172
173
|
else:
|
|
173
174
|
access = 'root'
|
|
174
175
|
|
|
175
|
-
account = models.Account(account=InternalAccount(access,
|
|
176
|
+
account = models.Account(account=InternalAccount(access, DEFAULT_VO), account_type=AccountType.SERVICE, status=AccountStatus.ACTIVE)
|
|
176
177
|
|
|
177
178
|
salt = urandom(255)
|
|
178
179
|
salted_password = salt + up_pwd.encode()
|
rucio/gateway/account.py
CHANGED
|
@@ -17,6 +17,7 @@ from typing import TYPE_CHECKING, Any, Optional
|
|
|
17
17
|
import rucio.common.exception
|
|
18
18
|
import rucio.core.identity
|
|
19
19
|
import rucio.gateway.permission
|
|
20
|
+
from rucio.common.constants import DEFAULT_VO
|
|
20
21
|
from rucio.common.schema import validate_schema
|
|
21
22
|
from rucio.common.types import InternalAccount
|
|
22
23
|
from rucio.common.utils import gateway_update_return_dict
|
|
@@ -37,7 +38,7 @@ def add_account(
|
|
|
37
38
|
type_: str,
|
|
38
39
|
email: str,
|
|
39
40
|
issuer: str,
|
|
40
|
-
vo: str =
|
|
41
|
+
vo: str = DEFAULT_VO,
|
|
41
42
|
) -> None:
|
|
42
43
|
"""
|
|
43
44
|
Creates an account with the provided account name, contact information, etc.
|
|
@@ -68,7 +69,7 @@ def add_account(
|
|
|
68
69
|
def del_account(
|
|
69
70
|
account: str,
|
|
70
71
|
issuer: str,
|
|
71
|
-
vo: str =
|
|
72
|
+
vo: str = DEFAULT_VO,
|
|
72
73
|
) -> None:
|
|
73
74
|
"""
|
|
74
75
|
Disables an account with the provided account name.
|
|
@@ -91,7 +92,7 @@ def del_account(
|
|
|
91
92
|
|
|
92
93
|
def get_account_info(
|
|
93
94
|
account: str,
|
|
94
|
-
vo: str =
|
|
95
|
+
vo: str = DEFAULT_VO,
|
|
95
96
|
) -> "Account":
|
|
96
97
|
"""
|
|
97
98
|
Returns the info like the statistics information associated to an account_core.
|
|
@@ -115,7 +116,7 @@ def update_account(
|
|
|
115
116
|
key: str,
|
|
116
117
|
value: Any,
|
|
117
118
|
issuer: str = 'root',
|
|
118
|
-
vo: str =
|
|
119
|
+
vo: str = DEFAULT_VO,
|
|
119
120
|
) -> None:
|
|
120
121
|
""" Update a property of an account_core.
|
|
121
122
|
|
|
@@ -138,7 +139,7 @@ def update_account(
|
|
|
138
139
|
return account_core.update_account(internal_account, key, value, session=session)
|
|
139
140
|
|
|
140
141
|
|
|
141
|
-
def list_accounts(filter_: Optional[dict[str, Any]] = None, vo: str =
|
|
142
|
+
def list_accounts(filter_: Optional[dict[str, Any]] = None, vo: str = DEFAULT_VO) -> 'Iterator[dict[str, Any]]':
|
|
142
143
|
"""
|
|
143
144
|
Lists all the Rucio account names.
|
|
144
145
|
|
|
@@ -164,7 +165,7 @@ def list_accounts(filter_: Optional[dict[str, Any]] = None, vo: str = 'def') ->
|
|
|
164
165
|
|
|
165
166
|
def account_exists(
|
|
166
167
|
account: str,
|
|
167
|
-
vo: str =
|
|
168
|
+
vo: str = DEFAULT_VO,
|
|
168
169
|
) -> bool:
|
|
169
170
|
"""
|
|
170
171
|
Checks to see if account exists. This procedure does not check it's status.
|
|
@@ -183,7 +184,7 @@ def account_exists(
|
|
|
183
184
|
|
|
184
185
|
def list_identities(
|
|
185
186
|
account: str,
|
|
186
|
-
vo: str =
|
|
187
|
+
vo: str = DEFAULT_VO,
|
|
187
188
|
) -> list["IdentityDict"]:
|
|
188
189
|
"""
|
|
189
190
|
List all identities on an account_core.
|
|
@@ -201,7 +202,7 @@ def list_identities(
|
|
|
201
202
|
|
|
202
203
|
def list_account_attributes(
|
|
203
204
|
account: str,
|
|
204
|
-
vo: str =
|
|
205
|
+
vo: str = DEFAULT_VO,
|
|
205
206
|
) -> list["AccountAttributesDict"]:
|
|
206
207
|
"""
|
|
207
208
|
Returns all the attributes for the given account.
|
|
@@ -222,7 +223,7 @@ def add_account_attribute(
|
|
|
222
223
|
value: Any,
|
|
223
224
|
account: str,
|
|
224
225
|
issuer: str,
|
|
225
|
-
vo: str =
|
|
226
|
+
vo: str = DEFAULT_VO,
|
|
226
227
|
) -> None:
|
|
227
228
|
"""
|
|
228
229
|
Add an attribute to an account.
|
|
@@ -252,7 +253,7 @@ def del_account_attribute(
|
|
|
252
253
|
key: str,
|
|
253
254
|
account: str,
|
|
254
255
|
issuer: str,
|
|
255
|
-
vo: str =
|
|
256
|
+
vo: str = DEFAULT_VO,
|
|
256
257
|
) -> None:
|
|
257
258
|
"""
|
|
258
259
|
Delete an attribute to an account.
|
|
@@ -278,7 +279,7 @@ def get_usage(
|
|
|
278
279
|
rse: str,
|
|
279
280
|
account: str,
|
|
280
281
|
issuer: str,
|
|
281
|
-
vo: str =
|
|
282
|
+
vo: str = DEFAULT_VO,
|
|
282
283
|
) -> "UsageDict":
|
|
283
284
|
"""
|
|
284
285
|
Returns current values of the specified counter, or raises CounterNotFound if the counter does not exist.
|
|
@@ -301,7 +302,7 @@ def get_usage_history(
|
|
|
301
302
|
rse: str,
|
|
302
303
|
account: str,
|
|
303
304
|
issuer: str,
|
|
304
|
-
vo: str =
|
|
305
|
+
vo: str = DEFAULT_VO,
|
|
305
306
|
) -> list["UsageDict"]:
|
|
306
307
|
"""
|
|
307
308
|
Returns historical values of the specified counter, or raises CounterNotFound if the counter does not exist.
|