qubes-installer-qubes-os/anaconda/tests/kickstart_tests/kstest-runner
M. Vefa Bicakci 38f3e28d77
anaconda: Update to 23.19.10
Use the output of

  git diff --full-index --binary anaconda-22.20.13-1..anaconda-23.19.10-1

from anaconda's git repository and fix-up merge conflicts.
2016-04-10 00:00:00 -04:00

310 lines
11 KiB
Python
Executable File

#!/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@redhat.com>
# Chris Lumens <clumens@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()