[PATCH 3/3] Run kickstart tests through an LMC-like program, not LMC itself.
Chris Lumens
clumens at redhat.com
Fri May 29 17:58:04 UTC 2015
This allows for specifying multiple (potentially initialized) disks and
fancier network setups. For the moment I only have support for the disk
portion. Networking will come later, when I learn what needs to be done.
---
tests/Makefile.am | 1 +
tests/kickstart_tests/kstest-runner | 309 ++++++++++++++++++++++++++++++++++++
tests/kickstart_tests/run_one_ks.sh | 37 ++---
3 files changed, 327 insertions(+), 20 deletions(-)
create mode 100755 tests/kickstart_tests/kstest-runner
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 2f29d9d..25575a1 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -53,6 +53,7 @@ dist_check_SCRIPTS = $(srcdir)/glade/*/*.py \
install/run_install_test.sh \
$(srcdir)/kickstart_tests/*.ks \
$(srcdir)/kickstart_tests/*.sh \
+ $(srcdir)/kickstart_tests/kstest-runner \
$(srcdir)/gui/*.ks \
$(srcdir)/gui/*.sh \
$(srcdir)/gui/inside/*.py \
diff --git a/tests/kickstart_tests/kstest-runner b/tests/kickstart_tests/kstest-runner
new file mode 100755
index 0000000..c0bcdc1
--- /dev/null
+++ b/tests/kickstart_tests/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")
+program_log = logging.getLogger("program")
+pylorax_log = logging.getLogger("pylorax")
+
+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=live: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):
+ """
+ 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])
+
+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()
+ 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.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/run_one_ks.sh b/tests/kickstart_tests/run_one_ks.sh
index b535d99..55752d0 100755
--- a/tests/kickstart_tests/run_one_ks.sh
+++ b/tests/kickstart_tests/run_one_ks.sh
@@ -82,38 +82,35 @@ runone() {
kargs="--kernel-args \"$kargs\""
fi
- eval livemedia-creator ${kargs} \
- --make-disk \
- --iso "${tmpdir}/$(basename ${IMAGE})" \
- --ks ${ksfile} \
- --tmp ${tmpdir} \
- --logfile ${tmpdir}/livemedia.log \
- --title Fedora \
- --project Fedora \
- --releasever 22 \
- --ram 2048 \
- --vcpus 2 \
- --vnc vnc \
- --timeout 60
- if [[ "$(grep CRIT ${tmpdir}/virt-install.log)" != "" ]]; then
+ mkdir -p ${tmpdir}/disks/
+ disks=$(prepare_disks ${tmpdir})
+ disk_args=$(for d in $disks; do echo --disk $d; done)
+
+ 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
- img=$(grep disk_img ${tmpdir}/livemedia.log | cut -d= -f2)
- trimmed=${img## }
-
if [[ "$(grep 'due to timeout' ${tmpdir}/livemedia.log)" != "" ]]; then
echo RESULT:${name}:FAILED:Test timed out.
cleanup ${tmpdir}
return 2
- elif [[ ! -f ${trimmed} ]]; then
- echo RESULT:${name}:FAILED:Disk image ${trimmed} does not exist.
+ elif [[ ! -d ${tmpdir}/disks ]]; then
+ echo RESULT:${name}:FAILED:Disk images do not exist.
cleanup ${tmpdir}
return 1
fi
- result=$(validate ${trimmed})
+ result=$(validate ${tmpdir}/disks)
if [[ $? != 0 ]]; then
echo RESULT:${name}:FAILED:"${result}"
cleanup ${tmpdir}
--
2.2.2
More information about the anaconda-patches
mailing list