From patchwork Tue Jul 19 14:31:09 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Fam Zheng X-Patchwork-Id: 72335 Delivered-To: patch@linaro.org Received: by 10.140.29.52 with SMTP id a49csp116953qga; Tue, 19 Jul 2016 07:40:41 -0700 (PDT) X-Received: by 10.37.2.82 with SMTP id 79mr13234382ybc.95.1468939241241; Tue, 19 Jul 2016 07:40:41 -0700 (PDT) Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id 189si3660431ybo.121.2016.07.19.07.40.40 for (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 19 Jul 2016 07:40:41 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org Received: from localhost ([::1]:56467 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bPWCO-00028A-9d for patch@linaro.org; Tue, 19 Jul 2016 10:40:40 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41436) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bPW3V-0006hM-P0 for qemu-devel@nongnu.org; Tue, 19 Jul 2016 10:31:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bPW3T-0002Nq-Fy for qemu-devel@nongnu.org; Tue, 19 Jul 2016 10:31:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53371) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bPW3T-0002Ni-7h for qemu-devel@nongnu.org; Tue, 19 Jul 2016 10:31:27 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CEBAE85547; Tue, 19 Jul 2016 14:31:26 +0000 (UTC) Received: from ad.usersys.redhat.com (dhcp-14-122.nay.redhat.com [10.66.14.122]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u6JEVLVf004350; Tue, 19 Jul 2016 10:31:25 -0400 From: Fam Zheng To: qemu-devel@nongnu.org Date: Tue, 19 Jul 2016 22:31:09 +0800 Message-Id: <1468938677-15607-3-git-send-email-famz@redhat.com> In-Reply-To: <1468938677-15607-1-git-send-email-famz@redhat.com> References: <1468938677-15607-1-git-send-email-famz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Tue, 19 Jul 2016 14:31:26 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 02/10] tests/docker/docker.py: support --include-executable X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, famz@redhat.com Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Alex Bennée When passed the path to a binary we copy it and any linked libraries (if it is dynamically linked) into the docker build context. These can then be included by a dockerfile with the line: # Copy all of context into container ADD . / This is mainly intended for setting up foreign architecture docker images which use qemu-$arch to do cross-architecture linux-user execution. It also relies on the host and guest file-system following reasonable multi-arch layouts so the copied libraries don't clash with the guest ones. Signed-off-by: Alex Bennée Message-id: 1468934445-32183-3-git-send-email-famz@redhat.com Signed-off-by: Fam Zheng --- tests/docker/docker.py | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) -- 2.7.4 diff --git a/tests/docker/docker.py b/tests/docker/docker.py index ae40bb3..96d906e 100755 --- a/tests/docker/docker.py +++ b/tests/docker/docker.py @@ -20,6 +20,7 @@ import atexit import uuid import argparse import tempfile +import re from shutil import copy, rmtree def _text_checksum(text): @@ -38,6 +39,54 @@ def _guess_docker_command(): raise Exception("Cannot find working docker command. Tried:\n%s" % \ commands_txt) +def _copy_with_mkdir(src, root_dir, sub_path): + """Copy src into root_dir, creating sub_path as needed.""" + dest_dir = os.path.normpath("%s/%s" % (root_dir, sub_path)) + try: + os.makedirs(dest_dir) + except OSError: + # we can safely ignore already created directories + pass + + dest_file = "%s/%s" % (dest_dir, os.path.basename(src)) + copy(src, dest_file) + + +def _get_so_libs(executable): + """Return a list of libraries associated with an executable. + + The paths may be symbolic links which would need to be resolved to + ensure theright data is copied.""" + + libs = [] + ldd_re = re.compile(r"(/.*/)(\S*)") + try: + ldd_output = subprocess.check_output(["ldd", executable]) + for line in ldd_output.split("\n"): + search = ldd_re.search(line) + if search and len(search.groups()) == 2: + so_path = search.groups()[0] + so_lib = search.groups()[1] + libs.append("%s/%s" % (so_path, so_lib)) + except subprocess.CalledProcessError: + print "%s had no associated libraries (static build?)" % (executable) + + return libs + +def _copy_binary_with_libs(src, dest_dir): + """Copy a binary executable and all its dependant libraries. + + This does rely on the host file-system being fairly multi-arch + aware so the file don't clash with the guests layout.""" + + _copy_with_mkdir(src, dest_dir, "/usr/bin") + + libs = _get_so_libs(src) + if libs: + for l in libs: + so_path = os.path.dirname(l) + _copy_with_mkdir(l , dest_dir, so_path) + class Docker(object): """ Running Docker commands """ def __init__(self): @@ -151,6 +200,10 @@ class BuildCommand(SubCommand): """ Build docker image out of a dockerfile. Arguments: """ name = "build" def args(self, parser): + parser.add_argument("--include-executable", "-e", + help="""Specify a binary that will be copied to the + container together with all its dependent + libraries""") parser.add_argument("tag", help="Image Tag") parser.add_argument("dockerfile", @@ -168,6 +221,11 @@ class BuildCommand(SubCommand): # Create a docker context directory for the build docker_dir = tempfile.mkdtemp(prefix="docker_build") + # Do we include a extra binary? + if args.include_executable: + _copy_binary_with_libs(args.include_executable, + docker_dir) + dkr.build_image(tag, docker_dir, dockerfile, quiet=args.quiet, argv=argv)