tests: docker.py be even smarter with persistent binfmt_misc

If we have a persistent mapping we don't need the QEMU binary copied
into the container as the kernel has already opened the file and will
pass the fd in. However the support libraries will still need to be
there.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
This commit is contained in:
Alex Bennée 2019-01-23 17:07:08 +00:00
parent 43c898b75a
commit d10404b193

View File

@ -96,13 +96,22 @@ def _get_so_libs(executable):
return libs return libs
def _copy_binary_with_libs(src, dest_dir): def _copy_binary_with_libs(src, bin_dest, dest_dir):
"""Copy a binary executable and all its dependent libraries. """Maybe copy a binary and all its dependent libraries.
If bin_dest isn't set we only copy the support libraries because
we don't need qemu in the docker path to run (due to persistent
mapping). Indeed users may get confused if we aren't running what
is in the image.
This does rely on the host file-system being fairly multi-arch This does rely on the host file-system being fairly multi-arch
aware so the file don't clash with the guests layout.""" aware so the file don't clash with the guests layout.
"""
_copy_with_mkdir(src, dest_dir, "/usr/bin") if bin_dest:
_copy_with_mkdir(src, dest_dir, os.path.dirname(bin_dest))
else:
print("only copying support libraries for %s" % (src))
libs = _get_so_libs(src) libs = _get_so_libs(src)
if libs: if libs:
@ -116,21 +125,26 @@ def _check_binfmt_misc(executable):
The details of setting up binfmt_misc are outside the scope of The details of setting up binfmt_misc are outside the scope of
this script but we should at least fail early with a useful this script but we should at least fail early with a useful
message if it won't work.""" message if it won't work.
Returns the configured binfmt path and a valid flag. For
persistent configurations we will still want to copy and dependent
libraries.
"""
binary = os.path.basename(executable) binary = os.path.basename(executable)
binfmt_entry = "/proc/sys/fs/binfmt_misc/%s" % (binary) binfmt_entry = "/proc/sys/fs/binfmt_misc/%s" % (binary)
if not os.path.exists(binfmt_entry): if not os.path.exists(binfmt_entry):
print ("No binfmt_misc entry for %s" % (binary)) print ("No binfmt_misc entry for %s" % (binary))
return None return None, False
with open(binfmt_entry) as x: entry = x.read() with open(binfmt_entry) as x: entry = x.read()
if re.search("flags:.*F.*\n", entry): if re.search("flags:.*F.*\n", entry):
print("binfmt_misc for %s uses persistent(F) mapping to host binary\n" % print("binfmt_misc for %s uses persistent(F) mapping to host binary\n" %
(binary)) (binary))
return None return None, True
m = re.search("interpreter (\S+)\n", entry) m = re.search("interpreter (\S+)\n", entry)
interp = m.group(1) interp = m.group(1)
@ -138,7 +152,8 @@ def _check_binfmt_misc(executable):
print("binfmt_misc for %s does not point to %s, using %s" % print("binfmt_misc for %s does not point to %s, using %s" %
(binary, executable, interp)) (binary, executable, interp))
return interp return interp, True
def _read_qemu_dockerfile(img_name): def _read_qemu_dockerfile(img_name):
# special case for Debian linux-user images # special case for Debian linux-user images
@ -345,7 +360,8 @@ class BuildCommand(SubCommand):
# Validate binfmt_misc will work # Validate binfmt_misc will work
if args.include_executable: if args.include_executable:
if not _check_binfmt_misc(args.include_executable): qpath, enabled = _check_binfmt_misc(args.include_executable)
if not enabled:
return 1 return 1
# Is there a .pre file to run in the build context? # Is there a .pre file to run in the build context?
@ -368,7 +384,9 @@ class BuildCommand(SubCommand):
# FIXME: there is no checksum of this executable and the linked # FIXME: there is no checksum of this executable and the linked
# libraries, once the image built any change of this executable # libraries, once the image built any change of this executable
# or any library won't trigger another build. # or any library won't trigger another build.
_copy_binary_with_libs(args.include_executable, docker_dir) _copy_binary_with_libs(args.include_executable,
qpath, docker_dir)
for filename in args.extra_files or []: for filename in args.extra_files or []:
_copy_with_mkdir(filename, docker_dir) _copy_with_mkdir(filename, docker_dir)
cksum += [(filename, _file_checksum(filename))] cksum += [(filename, _file_checksum(filename))]
@ -400,14 +418,16 @@ class UpdateCommand(SubCommand):
tmp_tar = TarFile(fileobj=tmp, mode='w') tmp_tar = TarFile(fileobj=tmp, mode='w')
# Add the executable to the tarball, using the current # Add the executable to the tarball, using the current
# configured binfmt_misc path. # configured binfmt_misc path. If we don't get a path then we
ff = _check_binfmt_misc(args.executable) # only need the support libraries copied
if not ff: ff, enabled = _check_binfmt_misc(args.executable)
bn = os.path.basename(args.executable)
ff = "/usr/bin/%s" % bn
print ("No binfmt_misc configured: copied to %s" % (ff))
tmp_tar.add(args.executable, arcname=ff) if not enabled:
print("binfmt_misc not enabled, update disabled")
return 1
if ff:
tmp_tar.add(args.executable, arcname=ff)
# Add any associated libraries # Add any associated libraries
libs = _get_so_libs(args.executable) libs = _get_so_libs(args.executable)