aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoshua Lock <joshua.g.lock@intel.com>2016-04-05 15:24:38 +0100
committerJoshua Lock <joshua.g.lock@intel.com>2016-04-13 10:17:32 +0100
commit9ffc69b4954f9fb21b9572a0599f685242a941d9 (patch)
treef1b7f274553981afb4c89ce6f351231e42ec0818
parentede9a6154b3c77f51abf848115f3a4c958a72b4a (diff)
downloadmeta-swupd-9ffc69b4954f9fb21b9572a0599f685242a941d9.tar.gz
meta-swupd-9ffc69b4954f9fb21b9572a0599f685242a941d9.tar.bz2
meta-swupd-9ffc69b4954f9fb21b9572a0599f685242a941d9.zip
swupd-image: implement image qa checks
Implement a task which runs after image creation and executes the functions defined in SWUPD_IMAGE_SANITY_CHECKS to validate the constructed image. do_swupd_sanity_check_image() is influenced heavily by the sanity_check_conffiles method in OE-Core's sanity.bbclass. Include a single QA function to start with, disabled by default, which checks whether there are any dangling symlinks in the image — this check is based on code from the Ostro Project by Patrick Ohly. Signed-off-by: Joshua Lock <joshua.g.lock@intel.com>
-rw-r--r--classes/swupd-image.bbclass85
1 files changed, 85 insertions, 0 deletions
diff --git a/classes/swupd-image.bbclass b/classes/swupd-image.bbclass
index 783c22b..7b0a7a1 100644
--- a/classes/swupd-image.bbclass
+++ b/classes/swupd-image.bbclass
@@ -565,3 +565,88 @@ swupd_patch_os_release () {
}
swupd_patch_os_release[vardepsexclude] = "OS_VERSION"
ROOTFS_POSTPROCESS_COMMAND += "swupd_patch_os_release; "
+
+SWUPD_IMAGE_SANITY_CHECKS = ""
+# Add image-level QA/sanity checks to SWUPD_IMAGE_SANITY_CHECKS
+#
+# SWUPD_IMAGE_SANITY_CHECKS += " \
+# swupd_check_dangling_symlinks \
+# "
+
+# This task runs all functions in SWUPD_IMAGE_SANITY_CHECKS after the image
+# construction has completed in order to validate the resulting image.
+# Image sanity checks should raise a NotImplementedError when they fail,
+# passing any failure messages to the Exception. For example:
+#
+# python swupd_image_check_always_fails () {
+# raise NotImplementedError('This check always fails')
+# }
+python do_swupd_sanity_check_image () {
+ funcs = (d.getVar('SWUPD_IMAGE_SANITY_CHECKS', True) or '').split()
+ qasane = True
+
+ for func in funcs:
+ try:
+ bb.build.exec_func(func, d, pythonexception=True)
+ except NotImplementedError as e:
+ qasane = False
+ bb.error(str(e))
+
+ if not qasane:
+ bb.fatal('QA errors found whilst checking swupd image sanity.')
+}
+addtask swupd_sanity_check_image after do_image_complete before do_build
+
+# Check whether the constructed image contains any dangling symlinks, these
+# are likely to indicate deeper issues.
+# NOTE: you'll almost certainly want to override these for your distro.
+# /run, /var/volatile and /dev only get mounted at runtime.
+SWUPD_IMAGE_SYMLINK_WHITELIST ??= " \
+ /run/lock \
+ /var/volatile/tmp \
+ /var/volatile/log \
+ /dev/null \
+ /proc/mounts \
+ /run/resolv.conf \
+"
+
+python swupd_check_dangling_symlinks() {
+ rootfs = d.getVar("IMAGE_ROOTFS", True)
+
+ def resolve_links(target, root):
+ if not target.startswith('/'):
+ target = os.path.normpath(os.path.join(root, target))
+ else:
+ # Absolute links are in fact relative to the rootfs.
+ # Can't use os.path.join() here, it skips the
+ # components before absolute paths.
+ target = os.path.normpath(rootfs + target)
+ if os.path.islink(target):
+ root = os.path.dirname(target)
+ target = os.readlink(target)
+ target = resolve_links(target, root)
+ return target
+
+ # Check for dangling symlinks. One common reason for them
+ # in swupd images is update-alternatives where the alternative
+ # that gets chosen in the mega image then is not installed
+ # in a sub-image.
+ #
+ # Some allowed cases are whitelisted.
+ whitelist = d.getVar('SWUPD_IMAGE_SYMLINK_WHITELIST', True).split()
+ message = ''
+ for root, dirs, files in os.walk(rootfs):
+ for entry in files + dirs:
+ path = os.path.join(root, entry)
+ if os.path.islink(path):
+ target = os.readlink(path)
+ final_target = resolve_links(target, root)
+ if not os.path.exists(final_target) and not final_target[len(rootfs):] in whitelist:
+ message = message + 'Dangling symlink: %s -> %s -> %s does not resolve to a valid filesystem entry.\n' % (path, target, final_target)
+
+ if message != '':
+ message = message + '\nIf these symlinks not pointing to a valid destination is not an issue \
+i.e. the link is to a file which only exists at runtime, such as files in /proc, add them to \
+SWUPD_IMAGE_SYMLINK_WHITELIST to resolve this error.'
+ raise NotImplementedError(message)
+}