livemedia-creator: Add --timeout option to cancel install after X minutes

Installations sometimes get stuck. This adds the option to cancel it
after some number of minutes have passed.
This commit is contained in:
Brian C. Lane 2015-02-02 12:24:06 -08:00
parent c1d38a9c48
commit 30c21a1b97
1 changed files with 22 additions and 7 deletions

View File

@ -32,6 +32,7 @@ import subprocess
import socket import socket
import threading import threading
import SocketServer import SocketServer
import time
from time import sleep from time import sleep
import shutil import shutil
import argparse import argparse
@ -181,6 +182,9 @@ class LogServer(SocketServer.TCPServer):
self.log_error = False self.log_error = False
self.error_line = "" self.error_line = ""
self.log_path = log_path self.log_path = log_path
self._timeout = kwargs.pop("timeout", None)
if self._timeout:
self._start_time = time.time()
SocketServer.TCPServer.__init__(self, *args, **kwargs) SocketServer.TCPServer.__init__(self, *args, **kwargs)
def log_check(self): def log_check(self):
@ -190,7 +194,13 @@ class LogServer(SocketServer.TCPServer):
:returns: True if there has been an error :returns: True if there has been an error
:rtype: bool :rtype: bool
""" """
return self.log_error if self._timeout:
taking_too_long = time.time() > self._start_time + (self._timeout * 60)
if taking_too_long:
log.error("Canceling installation due to timeout")
else:
taking_too_long = False
return self.log_error or taking_too_long
class LogMonitor(object): class LogMonitor(object):
@ -200,7 +210,7 @@ class LogMonitor(object):
This needs to be running before the virt-install runs, it expects This needs to be running before the virt-install runs, it expects
there to be a listener on the port used for the virtio log port. there to be a listener on the port used for the virtio log port.
""" """
def __init__(self, log_path=None, host="localhost", port=0): def __init__(self, log_path=None, host="localhost", port=0, timeout=None):
""" """
Start a thread to monitor the logs. Start a thread to monitor the logs.
@ -214,7 +224,7 @@ class LogMonitor(object):
If log_path isn't set then it only monitors the logs, instead of If log_path isn't set then it only monitors the logs, instead of
also writing them to disk. also writing them to disk.
""" """
self.server = LogServer(log_path, (host, port), LogRequestHandler) self.server = LogServer(log_path, (host, port), LogRequestHandler, timeout=timeout)
self.host, self.port = self.server.server_address self.host, self.port = self.server.server_address
self.log_path = log_path self.log_path = log_path
self.server_thread = threading.Thread(target=self.server.handle_request) self.server_thread = threading.Thread(target=self.server.handle_request)
@ -389,7 +399,6 @@ class VirtualInstall(object):
# TODO: If vnc has been passed, we should look up the port and print that # TODO: If vnc has been passed, we should look up the port and print that
# for the user at this point # for the user at this point
while dom.isActive() and not log_check(): while dom.isActive() and not log_check():
sys.stdout.write(".") sys.stdout.write(".")
sys.stdout.flush() sys.stdout.flush()
@ -815,7 +824,7 @@ def novirt_install(opts, disk_img, disk_size, repo_url):
# Create the sparse image # Create the sparse image
mksparse(disk_img, disk_size * 1024**2) mksparse(disk_img, disk_size * 1024**2)
log_monitor = LogMonitor() log_monitor = LogMonitor(timeout=opts.timeout)
args += ["--remotelog", "%s:%s" % (log_monitor.host, log_monitor.port)] args += ["--remotelog", "%s:%s" % (log_monitor.host, log_monitor.port)]
# Make sure anaconda has the right product and release # Make sure anaconda has the right product and release
@ -902,7 +911,7 @@ def virt_install(opts, install_log, disk_img, disk_size):
image and then optionally, based on the opts passed, creates tarfile. image and then optionally, based on the opts passed, creates tarfile.
""" """
iso_mount = IsoMountpoint(opts.iso, opts.location) iso_mount = IsoMountpoint(opts.iso, opts.location)
log_monitor = LogMonitor(install_log) log_monitor = LogMonitor(install_log, timeout=opts.timeout)
kernel_args = "" kernel_args = ""
if opts.kernel_args: if opts.kernel_args:
@ -941,7 +950,11 @@ def virt_install(opts, install_log, disk_img, disk_size):
iso_mount.umount() iso_mount.umount()
if log_monitor.server.log_check(): if log_monitor.server.log_check():
raise InstallError("virt_install failed on line: %s" % log_monitor.server.error_line) 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)
if opts.make_fsimage: if opts.make_fsimage:
make_fsimage(diskimg_path, disk_img, disk_size, label=opts.fs_label) make_fsimage(diskimg_path, disk_img, disk_size, label=opts.fs_label)
@ -1252,6 +1265,8 @@ def main():
parser.add_argument("--volid", default=None, help="volume id") parser.add_argument("--volid", default=None, help="volume id")
parser.add_argument("--squashfs_args", parser.add_argument("--squashfs_args",
help="additional squashfs args") help="additional squashfs args")
parser.add_argument("--timeout", default=None, type=int,
help="Cancel installer after X minutes")
opts = parser.parse_args() opts = parser.parse_args()