rucio 37.3.0__py3-none-any.whl → 37.5.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.

Files changed (128) hide show
  1. rucio/cli/rule.py +1 -1
  2. rucio/client/accountclient.py +205 -60
  3. rucio/client/accountlimitclient.py +84 -25
  4. rucio/client/baseclient.py +85 -48
  5. rucio/client/client.py +49 -41
  6. rucio/client/configclient.py +36 -13
  7. rucio/client/credentialclient.py +16 -6
  8. rucio/client/didclient.py +321 -133
  9. rucio/client/diracclient.py +13 -6
  10. rucio/client/downloadclient.py +435 -165
  11. rucio/client/exportclient.py +8 -2
  12. rucio/client/fileclient.py +10 -3
  13. rucio/client/importclient.py +4 -1
  14. rucio/client/lifetimeclient.py +48 -31
  15. rucio/client/lockclient.py +22 -7
  16. rucio/client/metaconventionsclient.py +59 -21
  17. rucio/client/pingclient.py +3 -1
  18. rucio/client/replicaclient.py +213 -96
  19. rucio/client/requestclient.py +124 -16
  20. rucio/client/rseclient.py +385 -160
  21. rucio/client/ruleclient.py +147 -51
  22. rucio/client/scopeclient.py +35 -10
  23. rucio/client/subscriptionclient.py +60 -27
  24. rucio/client/touchclient.py +16 -7
  25. rucio/common/constants.py +14 -17
  26. rucio/common/utils.py +18 -2
  27. rucio/core/permission/generic.py +40 -1
  28. rucio/core/replica.py +6 -6
  29. rucio/core/request.py +2 -2
  30. rucio/core/rule.py +5 -3
  31. rucio/core/transfer.py +4 -5
  32. rucio/daemons/conveyor/throttler.py +2 -1
  33. rucio/daemons/judge/evaluator.py +1 -1
  34. rucio/db/sqla/constants.py +3 -3
  35. rucio/db/sqla/migrate_repo/versions/13d4f70c66a9_introduce_transfer_limits.py +1 -1
  36. rucio/db/sqla/models.py +1 -1
  37. rucio/gateway/replica.py +129 -41
  38. rucio/gateway/request.py +177 -103
  39. rucio/gateway/subscription.py +90 -108
  40. rucio/rse/rsemanager.py +2 -2
  41. rucio/vcsversion.py +3 -3
  42. rucio/web/rest/flaskapi/v1/accountlimits.py +22 -22
  43. rucio/web/rest/flaskapi/v1/accounts.py +157 -157
  44. rucio/web/rest/flaskapi/v1/archives.py +10 -10
  45. rucio/web/rest/flaskapi/v1/auth.py +106 -106
  46. rucio/web/rest/flaskapi/v1/config.py +37 -37
  47. rucio/web/rest/flaskapi/v1/credentials.py +25 -25
  48. rucio/web/rest/flaskapi/v1/dids.py +381 -381
  49. rucio/web/rest/flaskapi/v1/dirac.py +8 -8
  50. rucio/web/rest/flaskapi/v1/export.py +6 -6
  51. rucio/web/rest/flaskapi/v1/heartbeats.py +14 -14
  52. rucio/web/rest/flaskapi/v1/identities.py +25 -25
  53. rucio/web/rest/flaskapi/v1/import.py +19 -19
  54. rucio/web/rest/flaskapi/v1/lifetime_exceptions.py +54 -54
  55. rucio/web/rest/flaskapi/v1/locks.py +60 -60
  56. rucio/web/rest/flaskapi/v1/meta_conventions.py +29 -29
  57. rucio/web/rest/flaskapi/v1/nongrid_traces.py +4 -4
  58. rucio/web/rest/flaskapi/v1/ping.py +4 -4
  59. rucio/web/rest/flaskapi/v1/redirect.py +17 -17
  60. rucio/web/rest/flaskapi/v1/replicas.py +282 -282
  61. rucio/web/rest/flaskapi/v1/requests.py +424 -229
  62. rucio/web/rest/flaskapi/v1/rses.py +427 -427
  63. rucio/web/rest/flaskapi/v1/rules.py +129 -129
  64. rucio/web/rest/flaskapi/v1/scopes.py +21 -21
  65. rucio/web/rest/flaskapi/v1/subscriptions.py +122 -122
  66. rucio/web/rest/flaskapi/v1/traces.py +18 -18
  67. rucio/web/rest/flaskapi/v1/vos.py +32 -32
  68. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/etc/rucio.cfg.template +0 -1
  69. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/etc/rucio_multi_vo.cfg.template +0 -1
  70. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/requirements.server.txt +1 -1
  71. {rucio-37.3.0.dist-info → rucio-37.5.0.dist-info}/METADATA +1 -1
  72. {rucio-37.3.0.dist-info → rucio-37.5.0.dist-info}/RECORD +128 -128
  73. {rucio-37.3.0.dist-info → rucio-37.5.0.dist-info}/WHEEL +1 -1
  74. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/etc/alembic.ini.template +0 -0
  75. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/etc/alembic_offline.ini.template +0 -0
  76. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/etc/globus-config.yml.template +0 -0
  77. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/etc/ldap.cfg.template +0 -0
  78. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
  79. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
  80. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
  81. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
  82. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
  83. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
  84. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
  85. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/etc/rucio.cfg.atlas.client.template +0 -0
  86. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/tools/bootstrap.py +0 -0
  87. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/tools/merge_rucio_configs.py +0 -0
  88. {rucio-37.3.0.data → rucio-37.5.0.data}/data/rucio/tools/reset_database.py +0 -0
  89. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio +0 -0
  90. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-abacus-account +0 -0
  91. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-abacus-collection-replica +0 -0
  92. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-abacus-rse +0 -0
  93. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-admin +0 -0
  94. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-atropos +0 -0
  95. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-auditor +0 -0
  96. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-automatix +0 -0
  97. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-bb8 +0 -0
  98. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-cache-client +0 -0
  99. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-cache-consumer +0 -0
  100. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-conveyor-finisher +0 -0
  101. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-conveyor-poller +0 -0
  102. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-conveyor-preparer +0 -0
  103. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-conveyor-receiver +0 -0
  104. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-conveyor-stager +0 -0
  105. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-conveyor-submitter +0 -0
  106. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-conveyor-throttler +0 -0
  107. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-dark-reaper +0 -0
  108. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-dumper +0 -0
  109. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-follower +0 -0
  110. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-hermes +0 -0
  111. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-judge-cleaner +0 -0
  112. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-judge-evaluator +0 -0
  113. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-judge-injector +0 -0
  114. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-judge-repairer +0 -0
  115. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-kronos +0 -0
  116. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-minos +0 -0
  117. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-minos-temporary-expiration +0 -0
  118. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-necromancer +0 -0
  119. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-oauth-manager +0 -0
  120. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-reaper +0 -0
  121. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-replica-recoverer +0 -0
  122. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-rse-decommissioner +0 -0
  123. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-storage-consistency-actions +0 -0
  124. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-transmogrifier +0 -0
  125. {rucio-37.3.0.data → rucio-37.5.0.data}/scripts/rucio-undertaker +0 -0
  126. {rucio-37.3.0.dist-info → rucio-37.5.0.dist-info}/licenses/AUTHORS.rst +0 -0
  127. {rucio-37.3.0.dist-info → rucio-37.5.0.dist-info}/licenses/LICENSE +0 -0
  128. {rucio-37.3.0.dist-info → rucio-37.5.0.dist-info}/top_level.txt +0 -0
@@ -13,18 +13,19 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import json
16
- from typing import TYPE_CHECKING
16
+ from typing import TYPE_CHECKING, Union, cast
17
17
 
18
18
  import flask
19
19
  from flask import Flask, Response
20
20
 
21
- from rucio.common.exception import RequestNotFound
21
+ from rucio.common.constants import TransferLimitDirection
22
+ from rucio.common.exception import AccessDenied, RequestNotFound
22
23
  from rucio.common.utils import APIEncoder, render_json
23
24
  from rucio.core.rse import get_rses_with_attribute_value
24
25
  from rucio.db.sqla.constants import RequestState
25
26
  from rucio.gateway import request
26
27
  from rucio.web.rest.flaskapi.authenticated_bp import AuthenticatedBlueprint
27
- from rucio.web.rest.flaskapi.v1.common import ErrorHandlingMethodView, check_accept_header_wrapper_flask, generate_http_error_flask, parse_scope_name, response_headers, try_stream
28
+ from rucio.web.rest.flaskapi.v1.common import ErrorHandlingMethodView, check_accept_header_wrapper_flask, generate_http_error_flask, json_parameters, param_get, parse_scope_name, response_headers, try_stream
28
29
 
29
30
  if TYPE_CHECKING:
30
31
  from collections.abc import Iterator
@@ -38,147 +39,147 @@ class RequestGet(ErrorHandlingMethodView):
38
39
  """
39
40
  ---
40
41
  summary: Get Request
41
- description: Get a request for a given DID to a destination RSE.
42
+ description: "Get a request for a given DID to a destination RSE."
42
43
  tags:
43
44
  - Requests
44
45
  parameters:
45
46
  - name: scope_name
46
47
  in: path
47
- description: Data identifier (scope)/(name).
48
+ description: "Data identifier (scope)/(name)."
48
49
  schema:
49
50
  type: string
50
51
  style: simple
51
52
  - name: rse
52
53
  in: path
53
- description: Destination rse.
54
+ description: "Destination rse."
54
55
  schema:
55
56
  type: string
56
57
  style: simple
57
58
  responses:
58
59
  200:
59
- description: OK
60
+ description: "OK"
60
61
  content:
61
62
  application/json:
62
63
  schema:
63
- description: The request associated with the DID and destination RSE.
64
+ description: "The request associated with the DID and destination RSE."
64
65
  type: object
65
66
  properties:
66
67
  id:
67
- description: The id of the request.
68
+ description: "The id of the request."
68
69
  type: string
69
70
  request_type:
70
- description: The request type.
71
+ description: "The request type."
71
72
  type: string
72
73
  enum: ["T", "U", "D", "I", "O"]
73
74
  scope:
74
- description: The scope of the transfer.
75
+ description: "The scope of the transfer."
75
76
  type: string
76
77
  name:
77
- description: The name of the transfer.
78
+ description: "The name of the transfer."
78
79
  type: string
79
80
  did_type:
80
- description: The did type.
81
+ description: "The did type."
81
82
  type: string
82
83
  dest_rse_id:
83
- description: The destination RSE id.
84
+ description: "The destination RSE id."
84
85
  type: string
85
86
  source_rse_id:
86
- description: The source RSE id.
87
+ description: "The source RSE id."
87
88
  type: string
88
89
  attributes:
89
- description: All attributes associated with the request.
90
+ description: "All attributes associated with the request."
90
91
  type: string
91
92
  state:
92
- description: The state of the request.
93
+ description: "The state of the request."
93
94
  type: string
94
95
  enum: ["Q", "G", "S", "F", "D", "L", "N", "O", "A", "M", "U", "W", "P"]
95
96
  external_id:
96
- description: External id of the request.
97
+ description: "External id of the request."
97
98
  type: string
98
99
  external_host:
99
- description: External host of the request.
100
+ description: "External host of the request."
100
101
  type: string
101
102
  retry_count:
102
- description: The numbers of attempted retires.
103
+ description: "The numbers of attempted retries."
103
104
  type: integer
104
105
  err_msg:
105
- description: An error message if one occurred.
106
+ description: "An error message if one occurred."
106
107
  type: string
107
108
  previous_attempt_id:
108
- description: The id of the previous attempt.
109
+ description: "The id of the previous attempt."
109
110
  type: string
110
111
  rule_id:
111
- description: The id of the associated replication rule.
112
+ description: "The id of the associated replication rule."
112
113
  type: string
113
114
  activity:
114
- description: The activity of the request.
115
+ description: "The activity of the request."
115
116
  type: string
116
117
  bytes:
117
- description: The size of the did in bytes.
118
+ description: "The size of the did in bytes."
118
119
  type: integer
119
120
  md5:
120
- description: The md5 checksum of the did to transfer.
121
+ description: "The md5 checksum of the did to transfer."
121
122
  type: string
122
123
  adler32:
123
- description: The adler32 checksum of the did to transfer.
124
+ description: "The adler32 checksum of the did to transfer."
124
125
  type: string
125
126
  dest_url:
126
- description: The destination url.
127
+ description: "The destination url."
127
128
  type: string
128
129
  submitted_at:
129
- description: The time the request got submitted.
130
+ description: "The time the request got submitted."
130
131
  type: string
131
132
  started_at:
132
- description: The time the request got started.
133
+ description: "The time the request got started."
133
134
  type: string
134
135
  transferred_at:
135
- description: The time the request got transferred.
136
+ description: "The time the request got transferred."
136
137
  type: string
137
138
  estimated_at:
138
- description: The time the request got estimated.
139
+ description: "The time the request got estimated."
139
140
  type: string
140
141
  submitter_id:
141
- description: The id of the submitter.
142
+ description: "The id of the submitter."
142
143
  type: string
143
144
  estimated_stated_at:
144
- description: The estimation of the started at value.
145
+ description: "The estimation of the started at value."
145
146
  type: string
146
147
  estimated_transferred_at:
147
- description: The estimation of the transferred at value.
148
+ description: "The estimation of the transferred at value."
148
149
  type: string
149
150
  staging_started_at:
150
- description: The time the staging got started.
151
+ description: "The time the staging got started."
151
152
  type: string
152
153
  staging_finished_at:
153
- description: The time the staging got finished.
154
+ description: "The time the staging got finished."
154
155
  type: string
155
156
  account:
156
- description: The account which issued the request.
157
+ description: "The account which issued the request."
157
158
  type: string
158
159
  requested_at:
159
- description: The time the request got requested.
160
+ description: "The time the request got requested."
160
161
  type: string
161
162
  priority:
162
- description: The priority of the request.
163
+ description: "The priority of the request."
163
164
  type: integer
164
165
  transfertool:
165
- description: The transfertool used.
166
+ description: "The transfertool used."
166
167
  type: string
167
168
  source_rse:
168
- description: The name of the source RSE.
169
+ description: "The name of the source RSE."
169
170
  type: string
170
171
  dest_rse:
171
- description: The name of the destination RSE.
172
+ description: "The name of the destination RSE."
172
173
  type: string
173
174
  401:
174
- description: Invalid Auth Token
175
+ description: "Invalid Auth Token"
175
176
  404:
176
- description: Not found
177
+ description: "Not found"
177
178
  406:
178
- description: Not acceptable
179
+ description: "Not acceptable"
179
180
  """
180
181
  try:
181
- scope, name = parse_scope_name(scope_name, flask.request.environ.get('vo'))
182
+ scope, name = parse_scope_name(scope_name, flask.request.environ['vo'])
182
183
  except ValueError as error:
183
184
  return generate_http_error_flask(400, error)
184
185
 
@@ -187,8 +188,8 @@ class RequestGet(ErrorHandlingMethodView):
187
188
  scope=scope,
188
189
  name=name,
189
190
  rse=rse,
190
- issuer=flask.request.environ.get('issuer'),
191
- vo=flask.request.environ.get('vo'),
191
+ issuer=flask.request.environ['issuer'],
192
+ vo=flask.request.environ['vo'],
192
193
  )
193
194
  return Response(json.dumps(request_data, cls=APIEncoder), content_type='application/json')
194
195
  except RequestNotFound as error:
@@ -203,147 +204,147 @@ class RequestHistoryGet(ErrorHandlingMethodView):
203
204
  """
204
205
  ---
205
206
  summary: Get Historical Request
206
- description: List a historical request for a given DID to a destination RSE.
207
+ description: "List a historical request for a given DID to a destination RSE."
207
208
  tags:
208
209
  - Requests
209
210
  parameters:
210
211
  - name: scope_name
211
212
  in: path
212
- description: Data identifier (scope)/(name).
213
+ description: "Data identifier (scope)/(name)."
213
214
  schema:
214
215
  type: string
215
216
  style: simple
216
217
  - name: rse
217
218
  in: path
218
- description: Destination rse.
219
+ description: "Destination rse."
219
220
  schema:
220
221
  type: string
221
222
  style: simple
222
223
  responses:
223
224
  200:
224
- description: OK
225
+ description: "OK"
225
226
  content:
226
227
  application/json:
227
228
  schema:
228
- description: The request associated with the DID and destination RSE.
229
+ description: "The request associated with the DID and destination RSE."
229
230
  type: object
230
231
  properties:
231
232
  id:
232
- description: The id of the request.
233
+ description: "The id of the request."
233
234
  type: string
234
235
  request_type:
235
- description: The request type.
236
+ description: "The request type."
236
237
  type: string
237
238
  enum: ["T", "U", "D", "I", "O"]
238
239
  scope:
239
- description: The scope of the transfer.
240
+ description: "The scope of the transfer."
240
241
  type: string
241
242
  name:
242
- description: The name of the transfer.
243
+ description: "The name of the transfer."
243
244
  type: string
244
245
  did_type:
245
- description: The did type.
246
+ description: "The did type."
246
247
  type: string
247
248
  dest_rse_id:
248
- description: The destination RSE id.
249
+ description: "The destination RSE id."
249
250
  type: string
250
251
  source_rse_id:
251
- description: The source RSE id.
252
+ description: "The source RSE id."
252
253
  type: string
253
254
  attributes:
254
- description: All attributes associated with the request.
255
+ description: "All attributes associated with the request."
255
256
  type: string
256
257
  state:
257
- description: The state of the request.
258
+ description: "The state of the request."
258
259
  type: string
259
260
  enum: ["Q", "G", "S", "F", "D", "L", "N", "O", "A", "M", "U", "W", "P"]
260
261
  external_id:
261
- description: External id of the request.
262
+ description: "External id of the request."
262
263
  type: string
263
264
  external_host:
264
- description: External host of the request.
265
+ description: "External host of the request."
265
266
  type: string
266
267
  retry_count:
267
- description: The numbers of attempted retires.
268
+ description: "The numbers of attempted retries."
268
269
  type: integer
269
270
  err_msg:
270
- description: An error message if one occurred.
271
+ description: "An error message if one occurred."
271
272
  type: string
272
273
  previous_attempt_id:
273
- description: The id of the previous attempt.
274
+ description: "The id of the previous attempt."
274
275
  type: string
275
276
  rule_id:
276
- description: The id of the associated replication rule.
277
+ description: "The id of the associated replication rule."
277
278
  type: string
278
279
  activity:
279
- description: The activity of the request.
280
+ description: "The activity of the request."
280
281
  type: string
281
282
  bytes:
282
- description: The size of the did in bytes.
283
+ description: "The size of the did in bytes."
283
284
  type: integer
284
285
  md5:
285
- description: The md5 checksum of the did to transfer.
286
+ description: "The md5 checksum of the did to transfer."
286
287
  type: string
287
288
  adler32:
288
- description: The adler32 checksum of the did to transfer.
289
+ description: "The adler32 checksum of the did to transfer."
289
290
  type: string
290
291
  dest_url:
291
- description: The destination url.
292
+ description: "The destination url."
292
293
  type: string
293
294
  submitted_at:
294
- description: The time the request got submitted.
295
+ description: "The time the request got submitted."
295
296
  type: string
296
297
  started_at:
297
- description: The time the request got started.
298
+ description: "The time the request got started."
298
299
  type: string
299
300
  transferred_at:
300
- description: The time the request got transferred.
301
+ description: "The time the request got transferred."
301
302
  type: string
302
303
  estimated_at:
303
- description: The time the request got estimated.
304
+ description: "The time the request got estimated."
304
305
  type: string
305
306
  submitter_id:
306
- description: The id of the submitter.
307
+ description: "The id of the submitter."
307
308
  type: string
308
309
  estimated_stated_at:
309
- description: The estimation of the started at value.
310
+ description: "The estimation of the started at value."
310
311
  type: string
311
312
  estimated_transferred_at:
312
- description: The estimation of the transferred at value.
313
+ description: "The estimation of the transferred at value."
313
314
  type: string
314
315
  staging_started_at:
315
- description: The time the staging got started.
316
+ description: "The time the staging got started."
316
317
  type: string
317
318
  staging_finished_at:
318
- description: The time the staging got finished.
319
+ description: "The time the staging got finished."
319
320
  type: string
320
321
  account:
321
- description: The account which issued the request.
322
+ description: "The account which issued the request."
322
323
  type: string
323
324
  requested_at:
324
- description: The time the request got requested.
325
+ description: "The time the request got requested."
325
326
  type: string
326
327
  priority:
327
- description: The priority of the request.
328
+ description: "The priority of the request."
328
329
  type: integer
329
330
  transfertool:
330
- description: The transfertool used.
331
+ description: "The transfertool used."
331
332
  type: string
332
333
  source_rse:
333
- description: The name of the source RSE.
334
+ description: "The name of the source RSE."
334
335
  type: string
335
336
  dest_rse:
336
- description: The name of the destination RSE.
337
+ description: "The name of the destination RSE."
337
338
  type: string
338
339
  401:
339
- description: Invalid Auth Token
340
+ description: "Invalid Auth Token"
340
341
  404:
341
- description: Not found
342
+ description: "Not found"
342
343
  406:
343
- description: Not acceptable
344
+ description: "Not acceptable"
344
345
  """
345
346
  try:
346
- scope, name = parse_scope_name(scope_name, flask.request.environ.get('vo'))
347
+ scope, name = parse_scope_name(scope_name, flask.request.environ['vo'])
347
348
  except ValueError as error:
348
349
  return generate_http_error_flask(400, error)
349
350
 
@@ -352,8 +353,8 @@ class RequestHistoryGet(ErrorHandlingMethodView):
352
353
  scope=scope,
353
354
  name=name,
354
355
  rse=rse,
355
- issuer=flask.request.environ.get('issuer'),
356
- vo=flask.request.environ.get('vo'),
356
+ issuer=flask.request.environ['issuer'],
357
+ vo=flask.request.environ['vo'],
357
358
  )
358
359
  return Response(json.dumps(request_data, cls=APIEncoder), content_type='application/json')
359
360
  except RequestNotFound as error:
@@ -368,13 +369,13 @@ class RequestList(ErrorHandlingMethodView):
368
369
  """
369
370
  ---
370
371
  summary: List Requests
371
- description: List requests for a given source and destination RSE or site.
372
+ description: "List requests for a given source and destination RSE or site."
372
373
  tags:
373
374
  - Requests
374
375
  parameters:
375
376
  - name: src_rse
376
377
  in: query
377
- description: The source rse.
378
+ description: "The source rse."
378
379
  schema:
379
380
  type: array
380
381
  items:
@@ -383,11 +384,11 @@ class RequestList(ErrorHandlingMethodView):
383
384
  - rse_id
384
385
  properties:
385
386
  rse_id:
386
- description: The id of the rse.
387
+ description: "The id of the rse."
387
388
  type: string
388
389
  - name: dest_rse
389
390
  in: query
390
- description: The destination rse.
391
+ description: "The destination rse."
391
392
  schema:
392
393
  type: array
393
394
  items:
@@ -396,148 +397,148 @@ class RequestList(ErrorHandlingMethodView):
396
397
  - rse_id
397
398
  properties:
398
399
  rse_id:
399
- description: The id of the rse.
400
+ description: "The id of the rse."
400
401
  type: string
401
402
  - name: src_site
402
403
  in: query
403
- description: The source site.
404
+ description: "The source site."
404
405
  schema:
405
406
  type: string
406
407
  - name: dest_site
407
408
  in: query
408
- description: The destination site.
409
+ description: "The destination site."
409
410
  schema:
410
411
  type: string
411
412
  - name: request_states
412
413
  in: query
413
- description: The accepted request states. Delimited by comma.
414
+ description: "The accepted request states. Delimited by comma."
414
415
  schema:
415
416
  type: string
416
417
  responses:
417
418
  200:
418
- description: OK
419
+ description: "OK"
419
420
  content:
420
421
  application/x-json-stream:
421
422
  schema:
422
- description: All requests matching the arguments. Separated by the new line character.
423
+ description: "All requests matching the arguments. Separated by the new line character."
423
424
  type: array
424
425
  items:
425
- description: A request.
426
+ description: "A request."
426
427
  type: object
427
428
  properties:
428
429
  id:
429
- description: The id of the request.
430
+ description: "The id of the request."
430
431
  type: string
431
432
  request_type:
432
- description: The request type.
433
+ description: "The request type."
433
434
  type: string
434
435
  enum: ["T", "U", "D", "I", "O"]
435
436
  scope:
436
- description: The scope of the transfer.
437
+ description: "The scope of the transfer."
437
438
  type: string
438
439
  name:
439
- description: The name of the transfer.
440
+ description: "The name of the transfer."
440
441
  type: string
441
442
  did_type:
442
- description: The did type.
443
+ description: "The did type."
443
444
  type: string
444
445
  dest_rse_id:
445
- description: The destination RSE id.
446
+ description: "The destination RSE id."
446
447
  type: string
447
448
  source_rse_id:
448
- description: The source RSE id.
449
+ description: "The source RSE id."
449
450
  type: string
450
451
  attributes:
451
- description: All attributes associated with the request.
452
+ description: "All attributes associated with the request."
452
453
  type: string
453
454
  state:
454
- description: The state of the request.
455
+ description: "The state of the request."
455
456
  type: string
456
457
  enum: ["Q", "G", "S", "F", "D", "L", "N", "O", "A", "M", "U", "W", "P"]
457
458
  external_id:
458
- description: External id of the request.
459
+ description: "External id of the request."
459
460
  type: string
460
461
  external_host:
461
- description: External host of the request.
462
+ description: "External host of the request."
462
463
  type: string
463
464
  retry_count:
464
- description: The numbers of attempted retires.
465
+ description: "The numbers of attempted retries."
465
466
  type: integer
466
467
  err_msg:
467
- description: An error message if one occurred.
468
+ description: "An error message if one occurred."
468
469
  type: string
469
470
  previous_attempt_id:
470
- description: The id of the previous attempt.
471
+ description: "The id of the previous attempt."
471
472
  type: string
472
473
  rule_id:
473
- description: The id of the associated replication rule.
474
+ description: "The id of the associated replication rule."
474
475
  type: string
475
476
  activity:
476
- description: The activity of the request.
477
+ description: "The activity of the request."
477
478
  type: string
478
479
  bytes:
479
- description: The size of the did in bytes.
480
+ description: "The size of the did in bytes."
480
481
  type: integer
481
482
  md5:
482
- description: The md5 checksum of the did to transfer.
483
+ description: "The md5 checksum of the did to transfer."
483
484
  type: string
484
485
  adler32:
485
- description: The adler32 checksum of the did to transfer.
486
+ description: "The adler32 checksum of the did to transfer."
486
487
  type: string
487
488
  dest_url:
488
- description: The destination url.
489
+ description: "The destination url."
489
490
  type: string
490
491
  submitted_at:
491
- description: The time the request got submitted.
492
+ description: "The time the request got submitted."
492
493
  type: string
493
494
  started_at:
494
- description: The time the request got started.
495
+ description: "The time the request got started."
495
496
  type: string
496
497
  transferred_at:
497
- description: The time the request got transferred.
498
+ description: "The time the request got transferred."
498
499
  type: string
499
500
  estimated_at:
500
- description: The time the request got estimated.
501
+ description: "The time the request got estimated."
501
502
  type: string
502
503
  submitter_id:
503
- description: The id of the submitter.
504
+ description: "The id of the submitter."
504
505
  type: string
505
506
  estimated_stated_at:
506
- description: The estimation of the started at value.
507
+ description: "The estimation of the started at value."
507
508
  type: string
508
509
  estimated_transferred_at:
509
- description: The estimation of the transferred at value.
510
+ description: "The estimation of the transferred at value."
510
511
  type: string
511
512
  staging_started_at:
512
- description: The time the staging got started.
513
+ description: "The time the staging got started."
513
514
  type: string
514
515
  staging_finished_at:
515
- description: The time the staging got finished.
516
+ description: "The time the staging got finished."
516
517
  type: string
517
518
  account:
518
- description: The account which issued the request.
519
+ description: "The account which issued the request."
519
520
  type: string
520
521
  requested_at:
521
- description: The time the request got requested.
522
+ description: "The time the request got requested."
522
523
  type: string
523
524
  priority:
524
- description: The priority of the request.
525
+ description: "The priority of the request."
525
526
  type: integer
526
527
  transfertool:
527
- description: The transfertool used.
528
+ description: "The transfertool used."
528
529
  type: string
529
530
  source_rse:
530
- description: The name of the source RSE.
531
+ description: "The name of the source RSE."
531
532
  type: string
532
533
  dest_rse:
533
- description: The name of the destination RSE.
534
+ description: "The name of the destination RSE."
534
535
  type: string
535
536
  401:
536
- description: Invalid Auth Token
537
+ description: "Invalid Auth Token"
537
538
  404:
538
- description: Not found
539
+ description: "Not found"
539
540
  406:
540
- description: Not acceptable
541
+ description: "Not acceptable"
541
542
  """
542
543
  src_rse = flask.request.args.get('src_rse', default=None)
543
544
  dst_rse = flask.request.args.get('dst_rse', default=None)
@@ -564,11 +565,11 @@ class RequestList(ErrorHandlingMethodView):
564
565
  src_rses = []
565
566
  dst_rses = []
566
567
  if src_site:
567
- src_rses = get_rses_with_attribute_value(key='site', value=src_site, vo=flask.request.environ.get('vo'))
568
+ src_rses = get_rses_with_attribute_value(key='site', value=src_site, vo=flask.request.environ['vo'])
568
569
  if not src_rses:
569
570
  return generate_http_error_flask(404, 'NotFound', f'Could not resolve site name {src_site} to RSE')
570
571
  src_rses = [rse['rse_name'] for rse in src_rses]
571
- dst_rses = get_rses_with_attribute_value(key='site', value=dst_site, vo=flask.request.environ.get('vo'))
572
+ dst_rses = get_rses_with_attribute_value(key='site', value=dst_site, vo=flask.request.environ['vo'])
572
573
  if not dst_rses:
573
574
  return generate_http_error_flask(404, 'NotFound', f'Could not resolve site name {dst_site} to RSE')
574
575
  dst_rses = [rse['rse_name'] for rse in dst_rses]
@@ -576,11 +577,15 @@ class RequestList(ErrorHandlingMethodView):
576
577
  dst_rses = [dst_rse]
577
578
  src_rses = [src_rse]
578
579
 
580
+ # Manual cast to list[str] as static code analysis erroneously sees these as list[Optional[str]]
581
+ src_rses = cast("list[str]", src_rses)
582
+ dst_rses = cast("list[str]", dst_rses)
583
+
579
584
  def generate(issuer, vo):
580
585
  for result in request.list_requests(src_rses, dst_rses, states, issuer=issuer, vo=vo):
581
586
  yield render_json(**result) + '\n'
582
587
 
583
- return try_stream(generate(issuer=flask.request.environ.get('issuer'), vo=flask.request.environ.get('vo')))
588
+ return try_stream(generate(issuer=flask.request.environ['issuer'], vo=flask.request.environ['vo']))
584
589
 
585
590
 
586
591
  class RequestHistoryList(ErrorHandlingMethodView):
@@ -591,13 +596,13 @@ class RequestHistoryList(ErrorHandlingMethodView):
591
596
  """
592
597
  ---
593
598
  summary: List Historic Requests
594
- description: List historical requests for a given source and destination RSE or site.
599
+ description: "List historical requests for a given source and destination RSE or site."
595
600
  tags:
596
601
  - Requests
597
602
  parameters:
598
603
  - name: src_rse
599
604
  in: query
600
- description: The source rse.
605
+ description: "The source rse."
601
606
  schema:
602
607
  type: array
603
608
  items:
@@ -606,11 +611,11 @@ class RequestHistoryList(ErrorHandlingMethodView):
606
611
  - rse_id
607
612
  properties:
608
613
  rse_id:
609
- description: The id of the rse.
614
+ description: "The id of the rse."
610
615
  type: string
611
616
  - name: dest_rse
612
617
  in: query
613
- description: The destination rse.
618
+ description: "The destination rse."
614
619
  schema:
615
620
  type: array
616
621
  items:
@@ -619,168 +624,168 @@ class RequestHistoryList(ErrorHandlingMethodView):
619
624
  - rse_id
620
625
  properties:
621
626
  rse_id:
622
- description: The id of the rse.
627
+ description: "The id of the rse."
623
628
  type: string
624
629
  - name: src_site
625
630
  in: query
626
- description: The source site.
631
+ description: "The source site."
627
632
  schema:
628
633
  type: string
629
634
  - name: dest_site
630
635
  in: query
631
- description: The destination site.
636
+ description: "The destination site."
632
637
  schema:
633
638
  type: string
634
639
  - name: request_states
635
640
  in: query
636
- description: The accepted request states. Delimited by comma.
641
+ description: "The accepted request states. Delimited by comma."
637
642
  schema:
638
643
  type: string
639
644
  - name: offset
640
645
  in: query
641
- description: The offset of the list.
646
+ description: "The offset of the list."
642
647
  schema:
643
648
  type: integer
644
649
  default: 0
645
650
  - name: limit
646
651
  in: query
647
- description: The maximum number of items to return.
652
+ description: "The maximum number of items to return."
648
653
  schema:
649
654
  type: integer
650
655
  default: 100
651
656
  responses:
652
657
  200:
653
- description: OK
658
+ description: "OK"
654
659
  content:
655
660
  application/x-json-stream:
656
661
  schema:
657
- description: All requests matching the arguments. Separated by a new line character.
662
+ description: "All requests matching the arguments. Separated by a new line character."
658
663
  type: array
659
664
  items:
660
- description: A request.
665
+ description: "A request."
661
666
  type: object
662
667
  properties:
663
668
  id:
664
- description: The id of the request.
669
+ description: "The id of the request."
665
670
  type: string
666
671
  request_type:
667
- description: The request type.
672
+ description: "The request type."
668
673
  type: string
669
674
  enum: ["T", "U", "D", "I", "O"]
670
675
  scope:
671
- description: The scope of the transfer.
676
+ description: "The scope of the transfer."
672
677
  type: string
673
678
  name:
674
- description: The name of the transfer.
679
+ description: "The name of the transfer."
675
680
  type: string
676
681
  did_type:
677
- description: The did type.
682
+ description: "The did type."
678
683
  type: string
679
684
  dest_rse_id:
680
- description: The destination RSE id.
685
+ description: "The destination RSE id."
681
686
  type: string
682
687
  source_rse_id:
683
- description: The source RSE id.
688
+ description: "The source RSE id."
684
689
  type: string
685
690
  attributes:
686
- description: All attributes associated with the request.
691
+ description: "All attributes associated with the request."
687
692
  type: string
688
693
  state:
689
- description: The state of the request.
694
+ description: "The state of the request."
690
695
  type: string
691
696
  enum: ["Q", "G", "S", "F", "D", "L", "N", "O", "A", "M", "U", "W", "P"]
692
697
  external_id:
693
- description: External id of the request.
698
+ description: "External id of the request."
694
699
  type: string
695
700
  external_host:
696
- description: External host of the request.
701
+ description: "External host of the request."
697
702
  type: string
698
703
  retry_count:
699
- description: The numbers of attempted retires.
704
+ description: "The numbers of attempted retries."
700
705
  type: integer
701
706
  err_msg:
702
- description: An error message if one occurred.
707
+ description: "An error message if one occurred."
703
708
  type: string
704
709
  previous_attempt_id:
705
- description: The id of the previous attempt.
710
+ description: "The id of the previous attempt."
706
711
  type: string
707
712
  rule_id:
708
- description: The id of the associated replication rule.
713
+ description: "The id of the associated replication rule."
709
714
  type: string
710
715
  activity:
711
- description: The activity of the request.
716
+ description: "The activity of the request."
712
717
  type: string
713
718
  bytes:
714
- description: The size of the did in bytes.
719
+ description: "The size of the did in bytes."
715
720
  type: integer
716
721
  md5:
717
- description: The md5 checksum of the did to transfer.
722
+ description: "The md5 checksum of the did to transfer."
718
723
  type: string
719
724
  adler32:
720
- description: The adler32 checksum of the did to transfer.
725
+ description: "The adler32 checksum of the did to transfer."
721
726
  type: string
722
727
  dest_url:
723
- description: The destination url.
728
+ description: "The destination url."
724
729
  type: string
725
730
  submitted_at:
726
- description: The time the request got submitted.
731
+ description: "The time the request got submitted."
727
732
  type: string
728
733
  started_at:
729
- description: The time the request got started.
734
+ description: "The time the request got started."
730
735
  type: string
731
736
  transferred_at:
732
- description: The time the request got transferred.
737
+ description: "The time the request got transferred."
733
738
  type: string
734
739
  estimated_at:
735
- description: The time the request got estimated.
740
+ description: "The time the request got estimated."
736
741
  type: string
737
742
  submitter_id:
738
- description: The id of the submitter.
743
+ description: "The id of the submitter."
739
744
  type: string
740
745
  estimated_stated_at:
741
- description: The estimation of the started at value.
746
+ description: "The estimation of the started at value."
742
747
  type: string
743
748
  estimated_transferred_at:
744
- description: The estimation of the transferred at value.
749
+ description: "The estimation of the transferred at value."
745
750
  type: string
746
751
  staging_started_at:
747
- description: The time the staging got started.
752
+ description: "The time the staging got started."
748
753
  type: string
749
754
  staging_finished_at:
750
- description: The time the staging got finished.
755
+ description: "The time the staging got finished."
751
756
  type: string
752
757
  account:
753
- description: The account which issued the request.
758
+ description: "The account which issued the request."
754
759
  type: string
755
760
  requested_at:
756
- description: The time the request got requested.
761
+ description: "The time the request got requested."
757
762
  type: string
758
763
  priority:
759
- description: The priority of the request.
764
+ description: "The priority of the request."
760
765
  type: integer
761
766
  transfertool:
762
- description: The transfertool used.
767
+ description: "The transfertool used."
763
768
  type: string
764
769
  source_rse:
765
- description: The name of the source RSE.
770
+ description: "The name of the source RSE."
766
771
  type: string
767
772
  dest_rse:
768
- description: The name of the destination RSE.
773
+ description: "The name of the destination RSE."
769
774
  type: string
770
775
  401:
771
- description: Invalid Auth Token
776
+ description: "Invalid Auth Token"
772
777
  404:
773
- description: Not found
778
+ description: "Not found"
774
779
  406:
775
- description: Not acceptable
780
+ description: "Not acceptable"
776
781
  """
777
782
  src_rse = flask.request.args.get('src_rse', default=None)
778
783
  dst_rse = flask.request.args.get('dst_rse', default=None)
779
784
  src_site = flask.request.args.get('src_site', default=None)
780
785
  dst_site = flask.request.args.get('dst_site', default=None)
781
786
  request_states = flask.request.args.get('request_states', default=None)
782
- offset = flask.request.args.get('offset', default=0)
783
- limit = flask.request.args.get('limit', default=100)
787
+ offset = flask.request.args.get('offset', type=int, default=0)
788
+ limit = flask.request.args.get('limit', type=int, default=100)
784
789
 
785
790
  if not request_states:
786
791
  return generate_http_error_flask(400, 'MissingParameter', 'Request state is missing')
@@ -801,11 +806,11 @@ class RequestHistoryList(ErrorHandlingMethodView):
801
806
  src_rses = []
802
807
  dst_rses = []
803
808
  if src_site:
804
- src_rses = get_rses_with_attribute_value(key='site', value=src_site, vo=flask.request.environ.get('vo'))
809
+ src_rses = get_rses_with_attribute_value(key='site', value=src_site, vo=flask.request.environ['vo'])
805
810
  if not src_rses:
806
811
  return generate_http_error_flask(404, 'NotFound', f'Could not resolve site name {src_site} to RSE')
807
812
  src_rses = [rse['rse_name'] for rse in src_rses]
808
- dst_rses = get_rses_with_attribute_value(key='site', value=dst_site, vo=flask.request.environ.get('vo'))
813
+ dst_rses = get_rses_with_attribute_value(key='site', value=dst_site, vo=flask.request.environ['vo'])
809
814
  if not dst_rses:
810
815
  return generate_http_error_flask(404, 'NotFound', f'Could not resolve site name {dst_site} to RSE')
811
816
  dst_rses = [rse['rse_name'] for rse in dst_rses]
@@ -813,11 +818,15 @@ class RequestHistoryList(ErrorHandlingMethodView):
813
818
  dst_rses = [dst_rse]
814
819
  src_rses = [src_rse]
815
820
 
821
+ # Manual cast to list[str] as static code analysis erroneously sees these as list[Optional[str]]
822
+ src_rses = cast("list[str]", src_rses)
823
+ dst_rses = cast("list[str]", dst_rses)
824
+
816
825
  def generate(issuer, vo):
817
826
  for result in request.list_requests_history(src_rses, dst_rses, states, issuer=issuer, vo=vo, offset=offset, limit=limit):
818
827
  yield render_json(**result) + '\n'
819
828
 
820
- return try_stream(generate(issuer=flask.request.environ.get('issuer'), vo=flask.request.environ.get('vo')))
829
+ return try_stream(generate(issuer=flask.request.environ['issuer'], vo=flask.request.environ['vo']))
821
830
 
822
831
 
823
832
  class RequestMetricsGet(ErrorHandlingMethodView):
@@ -828,72 +837,72 @@ class RequestMetricsGet(ErrorHandlingMethodView):
828
837
  """
829
838
  ---
830
839
  summary: Get Request Statistics
831
- description: Get statistics of requests grouped by source, destination, and activity.
840
+ description: "Get statistics of requests grouped by source, destination, and activity."
832
841
  tags:
833
842
  - Requests
834
843
  parameters:
835
844
  - name: dest_rse
836
845
  in: query
837
- description: The destination RSE name
846
+ description: "The destination RSE name"
838
847
  schema:
839
848
  type: string
840
849
  - name: source_rse
841
850
  in: query
842
- description: The source RSE name
851
+ description: "The source RSE name"
843
852
  schema:
844
853
  type: string
845
854
  - name: activity
846
855
  in: query
847
- description: The activity
856
+ description: "The activity"
848
857
  schema:
849
858
  type: string
850
859
  - name: group_by_rse_attribute
851
860
  in: query
852
- description: The parameter to group the RSEs by.
861
+ description: "The parameter to group the RSEs by."
853
862
  schema:
854
863
  type: string
855
864
  responses:
856
865
  200:
857
- description: OK
866
+ description: "OK"
858
867
  content:
859
868
  application/x-json-stream:
860
869
  schema:
861
- description: Statistics of requests by source, destination, and activity.
870
+ description: "Statistics of requests by source, destination, and activity."
862
871
  type: array
863
872
  items:
864
- description: Statistics of the request group for a given (source, destination, activity) tuple.
873
+ description: "Statistics of the request group for a given (source, destination, activity) tuple."
865
874
  type: object
866
875
  properties:
867
876
  src_rse:
868
877
  type: string
869
- description: The name of this links source RSE
878
+ description: "The name of this links source RSE"
870
879
  dst_rse:
871
880
  type: string
872
- description: The name of this links destination RSE
881
+ description: "The name of this links destination RSE"
873
882
  distance:
874
883
  type: integer
875
- description: The distance between the source and destination RSE
884
+ description: "The distance between the source and destination RSE"
876
885
  files:
877
886
  type: object
878
887
  properties:
879
888
  done-total-1h:
880
889
  type: integer
881
- description: The total number of files successfully transferred in the last 1 hour
890
+ description: "The total number of files successfully transferred in the last 1 hour"
882
891
  done-total-6h:
883
892
  type: integer
884
- description: The total number of files successfully transferred in the last 6 hours
893
+ description: "The total number of files successfully transferred in the last 6 hours"
885
894
  failed-total-1h:
886
895
  type: integer
887
- description: The total number of transfer failures in the last 1 hour
896
+ description: "The total number of transfer failures in the last 1 hour"
888
897
  failed-total-6h:
889
898
  type: integer
890
- description: The total number of transfer failures in the last 6 hours
899
+ description: "The total number of transfer failures in the last 6 hours"
891
900
  queued-total:
892
901
  type: integer
893
- description: The total number of files queued in rucio
902
+ description: "The total number of files queued in rucio"
894
903
  queued:
895
904
  type: object
896
- description: Per-activity number of queued files
905
+ description: "Per-activity number of queued files"
897
906
  additionalProperties:
898
907
  type: integer
899
908
  done:
@@ -907,7 +916,7 @@ class RequestMetricsGet(ErrorHandlingMethodView):
907
916
  type: integer
908
917
  failed:
909
918
  type: object
910
- description: Per-activity number of transfer failures in the last 1 and 6 hours
919
+ description: "Per-activity number of transfer failures in the last 1 and 6 hours"
911
920
  additionalProperties:
912
921
  type: object
913
922
  properties:
@@ -920,21 +929,21 @@ class RequestMetricsGet(ErrorHandlingMethodView):
920
929
  properties:
921
930
  done-total-1h:
922
931
  type: integer
923
- description: The total number of bytes successfully transferred in the last 1 hour
932
+ description: "The total number of bytes successfully transferred in the last 1 hour"
924
933
  done-total-6h:
925
934
  type: integer
926
- description: The total number of bytes successfully transferred in the last 6 hours
935
+ description: "The total number of bytes successfully transferred in the last 6 hours"
927
936
  queued-total:
928
937
  type: integer
929
- description: The total number of bytes queued to be transferred by rucio
938
+ description: "The total number of bytes queued to be transferred by rucio"
930
939
  queued:
931
940
  type: object
932
- description: Per-activity amount of queued bytes
941
+ description: "Per-activity amount of queued bytes"
933
942
  additionalProperties:
934
943
  type: integer
935
944
  done:
936
945
  type: object
937
- description: Per-activity number of transferred bytes in the last 1 and 6 hours
946
+ description: "Per-activity number of transferred bytes in the last 1 and 6 hours"
938
947
  additionalProperties:
939
948
  type: object
940
949
  properties:
@@ -947,7 +956,7 @@ class RequestMetricsGet(ErrorHandlingMethodView):
947
956
  - src_rse
948
957
  - dst_rse
949
958
  401:
950
- description: Invalid Auth Token
959
+ description: "Invalid Auth Token"
951
960
  """
952
961
  dst_rse = flask.request.args.get('dst_rse', default=None)
953
962
  src_rse = flask.request.args.get('src_rse', default=None)
@@ -960,8 +969,8 @@ class RequestMetricsGet(ErrorHandlingMethodView):
960
969
  src_rse=src_rse,
961
970
  activity=activity,
962
971
  group_by_rse_attribute=group_by_rse_attribute,
963
- issuer=flask.request.environ.get('issuer'),
964
- vo=flask.request.environ.get('vo')
972
+ issuer=flask.request.environ['issuer'],
973
+ vo=flask.request.environ['vo']
965
974
  )
966
975
 
967
976
  if format == 'panda':
@@ -973,6 +982,190 @@ class RequestMetricsGet(ErrorHandlingMethodView):
973
982
  return try_stream(generate())
974
983
 
975
984
 
985
+ class TransferLimits(ErrorHandlingMethodView):
986
+ """ REST API to get, set or delete transfer limits. """
987
+
988
+ @check_accept_header_wrapper_flask(['application/x-json-stream'])
989
+ def get(self) -> flask.Response:
990
+ """
991
+ ---
992
+ summary: Get Transfer Limits
993
+ description: "Get all the transfer limits."
994
+ tags:
995
+ - Requests
996
+ responses:
997
+ 200:
998
+ description: "OK"
999
+ content:
1000
+ application/x-json-stream:
1001
+ schema:
1002
+ description: "All the transfer limits"
1003
+ type: array
1004
+ items:
1005
+ type: object
1006
+ properties:
1007
+ id:
1008
+ description: "The transfer limit id."
1009
+ type: string
1010
+ rse_expression:
1011
+ description: "The RSE expression for which the limit applies."
1012
+ type: string
1013
+ direction:
1014
+ description: "The direction in which this limit applies (source/destination)"
1015
+ type: string
1016
+ max_transfers:
1017
+ description: "Maximum number of transfers allowed."
1018
+ type: integer
1019
+ volume:
1020
+ description: "Maximum transfer volume in bytes."
1021
+ type: integer
1022
+ deadline:
1023
+ description: "Maximum waiting time in hours until a dataset gets released."
1024
+ type: integer
1025
+ strategy:
1026
+ description: "Defines how to handle datasets: `fifo` (each file released separately) or `grouped_fifo` (wait for the entire dataset to fit)"
1027
+ type: string
1028
+ transfers:
1029
+ description: "Current number of active transfers"
1030
+ type: integer
1031
+ waitings:
1032
+ description: "Current number of waiting transfers"
1033
+ type: integer
1034
+ updated_at:
1035
+ description: "Datetime of the last update."
1036
+ type: string
1037
+ created_at:
1038
+ description: "Datetime of the creation of the transfer limit."
1039
+ type: string
1040
+ 401:
1041
+ description: "Invalid Auth Token"
1042
+ """
1043
+ transfer_limits = request.list_transfer_limits(issuer=flask.request.environ['issuer'], vo=flask.request.environ['vo'])
1044
+
1045
+ def generate() -> "Iterator[str]":
1046
+ for limit in transfer_limits:
1047
+ yield json.dumps(limit, cls=APIEncoder) + '\n'
1048
+ return try_stream(generate())
1049
+
1050
+ def put(self) -> Union[flask.Response, tuple[str, int]]:
1051
+ """
1052
+ ---
1053
+ summary: Set Transfer Limit
1054
+ description: "Create or update a transfer limit for a specific RSE expression and activity."
1055
+ tags:
1056
+ - Requests
1057
+ requestBody:
1058
+ content:
1059
+ application/json:
1060
+ schema:
1061
+ type: object
1062
+ required:
1063
+ - rse_expression
1064
+ - max_transfers
1065
+ properties:
1066
+ rse_expression:
1067
+ type: string
1068
+ description: "The RSE expression for which the transfer limit is being set."
1069
+ activity:
1070
+ type: string
1071
+ description: "The activity to which the transfer limit applies."
1072
+ max_transfers:
1073
+ type: integer
1074
+ description: "The maximum number of transfers allowed."
1075
+ direction:
1076
+ type: string
1077
+ description: "The direction of the transfer limit (source or destination)."
1078
+ enum: ["SOURCE", "DESTINATION"]
1079
+ default: "DESTINATION"
1080
+ volume:
1081
+ type: integer
1082
+ description: "The maximum transfer volume in bytes."
1083
+ deadline:
1084
+ type: integer
1085
+ description: "The maximum waiting time in hours until a dataset is released."
1086
+ strategy:
1087
+ type: string
1088
+ description: "The strategy for handling datasets (e.g., `fifo` or `grouped_fifo`)."
1089
+ transfers:
1090
+ type: integer
1091
+ description: "The current number of active transfers."
1092
+ waitings:
1093
+ type: integer
1094
+ description: "The current number of waiting transfers."
1095
+ responses:
1096
+ 201:
1097
+ description: "Transfer limit set successfully."
1098
+ 400:
1099
+ description: "Invalid input data."
1100
+ 401:
1101
+ description: "Invalid Auth Token."
1102
+ 500:
1103
+ description: "Internal server error."
1104
+ """
1105
+ parameters = json_parameters()
1106
+ rse_expression = param_get(parameters, 'rse_expression')
1107
+ max_transfers = param_get(parameters, 'max_transfers')
1108
+
1109
+ try:
1110
+ request.set_transfer_limit(
1111
+ rse_expression=rse_expression,
1112
+ max_transfers=max_transfers,
1113
+ activity=param_get(parameters, 'activity', default=None),
1114
+ direction=param_get(parameters, 'direction', default=TransferLimitDirection.DESTINATION),
1115
+ volume=param_get(parameters, 'volume', default=None),
1116
+ deadline=param_get(parameters, 'deadline', default=None),
1117
+ strategy=param_get(parameters, 'strategy', default=None),
1118
+ transfers=param_get(parameters, 'transfers', default=None),
1119
+ waitings=param_get(parameters, 'waitings', default=None),
1120
+ issuer=flask.request.environ['issuer'],
1121
+ vo=flask.request.environ['vo']
1122
+ )
1123
+ except AccessDenied as error:
1124
+ return generate_http_error_flask(401, error)
1125
+
1126
+ return '', 201
1127
+
1128
+ def delete(self) -> Union[flask.Response, tuple[str, int]]:
1129
+ """
1130
+ ---
1131
+ summary: Delete Transfer Limit
1132
+ description: "Delete a transfer limit for an RSE expression."
1133
+ tags:
1134
+ - Requests
1135
+ parameters:
1136
+ - name: rse_expression
1137
+ in: query
1138
+ description: "The RSE expression to delete the limit for."
1139
+ required: true
1140
+ schema:
1141
+ type: string
1142
+ responses:
1143
+ 200:
1144
+ description: "Transfer limit deleted successfully."
1145
+ 400:
1146
+ description: "Invalid input data."
1147
+ 401:
1148
+ description: "Invalid Auth Token."
1149
+ 500:
1150
+ description: "Internal server error."
1151
+ """
1152
+ parameters = json_parameters()
1153
+ rse_expression = param_get(parameters, 'rse_expression')
1154
+
1155
+ try:
1156
+ request.delete_transfer_limit(
1157
+ rse_expression=rse_expression,
1158
+ activity=param_get(parameters, 'activity', default=None),
1159
+ direction=param_get(parameters, 'direction', default=TransferLimitDirection.DESTINATION),
1160
+ issuer=flask.request.environ['issuer'],
1161
+ vo=flask.request.environ['vo']
1162
+ )
1163
+ except AccessDenied as error:
1164
+ return generate_http_error_flask(401, error)
1165
+
1166
+ return '', 200
1167
+
1168
+
976
1169
  def blueprint():
977
1170
  bp = AuthenticatedBlueprint('requests', __name__, url_prefix='/requests')
978
1171
 
@@ -986,6 +1179,8 @@ def blueprint():
986
1179
  bp.add_url_rule('/history/list', view_func=request_history_list_view, methods=['get', ])
987
1180
  request_metrics_view = RequestMetricsGet.as_view('request_metrics_get')
988
1181
  bp.add_url_rule('/metrics', view_func=request_metrics_view, methods=['get', ])
1182
+ transfer_limits_view = TransferLimits.as_view('transfer_limits_get')
1183
+ bp.add_url_rule('/transfer_limits', view_func=transfer_limits_view, methods=['get', 'put', 'delete'])
989
1184
 
990
1185
  bp.after_request(response_headers)
991
1186
  return bp