Archive location (Gitea issue 7): ARCHIVE_ROOT, Admin file-locations API, archive-copy job, doctor check
A filed packet's sealed data book, documents and a manifest are copied to the archive folder by the worker. A failed copy never blocks filing: it is retried with backoff and raises the archive_failed condition. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -23,7 +23,7 @@ from . import __version__
|
||||
from .settings import SecretFileError, Settings
|
||||
|
||||
PASS, WARN, FAIL, SKIP = "PASS", "WARN", "FAIL", "SKIP"
|
||||
SKIPPABLE = ("visual", "mfiles", "ldap", "smtp", "db", "volume", "clamav")
|
||||
SKIPPABLE = ("visual", "mfiles", "ldap", "smtp", "db", "volume", "clamav", "archive")
|
||||
FREE_WARN_BYTES = 2 * 1024**3
|
||||
EXPECTED_PS_GROUPS = 50
|
||||
IN_CHAIN = "1.2.840.113556.1.4.1941"
|
||||
@@ -261,6 +261,46 @@ def check_volume(s: Settings) -> list[Check]:
|
||||
return out
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- archive
|
||||
|
||||
|
||||
def check_archive(s: Settings) -> list[Check]:
|
||||
"""The archive folder check (probe write, read back, delete) against the saved folder, audited like the Admin's."""
|
||||
import psycopg
|
||||
|
||||
from . import db
|
||||
from .domain import archive
|
||||
|
||||
root = archive.root_of(s)
|
||||
if root is None:
|
||||
return [Check("archive", SKIP, "ARCHIVE_ROOT not set: filed packets are not copied to an archive")]
|
||||
try:
|
||||
with db.connect_as("app", s, autocommit=True) as conn:
|
||||
archive_dir = archive.load(conn)[0]
|
||||
except (SecretFileError, psycopg.Error) as e:
|
||||
return [Check("archive", FAIL, f"can't read the saved archive folder: {_first_line(e)}")]
|
||||
if archive_dir is None:
|
||||
return [Check("archive", SKIP, f"ARCHIVE_ROOT={root}, no archive folder saved (Admin, File locations)")]
|
||||
_, result = archive.check(root, archive_dir)
|
||||
note = ""
|
||||
try:
|
||||
with db.connect_as("app", s, autocommit=True) as conn:
|
||||
archive.audit_check(conn, result, archive_dir=archive_dir, source="doctor")
|
||||
except (SecretFileError, psycopg.Error) as e:
|
||||
note = f" (not audited: {_first_line(e)})"
|
||||
if not result.ok:
|
||||
return [
|
||||
Check(
|
||||
"archive",
|
||||
FAIL,
|
||||
f"{archive_dir} under {root}: {result.message}{note}",
|
||||
"is the share mounted and writable by uid 10001?",
|
||||
)
|
||||
]
|
||||
free = f", {result.free_bytes / 1024**3:.1f} GB free" if result.free_bytes is not None else ""
|
||||
return [Check("archive", WARN if note else PASS, f"{result.resolved} writable{free}{note}")]
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- clamav
|
||||
|
||||
|
||||
@@ -439,6 +479,7 @@ def run(
|
||||
("db", check_db),
|
||||
("volume", check_volume),
|
||||
("clamav", check_clamav),
|
||||
("archive", check_archive),
|
||||
("ldap", check_ldap),
|
||||
("smtp", lambda st: check_smtp(st, send_test)),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user