summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/classes/workdir_save.bbclass54
1 files changed, 54 insertions, 0 deletions
diff --git a/meta/classes/workdir_save.bbclass b/meta/classes/workdir_save.bbclass
new file mode 100644
index 0000000000..70070419a8
--- /dev/null
+++ b/meta/classes/workdir_save.bbclass
@@ -0,0 +1,54 @@
+# Save the work directory for a recipe when one of its tasks fails.
+# Useful in cases where the environment in which builds are run is
+# ephemeral or otherwise inaccessible for examination during
+# debugging.
+#
+# To enable, simply add the following to your configuration:
+#
+# INHERIT += "workdir_save"
+#
+# Notes:
+# * For this to work you also need corresponding logic in your build
+# orchestration tool to pick up any files written out to WORKDIR_SAVE_DIR
+# (with the other assumption being that no files are present there at
+# the start of the build).
+# * Work directories can be quite large, so saving them can take some time
+# and of course space.
+#
+# Copyright (c) 2020 Microsoft Corporation
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+WORKDIR_SAVE_DIR ?= "${TMPDIR}/workdir_save"
+WORKDIR_SAVE_ENABLED ?= "1"
+
+addhandler workdir_save_handler
+workdir_save_handler[eventmask] = "bb.build.TaskFailed"
+
+python workdir_save_handler() {
+ import datetime
+ if d.getVar('WORKDIR_SAVE_ENABLED') != '1':
+ return
+
+ base_workdir = d.getVar('BASE_WORKDIR')
+ workdir = d.getVar('WORKDIR')
+ outdir = d.getVar('WORKDIR_SAVE_DIR')
+ bb.utils.mkdirhier(outdir)
+ pn = d.getVar('PN')
+ tstamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
+ tarfn = 'workdir_%s_%s.tar.gz' % (pn, tstamp)
+ tarfp = os.path.join(outdir, tarfn)
+ taskname = d.getVar('BB_CURRENTTASK')
+ bb.plain('NOTE: Saving workdir for failed task %s.do_%s to %s' % (pn, taskname, tarfp))
+ try:
+ bb.process.run(['tar', 'czf', tarfp,
+ os.path.relpath(workdir, base_workdir)], cwd=base_workdir)
+ except bb.process.ExecutionError as e:
+ # It is possible for other tasks to be writing to the workdir
+ # while we are tarring it up, in which case tar will return 1,
+ # but we don't care in this situation (tar returns 2 for other
+ # errors so we we will see those)
+ if e.exitcode != 1:
+ bb.warn('workdir save error: %s' % str(e))
+}