Skip to content

Commit 014b8f2

Browse files
committed
wip:general librarian disable
1 parent 657cff3 commit 014b8f2

File tree

9 files changed

+182
-12
lines changed

9 files changed

+182
-12
lines changed

hera_librarian/client.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@
2929
from .models.admin import (
3030
AdminAddLibrarianRequest,
3131
AdminAddLibrarianResponse,
32+
AdminChangeLibrarianStatusRequest,
3233
AdminChangeLibrarianTransferStatusRequest,
3334
AdminCreateFileRequest,
3435
AdminCreateFileResponse,
3536
AdminDeleteInstanceRequest,
3637
AdminDeleteInstanceResponse,
38+
AdminLibrarianStatusResponse,
3739
AdminLibrarianTransferStatusResponse,
3840
AdminListLibrariansRequest,
3941
AdminListLibrariansResponse,
@@ -1322,7 +1324,7 @@ def remove_librarian(
13221324

13231325
return response.success, response.number_of_transfers_removed
13241326

1325-
def set_librarian_status(
1327+
def set_librarian_transfer_status(
13261328
self,
13271329
librarian_name: str,
13281330
transfers_enabled: bool,
@@ -1359,3 +1361,41 @@ def set_librarian_status(
13591361
raise e
13601362

13611363
return response.transfers_enabled
1364+
1365+
def set_librarian_status(
1366+
self,
1367+
librarian_name: str,
1368+
enabled: bool,
1369+
) -> bool:
1370+
"""
1371+
Set the status of transfers to the librarian.
1372+
1373+
Parameters
1374+
----------
1375+
librarian_name : str
1376+
The name of the librarian to set the status of.
1377+
enabled : bool
1378+
Whether the librarian should be enabled.
1379+
1380+
Returns
1381+
-------
1382+
bool
1383+
The new status.
1384+
"""
1385+
1386+
try:
1387+
response = self.post(
1388+
endpoint="admin/librarians/status/set",
1389+
request=AdminChangeLibrarianStatusRequest(
1390+
librarian_name=librarian_name,
1391+
enabled=enabled,
1392+
),
1393+
response=AdminLibrarianStatusResponse,
1394+
)
1395+
except LibrarianHTTPError as e:
1396+
if e.status_code == 400 and "Librarian" in e.reason:
1397+
raise LibrarianError(e.reason)
1398+
else:
1399+
raise e
1400+
1401+
return response.enabled

hera_librarian/models/admin.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,10 @@ class LibrarianListResponseItem(BaseModel):
167167
available: bool | None
168168
"Whether the librarian is available or not, only if ping is true."
169169

170-
enabled: bool
170+
transfers_enabled: bool
171171
"Whether transfers the librarian is enabled or not."
172+
enabled: bool
173+
"Whether the librarian is enabled or not."
172174

173175

174176
class AdminListLibrariansResponse(BaseModel):
@@ -256,6 +258,19 @@ class AdminChangeLibrarianTransferStatusRequest(BaseModel):
256258
transfers_enabled: bool
257259

258260

261+
class AdminChangeLibrarianStatusRequest(BaseModel):
262+
"""
263+
A request to change the transfer status of a librarian, either
264+
to enable or disable outbound transfers.
265+
"""
266+
267+
"The name of the librarian to change the transfer status of."
268+
librarian_name: str
269+
270+
"Whether to enable or disable outbound communication."
271+
enabled: bool
272+
273+
259274
class AdminLibrarianTransferStatusResponse(BaseModel):
260275
"""
261276
A response to a user change request.
@@ -266,3 +281,15 @@ class AdminLibrarianTransferStatusResponse(BaseModel):
266281

267282
"Whether the librarian has outbound transfers enabled."
268283
transfers_enabled: bool
284+
285+
286+
class AdminLibrarianStatusResponse(BaseModel):
287+
"""
288+
A response to a user change request.
289+
"""
290+
291+
"The name of the librarian that was changed."
292+
librarian_name: str
293+
294+
"Whether the librarian has communication enabled."
295+
enabled: bool

librarian_background/queues.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,11 @@ def check_on_consumed(
153153
.one_or_none()
154154
)
155155

156-
if librarian is None or not librarian.transfers_enabled:
156+
if (
157+
librarian is None
158+
or not librarian.transfers_enabled
159+
or not librarian.enabled
160+
):
157161
# We can't do anything with this librarian, but there may be other
158162
# librarians that are enabled.
159163
continue
@@ -258,7 +262,11 @@ def consume_queue_item(session_maker: Callable[[], "Session"]) -> bool:
258262
.one_or_none()
259263
)
260264

261-
if librarian is None or not librarian.transfers_enabled:
265+
if (
266+
librarian is None
267+
or not librarian.transfers_enabled
268+
or not librarian.enabled
269+
):
262270
# We can't do anything with this librarian, but there may be other
263271
# librarians that are enabled.
264272
return True

librarian_background/send_clone.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ def core(self, session: Session):
580580
return CancelJob
581581

582582
current_time = datetime.datetime.now(datetime.timezone.utc)
583-
if not librarian.transfers_enabled and (
583+
if (not librarian.transfers_enabled and not librarian.enabled) and (
584584
current_time - self._skip_timer
585585
) > datetime.timedelta(days=self.warn_disabled_timer):
586586
self._skip_timer = current_time

librarian_server/api/admin.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616
from hera_librarian.models.admin import (
1717
AdminAddLibrarianRequest,
1818
AdminAddLibrarianResponse,
19+
AdminChangeLibrarianStatusRequest,
1920
AdminChangeLibrarianTransferStatusRequest,
2021
AdminCreateFileRequest,
2122
AdminCreateFileResponse,
2223
AdminDeleteInstanceRequest,
2324
AdminDeleteInstanceResponse,
25+
AdminLibrarianStatusResponse,
2426
AdminLibrarianTransferStatusResponse,
2527
AdminListLibrariansRequest,
2628
AdminListLibrariansResponse,
@@ -390,7 +392,8 @@ def list_librarians(
390392
url=librarian.url,
391393
port=librarian.port,
392394
available=ping if request.ping else None,
393-
enabled=librarian.transfers_enabled,
395+
transfer_enabled=librarian.transfers_enabled,
396+
enabled=librarian.enabled,
394397
)
395398
)
396399

@@ -620,3 +623,39 @@ def change_librarian_transfer_status(
620623
librarian_name=librarian.name,
621624
transfers_enabled=librarian.transfers_enabled,
622625
)
626+
627+
628+
@router.post(
629+
path="/librarians/status/change",
630+
response_model=AdminLibrarianStatusResponse,
631+
)
632+
def change_librarian_status(
633+
request: AdminChangeLibrarianStatusRequest,
634+
user: AdminUserDependency,
635+
response: Response,
636+
session: Session = Depends(yield_session),
637+
) -> AdminLibrarianTransferStatusResponse:
638+
"""
639+
Change the transfer status of a librarian. This will enable or disable
640+
outbound transfers to the librarian.
641+
"""
642+
643+
librarian = (
644+
session.query(Librarian).filter_by(name=request.librarian_name).one_or_none()
645+
)
646+
647+
if librarian is None:
648+
response.status_code = status.HTTP_400_BAD_REQUEST
649+
return AdminRequestFailedResponse(
650+
reason=f"Librarian {request.librarian_name} does not exist",
651+
suggested_remedy="Please verify that the requested librarian exists",
652+
)
653+
654+
librarian.enabled = request.enabled
655+
656+
session.commit()
657+
658+
return AdminLibrarianStatusResponse(
659+
librarian_name=librarian.name,
660+
enabled=librarian.enabled,
661+
)

librarian_server/api/corrupt.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ def user_and_librarian_validation_flow(
135135
background_settings.consume_queue
136136
and background_settings.check_consumed_queue
137137
and librarian.transfers_enabled
138+
and librarian.enabled
138139
and login_success
139140
):
140141
logger.warning(
@@ -143,7 +144,7 @@ def user_and_librarian_validation_flow(
143144
librarian.name,
144145
bool(background_settings.consume_queue),
145146
bool(background_settings.check_consumed_queue),
146-
librarian.transfers_enabled,
147+
librarian.transfers_enabled and librarian.enabled,
147148
login_success,
148149
)
149150
raise HTTPException(

librarian_server/api/validate.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,13 @@
55
"""
66

77
import asyncio
8-
import datetime
9-
from functools import lru_cache
10-
from pathlib import Path
118
from time import perf_counter
129

1310
from asyncer import asyncify
1411
from fastapi import APIRouter, Depends, Response, status
1512
from sqlalchemy import select
1613
from sqlalchemy.orm import Session
1714

18-
from hera_librarian.errors import ErrorCategory, ErrorSeverity
1915
from hera_librarian.exceptions import (
2016
LibrarianError,
2117
LibrarianHTTPError,
@@ -84,6 +80,9 @@ def calculate_checksum_of_remote_copies(
8480
librarian,
8581
file_name,
8682
):
83+
if not librarian.enabled:
84+
return []
85+
8786
start = perf_counter()
8887
try:
8988
client = librarian.client()

librarian_server/orm/librarian.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ class Librarian(db.Base):
3737
authenticator = db.Column(db.String(256), nullable=False)
3838
"The authenticator so we can connect this librarian. This is encrypted."
3939
transfers_enabled = db.Column(db.Boolean, nullable=False, default=True)
40-
40+
"Whether transfers are enabled to this librarian."
41+
enabled = db.Column(db.Boolean, nullable=False, default=True)
42+
"Whether this librarian is enabled."
4143
last_seen = db.Column(db.DateTime, nullable=False)
4244
"The last time we connected to and verified this librarian exists."
4345
last_heard = db.Column(db.DateTime, nullable=False)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"""
2+
A command-line script, for use in containers, to change the behaviour
3+
of transfers to external librarians.
4+
"""
5+
6+
import argparse as ap
7+
8+
parser = ap.ArgumentParser(description=("Change the status of an external librarian."))
9+
10+
parser.add_argument(
11+
"--librarian",
12+
help="Name of the librarian to change the status of.",
13+
type=str,
14+
required=True,
15+
)
16+
17+
parser.add_argument(
18+
"--enable",
19+
help="Enable the librarian.",
20+
action="store_true",
21+
)
22+
23+
parser.add_argument(
24+
"--disable",
25+
help="Disable the librarian.",
26+
action="store_true",
27+
)
28+
29+
30+
def main():
31+
args = parser.parse_args()
32+
33+
if args.enable and args.disable:
34+
raise ValueError("Cannot enable and disable at the same time.")
35+
36+
if not args.enable and not args.disable:
37+
raise ValueError("Must enable or disable.")
38+
39+
from librarian_server.database import get_session
40+
from librarian_server.orm import Librarian
41+
42+
with get_session() as session:
43+
librarian = (
44+
session.query(Librarian).filter_by(name=args.librarian).one_or_none()
45+
)
46+
if librarian is None:
47+
raise ValueError(f"Librarian {args.librarian} does not exist.")
48+
49+
if args.enable:
50+
librarian.enabled = True
51+
elif args.disable:
52+
librarian.enabled = False
53+
54+
session.commit()

0 commit comments

Comments
 (0)