[master 1/7] Move kickstart test support files into a separate directory.

dashea installerbot-noreply at redhat.com
Thu Sep 3 22:08:45 UTC 2015


From: David Shea <dshea at redhat.com>

This way tests/kickstart_tests contains only the kickstart tests, the
shell scripts for the kickstart tests, functions.sh, and a scripts
directory that has everything else.
---
 tests/Makefile.am                                  |   5 +-
 tests/kickstart_tests/kstest-runner                | 309 ---------------------
 tests/kickstart_tests/make-addon-pkgs.py           | 119 --------
 tests/kickstart_tests/proxy-auth.ks                |   2 +-
 tests/kickstart_tests/proxy-cmdline.ks             |   2 +-
 tests/kickstart_tests/proxy-common.ks              |  79 ------
 tests/kickstart_tests/proxy-kickstart.ks           |   2 +-
 tests/kickstart_tests/run_kickstart_tests.sh       | 199 -------------
 tests/kickstart_tests/run_one_ks.sh                | 157 -----------
 tests/kickstart_tests/run_report.sh                |  26 --
 tests/kickstart_tests/scripts/kstest-runner        | 309 +++++++++++++++++++++
 tests/kickstart_tests/scripts/make-addon-pkgs.py   | 119 ++++++++
 tests/kickstart_tests/scripts/proxy-common.ks      |  79 ++++++
 .../kickstart_tests/scripts/run_kickstart_tests.sh | 199 +++++++++++++
 tests/kickstart_tests/scripts/run_one_ks.sh        | 157 +++++++++++
 tests/kickstart_tests/scripts/run_report.sh        |  26 ++
 16 files changed, 894 insertions(+), 895 deletions(-)
 delete mode 100755 tests/kickstart_tests/kstest-runner
 delete mode 100755 tests/kickstart_tests/make-addon-pkgs.py
 delete mode 100644 tests/kickstart_tests/proxy-common.ks
 delete mode 100755 tests/kickstart_tests/run_kickstart_tests.sh
 delete mode 100755 tests/kickstart_tests/run_one_ks.sh
 delete mode 100755 tests/kickstart_tests/run_report.sh
 create mode 100755 tests/kickstart_tests/scripts/kstest-runner
 create mode 100755 tests/kickstart_tests/scripts/make-addon-pkgs.py
 create mode 100644 tests/kickstart_tests/scripts/proxy-common.ks
 create mode 100755 tests/kickstart_tests/scripts/run_kickstart_tests.sh
 create mode 100755 tests/kickstart_tests/scripts/run_one_ks.sh
 create mode 100755 tests/kickstart_tests/scripts/run_report.sh

diff --git a/tests/Makefile.am b/tests/Makefile.am
index f3c1e80..c55e082 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -53,8 +53,7 @@ dist_check_SCRIPTS = $(srcdir)/glade/*.py \
 		     install/run_install_test.sh \
 		     $(srcdir)/kickstart_tests/*.ks \
 		     $(srcdir)/kickstart_tests/*.sh \
-		     $(srcdir)/kickstart_tests/*.py \
-		     $(srcdir)/kickstart_tests/kstest-runner \
+		     $(srcdir)/kickstart_tests/scripts/* \
 		     $(srcdir)/gui/*.ks \
 		     $(srcdir)/gui/*.sh \
 		     $(srcdir)/gui/inside/*.py \
@@ -72,7 +71,7 @@ TESTS = nosetests.sh \
 	gettext/contexts.py \
 	storage/run_storage_tests.py \
 	glade/run_glade_tests.sh \
-	kickstart_tests/run_kickstart_tests.sh
+	kickstart_tests/scripts/run_kickstart_tests.sh
 
 clean-local:
 	-rm -rf pylint/.pylint.d
diff --git a/tests/kickstart_tests/kstest-runner b/tests/kickstart_tests/kstest-runner
deleted file mode 100755
index 196aa36..0000000
--- a/tests/kickstart_tests/kstest-runner
+++ /dev/null
@@ -1,309 +0,0 @@
-#!/usr/bin/python3
-#
-# kstest-runner - LMC-like program that only does what's necessary for running
-# kickstart-based tests in anaconda
-#
-# Copyright (C) 2011-2015  Red Hat, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-# Author(s): Brian C. Lane <bcl at redhat.com>
-#            Chris Lumens <clumens at redhat.com>
-#
-import logging
-log = logging.getLogger("livemedia-creator")
-
-import os
-import sys
-import uuid
-import tempfile
-import subprocess
-from time import sleep
-import argparse
-
-# Use the Lorax treebuilder branch for iso creation
-from pylorax.treebuilder import udev_escape
-from pylorax.executils import execWithRedirect
-
-from pylorax import setup_logging
-from pylorax.monitor import LogMonitor
-from pylorax.mount import IsoMountpoint
-
-import libvirt
-
-class InstallError(Exception):
-    pass
-
-class VirtualInstall(object):
-    """
-    Run virt-install using an iso and a kickstart
-    """
-    def __init__(self, iso, ks_paths, disk_paths,
-                 kernel_args=None, memory=1024, vnc=None,
-                 log_check=None, virtio_host="127.0.0.1", virtio_port=6080):
-        """
-        Start the installation
-
-        :param iso: Information about the iso to use for the installation
-        :type iso: IsoMountpoint
-        :param list ks_paths: Paths to kickstart files. All are injected, the
-           first one is the one executed.
-        :param list disk_paths: Paths to pre-existing disk images.
-        :param str kernel_args: Extra kernel arguments to pass on the kernel cmdline
-        :param int memory: Amount of RAM to assign to the virt, in MiB
-        :param str vnc: Arguments to pass to virt-install --graphics
-        :param log_check: Method that returns True if the installation fails
-        :type log_check: method
-        :param str virtio_host: Hostname to connect virtio log to
-        :param int virtio_port: Port to connect virtio log to
-        """
-        self.virt_name = "LiveOS-"+str(uuid.uuid4())
-        # add --graphics none later
-        # add whatever serial cmds are needed later
-        args = ["-n", self.virt_name,
-                 "-r", str(memory),
-                 "--noreboot",
-                 "--noautoconsole"]
-
-        args.append("--graphics")
-        if vnc:
-            args.append(vnc)
-        else:
-            args.append("none")
-
-        for ks in ks_paths:
-            args.append("--initrd-inject")
-            args.append(ks)
-
-        for disk in disk_paths:
-            args.append("--disk")
-            args.append("path={0}".format(disk))
-
-        if iso.stage2:
-            disk_opts = "path={0},device=cdrom,readonly=on,shareable=on".format(iso.iso_path)
-            args.append("--disk")
-            args.append(disk_opts)
-
-        extra_args = "ks=file:/{0}".format(os.path.basename(ks_paths[0]))
-        if not vnc:
-            extra_args += " inst.cmdline"
-        if kernel_args:
-            extra_args += " " + kernel_args
-        if iso.stage2:
-            extra_args += " stage2=hd:CDLABEL={0}".format(udev_escape(iso.label))
-        args.append("--extra-args")
-        args.append(extra_args)
-
-        args.append("--location")
-        args.append(iso.mount_dir)
-
-        channel_args = "tcp,host={0}:{1},mode=connect,target_type=virtio" \
-                       ",name=org.fedoraproject.anaconda.log.0".format(
-                       virtio_host, virtio_port)
-        args.append("--channel")
-        args.append(channel_args)
-
-        log.info("Running virt-install.")
-        try:
-            execWithRedirect("virt-install", args, raise_err=True)
-        except subprocess.CalledProcessError as e:
-            raise InstallError("Problem starting virtual install: %s" % e)
-
-        conn = libvirt.openReadOnly(None)
-        dom = conn.lookupByName(self.virt_name)
-
-        # TODO: If vnc has been passed, we should look up the port and print that
-        # for the user at this point
-        while dom.isActive() and not log_check():
-            sys.stdout.write(".")
-            sys.stdout.flush()
-            sleep(10)
-        print()
-
-        if log_check():
-            log.info("Installation error detected. See logfile.")
-        else:
-            log.info("Install finished. Or at least virt shut down.")
-
-    def destroy(self, poolName):
-        """
-        Make sure the virt has been shut down and destroyed
-
-        Could use libvirt for this instead.
-        """
-        log.info("Shutting down %s", self.virt_name)
-        subprocess.call(["virsh", "destroy", self.virt_name])
-        subprocess.call(["virsh", "undefine", self.virt_name])
-        subprocess.call(["virsh", "pool-destroy", poolName])
-        subprocess.call(["virsh", "pool-undefine", poolName])
-
-def virt_install(opts, install_log):
-    """
-    Use virt-install to install to a disk image
-
-    :param opts: options passed to livemedia-creator
-    :type opts: argparse options
-    :param str install_log: The path to write the log from virt-install
-
-    This uses virt-install with a boot.iso and a kickstart to create a disk
-    image.
-    """
-    iso_mount = IsoMountpoint(opts.iso, opts.location)
-    log_monitor = LogMonitor(install_log, timeout=opts.timeout)
-
-    kernel_args = ""
-    if opts.kernel_args:
-        kernel_args += opts.kernel_args
-    if opts.proxy:
-        kernel_args += " proxy=" + opts.proxy
-
-    try:
-        virt = VirtualInstall(iso_mount, opts.ks, opts.disk_paths,
-                              kernel_args, opts.ram, opts.vnc,
-                              log_check = log_monitor.server.log_check,
-                              virtio_host = log_monitor.host,
-                              virtio_port = log_monitor.port)
-
-        virt.destroy(os.path.basename(opts.tmp))
-        log_monitor.shutdown()
-    except InstallError as e:
-        log.error("VirtualInstall failed: %s", e)
-        raise
-    finally:
-        log.info("unmounting the iso")
-        iso_mount.umount()
-
-    if log_monitor.server.log_check():
-        if not log_monitor.server.error_line and opts.timeout:
-            msg = "virt_install failed due to timeout"
-        else:
-            msg = "virt_install failed on line: %s" % log_monitor.server.error_line
-        raise InstallError(msg)
-
-
-def make_image(opts):
-    """
-    Install to a disk image
-
-    :param opts: options passed to livemedia-creator
-    :type opts: argparse options
-    :param str ks: Path to the kickstart to use for the installation
-
-    Use virt-install or anaconda to install to a disk image.
-    """
-    try:
-        install_log = os.path.abspath(os.path.dirname(opts.logfile))+"/virt-install.log"
-        log.info("install_log = %s", install_log)
-
-        virt_install(opts, install_log)
-    except InstallError as e:
-        log.error("Install failed: %s", e)
-
-        if not opts.keep_image:
-            log.info("Removing bad disk image")
-
-            for image in opts.disk_paths:
-                if os.path.exists(image):
-                    os.unlink(image)
-
-        raise
-
-    log.info("Disk Image install successful")
-
-def main():
-    parser = argparse.ArgumentParser(description="Run anaconda's kickstart-based tests",
-                                     fromfile_prefix_chars="@")
-
-    parser.add_argument("--iso", type=os.path.abspath,
-                        help="Anaconda installation .iso path to use for virt-install")
-    parser.add_argument("--ks", action="append", type=os.path.abspath,
-                        help="Kickstart file defining the install.")
-    parser.add_argument("--disk", action="append", type=os.path.abspath, dest="disk_paths",
-                        help="Pre-existing disk image to use for destination.")
-
-    parser.add_argument("--proxy",
-                        help="proxy URL to use for the install")
-    parser.add_argument("--location", default=None, type=os.path.abspath,
-                        help="location of iso directory tree with initrd.img "
-                             "and vmlinuz. Used to run virt-install with a "
-                             "newer initrd than the iso.")
-
-    parser.add_argument("--logfile", default="./livemedia.log",
-                        type=os.path.abspath,
-                        help="Path to logfile")
-    parser.add_argument("--tmp", default="/var/tmp", type=os.path.abspath,
-                        help="Top level temporary directory")
-
-    image_group = parser.add_argument_group("disk/fs image arguments")
-    image_group.add_argument("--keep-image", action="store_true",
-                             help="Keep raw disk image after .iso creation")
-
-    # Group of arguments to pass to virt-install
-    virt_group = parser.add_argument_group("virt-install arguments")
-    virt_group.add_argument("--ram", metavar="MEMORY", type=int, default=1024,
-                            help="Memory to allocate for installer in megabytes.")
-    virt_group.add_argument("--vnc",
-                            help="Passed to --graphics command")
-    virt_group.add_argument("--kernel-args",
-                            help="Additional argument to pass to the installation kernel")
-
-    parser.add_argument("--timeout", default=None, type=int,
-                        help="Cancel installer after X minutes")
-
-    opts = parser.parse_args()
-
-    setup_logging(opts.logfile, log)
-
-    log.debug( opts )
-
-    # Check for invalid combinations of options, print all the errors and exit.
-    errors = []
-    if opts.ks and not os.path.exists(opts.ks[0]):
-        errors.append("kickstart file (%s) is missing." % opts.ks[0])
-
-    if opts.iso and not os.path.exists(opts.iso):
-        errors.append("The iso %s is missing." % opts.iso)
-
-    if not opts.iso:
-        errors.append("virt install needs an install iso.")
-
-    if not os.path.exists("/usr/bin/virt-install"):
-        errors.append("virt-install needs to be installed.")
-
-    if os.getuid() != 0:
-        errors.append("You need to run this as root")
-
-    if errors:
-        list(log.error(e) for e in errors)
-        sys.exit(1)
-
-    tempfile.tempdir = opts.tmp
-
-    # Make the image.
-    try:
-        make_image(opts)
-    except InstallError as e:
-        log.error("ERROR: Image creation failed: %s", e)
-        sys.exit(1)
-
-    log.info("SUMMARY")
-    log.info("-------")
-    log.info("Logs are in %s", os.path.abspath(os.path.dirname(opts.logfile)))
-    log.info("Disk image(s) at %s", ",".join(opts.disk_paths))
-    log.info("Results are in %s", opts.tmp)
-
-    sys.exit( 0 )
-
-if __name__ == '__main__':
-    main()
diff --git a/tests/kickstart_tests/make-addon-pkgs.py b/tests/kickstart_tests/make-addon-pkgs.py
deleted file mode 100755
index e38cb7a..0000000
--- a/tests/kickstart_tests/make-addon-pkgs.py
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/usr/bin/python3
-#
-# Copyright (C) 2015  Red Hat, Inc.
-#
-# This copyrighted material is made available to anyone wishing to use,
-# modify, copy, or redistribute it subject to the terms and conditions of
-# the GNU General Public License v.2, or (at your option) any later version.
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY expressed or implied, including the implied warranties of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
-# Public License for more details.  You should have received a copy of the
-# GNU General Public License along with this program; if not, write to the
-# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the
-# source code or documentation are not subject to the GNU General Public
-# License and may only be used or replicated with the express permission of
-# Red Hat, Inc.
-#
-# Red Hat Author(s): David Shea <dshea at redhat.com>
-
-# This script creates all the packages used by nfs-repo-and-addon.ks.
-# The packages are created in two directories, http and nfs. After all the rpms
-# are made just copy everything to the locations set in $KSTEST_ADDON_HTTP_REPO
-# and $KSTEST_ADDON_NFS_REPO.
-#
-# This script imports things from tests/lib/mkdud.py, so tests/lib needs to be
-# in $PYTHONPATH.
-
-# Ignore interuptible calls
-# pylint: disable=interruptible-system-call
-
-import os
-from subprocess import check_call
-from mkdud import make_rpm
-import rpmfluff
-
-# Start with http
-os.mkdir('http')
-
-# Empty package to be added to @core
-pkg = rpmfluff.SimpleRpmBuild('testpkg-http-core', '1.0', '1')
-make_rpm(pkg, 'http')
-
-# Another empty package
-pkg = rpmfluff.SimpleRpmBuild('testpkg-http-addon', '1.0', '1')
-make_rpm(pkg, 'http')
-
-# Three packages with marker files
-pkg = rpmfluff.SimpleRpmBuild('testpkg-share1', '1.0', '1')
-pkg.add_installed_file('/usr/share/testpkg-1/http',
-        rpmfluff.SourceFile('http', ''))
-make_rpm(pkg, 'http')
-
-pkg = rpmfluff.SimpleRpmBuild('testpkg-share2', '1.0', '1')
-pkg.add_installed_file('/usr/share/testpkg-2/http',
-        rpmfluff.SourceFile('http', ''))
-make_rpm(pkg, 'http')
-
-pkg = rpmfluff.SimpleRpmBuild('testpkg-share3', '1.0', '1')
-pkg.add_installed_file('/usr/share/testpkg-3/http',
-        rpmfluff.SourceFile('http', ''))
-make_rpm(pkg, 'http')
-
-# Create a comps file and create the repo
-with open('http/comps.xml', 'wt') as comps:
-    comps.write('''<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE comps PUBLIC "-//Red Hat, Inc.//DTD Comps info//EN" "comps.dtd">
-<comps>
-  <group>
-    <id>core</id>
-    <packagelist>
-      <packagereq type="mandatory">testpkg-http-core</packagereq>
-    </packagelist>
-  </group>
-</comps>''')
-
-check_call(['createrepo_c', '-g', 'comps.xml', 'http'])
-
-# Do the same thing again for nfs
-os.mkdir('nfs')
-
-# Empty package to be added to @core
-pkg = rpmfluff.SimpleRpmBuild('testpkg-nfs-core', '1.0', '1')
-make_rpm(pkg, 'nfs')
-
-# Another empty package
-pkg = rpmfluff.SimpleRpmBuild('testpkg-nfs-addon', '1.0', '1')
-make_rpm(pkg, 'nfs')
-
-# Three packages with marker files
-pkg = rpmfluff.SimpleRpmBuild('testpkg-share1', '1.0', '1')
-pkg.add_installed_file('/usr/share/testpkg-1/nfs',
-        rpmfluff.SourceFile('nfs', ''))
-make_rpm(pkg, 'nfs')
-
-pkg = rpmfluff.SimpleRpmBuild('testpkg-share2', '1.0', '1')
-pkg.add_installed_file('/usr/share/testpkg-2/nfs',
-        rpmfluff.SourceFile('nfs', ''))
-make_rpm(pkg, 'nfs')
-
-pkg = rpmfluff.SimpleRpmBuild('testpkg-share3', '1.0', '1')
-pkg.add_installed_file('/usr/share/testpkg-3/nfs',
-        rpmfluff.SourceFile('nfs', ''))
-make_rpm(pkg, 'nfs')
-
-# Create a comps file and create the repo
-with open('nfs/comps.xml', 'wt') as comps:
-    comps.write('''<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE comps PUBLIC "-//Red Hat, Inc.//DTD Comps info//EN" "comps.dtd">
-<comps>
-  <group>
-    <id>core</id>
-    <packagelist>
-      <packagereq type="mandatory">testpkg-nfs-core</packagereq>
-    </packagelist>
-  </group>
-</comps>''')
-
-check_call(['createrepo_c', '-g', 'comps.xml', 'nfs'])
diff --git a/tests/kickstart_tests/proxy-auth.ks b/tests/kickstart_tests/proxy-auth.ks
index 199530f..874dd45 100644
--- a/tests/kickstart_tests/proxy-auth.ks
+++ b/tests/kickstart_tests/proxy-auth.ks
@@ -19,7 +19,7 @@ shutdown
 %end
 
 # Start the proxy server
-%include proxy-common.ks
+%include scripts/proxy-common.ks
 
 # Set a password on the proxy server
 %pre
diff --git a/tests/kickstart_tests/proxy-cmdline.ks b/tests/kickstart_tests/proxy-cmdline.ks
index 8252d43..7519724 100644
--- a/tests/kickstart_tests/proxy-cmdline.ks
+++ b/tests/kickstart_tests/proxy-cmdline.ks
@@ -18,7 +18,7 @@ shutdown
 %end
 
 # Run the proxy
-%include proxy-common.ks
+%include scripts/proxy-common.ks
 
 %post --nochroot
 # Look for the following as evidence that a proxy was used:
diff --git a/tests/kickstart_tests/proxy-common.ks b/tests/kickstart_tests/proxy-common.ks
deleted file mode 100644
index a95097a..0000000
--- a/tests/kickstart_tests/proxy-common.ks
+++ /dev/null
@@ -1,79 +0,0 @@
-# Start a super-simple proxy server on localhost
-# A list of proxied requests will be saved to /tmp/proxy.log
-%pre --erroronfail
-# Write the proxy script to a file in /tmp
-cat - << "EOF" > /tmp/proxy-test.py
-from http.server import SimpleHTTPRequestHandler
-import socketserver
-from urllib.request import urlopen
-import os
-from base64 import b64decode
-
-import logging
-log = logging.getLogger("proxy_test")
-log_handler = logging.FileHandler('/tmp/proxy.log')
-log.setLevel(logging.INFO)
-log.addHandler(log_handler)
-
-class ProxyHandler(SimpleHTTPRequestHandler):
-    def send_authenticate(self):
-        self.send_response(407)
-        self.send_header('Proxy-Authenticate', 'Basic realm=proxy-test')
-        self.end_headers()
-
-    def authenticate(self):
-        # If there is no /tmp/proxy.password file, anything goes
-        if not os.path.exists('/tmp/proxy.password'):
-            return True
-
-        # If there is no Authorization header, send a 407, Proxy authentication required
-        authorization = self.headers['Proxy-Authorization']
-        if not authorization:
-            self.send_authenticate()
-            return False
-
-        # Parse the Authorization header. It should be "Basic" followed
-        # user:pass encoded in base64
-        if not authorization.startswith('Basic'):
-            self.send_authenticate()
-            return False
-
-        try:
-            client_auth = b64decode(authorization.split()[1])
-        except IndexError:
-            self.send_authenticate()
-            return False
-
-        with open('/tmp/proxy.password', 'rb') as f:
-            server_auth = f.readline().strip()
-
-        if client_auth != server_auth:
-            self.send_authenticate()
-            return False
-
-        return True
-
-    def do_GET(self):
-        if not self.authenticate():
-            return
-
-        # Log the path then proxy the request via urllib
-        log.info(self.path)
-        data = urlopen(self.path).read()
-        self.send_response(200)
-        self.send_header('Content-Length', str(len(data)))
-        self.end_headers()
-        self.wfile.write(data)
-
-class ProxyServer(socketserver.TCPServer):
-    allow_reuse_address = True
-
-    def __init__(self):
-        socketserver.TCPServer.__init__(self, ('', 8080), ProxyHandler)
-
-ProxyServer().serve_forever()
-EOF
-
-# Run the server in the background and exit
-python3 /tmp/proxy-test.py > /dev/null 2>&1 &
-%end
diff --git a/tests/kickstart_tests/proxy-kickstart.ks b/tests/kickstart_tests/proxy-kickstart.ks
index 317ef63..6708c88 100644
--- a/tests/kickstart_tests/proxy-kickstart.ks
+++ b/tests/kickstart_tests/proxy-kickstart.ks
@@ -19,7 +19,7 @@ shutdown
 %end
 
 # Start the proxy server
-%include proxy-common.ks
+%include scripts/proxy-common.ks
 
 %post --nochroot
 # Look for the following as evidence that a proxy was used:
diff --git a/tests/kickstart_tests/run_kickstart_tests.sh b/tests/kickstart_tests/run_kickstart_tests.sh
deleted file mode 100755
index 0b03a2f..0000000
--- a/tests/kickstart_tests/run_kickstart_tests.sh
+++ /dev/null
@@ -1,199 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2014, 2015  Red Hat, Inc.
-#
-# This copyrighted material is made available to anyone wishing to use,
-# modify, copy, or redistribute it subject to the terms and conditions of
-# the GNU General Public License v.2, or (at your option) any later version.
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY expressed or implied, including the implied warranties of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
-# Public License for more details.  You should have received a copy of the
-# GNU General Public License along with this program; if not, write to the
-# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the
-# source code or documentation are not subject to the GNU General Public
-# License and may only be used or replicated with the express permission of
-# Red Hat, Inc.
-#
-# Red Hat Author(s): Chris Lumens <clumens at redhat.com>
-
-# This script runs the entire kickstart_tests suite.  It is an interface
-# between "make check" (which is why it takes environment variables instead
-# of arguments) and livemedia-creator.  Each test consists of a kickstart
-# file that specifies most everything about the installation, and a shell
-# script that does validation and specifies kernel boot parameters.  lmc
-# then fires up a VM and watches for tracebacks or stuck installs.
-#
-# A boot ISO is required, which should be specified with TEST_BOOT_ISO=.
-#
-# The number of jobs corresponds to the number of VMs that will be started
-# simultaneously.  Each one wants about 2 GB of memory.  The default is
-# two simultaneous jobs, but you can control this with TEST_JOBS=.  It is
-# suggested you not run out of memory.
-#
-# You can control what logs are held onto after the test is complete via the
-# KEEPIT= variable, explained below.  By default, nothing is kept.
-#
-# Finally, you can run tests across multiple computers at the same time by
-# putting all the hostnames into TEST_REMOTES= as a space separated list.
-# Do not add localhost manually, as it will always be added for you.  You
-# must create a user named kstest on each remote system, allow that user to
-# sudo to root for purposes of running livemedia-creator, and have ssh keys
-# set up so that the user running this script can login to the remote systems
-# as kstest without a password.  TEST_JOBS= applies on a per-system basis.
-# KEEPIT= controls how much will be kept on the master system (where "make
-# check" is run).  All results will be removed from the slave systems.
-
-# The boot.iso location can come from one of two different places:
-# (1) $TEST_BOOT_ISO, if this script is being called from "make check"
-# (2) The command line, if this script is being called directly.  That will
-#     be checked below.
-IMAGE="${TEST_BOOT_ISO}"
-
-# Possible values for this parameter:
-# 0 - Keep nothing (the default)
-# 1 - Keep log files
-# 2 - Keep log files and disk images (will take up a lot of space)
-KEEPIT=${KEEPIT:-0}
-
-TESTTYPE=""
-
-while getopts ":i:k:t:" opt; do
-    case $opt in
-       i)
-           # If this wasn't set from the environment, set it from the command line
-           # here.  If it never gets set, we'll catch that later and error out.
-           IMAGE=$OPTARG
-           ;;
-
-       k)
-           # This overrides either the $KEEPIT environment variable, or the default
-           # setting from above.
-           KEEPIT=$OPTARG
-           ;;
-
-       t)
-           # Only run tests that have TESTTYPE=<this value> in them.  Tests can have
-           # more than one type.  We'll do a pretty stupid test for it.
-           TESTTYPE=$OPTARG
-           ;;
-
-       *)
-           echo "Usage: run_kickstart_tests.sh [-i boot.iso] [-k 0|1|2] [tests]"
-           exit 1
-           ;;
-    esac
-done
-
-if [[ ! -e "${IMAGE}" ]]; then
-    echo "Required boot.iso does not exist; skipping."
-    exit 77
-fi
-
-shift $((OPTIND - 1))
-
-# This is for environment variables that parallel needs to pass to
-# remote systems.
-#
-# NOTE:  You will also need to add these to the list in /etc/sudoers
-# if you are using env_reset there, or they will not get passed from
-# this script to parallel.
-env_args=$(printenv | while read line; do
-    v="$(echo $line | cut -d'=' -f1)"
-    [[ "${v}" =~ ^KSTEST_ ]] && echo "--env ${v}"
- done)
-
-# We get the list of tests from one of two places:
-# (1) From the command line, all the other arguments.
-# (2) By applying any TESTTYPE given on the command line.
-# (3) From finding all scripts in kickstart_tests/ that are executable and are
-#     not support files.
-if [[ $# != 0 ]]; then
-    tests="$*"
-else
-    tests=$(find kickstart_tests -name '*sh' -a -perm -o+x -a \! -wholename 'kickstart_tests/run_*.sh')
-
-    newtests=""
-    if [[ "$TESTTYPE" != "" ]]; then
-        for f in ${tests}; do
-            if [[ "$(grep "TESTTYPE=" ${f})" =~ "${TESTTYPE}" ]]; then
-                newtests+="${f} "
-            fi
-        done
-
-        tests="${newtests}"
-    fi
-fi
-
-if [[ "${tests}" == "" ]]; then
-    echo "No tests provided; skipping."
-    exit 77
-fi
-
-if [[ "$TEST_REMOTES" != "" ]]; then
-    _IMAGE=kickstart_tests/$(basename ${IMAGE})
-
-    # (1) Copy everything to the remote systems.  We do this ourselves because
-    # parallel doesn't like globs, and we need to put the boot image somewhere
-    # that qemu on the remote systems can read.
-    for remote in ${TEST_REMOTES}; do
-        scp -r kickstart_tests kstest@${remote}:
-        scp ${IMAGE} kstest@${remote}:kickstart_tests/
-    done
-
-    # (1a) We also need to copy the provided image to under kickstart_tests/ on
-    # the local system too.  This is because parallel will attempt to run the
-    # same command line on every system and that requires the image to also be
-    # in the same location.
-    cp ${IMAGE} ${_IMAGE}
-
-    # (2) Run parallel.  We always add the local system to the list of machines
-    # being passed to parallel.  Don't add it yourself.
-    remote_args="--sshlogin :"
-    for remote in ${TEST_REMOTES}; do
-        remote_args="${remote_args} --sshlogin kstest@${remote}"
-    done
-
-    parallel --no-notice ${remote_args} \
-             ${env_args} --jobs ${TEST_JOBS:-2} \
-             sudo PYTHONPATH=$PYTHONPATH kickstart_tests/run_one_ks.sh -i ${_IMAGE} -k ${KEEPIT} {} ::: ${tests}
-    rc=$?
-
-    # (3) Get all the results back from the remote systems, which will have already
-    # applied the KEEPIT setting.  However if KEEPIT is 0 (meaning, don't save
-    # anything) there's no point in trying.  We do this ourselves because, again,
-    # parallel doesn't like globs.
-    #
-    # We also need to clean up the stuff we copied over in step 1, and then clean up
-    # the results from the remotes too.  We don't want to keep things scattered all
-    # over the place.
-    for remote in ${TEST_REMOTES}; do
-        if [[ ${KEEPIT} > 0 ]]; then
-            scp -r kstest@${remote}:/var/tmp/kstest-\* /var/tmp/
-        fi
-
-        ssh kstest@${remote} sudo rm -rf kickstart_tests /var/tmp/kstest-\*
-    done
-
-    # (3a) And then also remove the copy of the image we made earlier.
-    rm ${_IMAGE}
-
-    # (4) Exit the subshell defined by "find ... | " way up at the top.  The exit
-    # code will be caught outside and converted into the overall exit code.
-    exit ${rc}
-else
-    parallel --no-notice ${env_args} --jobs ${TEST_JOBS:-2} \
-        sudo PYTHONPATH=$PYTHONPATH kickstart_tests/run_one_ks.sh -i ${IMAGE} -k ${KEEPIT} {} ::: ${tests}
-
-    # For future expansion - any cleanup code can go in between the variable
-    # setting and the exit, like in the other branch of the if-else above.
-    rc=$?
-    exit ${rc}
-fi
-
-# Catch the exit code of the subshell and return it.  This is structured for
-# future expansion, too.  Any extra global cleanup code can go in between the
-# variable setting and the exit.
-rc=$?
-exit ${rc}
diff --git a/tests/kickstart_tests/run_one_ks.sh b/tests/kickstart_tests/run_one_ks.sh
deleted file mode 100755
index cf48f4b..0000000
--- a/tests/kickstart_tests/run_one_ks.sh
+++ /dev/null
@@ -1,157 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2015  Red Hat, Inc.
-#
-# This copyrighted material is made available to anyone wishing to use,
-# modify, copy, or redistribute it subject to the terms and conditions of
-# the GNU General Public License v.2, or (at your option) any later version.
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY expressed or implied, including the implied warranties of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
-# Public License for more details.  You should have received a copy of the
-# GNU General Public License along with this program; if not, write to the
-# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the
-# source code or documentation are not subject to the GNU General Public
-# License and may only be used or replicated with the express permission of
-# Red Hat, Inc.
-#
-# Red Hat Author(s): Chris Lumens <clumens at redhat.com>
-
-# This script runs a single kickstart test on a single system.  It takes
-# command line arguments instead of environment variables because it is
-# designed to be driven by run_kickstart_tests.sh via parallel.  It is
-# not for direct use, though as long as you pass the right arguments there's
-# no reason it couldn't work.
-
-# Possible return values:
-# 0  - Everything worked
-# 1  - Test failed for unspecified reasons
-# 2  - Test failed due to time out
-# 77 - Something needed by the test doesn't exist, so skip
-
-IMAGE=
-KEEPIT=0
-
-cleanup() {
-    d=$1
-
-    # Always remove the copy of the boot.iso.
-    rm ${d}/$(basename ${IMAGE})
-
-    if [[ ${KEEPIT} == 2 ]]; then
-        return
-    elif [[ ${KEEPIT} == 1 ]]; then
-        rm -f ${d}/disk-*.img ${d}/*ks
-    elif [[ ${KEEPIT} == 0 ]]; then
-        rm -rf ${d}
-    fi
-}
-
-runone() {
-    t=$1
-
-    export KSTESTDIR=$(pwd)/kickstart_tests
-
-    ks=${t/.sh/.ks}
-    . $t
-
-    name=$(basename ${t%.sh})
-
-    echo
-    echo ===========================================================================
-    echo ${ks} on $(hostname)
-    echo ===========================================================================
-
-    # qemu user needs to be able to read the directory and the boot.iso, so put that
-    # into this directory as well.  It will get deleted later, regardless of the
-    # KEEPIT setting.
-    tmpdir=$(mktemp -d --tmpdir=/var/tmp kstest-${name}.XXXXXXXX)
-    chmod 755 ${tmpdir}
-    cp ${IMAGE} ${tmpdir}
-
-    ksfile=$(prepare ${ks} ${tmpdir})
-    if [[ $? != 0 ]]; then
-        echo RESULT:${name}:FAILED:Test prep failed: ${ksfile}
-        cleanup ${tmpdir}
-        return 1
-    fi
-
-    kargs=$(kernel_args)
-    if [[ "${kargs}" != "" ]]; then
-        kargs="--kernel-args \"$kargs\""
-    fi
-
-    disks=$(prepare_disks ${tmpdir})
-    disk_args=$(for d in $disks; do echo --disk $d; done)
-
-    echo "PYTHONPATH=$PYTHONPATH"
-    eval ${KSTESTDIR}/kstest-runner ${kargs} \
-                       --iso "${tmpdir}/$(basename ${IMAGE})" \
-                       --ks ${ksfile} \
-                       --tmp ${tmpdir} \
-                       --logfile ${tmpdir}/livemedia.log \
-                       --ram 2048 \
-                       --vnc vnc \
-                       --timeout 60 \
-                       ${disk_args}
-    if [[ -f ${tmpdir}/virt-install.log && "$(grep CRIT ${tmpdir}/virt-install.log)" != "" ]]; then
-        echo RESULT:${name}:FAILED:$(grep CRIT ${tmpdir}/virt-install.log)
-        cleanup ${tmpdir}
-        return 1
-    elif [[ -f ${tmpdir}/livemedia.log ]]; then
-        if [[ "$(grep 'due to timeout' ${tmpdir}/livemedia.log)" != "" ]]; then
-            echo RESULT:${name}:FAILED:Test timed out.
-            cleanup ${tmpdir}
-            return 2
-        fi
-
-        result=$(validate ${tmpdir})
-        if [[ $? != 0 ]]; then
-            echo RESULT:${name}:FAILED:"${result}"
-            cleanup ${tmpdir}
-            return 1
-        fi
-    fi
-
-    echo RESULT:${name}:SUCCESS
-    cleanup ${tmpdir}
-    return 0
-}
-
-# Have to be root to run this test, as it requires creating disk images.
-if [[ ${EUID} != 0 ]]; then
-    echo "You must be root to run this test."
-    exit 77
-fi
-
-while getopts ":i:k:" opt; do
-    case $opt in
-        i)
-            IMAGE=$OPTARG
-            ;;
-
-        k)
-            KEEPIT=$OPTARG
-            ;;
-
-        *)
-            echo "Usage: run_one_ks.sh -i ISO [-k KEEPIT] ks-test.sh"
-            exit 1
-            ;;
-    esac
-done
-
-shift $((OPTIND - 1))
-
-if [[ ! -e "${IMAGE}" ]]; then
-    echo "Required boot.iso does not exist."
-    exit 77
-fi
-
-if [[ $# == 0 || ! -x $1 ]]; then
-    echo "Test not provided or is not executable."
-    exit 1
-fi
-
-runone $1
diff --git a/tests/kickstart_tests/run_report.sh b/tests/kickstart_tests/run_report.sh
deleted file mode 100755
index b62b128..0000000
--- a/tests/kickstart_tests/run_report.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/gawk -f
-
-BEGIN {
-    printf("\n\n\n%-30s | %-10s | %s\n", "TEST", "RESULT", "EXPLANATION");
-    printf("-------------------------------+------------+--------------------------------------------------------\n");
-    FS=":"
-}
-/^RESULT:/ { if ($4 == "Test timed out.") {
-                 result = "TIMED OUT";
-                 explanation = "";
-             } else if (match($0, "Traceback")) {
-                 result = "FAILED";
-                 explanation = "Traceback";
-             } else if (match($0, "SUCCESS")) {
-                 result = $3;
-                 explanation = "";
-             } else {
-                 result = $3;
-                 explanation = substr($0, index($0, $4), 55);
-             }
-
-             printf("%-30s | %-10s | %s\n", $2, result, explanation);
-           }
-END {
-    printf("\n\n");
-}
diff --git a/tests/kickstart_tests/scripts/kstest-runner b/tests/kickstart_tests/scripts/kstest-runner
new file mode 100755
index 0000000..196aa36
--- /dev/null
+++ b/tests/kickstart_tests/scripts/kstest-runner
@@ -0,0 +1,309 @@
+#!/usr/bin/python3
+#
+# kstest-runner - LMC-like program that only does what's necessary for running
+# kickstart-based tests in anaconda
+#
+# Copyright (C) 2011-2015  Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): Brian C. Lane <bcl at redhat.com>
+#            Chris Lumens <clumens at redhat.com>
+#
+import logging
+log = logging.getLogger("livemedia-creator")
+
+import os
+import sys
+import uuid
+import tempfile
+import subprocess
+from time import sleep
+import argparse
+
+# Use the Lorax treebuilder branch for iso creation
+from pylorax.treebuilder import udev_escape
+from pylorax.executils import execWithRedirect
+
+from pylorax import setup_logging
+from pylorax.monitor import LogMonitor
+from pylorax.mount import IsoMountpoint
+
+import libvirt
+
+class InstallError(Exception):
+    pass
+
+class VirtualInstall(object):
+    """
+    Run virt-install using an iso and a kickstart
+    """
+    def __init__(self, iso, ks_paths, disk_paths,
+                 kernel_args=None, memory=1024, vnc=None,
+                 log_check=None, virtio_host="127.0.0.1", virtio_port=6080):
+        """
+        Start the installation
+
+        :param iso: Information about the iso to use for the installation
+        :type iso: IsoMountpoint
+        :param list ks_paths: Paths to kickstart files. All are injected, the
+           first one is the one executed.
+        :param list disk_paths: Paths to pre-existing disk images.
+        :param str kernel_args: Extra kernel arguments to pass on the kernel cmdline
+        :param int memory: Amount of RAM to assign to the virt, in MiB
+        :param str vnc: Arguments to pass to virt-install --graphics
+        :param log_check: Method that returns True if the installation fails
+        :type log_check: method
+        :param str virtio_host: Hostname to connect virtio log to
+        :param int virtio_port: Port to connect virtio log to
+        """
+        self.virt_name = "LiveOS-"+str(uuid.uuid4())
+        # add --graphics none later
+        # add whatever serial cmds are needed later
+        args = ["-n", self.virt_name,
+                 "-r", str(memory),
+                 "--noreboot",
+                 "--noautoconsole"]
+
+        args.append("--graphics")
+        if vnc:
+            args.append(vnc)
+        else:
+            args.append("none")
+
+        for ks in ks_paths:
+            args.append("--initrd-inject")
+            args.append(ks)
+
+        for disk in disk_paths:
+            args.append("--disk")
+            args.append("path={0}".format(disk))
+
+        if iso.stage2:
+            disk_opts = "path={0},device=cdrom,readonly=on,shareable=on".format(iso.iso_path)
+            args.append("--disk")
+            args.append(disk_opts)
+
+        extra_args = "ks=file:/{0}".format(os.path.basename(ks_paths[0]))
+        if not vnc:
+            extra_args += " inst.cmdline"
+        if kernel_args:
+            extra_args += " " + kernel_args
+        if iso.stage2:
+            extra_args += " stage2=hd:CDLABEL={0}".format(udev_escape(iso.label))
+        args.append("--extra-args")
+        args.append(extra_args)
+
+        args.append("--location")
+        args.append(iso.mount_dir)
+
+        channel_args = "tcp,host={0}:{1},mode=connect,target_type=virtio" \
+                       ",name=org.fedoraproject.anaconda.log.0".format(
+                       virtio_host, virtio_port)
+        args.append("--channel")
+        args.append(channel_args)
+
+        log.info("Running virt-install.")
+        try:
+            execWithRedirect("virt-install", args, raise_err=True)
+        except subprocess.CalledProcessError as e:
+            raise InstallError("Problem starting virtual install: %s" % e)
+
+        conn = libvirt.openReadOnly(None)
+        dom = conn.lookupByName(self.virt_name)
+
+        # TODO: If vnc has been passed, we should look up the port and print that
+        # for the user at this point
+        while dom.isActive() and not log_check():
+            sys.stdout.write(".")
+            sys.stdout.flush()
+            sleep(10)
+        print()
+
+        if log_check():
+            log.info("Installation error detected. See logfile.")
+        else:
+            log.info("Install finished. Or at least virt shut down.")
+
+    def destroy(self, poolName):
+        """
+        Make sure the virt has been shut down and destroyed
+
+        Could use libvirt for this instead.
+        """
+        log.info("Shutting down %s", self.virt_name)
+        subprocess.call(["virsh", "destroy", self.virt_name])
+        subprocess.call(["virsh", "undefine", self.virt_name])
+        subprocess.call(["virsh", "pool-destroy", poolName])
+        subprocess.call(["virsh", "pool-undefine", poolName])
+
+def virt_install(opts, install_log):
+    """
+    Use virt-install to install to a disk image
+
+    :param opts: options passed to livemedia-creator
+    :type opts: argparse options
+    :param str install_log: The path to write the log from virt-install
+
+    This uses virt-install with a boot.iso and a kickstart to create a disk
+    image.
+    """
+    iso_mount = IsoMountpoint(opts.iso, opts.location)
+    log_monitor = LogMonitor(install_log, timeout=opts.timeout)
+
+    kernel_args = ""
+    if opts.kernel_args:
+        kernel_args += opts.kernel_args
+    if opts.proxy:
+        kernel_args += " proxy=" + opts.proxy
+
+    try:
+        virt = VirtualInstall(iso_mount, opts.ks, opts.disk_paths,
+                              kernel_args, opts.ram, opts.vnc,
+                              log_check = log_monitor.server.log_check,
+                              virtio_host = log_monitor.host,
+                              virtio_port = log_monitor.port)
+
+        virt.destroy(os.path.basename(opts.tmp))
+        log_monitor.shutdown()
+    except InstallError as e:
+        log.error("VirtualInstall failed: %s", e)
+        raise
+    finally:
+        log.info("unmounting the iso")
+        iso_mount.umount()
+
+    if log_monitor.server.log_check():
+        if not log_monitor.server.error_line and opts.timeout:
+            msg = "virt_install failed due to timeout"
+        else:
+            msg = "virt_install failed on line: %s" % log_monitor.server.error_line
+        raise InstallError(msg)
+
+
+def make_image(opts):
+    """
+    Install to a disk image
+
+    :param opts: options passed to livemedia-creator
+    :type opts: argparse options
+    :param str ks: Path to the kickstart to use for the installation
+
+    Use virt-install or anaconda to install to a disk image.
+    """
+    try:
+        install_log = os.path.abspath(os.path.dirname(opts.logfile))+"/virt-install.log"
+        log.info("install_log = %s", install_log)
+
+        virt_install(opts, install_log)
+    except InstallError as e:
+        log.error("Install failed: %s", e)
+
+        if not opts.keep_image:
+            log.info("Removing bad disk image")
+
+            for image in opts.disk_paths:
+                if os.path.exists(image):
+                    os.unlink(image)
+
+        raise
+
+    log.info("Disk Image install successful")
+
+def main():
+    parser = argparse.ArgumentParser(description="Run anaconda's kickstart-based tests",
+                                     fromfile_prefix_chars="@")
+
+    parser.add_argument("--iso", type=os.path.abspath,
+                        help="Anaconda installation .iso path to use for virt-install")
+    parser.add_argument("--ks", action="append", type=os.path.abspath,
+                        help="Kickstart file defining the install.")
+    parser.add_argument("--disk", action="append", type=os.path.abspath, dest="disk_paths",
+                        help="Pre-existing disk image to use for destination.")
+
+    parser.add_argument("--proxy",
+                        help="proxy URL to use for the install")
+    parser.add_argument("--location", default=None, type=os.path.abspath,
+                        help="location of iso directory tree with initrd.img "
+                             "and vmlinuz. Used to run virt-install with a "
+                             "newer initrd than the iso.")
+
+    parser.add_argument("--logfile", default="./livemedia.log",
+                        type=os.path.abspath,
+                        help="Path to logfile")
+    parser.add_argument("--tmp", default="/var/tmp", type=os.path.abspath,
+                        help="Top level temporary directory")
+
+    image_group = parser.add_argument_group("disk/fs image arguments")
+    image_group.add_argument("--keep-image", action="store_true",
+                             help="Keep raw disk image after .iso creation")
+
+    # Group of arguments to pass to virt-install
+    virt_group = parser.add_argument_group("virt-install arguments")
+    virt_group.add_argument("--ram", metavar="MEMORY", type=int, default=1024,
+                            help="Memory to allocate for installer in megabytes.")
+    virt_group.add_argument("--vnc",
+                            help="Passed to --graphics command")
+    virt_group.add_argument("--kernel-args",
+                            help="Additional argument to pass to the installation kernel")
+
+    parser.add_argument("--timeout", default=None, type=int,
+                        help="Cancel installer after X minutes")
+
+    opts = parser.parse_args()
+
+    setup_logging(opts.logfile, log)
+
+    log.debug( opts )
+
+    # Check for invalid combinations of options, print all the errors and exit.
+    errors = []
+    if opts.ks and not os.path.exists(opts.ks[0]):
+        errors.append("kickstart file (%s) is missing." % opts.ks[0])
+
+    if opts.iso and not os.path.exists(opts.iso):
+        errors.append("The iso %s is missing." % opts.iso)
+
+    if not opts.iso:
+        errors.append("virt install needs an install iso.")
+
+    if not os.path.exists("/usr/bin/virt-install"):
+        errors.append("virt-install needs to be installed.")
+
+    if os.getuid() != 0:
+        errors.append("You need to run this as root")
+
+    if errors:
+        list(log.error(e) for e in errors)
+        sys.exit(1)
+
+    tempfile.tempdir = opts.tmp
+
+    # Make the image.
+    try:
+        make_image(opts)
+    except InstallError as e:
+        log.error("ERROR: Image creation failed: %s", e)
+        sys.exit(1)
+
+    log.info("SUMMARY")
+    log.info("-------")
+    log.info("Logs are in %s", os.path.abspath(os.path.dirname(opts.logfile)))
+    log.info("Disk image(s) at %s", ",".join(opts.disk_paths))
+    log.info("Results are in %s", opts.tmp)
+
+    sys.exit( 0 )
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/kickstart_tests/scripts/make-addon-pkgs.py b/tests/kickstart_tests/scripts/make-addon-pkgs.py
new file mode 100755
index 0000000..e38cb7a
--- /dev/null
+++ b/tests/kickstart_tests/scripts/make-addon-pkgs.py
@@ -0,0 +1,119 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2015  Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
+# Public License for more details.  You should have received a copy of the
+# GNU General Public License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+# Red Hat Author(s): David Shea <dshea at redhat.com>
+
+# This script creates all the packages used by nfs-repo-and-addon.ks.
+# The packages are created in two directories, http and nfs. After all the rpms
+# are made just copy everything to the locations set in $KSTEST_ADDON_HTTP_REPO
+# and $KSTEST_ADDON_NFS_REPO.
+#
+# This script imports things from tests/lib/mkdud.py, so tests/lib needs to be
+# in $PYTHONPATH.
+
+# Ignore interuptible calls
+# pylint: disable=interruptible-system-call
+
+import os
+from subprocess import check_call
+from mkdud import make_rpm
+import rpmfluff
+
+# Start with http
+os.mkdir('http')
+
+# Empty package to be added to @core
+pkg = rpmfluff.SimpleRpmBuild('testpkg-http-core', '1.0', '1')
+make_rpm(pkg, 'http')
+
+# Another empty package
+pkg = rpmfluff.SimpleRpmBuild('testpkg-http-addon', '1.0', '1')
+make_rpm(pkg, 'http')
+
+# Three packages with marker files
+pkg = rpmfluff.SimpleRpmBuild('testpkg-share1', '1.0', '1')
+pkg.add_installed_file('/usr/share/testpkg-1/http',
+        rpmfluff.SourceFile('http', ''))
+make_rpm(pkg, 'http')
+
+pkg = rpmfluff.SimpleRpmBuild('testpkg-share2', '1.0', '1')
+pkg.add_installed_file('/usr/share/testpkg-2/http',
+        rpmfluff.SourceFile('http', ''))
+make_rpm(pkg, 'http')
+
+pkg = rpmfluff.SimpleRpmBuild('testpkg-share3', '1.0', '1')
+pkg.add_installed_file('/usr/share/testpkg-3/http',
+        rpmfluff.SourceFile('http', ''))
+make_rpm(pkg, 'http')
+
+# Create a comps file and create the repo
+with open('http/comps.xml', 'wt') as comps:
+    comps.write('''<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE comps PUBLIC "-//Red Hat, Inc.//DTD Comps info//EN" "comps.dtd">
+<comps>
+  <group>
+    <id>core</id>
+    <packagelist>
+      <packagereq type="mandatory">testpkg-http-core</packagereq>
+    </packagelist>
+  </group>
+</comps>''')
+
+check_call(['createrepo_c', '-g', 'comps.xml', 'http'])
+
+# Do the same thing again for nfs
+os.mkdir('nfs')
+
+# Empty package to be added to @core
+pkg = rpmfluff.SimpleRpmBuild('testpkg-nfs-core', '1.0', '1')
+make_rpm(pkg, 'nfs')
+
+# Another empty package
+pkg = rpmfluff.SimpleRpmBuild('testpkg-nfs-addon', '1.0', '1')
+make_rpm(pkg, 'nfs')
+
+# Three packages with marker files
+pkg = rpmfluff.SimpleRpmBuild('testpkg-share1', '1.0', '1')
+pkg.add_installed_file('/usr/share/testpkg-1/nfs',
+        rpmfluff.SourceFile('nfs', ''))
+make_rpm(pkg, 'nfs')
+
+pkg = rpmfluff.SimpleRpmBuild('testpkg-share2', '1.0', '1')
+pkg.add_installed_file('/usr/share/testpkg-2/nfs',
+        rpmfluff.SourceFile('nfs', ''))
+make_rpm(pkg, 'nfs')
+
+pkg = rpmfluff.SimpleRpmBuild('testpkg-share3', '1.0', '1')
+pkg.add_installed_file('/usr/share/testpkg-3/nfs',
+        rpmfluff.SourceFile('nfs', ''))
+make_rpm(pkg, 'nfs')
+
+# Create a comps file and create the repo
+with open('nfs/comps.xml', 'wt') as comps:
+    comps.write('''<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE comps PUBLIC "-//Red Hat, Inc.//DTD Comps info//EN" "comps.dtd">
+<comps>
+  <group>
+    <id>core</id>
+    <packagelist>
+      <packagereq type="mandatory">testpkg-nfs-core</packagereq>
+    </packagelist>
+  </group>
+</comps>''')
+
+check_call(['createrepo_c', '-g', 'comps.xml', 'nfs'])
diff --git a/tests/kickstart_tests/scripts/proxy-common.ks b/tests/kickstart_tests/scripts/proxy-common.ks
new file mode 100644
index 0000000..a95097a
--- /dev/null
+++ b/tests/kickstart_tests/scripts/proxy-common.ks
@@ -0,0 +1,79 @@
+# Start a super-simple proxy server on localhost
+# A list of proxied requests will be saved to /tmp/proxy.log
+%pre --erroronfail
+# Write the proxy script to a file in /tmp
+cat - << "EOF" > /tmp/proxy-test.py
+from http.server import SimpleHTTPRequestHandler
+import socketserver
+from urllib.request import urlopen
+import os
+from base64 import b64decode
+
+import logging
+log = logging.getLogger("proxy_test")
+log_handler = logging.FileHandler('/tmp/proxy.log')
+log.setLevel(logging.INFO)
+log.addHandler(log_handler)
+
+class ProxyHandler(SimpleHTTPRequestHandler):
+    def send_authenticate(self):
+        self.send_response(407)
+        self.send_header('Proxy-Authenticate', 'Basic realm=proxy-test')
+        self.end_headers()
+
+    def authenticate(self):
+        # If there is no /tmp/proxy.password file, anything goes
+        if not os.path.exists('/tmp/proxy.password'):
+            return True
+
+        # If there is no Authorization header, send a 407, Proxy authentication required
+        authorization = self.headers['Proxy-Authorization']
+        if not authorization:
+            self.send_authenticate()
+            return False
+
+        # Parse the Authorization header. It should be "Basic" followed
+        # user:pass encoded in base64
+        if not authorization.startswith('Basic'):
+            self.send_authenticate()
+            return False
+
+        try:
+            client_auth = b64decode(authorization.split()[1])
+        except IndexError:
+            self.send_authenticate()
+            return False
+
+        with open('/tmp/proxy.password', 'rb') as f:
+            server_auth = f.readline().strip()
+
+        if client_auth != server_auth:
+            self.send_authenticate()
+            return False
+
+        return True
+
+    def do_GET(self):
+        if not self.authenticate():
+            return
+
+        # Log the path then proxy the request via urllib
+        log.info(self.path)
+        data = urlopen(self.path).read()
+        self.send_response(200)
+        self.send_header('Content-Length', str(len(data)))
+        self.end_headers()
+        self.wfile.write(data)
+
+class ProxyServer(socketserver.TCPServer):
+    allow_reuse_address = True
+
+    def __init__(self):
+        socketserver.TCPServer.__init__(self, ('', 8080), ProxyHandler)
+
+ProxyServer().serve_forever()
+EOF
+
+# Run the server in the background and exit
+python3 /tmp/proxy-test.py > /dev/null 2>&1 &
+%end
diff --git a/tests/kickstart_tests/scripts/run_kickstart_tests.sh b/tests/kickstart_tests/scripts/run_kickstart_tests.sh
new file mode 100755
index 0000000..904f90f
--- /dev/null
+++ b/tests/kickstart_tests/scripts/run_kickstart_tests.sh
@@ -0,0 +1,199 @@
+#!/bin/bash
+#
+# Copyright (C) 2014, 2015  Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
+# Public License for more details.  You should have received a copy of the
+# GNU General Public License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+# Red Hat Author(s): Chris Lumens <clumens at redhat.com>
+
+# This script runs the entire kickstart_tests suite.  It is an interface
+# between "make check" (which is why it takes environment variables instead
+# of arguments) and livemedia-creator.  Each test consists of a kickstart
+# file that specifies most everything about the installation, and a shell
+# script that does validation and specifies kernel boot parameters.  lmc
+# then fires up a VM and watches for tracebacks or stuck installs.
+#
+# A boot ISO is required, which should be specified with TEST_BOOT_ISO=.
+#
+# The number of jobs corresponds to the number of VMs that will be started
+# simultaneously.  Each one wants about 2 GB of memory.  The default is
+# two simultaneous jobs, but you can control this with TEST_JOBS=.  It is
+# suggested you not run out of memory.
+#
+# You can control what logs are held onto after the test is complete via the
+# KEEPIT= variable, explained below.  By default, nothing is kept.
+#
+# Finally, you can run tests across multiple computers at the same time by
+# putting all the hostnames into TEST_REMOTES= as a space separated list.
+# Do not add localhost manually, as it will always be added for you.  You
+# must create a user named kstest on each remote system, allow that user to
+# sudo to root for purposes of running livemedia-creator, and have ssh keys
+# set up so that the user running this script can login to the remote systems
+# as kstest without a password.  TEST_JOBS= applies on a per-system basis.
+# KEEPIT= controls how much will be kept on the master system (where "make
+# check" is run).  All results will be removed from the slave systems.
+
+# The boot.iso location can come from one of two different places:
+# (1) $TEST_BOOT_ISO, if this script is being called from "make check"
+# (2) The command line, if this script is being called directly.  That will
+#     be checked below.
+IMAGE="${TEST_BOOT_ISO}"
+
+# Possible values for this parameter:
+# 0 - Keep nothing (the default)
+# 1 - Keep log files
+# 2 - Keep log files and disk images (will take up a lot of space)
+KEEPIT=${KEEPIT:-0}
+
+TESTTYPE=""
+
+while getopts ":i:k:t:" opt; do
+    case $opt in
+       i)
+           # If this wasn't set from the environment, set it from the command line
+           # here.  If it never gets set, we'll catch that later and error out.
+           IMAGE=$OPTARG
+           ;;
+
+       k)
+           # This overrides either the $KEEPIT environment variable, or the default
+           # setting from above.
+           KEEPIT=$OPTARG
+           ;;
+
+       t)
+           # Only run tests that have TESTTYPE=<this value> in them.  Tests can have
+           # more than one type.  We'll do a pretty stupid test for it.
+           TESTTYPE=$OPTARG
+           ;;
+
+       *)
+           echo "Usage: run_kickstart_tests.sh [-i boot.iso] [-k 0|1|2] [tests]"
+           exit 1
+           ;;
+    esac
+done
+
+if [[ ! -e "${IMAGE}" ]]; then
+    echo "Required boot.iso does not exist; skipping."
+    exit 77
+fi
+
+shift $((OPTIND - 1))
+
+# This is for environment variables that parallel needs to pass to
+# remote systems.
+#
+# NOTE:  You will also need to add these to the list in /etc/sudoers
+# if you are using env_reset there, or they will not get passed from
+# this script to parallel.
+env_args=$(printenv | while read line; do
+    v="$(echo $line | cut -d'=' -f1)"
+    [[ "${v}" =~ ^KSTEST_ ]] && echo "--env ${v}"
+ done)
+
+# We get the list of tests from one of two places:
+# (1) From the command line, all the other arguments.
+# (2) By applying any TESTTYPE given on the command line.
+# (3) From finding all scripts in kickstart_tests/ that are executable and are
+#     not support files.
+if [[ $# != 0 ]]; then
+    tests="$*"
+else
+    tests=$(find kickstart_tests -name '*sh' -a -perm -o+x -a \! -wholename 'kickstart_tests/run_*.sh')
+
+    newtests=""
+    if [[ "$TESTTYPE" != "" ]]; then
+        for f in ${tests}; do
+            if [[ "$(grep "TESTTYPE=" ${f})" =~ "${TESTTYPE}" ]]; then
+                newtests+="${f} "
+            fi
+        done
+
+        tests="${newtests}"
+    fi
+fi
+
+if [[ "${tests}" == "" ]]; then
+    echo "No tests provided; skipping."
+    exit 77
+fi
+
+if [[ "$TEST_REMOTES" != "" ]]; then
+    _IMAGE=kickstart_tests/$(basename ${IMAGE})
+
+    # (1) Copy everything to the remote systems.  We do this ourselves because
+    # parallel doesn't like globs, and we need to put the boot image somewhere
+    # that qemu on the remote systems can read.
+    for remote in ${TEST_REMOTES}; do
+        scp -r kickstart_tests kstest@${remote}:
+        scp ${IMAGE} kstest@${remote}:kickstart_tests/
+    done
+
+    # (1a) We also need to copy the provided image to under kickstart_tests/ on
+    # the local system too.  This is because parallel will attempt to run the
+    # same command line on every system and that requires the image to also be
+    # in the same location.
+    cp ${IMAGE} ${_IMAGE}
+
+    # (2) Run parallel.  We always add the local system to the list of machines
+    # being passed to parallel.  Don't add it yourself.
+    remote_args="--sshlogin :"
+    for remote in ${TEST_REMOTES}; do
+        remote_args="${remote_args} --sshlogin kstest@${remote}"
+    done
+
+    parallel --no-notice ${remote_args} \
+             ${env_args} --jobs ${TEST_JOBS:-2} \
+             sudo PYTHONPATH=$PYTHONPATH kickstart_tests/scripts/run_one_ks.sh -i ${_IMAGE} -k ${KEEPIT} {} ::: ${tests}
+    rc=$?
+
+    # (3) Get all the results back from the remote systems, which will have already
+    # applied the KEEPIT setting.  However if KEEPIT is 0 (meaning, don't save
+    # anything) there's no point in trying.  We do this ourselves because, again,
+    # parallel doesn't like globs.
+    #
+    # We also need to clean up the stuff we copied over in step 1, and then clean up
+    # the results from the remotes too.  We don't want to keep things scattered all
+    # over the place.
+    for remote in ${TEST_REMOTES}; do
+        if [[ ${KEEPIT} > 0 ]]; then
+            scp -r kstest@${remote}:/var/tmp/kstest-\* /var/tmp/
+        fi
+
+        ssh kstest@${remote} sudo rm -rf kickstart_tests /var/tmp/kstest-\*
+    done
+
+    # (3a) And then also remove the copy of the image we made earlier.
+    rm ${_IMAGE}
+
+    # (4) Exit the subshell defined by "find ... | " way up at the top.  The exit
+    # code will be caught outside and converted into the overall exit code.
+    exit ${rc}
+else
+    parallel --no-notice ${env_args} --jobs ${TEST_JOBS:-2} \
+        sudo PYTHONPATH=$PYTHONPATH kickstart_tests/scripts/run_one_ks.sh -i ${IMAGE} -k ${KEEPIT} {} ::: ${tests}
+
+    # For future expansion - any cleanup code can go in between the variable
+    # setting and the exit, like in the other branch of the if-else above.
+    rc=$?
+    exit ${rc}
+fi
+
+# Catch the exit code of the subshell and return it.  This is structured for
+# future expansion, too.  Any extra global cleanup code can go in between the
+# variable setting and the exit.
+rc=$?
+exit ${rc}
diff --git a/tests/kickstart_tests/scripts/run_one_ks.sh b/tests/kickstart_tests/scripts/run_one_ks.sh
new file mode 100755
index 0000000..2ed2b36
--- /dev/null
+++ b/tests/kickstart_tests/scripts/run_one_ks.sh
@@ -0,0 +1,157 @@
+#!/bin/bash
+#
+# Copyright (C) 2015  Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
+# Public License for more details.  You should have received a copy of the
+# GNU General Public License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+# Red Hat Author(s): Chris Lumens <clumens at redhat.com>
+
+# This script runs a single kickstart test on a single system.  It takes
+# command line arguments instead of environment variables because it is
+# designed to be driven by run_kickstart_tests.sh via parallel.  It is
+# not for direct use, though as long as you pass the right arguments there's
+# no reason it couldn't work.
+
+# Possible return values:
+# 0  - Everything worked
+# 1  - Test failed for unspecified reasons
+# 2  - Test failed due to time out
+# 77 - Something needed by the test doesn't exist, so skip
+
+IMAGE=
+KEEPIT=0
+
+cleanup() {
+    d=$1
+
+    # Always remove the copy of the boot.iso.
+    rm ${d}/$(basename ${IMAGE})
+
+    if [[ ${KEEPIT} == 2 ]]; then
+        return
+    elif [[ ${KEEPIT} == 1 ]]; then
+        rm -f ${d}/disk-*.img ${d}/*ks
+    elif [[ ${KEEPIT} == 0 ]]; then
+        rm -rf ${d}
+    fi
+}
+
+runone() {
+    t=$1
+
+    export KSTESTDIR=$(pwd)/kickstart_tests
+
+    ks=${t/.sh/.ks}
+    . $t
+
+    name=$(basename ${t%.sh})
+
+    echo
+    echo ===========================================================================
+    echo ${ks} on $(hostname)
+    echo ===========================================================================
+
+    # qemu user needs to be able to read the directory and the boot.iso, so put that
+    # into this directory as well.  It will get deleted later, regardless of the
+    # KEEPIT setting.
+    tmpdir=$(mktemp -d --tmpdir=/var/tmp kstest-${name}.XXXXXXXX)
+    chmod 755 ${tmpdir}
+    cp ${IMAGE} ${tmpdir}
+
+    ksfile=$(prepare ${ks} ${tmpdir})
+    if [[ $? != 0 ]]; then
+        echo RESULT:${name}:FAILED:Test prep failed: ${ksfile}
+        cleanup ${tmpdir}
+        return 1
+    fi
+
+    kargs=$(kernel_args)
+    if [[ "${kargs}" != "" ]]; then
+        kargs="--kernel-args \"$kargs\""
+    fi
+
+    disks=$(prepare_disks ${tmpdir})
+    disk_args=$(for d in $disks; do echo --disk $d; done)
+
+    echo "PYTHONPATH=$PYTHONPATH"
+    eval ${KSTESTDIR}/scripts/kstest-runner ${kargs} \
+                       --iso "${tmpdir}/$(basename ${IMAGE})" \
+                       --ks ${ksfile} \
+                       --tmp ${tmpdir} \
+                       --logfile ${tmpdir}/livemedia.log \
+                       --ram 2048 \
+                       --vnc vnc \
+                       --timeout 60 \
+                       ${disk_args}
+    if [[ -f ${tmpdir}/virt-install.log && "$(grep CRIT ${tmpdir}/virt-install.log)" != "" ]]; then
+        echo RESULT:${name}:FAILED:$(grep CRIT ${tmpdir}/virt-install.log)
+        cleanup ${tmpdir}
+        return 1
+    elif [[ -f ${tmpdir}/livemedia.log ]]; then
+        if [[ "$(grep 'due to timeout' ${tmpdir}/livemedia.log)" != "" ]]; then
+            echo RESULT:${name}:FAILED:Test timed out.
+            cleanup ${tmpdir}
+            return 2
+        fi
+
+        result=$(validate ${tmpdir})
+        if [[ $? != 0 ]]; then
+            echo RESULT:${name}:FAILED:"${result}"
+            cleanup ${tmpdir}
+            return 1
+        fi
+    fi
+
+    echo RESULT:${name}:SUCCESS
+    cleanup ${tmpdir}
+    return 0
+}
+
+# Have to be root to run this test, as it requires creating disk images.
+if [[ ${EUID} != 0 ]]; then
+    echo "You must be root to run this test."
+    exit 77
+fi
+
+while getopts ":i:k:" opt; do
+    case $opt in
+        i)
+            IMAGE=$OPTARG
+            ;;
+
+        k)
+            KEEPIT=$OPTARG
+            ;;
+
+        *)
+            echo "Usage: run_one_ks.sh -i ISO [-k KEEPIT] ks-test.sh"
+            exit 1
+            ;;
+    esac
+done
+
+shift $((OPTIND - 1))
+
+if [[ ! -e "${IMAGE}" ]]; then
+    echo "Required boot.iso does not exist."
+    exit 77
+fi
+
+if [[ $# == 0 || ! -x $1 ]]; then
+    echo "Test not provided or is not executable."
+    exit 1
+fi
+
+runone $1
diff --git a/tests/kickstart_tests/scripts/run_report.sh b/tests/kickstart_tests/scripts/run_report.sh
new file mode 100755
index 0000000..b62b128
--- /dev/null
+++ b/tests/kickstart_tests/scripts/run_report.sh
@@ -0,0 +1,26 @@
+#!/bin/gawk -f
+
+BEGIN {
+    printf("\n\n\n%-30s | %-10s | %s\n", "TEST", "RESULT", "EXPLANATION");
+    printf("-------------------------------+------------+--------------------------------------------------------\n");
+    FS=":"
+}
+/^RESULT:/ { if ($4 == "Test timed out.") {
+                 result = "TIMED OUT";
+                 explanation = "";
+             } else if (match($0, "Traceback")) {
+                 result = "FAILED";
+                 explanation = "Traceback";
+             } else if (match($0, "SUCCESS")) {
+                 result = $3;
+                 explanation = "";
+             } else {
+                 result = $3;
+                 explanation = substr($0, index($0, $4), 55);
+             }
+
+             printf("%-30s | %-10s | %s\n", $2, result, explanation);
+           }
+END {
+    printf("\n\n");
+}


-- 
To view this commit on github, visit https://github.com/rhinstaller/anaconda/commit/4248347cb77bfa5bffc1b25052f27eaaeaca5474


More information about the anaconda-patches mailing list