pmb.config.workdir: save/check chroot init date (!1878)

Whenever initializing new chroots, save the date in $WORK/workdir.cfg.
Add pmb.config.workdir.chroots_outdated() to check if it's time to zap
the chroots or not (since we don't update them automatically). Mark them
as outdated after two days.

This will be the first check in "pmbootstrap status" (future patches).
Related: #1829
This commit is contained in:
Oliver Smith 2020-02-05 00:18:39 +01:00
parent f21c216a26
commit 17673c5bf1
No known key found for this signature in database
GPG Key ID: 5AE7F5513E0885CB
5 changed files with 201 additions and 0 deletions

View File

@ -8,6 +8,7 @@ import filecmp
import pmb.chroot
import pmb.chroot.apk_static
import pmb.config
import pmb.config.workdir
import pmb.helpers.repo
import pmb.helpers.run
import pmb.parse.arch
@ -73,6 +74,8 @@ def init(args, suffix="native"):
copy_resolv_conf(args, suffix)
pmb.chroot.apk.update_repository_list(args, suffix)
pmb.config.workdir.chroot_save_date(args, suffix)
# Install alpine-base
pmb.helpers.repo.update(args, arch)
pmb.chroot.apk_static.run(args, ["--no-progress", "--root", chroot,

View File

@ -6,6 +6,7 @@ import math
import os
import pmb.chroot
import pmb.config.workdir
import pmb.helpers.pmaports
import pmb.helpers.run
import pmb.parse.apkindex
@ -72,6 +73,9 @@ def zap(args, confirm=True, dry=False, pkgs_local=False, http=False,
if not dry:
pmb.helpers.run.root(args, ["rm", "-rf", match])
# Remove config init dates for deleted chroots
pmb.config.workdir.clean(args)
# Chroots were zapped, so no repo lists exist anymore
args.cache["apk_repository_list_updated"].clear()

View File

@ -148,6 +148,10 @@ chroot_device_nodes = [
# You can force-update them with 'pmbootstrap update'.
apkindex_retention_time = 4
# When chroot is considered outdated (in seconds)
chroot_outdated = 3600 * 24 * 2
#
# BUILD
#

87
pmb/config/workdir.py Normal file
View File

@ -0,0 +1,87 @@
# Copyright 2020 Oliver Smith
# SPDX-License-Identifier: GPL-3.0-or-later
""" Save, read, verify workdir state related information in $WORK/workdir.cfg,
for example the init dates of the chroots. This is not saved in
pmbootstrap.cfg, because pmbootstrap.cfg is not tied to a specific work
dir. """
import configparser
import os
import time
import pmb.config
def chroot_save_date(args, suffix):
""" Save the chroot initialization date in $WORK/workdir.cfg. """
# Read existing cfg
cfg = configparser.ConfigParser()
path = args.work + "/workdir.cfg"
if os.path.isfile(path):
cfg.read(path)
# Set current date for chroot suffix
key = "chroot-init-dates"
if key not in cfg:
cfg[key] = {}
cfg[key][suffix] = str(int(time.time()))
# Write back
with open(path, "w") as handle:
cfg.write(handle)
def chroots_outdated(args):
""" Check if init dates from workdir.cfg indicate that any chroot is
outdated.
:returns: True if any of the chroots are outdated and should be zapped,
False otherwise """
# Skip if workdir.cfg doesn't exist
path = args.work + "/workdir.cfg"
if not os.path.exists(path):
return False
cfg = configparser.ConfigParser()
cfg.read(path)
key = "chroot-init-dates"
if key not in cfg:
return False
date_outdated = time.time() - pmb.config.chroot_outdated
for suffix in cfg[key]:
date_init = int(cfg[key][suffix])
if date_init <= date_outdated:
return True
return False
def clean(args):
""" Remove obsolete data data from workdir.cfg.
:returns: None if workdir does not exist,
True if config was rewritten,
False if config did not change """
# Skip if workdir.cfg doesn't exist
path = args.work + "/workdir.cfg"
if not os.path.exists(path):
return None
# Read
cfg = configparser.ConfigParser()
cfg.read(path)
# Remove entries for deleted chroots
key = "chroot-init-dates"
changed = False
if key in cfg:
for suffix in cfg[key]:
path_suffix = args.work + "/chroot_" + suffix
if os.path.exists(path_suffix):
continue
changed = True
del cfg[key][suffix]
# Write back
if changed:
with open(path, "w") as handle:
cfg.write(handle)
return changed

103
test/test_config_workdir.py Normal file
View File

@ -0,0 +1,103 @@
# Copyright 2020 Oliver Smith
# SPDX-License-Identifier: GPL-3.0-or-later
""" Test pmb/config/workdir.py """
import os
import pytest
import sys
import time
import pmb_test # noqa
import pmb.config
import pmb.config.workdir
@pytest.fixture
def args(request):
import pmb.parse
sys.argv = ["pmbootstrap", "init"]
args = pmb.parse.arguments()
args.log = args.work + "/log_testsuite.txt"
pmb.helpers.logging.init(args)
request.addfinalizer(args.logfd.close)
return args
def test_chroot_save_date(args, tmpdir, monkeypatch):
# Override time.time()
def fake_time():
return 1234567890.1234
monkeypatch.setattr(time, "time", fake_time)
args.work = str(tmpdir)
func = pmb.config.workdir.chroot_save_date
func(args, "native")
expected = "[chroot-init-dates]\nnative = 1234567890\n\n"
with open(args.work + "/workdir.cfg", "r") as handle:
assert handle.read() == expected
# Write again (different code path)
func(args, "buildroot_armhf")
expected = ("[chroot-init-dates]\nnative = 1234567890\n"
"buildroot_armhf = 1234567890\n\n")
with open(args.work + "/workdir.cfg", "r") as handle:
assert handle.read() == expected
def test_chroots_outdated(args, tmpdir, monkeypatch):
args.work = str(tmpdir)
# Override time.time(): now is "100"
def fake_time():
return 100.0
monkeypatch.setattr(time, "time", fake_time)
# workdir.cfg does not exist
func = pmb.config.workdir.chroots_outdated
assert func(args) is False
# workdir.cfg is empty file
with open(args.work + "/workdir.cfg", "w") as handle:
handle.write("")
assert func(args) is False
# Write fake workdir.cfg: native was created at "90"
with open(args.work + "/workdir.cfg", "w") as handle:
handle.write("[chroot-init-dates]\nnative = 90\n\n")
# Outdated (date_outdated: 90)
monkeypatch.setattr(pmb.config, "chroot_outdated", 10)
assert func(args) is True
# Not outdated (date_outdated: 89)
monkeypatch.setattr(pmb.config, "chroot_outdated", 11)
assert func(args) is False
def test_clean(args, tmpdir):
args.work = str(tmpdir)
# 0. workdir.cfg does not exist
func = pmb.config.workdir.clean
assert func(args) is None
# Write fake workdir.cfg
cfg_fake = "[chroot-init-dates]\nnative = 1337\n\n"
with open(args.work + "/workdir.cfg", "w") as handle:
handle.write(cfg_fake)
# 1. chroot_native dir exists
os.makedirs(args.work + "/chroot_native")
assert func(args) is False
# workdir.cfg: unchanged
with open(args.work + "/workdir.cfg", "r") as handle:
assert handle.read() == cfg_fake
# 2. chroot_native dir does not exist
os.rmdir(args.work + "/chroot_native")
assert func(args) is True
# workdir.cfg: "native" entry removed
with open(args.work + "/workdir.cfg", "r") as handle:
assert handle.read() == "[chroot-init-dates]\n\n"