From a176ee3c265c113a3ccc5f4f40e8867bc4368d75 Mon Sep 17 00:00:00 2001 From: Fredrik Eriksson Date: Sat, 20 Sep 2025 11:45:08 +0200 Subject: [PATCH] add support for cleaning zfs system snapshots --- sau/freebsd.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sau/freebsd.py b/sau/freebsd.py index bf3b713..6a536fe 100644 --- a/sau/freebsd.py +++ b/sau/freebsd.py @@ -10,11 +10,14 @@ import sau.helpers PKG_PATH='/usr/sbin/pkg' SERVICE_PATH='/usr/sbin/service' FREEBSD_UPDATE_PATH='/usr/sbin/freebsd-update' +ZFS='/sbin/zfs' # regex to identify rc.d-files rc_script_re = re.compile(r'^(?:/usr/local)?/etc/rc\.d/(.*)$') # regex to parse packages pkg_upgrade_re = re.compile(r'^\s([^\s]*): ([^\s]*) -> ([^\s]*).*$') +# regex for system zfs snapshots +system_snaps_re=re.compile(r'^zroot/ROOT/default@\d{4}-\d\d-\d\d-\d\d:\d\d:\d\d-\d+(?:\s|$)') def identify_service_from_bin(exe): @@ -55,7 +58,24 @@ def restart_service(service): else: log.info("restarted service {}".format(service)) +def clean_zfs(to_keep=5): + log = logging.getLogger(sau.LOGNAME) + cmd = [ ZFS, 'list', '-t', 'snapshot', '-H' ] + ret, out, err = sau.helpers.exec_cmd(cmd, timeout=300) + + snapshots = sorted([l.split()[0] for l in out.splitlines() if re.match(system_snaps_re, l)], reverse=True) + + if to_keep < 1: + log.warning(f'set to save {to_keep} snapshots; NO WAY!, will keep one anyway') + to_keep = 1 + + for s in snapshots[to_keep:]: + log.info(f'Removing old system snapshot "{s}"') + cmd = [ ZFS, 'destroy', '-R', s ] + ret, out, err = sau.helpers.exec_cmd(cmd, timeout=600) + def system_upgrade(): + conf = sau.config log = logging.getLogger(sau.LOGNAME) # this is how freebsd wants it... time.sleep(random.randint(0, 3600)) @@ -70,6 +90,8 @@ def system_upgrade(): log.info('System updates installed:') for line in out.splitlines(): log.info(line) + keep_snapshots = conf.getint('default', 'keep_snapshots', fallback=4) + clean_zfs(keep_snapshots) return True else: log.warning('System upgrade failed (return code {}):'.format(ret))