The attached patch should help the comparison to continue instead of crashing.
A few points are still open/unclear for me: * When FsImageContainer.open_archive returns None, the rest of the code still thinks there are files to extract and calls get_member_names? Is this OK? Should i behave more like if an exception was raised? * Is it OK that the extracting error shows up in the HTML output? * Should we create a test for missing guestfs and guestfs launch failed? * Should we tell the user about the possibility that unreadable kernels under /boot can cause this problem? And should this information be included in the HTML output or only in the log outupt * Is it possible to have a mechanism like @tool_required or raise RequiredToolNotFound for missing python modules like "guestfs"
>From 0fdaa5ddabdf3846e56ab9c7af342fc2ffd1352b Mon Sep 17 00:00:00 2001 From: Peter Oberndorfer <kumbay...@arcor.de> Date: Sun, 21 May 2017 21:54:50 +0200 Subject: [PATCH] Better handle errors in FsImageContainer.open_archive() Under some conditions GuestFS.launch() can fail. For example under Ubuntu 17.04 the linux kernel images under /boot/ are only readable by root. https://bugs.launchpad.net/ubuntu/+source/linux/+bug/759725 The failure is handled in open_archive but extract and close_archive are still called and do not handle the half initialized FsImageContainer. They throw the following exceptions when called: RuntimeError: tar_out: call launch before using this function. RuntimeError: umount_all: call launch before using this function Avoid this problem the following way: * If starting guestfs fails, raise a ContainerExtractionError. This will cause the image to be compared as a raw file without calling any other container extraction methods. It will also leave information about the failed extraction in the result. * If guestfs is not available, return an empty array from get_member_names. This will cause the image to be compared as a raw file. It would be nice to raise a RequiredToolNotFound in this case but currently it supports missing tools, but not missing python modules. This should help with https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=837681 --- diffoscope/comparators/fsimage.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/diffoscope/comparators/fsimage.py b/diffoscope/comparators/fsimage.py index 028d8c6..e7f1334 100644 --- a/diffoscope/comparators/fsimage.py +++ b/diffoscope/comparators/fsimage.py @@ -22,6 +22,7 @@ import logging import os.path from diffoscope.difference import Difference +from diffoscope.exc import ContainerExtractionError from .utils.file import File from .utils.archive import Archive @@ -36,6 +37,7 @@ logger = logging.getLogger(__name__) class FsImageContainer(Archive): def open_archive(self): + self.launched = False if not guestfs: return None @@ -47,25 +49,31 @@ class FsImageContainer(Archive): self.g.add_drive_opts (self.source.path, format="raw", readonly=1) try: self.g.launch() - except RuntimeError: + except RuntimeError as exc: logger.exception("guestfs can't be launched") logger.error("If memory is too tight for 512 MiB, try running with LIBGUESTFS_MEMSIZE=256 or lower.") - return None + self.g.close() + self.g = None + raise ContainerExtractionError(self.source.path, exc) + self.launched = True devices = self.g.list_devices() self.g.mount(devices[0], "/") self.fs = self.g.list_filesystems()[devices[0]] return self def close_archive(self): - if not guestfs: + if not guestfs or not self.launched: return None self.g.umount_all() self.g.close() def get_member_names(self): + if not guestfs or not self.launched: + return [] return [os.path.basename(self.source.path) + '.tar'] def extract(self, member_name, dest_dir): + assert guestfs and self.launched dest_path = os.path.join(dest_dir, member_name) logger.debug('filesystem image extracting to %s', dest_path) self.g.tar_out("/", dest_path) -- 2.11.0
_______________________________________________ Reproducible-builds mailing list Reproducible-builds@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/reproducible-builds