v2: Fix warning due to include.
Various temp dir/file changes. Don't use "find -executable" to be compatible with Mac. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQEcBAABCAAGBQJXTqs5AAoJEMo1YkxqkXHGhRkIAIjmtKdjKaR2KkdqeziD/enB FCY5Kvm90UvZxpEmQuA0SXyOuxP3gRPSTG5XU96tNqd40fbhkWTaLzo6PjyS3d/P 6GzEsi4R6zu4q664z7akwvY2Q6mpph5iPtSc9PIrWv2GB4h3j4Hwps/X67smaME0 zstaU8A+LhxNFMS7x0TBNXwy56NmAirOrdIWdKwx+RQBGYDdC10FtrMbgLh3G0So oZM5MSqAAeieN6QEzQM8QFEmmiJgDhnwi7TM82tUgqTrww4QVZnhMYaZzope0ias tA1LvbkfMXIH4NtBJET5ZMlr/fxrvfDVcxDUOUgLzi35h1tjLd56d7hFzAJd27E= =hPhl -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/famz/tags/pull-docker-20160601' into staging v2: Fix warning due to include. Various temp dir/file changes. Don't use "find -executable" to be compatible with Mac. # gpg: Signature made Wed 01 Jun 2016 10:30:33 BST using RSA key ID 6A9171C6 # gpg: Good signature from "Fam Zheng <famz@redhat.com>" # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 5003 7CB7 9706 0F76 F021 AD56 CA35 624C 6A91 71C6 * remotes/famz/tags/pull-docker-20160601: .gitignore: Ignore docker source copy MAINTAINERS: Add tests/docker docker: Add EXTRA_CONFIGURE_OPTS docs: Add text for tests/docker in build-system.txt docker: Add travis tool docker: Add mingw test docker: Add clang test docker: Add full test docker: Add quick test docker: Add common.rc docker: Add test runner docker: Add images Makefile: Rules for docker testing Makefile: Always include rules.mak rules.mak: Add "COMMA" constant tests: Add utilities for docker testing Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
cbd614870f
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -108,4 +108,5 @@
|
||||||
cscope.*
|
cscope.*
|
||||||
tags
|
tags
|
||||||
TAGS
|
TAGS
|
||||||
|
docker-src.*
|
||||||
*~
|
*~
|
||||||
|
|
|
@ -1615,3 +1615,10 @@ Build system architecture
|
||||||
M: Daniel P. Berrange <berrange@redhat.com>
|
M: Daniel P. Berrange <berrange@redhat.com>
|
||||||
S: Odd Fixes
|
S: Odd Fixes
|
||||||
F: docs/build-system.txt
|
F: docs/build-system.txt
|
||||||
|
|
||||||
|
Docker testing
|
||||||
|
--------------
|
||||||
|
Docker based testing framework and cases
|
||||||
|
M: Fam Zheng <famz@redhat.com>
|
||||||
|
S: Maintained
|
||||||
|
F: tests/docker/
|
||||||
|
|
7
Makefile
7
Makefile
|
@ -6,7 +6,7 @@ BUILD_DIR=$(CURDIR)
|
||||||
# Before including a proper config-host.mak, assume we are in the source tree
|
# Before including a proper config-host.mak, assume we are in the source tree
|
||||||
SRC_PATH=.
|
SRC_PATH=.
|
||||||
|
|
||||||
UNCHECKED_GOALS := %clean TAGS cscope ctags
|
UNCHECKED_GOALS := %clean TAGS cscope ctags docker docker-%
|
||||||
|
|
||||||
# All following code might depend on configuration variables
|
# All following code might depend on configuration variables
|
||||||
ifneq ($(wildcard config-host.mak),)
|
ifneq ($(wildcard config-host.mak),)
|
||||||
|
@ -30,7 +30,6 @@ CONFIG_ALL=y
|
||||||
-include config-all-devices.mak
|
-include config-all-devices.mak
|
||||||
-include config-all-disas.mak
|
-include config-all-disas.mak
|
||||||
|
|
||||||
include $(SRC_PATH)/rules.mak
|
|
||||||
config-host.mak: $(SRC_PATH)/configure
|
config-host.mak: $(SRC_PATH)/configure
|
||||||
@echo $@ is out-of-date, running configure
|
@echo $@ is out-of-date, running configure
|
||||||
@# TODO: The next lines include code which supports a smooth
|
@# TODO: The next lines include code which supports a smooth
|
||||||
|
@ -49,6 +48,8 @@ ifneq ($(filter-out $(UNCHECKED_GOALS),$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fa
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
include $(SRC_PATH)/rules.mak
|
||||||
|
|
||||||
GENERATED_HEADERS = config-host.h qemu-options.def
|
GENERATED_HEADERS = config-host.h qemu-options.def
|
||||||
GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
|
GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
|
||||||
GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c
|
GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c
|
||||||
|
@ -643,3 +644,5 @@ endif
|
||||||
# Include automatically generated dependency files
|
# Include automatically generated dependency files
|
||||||
# Dependencies in Makefile.objs files come from our recursive subdir rules
|
# Dependencies in Makefile.objs files come from our recursive subdir rules
|
||||||
-include $(wildcard *.d tests/*.d)
|
-include $(wildcard *.d tests/*.d)
|
||||||
|
|
||||||
|
include $(SRC_PATH)/tests/docker/Makefile.include
|
||||||
|
|
|
@ -438,6 +438,11 @@ top level Makefile, so anything defined in this file will influence the
|
||||||
entire build system. Care needs to be taken when writing rules for tests
|
entire build system. Care needs to be taken when writing rules for tests
|
||||||
to ensure they only apply to the unit test execution / build.
|
to ensure they only apply to the unit test execution / build.
|
||||||
|
|
||||||
|
- tests/docker/Makefile.include
|
||||||
|
|
||||||
|
Rules for Docker tests. Like tests/Makefile, this file is included
|
||||||
|
directly by the top level Makefile, anything defined in this file will
|
||||||
|
influence the entire build system.
|
||||||
|
|
||||||
- po/Makefile
|
- po/Makefile
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
|
||||||
|
COMMA := ,
|
||||||
|
|
||||||
# Don't use implicit rules or variables
|
# Don't use implicit rules or variables
|
||||||
# we have explicit rules for everything
|
# we have explicit rules for everything
|
||||||
MAKEFLAGS += -rR
|
MAKEFLAGS += -rR
|
||||||
|
|
126
tests/docker/Makefile.include
Normal file
126
tests/docker/Makefile.include
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
# Makefile for Docker tests
|
||||||
|
|
||||||
|
.PHONY: docker docker-test docker-clean docker-image docker-qemu-src
|
||||||
|
|
||||||
|
DOCKER_SUFFIX := .docker
|
||||||
|
DOCKER_FILES_DIR := $(SRC_PATH)/tests/docker/dockerfiles
|
||||||
|
DOCKER_IMAGES := $(notdir $(basename $(wildcard $(DOCKER_FILES_DIR)/*.docker)))
|
||||||
|
DOCKER_TARGETS := $(patsubst %,docker-image-%,$(DOCKER_IMAGES))
|
||||||
|
# Use a global constant ccache directory to speed up repetitive builds
|
||||||
|
DOCKER_CCACHE_DIR := $$HOME/.cache/qemu-docker-ccache
|
||||||
|
|
||||||
|
DOCKER_TESTS := $(notdir $(shell \
|
||||||
|
find $(SRC_PATH)/tests/docker/ -name 'test-*' -type f))
|
||||||
|
|
||||||
|
DOCKER_TOOLS := travis
|
||||||
|
|
||||||
|
TESTS ?= %
|
||||||
|
IMAGES ?= %
|
||||||
|
|
||||||
|
# Make archive from git repo $1 to tar.gz $2
|
||||||
|
make-archive-maybe = $(if $(wildcard $1/*), \
|
||||||
|
$(call quiet-command, \
|
||||||
|
(cd $1; if git diff-index --quiet HEAD -- &>/dev/null; then \
|
||||||
|
git archive -1 HEAD --format=tar.gz -o $2; \
|
||||||
|
else \
|
||||||
|
git archive -1 $$(git stash create) --format=tar.gz -o $2; \
|
||||||
|
fi), \
|
||||||
|
" ARCHIVE $(notdir $2)"))
|
||||||
|
|
||||||
|
CUR_TIME := $(shell date +%Y-%m-%d-%H.%M.%S.$$$$)
|
||||||
|
# Makes the definition constant after the first expansion
|
||||||
|
DOCKER_SRC_COPY = $(eval DOCKER_SRC_COPY := docker-src.$(CUR_TIME))$(DOCKER_SRC_COPY)
|
||||||
|
|
||||||
|
$(DOCKER_SRC_COPY):
|
||||||
|
@mkdir $@
|
||||||
|
$(call make-archive-maybe, $(SRC_PATH), $@/qemu.tgz)
|
||||||
|
$(call make-archive-maybe, $(SRC_PATH)/dtc, $@/dtc.tgz)
|
||||||
|
$(call make-archive-maybe, $(SRC_PATH)/pixman, $@/pixman.tgz)
|
||||||
|
$(call quiet-command, cp $(SRC_PATH)/tests/docker/run $@/run, \
|
||||||
|
" COPY RUNNER")
|
||||||
|
|
||||||
|
docker-qemu-src: $(DOCKER_SRC_COPY)
|
||||||
|
|
||||||
|
docker-image: ${DOCKER_TARGETS}
|
||||||
|
|
||||||
|
# General rule for building docker images
|
||||||
|
docker-image-%: $(DOCKER_FILES_DIR)/%.docker
|
||||||
|
$(call quiet-command,\
|
||||||
|
$(SRC_PATH)/tests/docker/docker.py build qemu:$* $< \
|
||||||
|
$(if $V,,--quiet) $(if $(NOCACHE),--no-cache),\
|
||||||
|
" BUILD $*")
|
||||||
|
|
||||||
|
# Expand all the pre-requistes for each docker image and test combination
|
||||||
|
$(foreach i,$(DOCKER_IMAGES), \
|
||||||
|
$(foreach t,$(DOCKER_TESTS) $(DOCKER_TOOLS), \
|
||||||
|
$(eval .PHONY: docker-$t@$i) \
|
||||||
|
$(eval docker-$t@$i: docker-image-$i docker-run-$t@$i) \
|
||||||
|
) \
|
||||||
|
$(foreach t,$(DOCKER_TESTS), \
|
||||||
|
$(eval docker-test: docker-$t@$i) \
|
||||||
|
) \
|
||||||
|
)
|
||||||
|
|
||||||
|
docker:
|
||||||
|
@echo 'Build QEMU and run tests inside Docker containers'
|
||||||
|
@echo
|
||||||
|
@echo 'Available targets:'
|
||||||
|
@echo
|
||||||
|
@echo ' docker: Print this help.'
|
||||||
|
@echo ' docker-test: Run all image/test combinations.'
|
||||||
|
@echo ' docker-clean: Kill and remove residual docker testing containers.'
|
||||||
|
@echo ' docker-TEST@IMAGE: Run "TEST" in container "IMAGE".'
|
||||||
|
@echo ' Note: "TEST" is one of the listed test name,'
|
||||||
|
@echo ' or a script name under $$QEMU_SRC/tests/docker/;'
|
||||||
|
@echo ' "IMAGE" is one of the listed container name."'
|
||||||
|
@echo ' docker-image: Build all images.'
|
||||||
|
@echo ' docker-image-IMAGE: Build image "IMAGE".'
|
||||||
|
@echo
|
||||||
|
@echo 'Available container images:'
|
||||||
|
@echo ' $(DOCKER_IMAGES)'
|
||||||
|
@echo
|
||||||
|
@echo 'Available tests:'
|
||||||
|
@echo ' $(DOCKER_TESTS)'
|
||||||
|
@echo
|
||||||
|
@echo 'Available tools:'
|
||||||
|
@echo ' $(DOCKER_TOOLS)'
|
||||||
|
@echo
|
||||||
|
@echo 'Special variables:'
|
||||||
|
@echo ' TARGET_LIST=a,b,c Override target list in builds.'
|
||||||
|
@echo ' EXTRA_CONFIGURE_OPTS="..."'
|
||||||
|
@echo ' Extra configure options.'
|
||||||
|
@echo ' IMAGES="a b c ..": Filters which images to build or run.'
|
||||||
|
@echo ' TESTS="x y z .." Filters which tests to run (for docker-test).'
|
||||||
|
@echo ' J=[0..9]* Overrides the -jN parameter for make commands'
|
||||||
|
@echo ' (default is 1)'
|
||||||
|
@echo ' DEBUG=1 Stop and drop to shell in the created container'
|
||||||
|
@echo ' before running the command.'
|
||||||
|
@echo ' NOCACHE=1 Ignore cache when build images.'
|
||||||
|
|
||||||
|
docker-run-%: CMD = $(shell echo '$@' | sed -e 's/docker-run-\([^@]*\)@\(.*\)/\1/')
|
||||||
|
docker-run-%: IMAGE = $(shell echo '$@' | sed -e 's/docker-run-\([^@]*\)@\(.*\)/\2/')
|
||||||
|
docker-run-%: docker-qemu-src
|
||||||
|
@mkdir -p "$(DOCKER_CCACHE_DIR)"
|
||||||
|
@if test -z "$(IMAGE)" || test -z "$(CMD)"; \
|
||||||
|
then echo "Invalid target"; exit 1; \
|
||||||
|
fi
|
||||||
|
$(if $(filter $(TESTS),$(CMD)),$(if $(filter $(IMAGES),$(IMAGE)), \
|
||||||
|
$(call quiet-command,\
|
||||||
|
$(SRC_PATH)/tests/docker/docker.py run $(if $V,,--rm) \
|
||||||
|
-t \
|
||||||
|
$(if $(DEBUG),-i,--net=none) \
|
||||||
|
-e TARGET_LIST=$(TARGET_LIST) \
|
||||||
|
-e EXTRA_CONFIGURE_OPTS=$(EXTRA_CONFIGURE_OPTS) \
|
||||||
|
-e V=$V -e J=$J -e DEBUG=$(DEBUG)\
|
||||||
|
-e CCACHE_DIR=/var/tmp/ccache \
|
||||||
|
-v $$(realpath $(DOCKER_SRC_COPY)):/var/tmp/qemu:z$(COMMA)ro \
|
||||||
|
-v $(DOCKER_CCACHE_DIR):/var/tmp/ccache:z \
|
||||||
|
-w /var/tmp/qemu \
|
||||||
|
qemu:$(IMAGE) \
|
||||||
|
$(if $V,/bin/bash -x ,) \
|
||||||
|
./run \
|
||||||
|
$(CMD); \
|
||||||
|
, " RUN $(CMD) in $(IMAGE)")))
|
||||||
|
|
||||||
|
docker-clean:
|
||||||
|
$(call quiet-command, $(SRC_PATH)/tests/docker/docker.py clean)
|
32
tests/docker/common.rc
Executable file
32
tests/docker/common.rc
Executable file
|
@ -0,0 +1,32 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Common routines for docker test scripts.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016 Red Hat Inc.
|
||||||
|
#
|
||||||
|
# Authors:
|
||||||
|
# Fam Zheng <famz@redhat.com>
|
||||||
|
#
|
||||||
|
# This work is licensed under the terms of the GNU GPL, version 2
|
||||||
|
# or (at your option) any later version. See the COPYING file in
|
||||||
|
# the top-level directory.
|
||||||
|
|
||||||
|
requires()
|
||||||
|
{
|
||||||
|
for c in $@; do
|
||||||
|
if ! echo "$FEATURES" | grep -wq -e "$c"; then
|
||||||
|
echo "Prerequisite '$c' not present, skip"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
build_qemu()
|
||||||
|
{
|
||||||
|
$QEMU_SRC/configure \
|
||||||
|
--target-list="${TARGET_LIST}" \
|
||||||
|
--prefix="$PWD/install" \
|
||||||
|
$EXTRA_CONFIGURE_OPTS \
|
||||||
|
"$@"
|
||||||
|
make $MAKEFLAGS
|
||||||
|
}
|
194
tests/docker/docker.py
Executable file
194
tests/docker/docker.py
Executable file
|
@ -0,0 +1,194 @@
|
||||||
|
#!/usr/bin/env python2
|
||||||
|
#
|
||||||
|
# Docker controlling module
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016 Red Hat Inc.
|
||||||
|
#
|
||||||
|
# Authors:
|
||||||
|
# Fam Zheng <famz@redhat.com>
|
||||||
|
#
|
||||||
|
# This work is licensed under the terms of the GNU GPL, version 2
|
||||||
|
# or (at your option) any later version. See the COPYING file in
|
||||||
|
# the top-level directory.
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
import json
|
||||||
|
import hashlib
|
||||||
|
import atexit
|
||||||
|
import uuid
|
||||||
|
import argparse
|
||||||
|
import tempfile
|
||||||
|
from shutil import copy
|
||||||
|
|
||||||
|
def _text_checksum(text):
|
||||||
|
"""Calculate a digest string unique to the text content"""
|
||||||
|
return hashlib.sha1(text).hexdigest()
|
||||||
|
|
||||||
|
def _guess_docker_command():
|
||||||
|
""" Guess a working docker command or raise exception if not found"""
|
||||||
|
commands = [["docker"], ["sudo", "-n", "docker"]]
|
||||||
|
for cmd in commands:
|
||||||
|
if subprocess.call(cmd + ["images"],
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE) == 0:
|
||||||
|
return cmd
|
||||||
|
commands_txt = "\n".join([" " + " ".join(x) for x in commands])
|
||||||
|
raise Exception("Cannot find working docker command. Tried:\n%s" % \
|
||||||
|
commands_txt)
|
||||||
|
|
||||||
|
class Docker(object):
|
||||||
|
""" Running Docker commands """
|
||||||
|
def __init__(self):
|
||||||
|
self._command = _guess_docker_command()
|
||||||
|
self._instances = []
|
||||||
|
atexit.register(self._kill_instances)
|
||||||
|
|
||||||
|
def _do(self, cmd, quiet=True, **kwargs):
|
||||||
|
if quiet:
|
||||||
|
kwargs["stdout"] = subprocess.PIPE
|
||||||
|
return subprocess.call(self._command + cmd, **kwargs)
|
||||||
|
|
||||||
|
def _do_kill_instances(self, only_known, only_active=True):
|
||||||
|
cmd = ["ps", "-q"]
|
||||||
|
if not only_active:
|
||||||
|
cmd.append("-a")
|
||||||
|
for i in self._output(cmd).split():
|
||||||
|
resp = self._output(["inspect", i])
|
||||||
|
labels = json.loads(resp)[0]["Config"]["Labels"]
|
||||||
|
active = json.loads(resp)[0]["State"]["Running"]
|
||||||
|
if not labels:
|
||||||
|
continue
|
||||||
|
instance_uuid = labels.get("com.qemu.instance.uuid", None)
|
||||||
|
if not instance_uuid:
|
||||||
|
continue
|
||||||
|
if only_known and instance_uuid not in self._instances:
|
||||||
|
continue
|
||||||
|
print "Terminating", i
|
||||||
|
if active:
|
||||||
|
self._do(["kill", i])
|
||||||
|
self._do(["rm", i])
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
self._do_kill_instances(False, False)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def _kill_instances(self):
|
||||||
|
return self._do_kill_instances(True)
|
||||||
|
|
||||||
|
def _output(self, cmd, **kwargs):
|
||||||
|
return subprocess.check_output(self._command + cmd,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
|
def get_image_dockerfile_checksum(self, tag):
|
||||||
|
resp = self._output(["inspect", tag])
|
||||||
|
labels = json.loads(resp)[0]["Config"].get("Labels", {})
|
||||||
|
return labels.get("com.qemu.dockerfile-checksum", "")
|
||||||
|
|
||||||
|
def build_image(self, tag, dockerfile, df_path, quiet=True, argv=None):
|
||||||
|
if argv == None:
|
||||||
|
argv = []
|
||||||
|
tmp_dir = tempfile.mkdtemp(prefix="docker_build")
|
||||||
|
|
||||||
|
tmp_df = tempfile.NamedTemporaryFile(dir=tmp_dir, suffix=".docker")
|
||||||
|
tmp_df.write(dockerfile)
|
||||||
|
|
||||||
|
tmp_df.write("\n")
|
||||||
|
tmp_df.write("LABEL com.qemu.dockerfile-checksum=%s" %
|
||||||
|
_text_checksum(dockerfile))
|
||||||
|
tmp_df.flush()
|
||||||
|
self._do(["build", "-t", tag, "-f", tmp_df.name] + argv + \
|
||||||
|
[tmp_dir],
|
||||||
|
quiet=quiet)
|
||||||
|
|
||||||
|
def image_matches_dockerfile(self, tag, dockerfile):
|
||||||
|
try:
|
||||||
|
checksum = self.get_image_dockerfile_checksum(tag)
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
return checksum == _text_checksum(dockerfile)
|
||||||
|
|
||||||
|
def run(self, cmd, keep, quiet):
|
||||||
|
label = uuid.uuid1().hex
|
||||||
|
if not keep:
|
||||||
|
self._instances.append(label)
|
||||||
|
ret = self._do(["run", "--label",
|
||||||
|
"com.qemu.instance.uuid=" + label] + cmd,
|
||||||
|
quiet=quiet)
|
||||||
|
if not keep:
|
||||||
|
self._instances.remove(label)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
class SubCommand(object):
|
||||||
|
"""A SubCommand template base class"""
|
||||||
|
name = None # Subcommand name
|
||||||
|
def shared_args(self, parser):
|
||||||
|
parser.add_argument("--quiet", action="store_true",
|
||||||
|
help="Run quietly unless an error occured")
|
||||||
|
|
||||||
|
def args(self, parser):
|
||||||
|
"""Setup argument parser"""
|
||||||
|
pass
|
||||||
|
def run(self, args, argv):
|
||||||
|
"""Run command.
|
||||||
|
args: parsed argument by argument parser.
|
||||||
|
argv: remaining arguments from sys.argv.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
class RunCommand(SubCommand):
|
||||||
|
"""Invoke docker run and take care of cleaning up"""
|
||||||
|
name = "run"
|
||||||
|
def args(self, parser):
|
||||||
|
parser.add_argument("--keep", action="store_true",
|
||||||
|
help="Don't remove image when command completes")
|
||||||
|
def run(self, args, argv):
|
||||||
|
return Docker().run(argv, args.keep, quiet=args.quiet)
|
||||||
|
|
||||||
|
class BuildCommand(SubCommand):
|
||||||
|
""" Build docker image out of a dockerfile. Arguments: <tag> <dockerfile>"""
|
||||||
|
name = "build"
|
||||||
|
def args(self, parser):
|
||||||
|
parser.add_argument("tag",
|
||||||
|
help="Image Tag")
|
||||||
|
parser.add_argument("dockerfile",
|
||||||
|
help="Dockerfile name")
|
||||||
|
|
||||||
|
def run(self, args, argv):
|
||||||
|
dockerfile = open(args.dockerfile, "rb").read()
|
||||||
|
tag = args.tag
|
||||||
|
|
||||||
|
dkr = Docker()
|
||||||
|
if dkr.image_matches_dockerfile(tag, dockerfile):
|
||||||
|
if not args.quiet:
|
||||||
|
print "Image is up to date."
|
||||||
|
return 0
|
||||||
|
|
||||||
|
dkr.build_image(tag, dockerfile, args.dockerfile,
|
||||||
|
quiet=args.quiet, argv=argv)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
class CleanCommand(SubCommand):
|
||||||
|
"""Clean up docker instances"""
|
||||||
|
name = "clean"
|
||||||
|
def run(self, args, argv):
|
||||||
|
Docker().clean()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description="A Docker helper",
|
||||||
|
usage="%s <subcommand> ..." % os.path.basename(sys.argv[0]))
|
||||||
|
subparsers = parser.add_subparsers(title="subcommands", help=None)
|
||||||
|
for cls in SubCommand.__subclasses__():
|
||||||
|
cmd = cls()
|
||||||
|
subp = subparsers.add_parser(cmd.name, help=cmd.__doc__)
|
||||||
|
cmd.shared_args(subp)
|
||||||
|
cmd.args(subp)
|
||||||
|
subp.set_defaults(cmdobj=cmd)
|
||||||
|
args, argv = parser.parse_known_args()
|
||||||
|
return args.cmdobj.run(args, argv)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
6
tests/docker/dockerfiles/centos6.docker
Normal file
6
tests/docker/dockerfiles/centos6.docker
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
FROM centos:6
|
||||||
|
RUN yum install -y \
|
||||||
|
tar git make gcc g++ \
|
||||||
|
zlib-devel glib2-devel SDL-devel pixman-devel \
|
||||||
|
epel-release
|
||||||
|
RUN yum install -y libfdt-devel ccache
|
7
tests/docker/dockerfiles/fedora.docker
Normal file
7
tests/docker/dockerfiles/fedora.docker
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
FROM fedora:23
|
||||||
|
RUN dnf install -y \
|
||||||
|
ccache git tar \
|
||||||
|
glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel \
|
||||||
|
gcc gcc-c++ clang make perl which bc findutils \
|
||||||
|
mingw{32,64}-{pixman,glib2,gmp,SDL,pkg-config,gtk2,gtk3,gnutls,nettle,libtasn1,libjpeg-turbo,libpng,curl,libssh2,bzip2}
|
||||||
|
ENV FEATURES mingw clang
|
11
tests/docker/dockerfiles/ubuntu.docker
Normal file
11
tests/docker/dockerfiles/ubuntu.docker
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
FROM ubuntu:14.04
|
||||||
|
RUN echo "deb http://archive.ubuntu.com/ubuntu/ trusty universe multiverse" >> \
|
||||||
|
/etc/apt/sources.list
|
||||||
|
RUN apt-get update
|
||||||
|
RUN apt-get -y install \
|
||||||
|
libusb-1.0-0-dev libiscsi-dev librados-dev libncurses5-dev \
|
||||||
|
libseccomp-dev libgnutls-dev libssh2-1-dev libspice-server-dev \
|
||||||
|
libspice-protocol-dev libnss3-dev libfdt-dev \
|
||||||
|
libgtk-3-dev libvte-2.90-dev libsdl1.2-dev libpng12-dev libpixman-1-dev \
|
||||||
|
git make ccache python-yaml gcc clang sparse
|
||||||
|
ENV FEATURES clang ccache pyyaml
|
58
tests/docker/run
Executable file
58
tests/docker/run
Executable file
|
@ -0,0 +1,58 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
#
|
||||||
|
# Docker test runner
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016 Red Hat Inc.
|
||||||
|
#
|
||||||
|
# Authors:
|
||||||
|
# Fam Zheng <famz@redhat.com>
|
||||||
|
#
|
||||||
|
# This work is licensed under the terms of the GNU GPL, version 2
|
||||||
|
# or (at your option) any later version. See the COPYING file in
|
||||||
|
# the top-level directory.
|
||||||
|
|
||||||
|
# Prepare the environment
|
||||||
|
. /etc/profile || true
|
||||||
|
export PATH=/usr/lib/ccache:$PATH
|
||||||
|
|
||||||
|
if test -n "$J"; then
|
||||||
|
export MAKEFLAGS="$MAKEFLAGS -j$J"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# We are in the container so the whole file system belong to us
|
||||||
|
export TEST_DIR=/tmp/qemu-test
|
||||||
|
mkdir -p $TEST_DIR/{src,build,install}
|
||||||
|
|
||||||
|
# Extract the source tarballs
|
||||||
|
tar -C $TEST_DIR/src -xzf qemu.tgz
|
||||||
|
for p in dtc pixman; do
|
||||||
|
if test -f $p.tgz; then
|
||||||
|
tar -C $TEST_DIR/src/$p -xzf $p.tgz
|
||||||
|
export FEATURES="$FEATURES $p"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
export QEMU_SRC="$TEST_DIR/src"
|
||||||
|
|
||||||
|
cd "$QEMU_SRC/tests/docker"
|
||||||
|
|
||||||
|
CMD="$QEMU_SRC/tests/docker/$@"
|
||||||
|
|
||||||
|
if test -n "$DEBUG"; then
|
||||||
|
echo "* Prepared to run command:"
|
||||||
|
echo " $CMD"
|
||||||
|
echo "* Hit Ctrl-D to continue, or type 'exit 1' to abort"
|
||||||
|
echo
|
||||||
|
$SHELL
|
||||||
|
fi
|
||||||
|
|
||||||
|
if "$CMD"; then
|
||||||
|
exit 0
|
||||||
|
elif test -n "$DEBUG"; then
|
||||||
|
echo "* Command failed:"
|
||||||
|
echo " $CMD"
|
||||||
|
echo "* Hit Ctrl-D to exit"
|
||||||
|
echo
|
||||||
|
# Force error after shell exits
|
||||||
|
$SHELL && exit 1
|
||||||
|
fi
|
26
tests/docker/test-clang
Executable file
26
tests/docker/test-clang
Executable file
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
#
|
||||||
|
# Compile and check with clang.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016 Red Hat Inc.
|
||||||
|
#
|
||||||
|
# Authors:
|
||||||
|
# Fam Zheng <famz@redhat.com>
|
||||||
|
#
|
||||||
|
# This work is licensed under the terms of the GNU GPL, version 2
|
||||||
|
# or (at your option) any later version. See the COPYING file in
|
||||||
|
# the top-level directory.
|
||||||
|
|
||||||
|
. common.rc
|
||||||
|
|
||||||
|
requires clang
|
||||||
|
|
||||||
|
OPTS="--enable-debug --cxx=clang++ --cc=clang --host-cc=clang"
|
||||||
|
# -fsanitize=undefined is broken on Fedora 23, skip it for now
|
||||||
|
# See also: https://bugzilla.redhat.com/show_bug.cgi?id=1263834
|
||||||
|
#OPTS="$OPTS --extra-cflags=-fsanitize=undefined \
|
||||||
|
#--extra-cflags=-fno-sanitize=float-divide-by-zero"
|
||||||
|
DEF_TARGET_LIST="$(echo {x86_64,aarch64}-softmmu)"
|
||||||
|
TARGET_LIST=${TARGET_LIST:-$DEF_TARGET_LIST} \
|
||||||
|
build_qemu $OPTS
|
||||||
|
make $MAKEFLAGS check
|
17
tests/docker/test-full
Executable file
17
tests/docker/test-full
Executable file
|
@ -0,0 +1,17 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
#
|
||||||
|
# Compile all the targets.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016 Red Hat Inc.
|
||||||
|
#
|
||||||
|
# Authors:
|
||||||
|
# Fam Zheng <famz@redhat.com>
|
||||||
|
#
|
||||||
|
# This work is licensed under the terms of the GNU GPL, version 2
|
||||||
|
# or (at your option) any later version. See the COPYING file in
|
||||||
|
# the top-level directory.
|
||||||
|
|
||||||
|
. common.rc
|
||||||
|
|
||||||
|
build_qemu
|
||||||
|
make check $MAKEFLAGS
|
34
tests/docker/test-mingw
Executable file
34
tests/docker/test-mingw
Executable file
|
@ -0,0 +1,34 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
#
|
||||||
|
# Cross compile QEMU with mingw toolchain on Linux.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016 Red Hat Inc.
|
||||||
|
#
|
||||||
|
# Authors:
|
||||||
|
# Fam Zheng <famz@redhat.com>
|
||||||
|
#
|
||||||
|
# This work is licensed under the terms of the GNU GPL, version 2
|
||||||
|
# or (at your option) any later version. See the COPYING file in
|
||||||
|
# the top-level directory.
|
||||||
|
|
||||||
|
. common.rc
|
||||||
|
|
||||||
|
requires mingw dtc
|
||||||
|
|
||||||
|
for prefix in x86_64-w64-mingw32- i686-w64-mingw32-; do
|
||||||
|
TARGET_LIST=x86_64-softmmu,aarch64-softmmu \
|
||||||
|
build_qemu --cross-prefix=$prefix \
|
||||||
|
--enable-trace-backends=simple \
|
||||||
|
--enable-debug \
|
||||||
|
--enable-gnutls \
|
||||||
|
--enable-nettle \
|
||||||
|
--enable-curl \
|
||||||
|
--enable-vnc \
|
||||||
|
--enable-bzip2 \
|
||||||
|
--enable-guest-agent \
|
||||||
|
--with-sdlabi=1.2 \
|
||||||
|
--with-gtkabi=2.0
|
||||||
|
make clean
|
||||||
|
|
||||||
|
done
|
||||||
|
|
19
tests/docker/test-quick
Executable file
19
tests/docker/test-quick
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
#
|
||||||
|
# Quick compiling test that everyone already does. But why not automate it?
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016 Red Hat Inc.
|
||||||
|
#
|
||||||
|
# Authors:
|
||||||
|
# Fam Zheng <famz@redhat.com>
|
||||||
|
#
|
||||||
|
# This work is licensed under the terms of the GNU GPL, version 2
|
||||||
|
# or (at your option) any later version. See the COPYING file in
|
||||||
|
# the top-level directory.
|
||||||
|
|
||||||
|
. common.rc
|
||||||
|
|
||||||
|
DEF_TARGET_LIST="$(echo {x86_64,aarch64}-softmmu)"
|
||||||
|
TARGET_LIST=${TARGET_LIST:-$DEF_TARGET_LIST} \
|
||||||
|
build_qemu
|
||||||
|
make check $MAKEFLAGS
|
21
tests/docker/travis
Executable file
21
tests/docker/travis
Executable file
|
@ -0,0 +1,21 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
#
|
||||||
|
# Mimic a travis testing matrix
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016 Red Hat Inc.
|
||||||
|
#
|
||||||
|
# Authors:
|
||||||
|
# Fam Zheng <famz@redhat.com>
|
||||||
|
#
|
||||||
|
# This work is licensed under the terms of the GNU GPL, version 2
|
||||||
|
# or (at your option) any later version. See the COPYING file in
|
||||||
|
# the top-level directory.
|
||||||
|
|
||||||
|
. common.rc
|
||||||
|
|
||||||
|
requires pyyaml
|
||||||
|
cmdfile=/tmp/travis_cmd_list.sh
|
||||||
|
$QEMU_SRC/tests/docker/travis.py $QEMU_SRC/.travis.yml > $cmdfile
|
||||||
|
chmod +x $cmdfile
|
||||||
|
cd "$QEMU_SRC"
|
||||||
|
$cmdfile
|
48
tests/docker/travis.py
Executable file
48
tests/docker/travis.py
Executable file
|
@ -0,0 +1,48 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Travis YAML config parser
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016 Red Hat Inc.
|
||||||
|
#
|
||||||
|
# Authors:
|
||||||
|
# Fam Zheng <famz@redhat.com>
|
||||||
|
#
|
||||||
|
# This work is licensed under the terms of the GNU GPL, version 2
|
||||||
|
# or (at your option) any later version. See the COPYING file in
|
||||||
|
# the top-level directory.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import yaml
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
def load_yaml(fname):
|
||||||
|
return yaml.load(open(fname, "r").read())
|
||||||
|
|
||||||
|
def conf_iter(conf):
|
||||||
|
def env_to_list(env):
|
||||||
|
return env if isinstance(env, list) else [env]
|
||||||
|
global_env = conf["env"]["global"]
|
||||||
|
for entry in conf["matrix"]["include"]:
|
||||||
|
yield {"env": global_env + env_to_list(entry["env"]),
|
||||||
|
"compiler": entry["compiler"]}
|
||||||
|
for entry in itertools.product(conf["compiler"],
|
||||||
|
conf["env"]["matrix"]):
|
||||||
|
yield {"env": global_env + env_to_list(entry[1]),
|
||||||
|
"compiler": entry[0]}
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
sys.stderr.write("Usage: %s <travis-file>\n" % sys.argv[0])
|
||||||
|
return 1
|
||||||
|
conf = load_yaml(sys.argv[1])
|
||||||
|
for config in conf_iter(conf):
|
||||||
|
print "("
|
||||||
|
print "\n".join(config["env"])
|
||||||
|
print "alias cc=" + config["compiler"]
|
||||||
|
print "\n".join(conf["before_script"])
|
||||||
|
print "\n".join(conf["script"])
|
||||||
|
print ")"
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
Loading…
Reference in a new issue