On 8/22/19 3:47 PM, Marc-André Lureau wrote: > Add a --engine option to select either docker, podman or auto. > > Among other advantages, podman allows to run rootless & daemonless > containers, fortunately sharing compatible CLI with docker. > > With current podman, we have to use a uidmap trick in order to be able > to rw-share the ccache directory with the container user. > > With a user 1000, the default mapping is: > > 1000 (host) -> 0 > (container). > So write access to /var/tmp/ccache ends will end with permission > denied error. > > With "--uidmap 1000:0:1 --uidmap 0:1:1000", the mapping is: > 1000 (host) -> 0 (container, 1st namespace) -> 1000 (container, 2nd > namespace). > (the rest is mumbo jumbo to avoid holes in the range of UIDs) > > A future podman version may have an option such as --userns-keep-uid. > Thanks to Debarshi Ray <ri...@redhat.com> for the help! > > Signed-off-by: Marc-André Lureau <marcandre.lur...@redhat.com> > Acked-by: Alex Bennée <alex.ben...@linaro.org> > Reviewed-by: Daniel P. Berrangé <berra...@redhat.com> > --- > tests/docker/docker.py | 48 +++++++++++++++++++++++++++++++++++++----- > 1 file changed, 43 insertions(+), 5 deletions(-) > > diff --git a/tests/docker/docker.py b/tests/docker/docker.py > index f15545aeea..ac5baab4ca 100755 > --- a/tests/docker/docker.py > +++ b/tests/docker/docker.py > @@ -20,6 +20,7 @@ import hashlib > import atexit > import uuid > import argparse > +import enum
This broke Shippable: https://app.shippable.com/github/qemu/qemu/runs/1897/summary/console Traceback (most recent call last): File "./tests/docker/docker.py", line 23, in <module> import enum ImportError: No module named enum > import tempfile > import re > import signal > @@ -38,6 +39,26 @@ FILTERED_ENV_NAMES = ['ftp_proxy', 'http_proxy', > 'https_proxy'] > > DEVNULL = open(os.devnull, 'wb') > > +class EngineEnum(enum.IntEnum): > + AUTO = 1 > + DOCKER = 2 > + PODMAN = 3 > + > + def __str__(self): > + return self.name.lower() > + > + def __repr__(self): > + return str(self) > + > + @staticmethod > + def argparse(s): > + try: > + return EngineEnum[s.upper()] > + except KeyError: > + return s > + > + > +USE_ENGINE = EngineEnum.AUTO > > def _text_checksum(text): > """Calculate a digest string unique to the text content""" > @@ -48,9 +69,14 @@ def _file_checksum(filename): > return _text_checksum(open(filename, 'rb').read()) > > > -def _guess_docker_command(): > - """ Guess a working docker command or raise exception if not found""" > - commands = [["docker"], ["sudo", "-n", "docker"]] > +def _guess_engine_command(): > + """ Guess a working engine command or raise exception if not found""" > + commands = [] > + > + if USE_ENGINE in [EngineEnum.AUTO, EngineEnum.PODMAN]: > + commands += [["podman"]] > + if USE_ENGINE in [EngineEnum.AUTO, EngineEnum.DOCKER]: > + commands += [["docker"], ["sudo", "-n", "docker"]] > for cmd in commands: > try: > # docker version will return the client details in stdout > @@ -61,7 +87,7 @@ def _guess_docker_command(): > except OSError: > pass > commands_txt = "\n".join([" " + " ".join(x) for x in commands]) > - raise Exception("Cannot find working docker command. Tried:\n%s" % > + raise Exception("Cannot find working engine command. Tried:\n%s" % > commands_txt) > > > @@ -190,7 +216,7 @@ def _dockerfile_preprocess(df): > class Docker(object): > """ Running Docker commands """ > def __init__(self): > - self._command = _guess_docker_command() > + self._command = _guess_engine_command() > self._instances = [] > atexit.register(self._kill_instances) > signal.signal(signal.SIGTERM, self._kill_instances) > @@ -340,6 +366,11 @@ class RunCommand(SubCommand): > if args.run_as_current_user: > uid = os.getuid() > argv = [ "-u", str(uid) ] + argv > + docker = Docker() > + if docker._command[0] == "podman": > + argv = [ "--uidmap", "%d:0:1" % uid, > + "--uidmap", "0:1:%d" % uid, > + "--uidmap", "%d:%d:64536" % (uid + 1, uid + 1)] + > argv > return Docker().run(argv, args.keep, quiet=args.quiet) > > > @@ -507,6 +538,8 @@ class ProbeCommand(SubCommand): > print("yes") > elif docker._command[0] == "sudo": > print("sudo") > + elif docker._command[0] == "podman": > + print("podman") > except Exception: > print("no") > > @@ -602,9 +635,13 @@ class CheckCommand(SubCommand): > > > def main(): > + global USE_ENGINE > + > parser = argparse.ArgumentParser(description="A Docker helper", > usage="%s <subcommand> ..." % > os.path.basename(sys.argv[0])) > + parser.add_argument("--engine", type=EngineEnum.argparse, > choices=list(EngineEnum), > + help="specify which container engine to use") > subparsers = parser.add_subparsers(title="subcommands", help=None) > for cls in SubCommand.__subclasses__(): > cmd = cls() > @@ -613,6 +650,7 @@ def main(): > cmd.args(subp) > subp.set_defaults(cmdobj=cmd) > args, argv = parser.parse_known_args() > + USE_ENGINE = args.engine > return args.cmdobj.run(args, argv) > > >