1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
|
#!/usr/bin/env python3
# This file is part of Cockpit.
#
# Copyright (C) 2015 Red Hat, Inc.
#
# Cockpit is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# Cockpit is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
import argparse
import errno
import os
import sys
import subprocess
from verify import parent
import make_dist
import testvm
parent # pyflakes
TEST = os.path.abspath(os.path.dirname(__file__))
BASE = os.path.normpath(os.path.join(TEST, ".."))
BOTS = os.path.join(BASE, "bots")
os.environ["PATH"] = "{0}:{1}".format(os.environ.get("PATH"), BOTS)
networking = None
def main():
parser = argparse.ArgumentParser(
description='Prepare testing environment, download images and build and install cockpit',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-v', '--verbose', action='store_true', help='Display verbose progress details')
parser.add_argument('-s', '--sit', action='store_true', help='Sit and wait if install script fails')
parser.add_argument('-q', '--quick', action='store_true', help='Skip unit tests to build faster')
parser.add_argument('-o', '--overlay', action='store_true', help='Install into existing test/image/ overlay instead of from pristine base image')
parser.add_argument('-b', '--build-image', action='store', help='Build in this image')
parser.add_argument('-B', '--build-only', action='store_true', help='Only build and download results')
parser.add_argument('-I', '--install-only', action='store_true', help='Only upload and install')
parser.add_argument('-c', '--containers', action='store_true', help='Install container images')
parser.add_argument('--address', help='Address of already running machine, implies --install-only')
parser.add_argument('image', nargs='?', default=testvm.DEFAULT_IMAGE, help='The image to use')
args = parser.parse_args()
# The basic operating system we're preparing on top of. Never written to
base_image = args.image
# The image we're going to build in. This image is never written to
build_image = None
if not args.install_only:
build_image = testvm.get_build_image(args.build_image or base_image)
# Depending on the operating system ignore some things
skips = []
if args.address:
skips.append("cockpit-tests")
args.install_only = True
if args.install_only and args.build_only:
sys.stderr.write("image-prepare: use of --install-only with --build-only is incompatible\n")
return 2
results = os.path.abspath("tmp/build-results")
# Make sure any images are downloaded
try:
if not args.address and not os.path.exists(base_image):
subprocess.check_call(["image-download", base_image])
if build_image and not os.path.exists(build_image):
subprocess.check_call(["image-download", build_image])
except OSError as ex:
if ex.errno != errno.ENOENT:
raise
sys.stderr.write("image-prepare: missing tools to download images\n")
except subprocess.CalledProcessError:
sys.stderr.write("image-prepare: unable to download all necessary images\n")
return 1
try:
if not args.install_only:
build_and_install(build_image, results, skips, args)
if not args.build_only and build_image != base_image:
only_install(base_image, results, skips, args)
except (RuntimeError, testvm.Failure) as ex:
sys.stderr.write("image-prepare: {0}\n".format(str(ex)))
return 2
return 0
def upload_scripts(machine, args):
machine.execute("rm -rf /var/lib/testvm")
machine.upload([os.path.join(testvm.SCRIPTS_DIR, "lib")], "/var/lib/testvm")
machine.upload([os.path.join(BASE, "tools", "make-srpm")], "/var/lib/testvm")
machine.upload([os.path.join(testvm.SCRIPTS_DIR, "%s.install" % machine.image)], "/var/tmp")
machine.upload([os.path.join(BASE, "containers")], "/var/tmp")
# Create the necessary layered image for the build/install
def prepare_install_image(base_image, overlay=False):
if "/" not in base_image:
base_image = os.path.join(testvm.IMAGES_DIR, base_image)
test_images = os.path.join(TEST, "images")
os.makedirs(test_images, exist_ok=True)
install_image = os.path.join(test_images, os.path.basename(base_image))
if not os.path.exists(install_image) or not overlay:
base_image = os.path.realpath(testvm.get_test_image(base_image))
qcow2_image = "{0}.qcow2".format(install_image)
subprocess.check_call(["qemu-img", "create", "-q", "-f", "qcow2",
"-o", "backing_file={0},backing_fmt=qcow2".format(base_image),
qcow2_image])
if os.path.lexists(install_image):
os.unlink(install_image)
os.symlink(os.path.basename(qcow2_image), install_image)
return install_image
def run_install_script(machine, do_build, do_install, skips, arg, args):
install = do_install
if args.containers and not do_build:
do_install = False
skips = list(skips or [])
skip_args = [" --skip '%s'" % skip for skip in skips]
cmd = "cd /var/tmp; ./%s.install%s%s%s%s%s%s" % (machine.image,
" --verbose" if args.verbose else "",
" --quick" if args.quick else "",
" --build" if do_build else "",
" --install" if do_install else "",
" ".join(skip_args),
" '%s'" % arg if arg else "")
machine.execute(cmd, timeout=1800)
if install and args.containers:
machine.execute("/var/lib/testvm/containers.install", timeout=900)
def build_and_install(build_image, build_results, skips, args):
"""Build and maybe install Cockpit into a test image"""
build_image = prepare_install_image(build_image, args.overlay)
machine = testvm.VirtMachine(verbose=args.verbose, image=build_image,
memory_mb=2048, cpus=4, maintain=True, networking=networking)
completed = False
# While the machine is booting, make a dist tarball
source = make_dist.make_dist()
machine.start()
completed = False
try:
machine.wait_boot()
upload_scripts(machine, args=args)
machine.upload([source], "/var/tmp")
run_install_script(machine, True, True, skips, os.path.basename(source), args)
completed = True
finally:
if not completed and args.sit:
sys.stderr.write(machine.diagnose())
input("Press RET to continue... ")
try:
if os.path.exists(build_results):
subprocess.check_call(["rm", "-rf", build_results])
os.makedirs(build_results)
machine.download("/var/tmp/build-results/*", build_results)
finally:
machine.stop()
def only_install(image, build_results, skips, args):
"""Install Cockpit into a test image"""
started = False
if args.address:
machine = testvm.Machine(address=args.address, verbose=args.verbose, image=image)
else:
image = prepare_install_image(image, args.overlay)
machine = testvm.VirtMachine(verbose=args.verbose, image=image, networking=networking, maintain=True)
machine.start()
started = True
completed = False
try:
if started:
machine.wait_boot()
upload_scripts(machine, args=args)
machine.execute("rm -rf /var/tmp/build-results")
machine.upload([build_results], "/var/tmp/build-results")
run_install_script(machine, False, True, skips, None, args)
completed = True
finally:
if not completed and args.sit:
sys.stderr.write(machine.diagnose())
input("Press RET to continue... ")
if started:
machine.stop()
if __name__ == "__main__":
sys.exit(main())
|