Forgot to add the new templates.

This commit is contained in:
Andrea Dell'Amico 2026-09-14 10:48:16 +02:00
parent 137988220b
commit 8600827e31
Signed by: adellam
GPG Key ID: 147ABE6CEB9E20FF
3 changed files with 133 additions and 0 deletions

View File

@ -0,0 +1,108 @@
#!{{ mailman_bindir }}/python3
"""Disable HyperKitty for Mailman lists whose archive policy is never."""
import argparse
import fcntl
import logging
import sys
from mailman.config import config
from mailman.core.initialize import initialize
from mailman.interfaces.listmanager import IListManager
from mailman.interfaces.mailinglist import IListArchiverSet
from zope.component import getUtility
CONFIG_FILE = {{ (mailman_conf_dir + '/mailman.cfg') | to_json }}
LOCK_FILE = {{ mailman_hyperkitty_archiver_reconciliation_lock | to_json }}
ARCHIVER_NAME = 'hyperkitty'
logging.basicConfig(
level=logging.INFO,
format='mailman-hyperkitty-archiver-reconcile: %(levelname)s: %(message)s')
LOG = logging.getLogger(__name__)
def normalize_policy(value):
if hasattr(value, 'name'):
value = value.name
if isinstance(value, int):
return {0: 'never', 1: 'private', 2: 'public'}.get(value, str(value))
return str(value).strip().lower()
def reconcile(dry_run):
initialize(CONFIG_FILE)
lists = sorted(
getUtility(IListManager).mailing_lists,
key=lambda mailing_list: mailing_list.fqdn_listname.casefold())
candidates = []
for mailing_list in lists:
if normalize_policy(mailing_list.archive_policy) != 'never':
continue
archiver = IListArchiverSet(mailing_list).get(ARCHIVER_NAME)
if archiver is not None and archiver.is_enabled:
candidates.append((mailing_list, archiver))
changed = 0
if dry_run:
for mailing_list, _archiver in candidates:
LOG.info(
'would disable %s for %s (archive policy is never)',
ARCHIVER_NAME, mailing_list.fqdn_listname)
config.db.abort()
else:
for mailing_list, archiver in candidates:
# Re-read both rows before changing them so a concurrent Postorius
# update cannot be overwritten from the initial snapshot.
config.db.store.refresh(mailing_list)
config.db.store.refresh(archiver)
if (normalize_policy(mailing_list.archive_policy) != 'never' or
not archiver.is_enabled):
LOG.warning(
'skipping %s: settings changed during reconciliation',
mailing_list.fqdn_listname)
continue
archiver.is_enabled = False
changed += 1
LOG.info(
'disabled %s for %s (archive policy is never)',
ARCHIVER_NAME, mailing_list.fqdn_listname)
config.db.commit()
LOG.info(
'%d Core lists, %d inconsistent archiver settings, %d changed',
len(lists), len(candidates), changed)
return 0
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
'--dry-run', action='store_true',
help='report inconsistent lists without changing Mailman Core')
arguments = parser.parse_args()
try:
with open(LOCK_FILE, 'w') as lock_handle:
try:
fcntl.flock(lock_handle, fcntl.LOCK_EX | fcntl.LOCK_NB)
except OSError:
LOG.error('another reconciliation process holds %s', LOCK_FILE)
return 1
return reconcile(arguments.dry_run)
except Exception as error:
try:
config.db.abort()
except Exception:
# Preserve the original initialization or database exception.
pass
LOG.exception('reconciliation failed: %s', error)
return 1
if __name__ == '__main__':
sys.exit(main())

View File

@ -0,0 +1,13 @@
[Unit]
Description=Disable HyperKitty for Mailman lists with archive policy never
After=network-online.target mailman.service
Wants=network-online.target
ConditionPathExists={{ mailman_conf_dir }}/mailman.cfg
[Service]
Type=oneshot
User={{ mailman_user }}
Group={{ mailman_user }}
ExecStart={{ mailman_hyperkitty_archiver_reconciliation_script }}
TimeoutStartSec=5min
Nice=10

View File

@ -0,0 +1,12 @@
[Unit]
Description=Periodically reconcile Mailman and HyperKitty archive settings
[Timer]
OnActiveSec={{ mailman_hyperkitty_archiver_reconciliation_on_active }}
OnUnitActiveSec={{ mailman_hyperkitty_archiver_reconciliation_interval }}
AccuracySec=1min
Persistent=false
Unit=mailman-hyperkitty-archiver-reconcile.service
[Install]
WantedBy=timers.target