From fe45fa3610875491199ad505e8f10563cac31df6 Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Mon, 20 Jan 2020 15:55:12 -0800 Subject: [PATCH] lorax: Catch rootfs out of space failures It isn't always obvious what happened when the rootfs runs out of space, especially when using lorax via pungi. So this checks for the out of space error string when building the runtime image and logs it to the primary logfile and console as an error with the rootfs size. eg. 2020-01-20 18:52:58,920: The rootfs ran out of space with size=1 --- src/pylorax/treebuilder.py | 11 +++++++++-- tests/pylorax/test_imgutils.py | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/pylorax/treebuilder.py b/src/pylorax/treebuilder.py index c02d0ea6..395d71e2 100644 --- a/src/pylorax/treebuilder.py +++ b/src/pylorax/treebuilder.py @@ -23,6 +23,7 @@ logger = logging.getLogger("pylorax.treebuilder") import os, re from os.path import basename from shutil import copytree, copy2 +from subprocess import CalledProcessError from pathlib import Path import itertools @@ -228,8 +229,14 @@ class RuntimeBuilder(object): workdir = joinpaths(os.path.dirname(outfile), "runtime-workdir") os.makedirs(joinpaths(workdir, "LiveOS")) - imgutils.mkrootfsimg(self.vars.root, joinpaths(workdir, "LiveOS/rootfs.img"), - "Anaconda", size=size) + # Catch problems with the rootfs being too small and clearly log them + try: + imgutils.mkrootfsimg(self.vars.root, joinpaths(workdir, "LiveOS/rootfs.img"), + "Anaconda", size=size) + except CalledProcessError as e: + if e.stdout and "No space left on device" in e.stdout: + logger.error("The rootfs ran out of space with size=%d", size) + raise # squash the live rootfs and clean up workdir imgutils.mksquashfs(workdir, outfile, compression, compressargs) diff --git a/tests/pylorax/test_imgutils.py b/tests/pylorax/test_imgutils.py index f40f6bd8..56d2dcad 100644 --- a/tests/pylorax/test_imgutils.py +++ b/tests/pylorax/test_imgutils.py @@ -17,6 +17,7 @@ import glob import os import parted +from subprocess import CalledProcessError import tarfile import tempfile import unittest @@ -270,6 +271,22 @@ class ImgUtilsTest(unittest.TestCase): file_details = get_file_magic(disk_img.name) self.assertTrue("ext2 filesystem" in file_details, file_details) + @unittest.skipUnless(os.geteuid() == 0 and not os.path.exists("/.in-container"), "requires root privileges, and no containers") + def test_small_mkext4img(self): + """Test mkext4img error handling""" + with tempfile.TemporaryDirectory(prefix="lorax.test.") as work_dir: + with tempfile.NamedTemporaryFile(prefix="lorax.test.disk.") as disk_img: + mkfakerootdir(work_dir) + # Add a 8MiB file + with open(joinpaths(work_dir, "large-file"), "w") as f: + for _ in range(5): + f.write("A" * 1024**2) + graft = {work_dir+"/etc/yum.repos.d/": "./tests/pylorax/repos/server-2.repo"} + try: + mkext4img(work_dir, disk_img.name, graft=graft, size=5*1024**2) + except CalledProcessError as e: + self.assertTrue(e.stdout and "No space left on device" in e.stdout) + @unittest.skipUnless(os.geteuid() == 0 and not os.path.exists("/.in-container"), "requires root privileges, and no containers") def test_mkbtrfsimg(self): """Test mkbtrfsimg function (requires loop)"""