[PATCH] Add log monitoring to lmc --novirt installation
by Brian C. Lane
Previously if there was an error during a novirt installation that
didn't exit the process there was no way to detect it. This uses the new
--remotelog option for anaconda to monitor the logs for errors using the
same criteria as it does when monitoring a virt install. If there is an
error the anaconda process will be terminated and the logs will be
gathered up into ./anaconda/
---
src/pylorax/executils.py | 10 +++++++++-
src/sbin/livemedia-creator | 40 ++++++++++++++++++++++++++++++++++------
2 files changed, 43 insertions(+), 7 deletions(-)
diff --git a/src/pylorax/executils.py b/src/pylorax/executils.py
index 0b261c3..6fbb271 100644
--- a/src/pylorax/executils.py
+++ b/src/pylorax/executils.py
@@ -23,6 +23,7 @@
import os, sys
import subprocess
import threading
+from time import sleep
import logging
log = logging.getLogger("pylorax")
@@ -66,7 +67,7 @@ class tee(threading.Thread):
def execWithRedirect(command, argv, stdin = None, stdout = None,
stderr = None, root = None, preexec_fn=None, cwd=None,
- raise_err=False):
+ raise_err=False, callback=None):
""" Run an external program and redirect the output to a file.
@param command The command to run.
@param argv A list of arguments.
@@ -77,7 +78,11 @@ def execWithRedirect(command, argv, stdin = None, stdout = None,
@param preexec_fn function to pass to Popen
@param cwd working directory to pass to Popen
@param raise_err raise CalledProcessError when the returncode is not 0
+ @param callback method to call while waiting for process to exit.
@return The return code of command.
+
+ The callback is passed the Popen object. It should return False if
+ the polling loop should be exited.
"""
def chroot ():
os.chroot(root)
@@ -143,6 +148,9 @@ def execWithRedirect(command, argv, stdin = None, stdout = None,
preexec_fn=preexec_fn, cwd=cwd,
env=env)
+ if callback:
+ while callback(proc) and proc.poll() is None:
+ sleep(1)
proc.wait()
ret = proc.returncode
diff --git a/src/sbin/livemedia-creator b/src/sbin/livemedia-creator
index 1472f21..b21cdbe 100755
--- a/src/sbin/livemedia-creator
+++ b/src/sbin/livemedia-creator
@@ -88,7 +88,7 @@ class LogRequestHandler(SocketServer.BaseRequestHandler):
if self.server.log_path:
self.fp = open(self.server.log_path, "w") # pylint: disable=attribute-defined-outside-init
else:
- print "no log_path specified"
+ self.fp = None
self.request.settimeout(10)
def handle(self):
@@ -107,8 +107,9 @@ class LogRequestHandler(SocketServer.BaseRequestHandler):
try:
data = self.request.recv(4096)
- self.fp.write(data)
- self.fp.flush()
+ if self.fp:
+ self.fp.write(data)
+ self.fp.flush()
# check the data for errors and set error flag
# need to assemble it into lines so we can test for the error
@@ -130,7 +131,8 @@ class LogRequestHandler(SocketServer.BaseRequestHandler):
def finish(self):
self.request.close()
- self.fp.close()
+ if self.fp:
+ self.fp.close()
def iserror(self, line):
"""
@@ -193,7 +195,7 @@ class LogMonitor(object):
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.
"""
- def __init__(self, log_path, host="localhost", port=0):
+ def __init__(self, log_path=None, host="localhost", port=0):
"""
Start a thread to monitor the logs.
@@ -203,6 +205,9 @@ class LogMonitor(object):
If 0 is passed for the port the dynamically assigned port will be
available as self.port
+
+ If log_path isn't set then it only monitors the logs, instead of
+ also writing them to disk.
"""
self.server = LogServer(log_path, (host, port), LogRequestHandler)
self.host, self.port = self.server.server_address
@@ -590,6 +595,23 @@ def make_livecd(opts, mount_dir, work_dir):
return work_dir
+def novirt_log_check(log_check, proc):
+ """
+ Check to see if there has been an error in the logs
+
+ :param log_check: method to call to check for an error in the logs
+ :param proc: Popen object for the anaconda process
+ :returns: True if the process has been terminated
+
+ The log_check method should return a True if an error has been detected.
+ When an error is detected the process is terminated and this returns True
+ """
+ if log_check():
+ proc.terminate()
+ return True
+ return False
+
+
def novirt_install(opts, disk_img, disk_size, repo_url):
"""
Use Anaconda to install to a disk image
@@ -648,12 +670,16 @@ def novirt_install(opts, disk_img, disk_size, repo_url):
# Create the sparse image
mksparse(disk_img, disk_size * 1024**2)
+ log_monitor = LogMonitor()
+ args += ["--remotelog", "%s:%s" % (log_monitor.host, log_monitor.port)]
+
# Make sure anaconda has the right product and release
os.environ["ANACONDA_PRODUCTNAME"] = opts.project
os.environ["ANACONDA_PRODUCTVERSION"] = opts.releasever
log.info("Running anaconda.")
try:
- execWithRedirect("anaconda", args, raise_err=True)
+ execWithRedirect("anaconda", args, raise_err=True,
+ callback=lambda p: not novirt_log_check(log_monitor.server.log_check, p))
# Make sure the new filesystem is correctly labeled
args = ["-e", "/proc", "-e", "/sys", "-e", "/dev",
@@ -668,6 +694,8 @@ def novirt_install(opts, disk_img, disk_size, repo_url):
log.error("Running anaconda failed: %s", e)
raise InstallError("novirt_install failed")
finally:
+ log_monitor.shutdown()
+
# Move the anaconda logs over to a log directory
log_dir = os.path.abspath(os.path.dirname(opts.logfile))
log_anaconda = joinpaths(log_dir, "anaconda")
--
1.9.3
9 years, 5 months
[PATCH] Add support for sending logs to a remote host with --remotelog
by Brian C. Lane
Send all the logs to a remote host:port instead of modifying the rsyslog
configuration of the host. This will be useful when running anaconda
from the cmdline or via livemedia-creator
All that's required on the receiving side is netcat listening to the
port.
---
anaconda | 14 ++++++++++++--
pyanaconda/anaconda_log.py | 11 ++++++++++-
2 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/anaconda b/anaconda
index 4ded503..d97b682 100755
--- a/anaconda
+++ b/anaconda
@@ -309,6 +309,7 @@ def parseArguments(argv=None, boot_cmdline=None):
# Obvious
ap.add_argument("--loglevel", metavar="LEVEL", help=help_parser.help_text("loglevel"))
ap.add_argument("--syslog", metavar="HOST[:PORT]", help=help_parser.help_text("syslog"))
+ ap.add_argument("--remotelog", metavar="HOST:PORT", help=help_parser.help_text("remotelog"))
from pykickstart.constants import SELINUX_DISABLED, SELINUX_ENFORCING
from pyanaconda.constants import SELINUX_DEFAULT
@@ -409,8 +410,17 @@ def setupLoggingFromOpts(options):
packaging_log = logging.getLogger("packaging")
anaconda_log.setHandlersLevel(packaging_log, level)
- if options.syslog:
- anaconda_log.logger.updateRemote(options.syslog)
+ if can_touch_runtime_system("syslog setup"):
+ if options.syslog:
+ anaconda_log.logger.updateRemote(options.syslog)
+
+ if options.remotelog:
+ try:
+ host, port = options.remotelog.split(":", 1)
+ port = int(port)
+ anaconda_log.logger.setup_remotelog(host, port)
+ except ValueError:
+ log.error("Could not setup remotelog with %s", options.remotelog)
def gtk_warning(title, reason):
from gi.repository import Gtk
diff --git a/pyanaconda/anaconda_log.py b/pyanaconda/anaconda_log.py
index 498d64a..b5e525c 100644
--- a/pyanaconda/anaconda_log.py
+++ b/pyanaconda/anaconda_log.py
@@ -23,7 +23,7 @@
#
import logging
-from logging.handlers import SysLogHandler, SYSLOG_UDP_PORT
+from logging.handlers import SysLogHandler, SocketHandler, SYSLOG_UDP_PORT
import os
import sys
import types
@@ -86,6 +86,10 @@ class AnacondaSyslogHandler(SysLogHandler):
"""Map the priority level to a syslog level """
return self.levelMap.get(level, SysLogHandler.mapPriority(self, level))
+class AnacondaSocketHandler(SocketHandler):
+ def makePickle(self, record):
+ return ENTRY_FORMAT % record.__dict__ + "\n"
+
class AnacondaLog:
SYSLOG_CFGFILE = "/etc/rsyslog.conf"
VIRTIO_PORT = "/dev/virtio-ports/org.fedoraproject.anaconda.log.0"
@@ -203,6 +207,11 @@ class AnacondaLog:
self.anaconda_logger.warning("%s", warnings.formatwarning(
message, category, filename, lineno, line))
+ def setup_remotelog(self, host, port):
+ remotelog = AnacondaSocketHandler(host, port)
+ remotelog.setLevel(logging.DEBUG)
+ logging.getLogger().addHandler(remotelog)
+
def restartSyslog(self):
# Import here instead of at the module level to avoid an import loop
from pyanaconda.iutil import execWithRedirect
--
1.9.3
9 years, 5 months
[PATCH] Implement askmethod in dnfpayload
by David Shea
As a related change, don't fall back to closest mirror if the kickstart
method is missing or fails.
---
pyanaconda/packaging/dnfpayload.py | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/pyanaconda/packaging/dnfpayload.py b/pyanaconda/packaging/dnfpayload.py
index 1b3e4e7..21c68b8 100644
--- a/pyanaconda/packaging/dnfpayload.py
+++ b/pyanaconda/packaging/dnfpayload.py
@@ -712,6 +712,11 @@ class DNFPayload(packaging.PackagePayload):
enabled.append(repo.id)
repo.disable()
+ # If askmethod was specified on the command-line, leave all the repos
+ # disabled and return
+ if flags.askmethod:
+ return
+
if method.method:
try:
self._base.conf.releasever = self._getReleaseVersion(url)
@@ -740,6 +745,11 @@ class DNFPayload(packaging.PackagePayload):
# We need to check this again separately in case method.method was unset above.
if not method.method:
+ # If this is a kickstart install, just return now
+ if flags.automatedInstall:
+ return
+
+ # Otherwise, fall back to the default repos that we disabled above
for (id_, repo) in self._base.repos.iteritems():
if id_ in enabled:
repo.enable()
--
2.1.0
9 years, 5 months
[PATCH 0/4] Set a default software environment from the instclass
by David Shea
And some related TUI fixes I found on the way
David Shea (4):
Translate 'c' in the tui software spoke
Add missing translation contexts for TUI navigation keys
Fix the FIXME re: tui default software selection
Add an installclass property for the default package environment
(#1175826)
pyanaconda/installclass.py | 3 +
pyanaconda/ui/gui/spokes/software.py | 4 ++
pyanaconda/ui/tui/hubs/summary.py | 6 +-
pyanaconda/ui/tui/spokes/langsupport.py | 4 +-
pyanaconda/ui/tui/spokes/software.py | 111 +++++++++++++++++++++++---------
5 files changed, 91 insertions(+), 37 deletions(-)
--
2.1.0
9 years, 5 months
[PATCH] Switch kickstart tests to doing VNC instead of graphical.
by Chris Lumens
X has not been starting properly on these tests for the last couple days, but
VNC does work. So switch to that. I'll likely forget to switch it back.
---
tests/kickstart_tests/basic-ostree.sh | 2 +-
tests/kickstart_tests/groups-and-envs-1.sh | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/kickstart_tests/basic-ostree.sh b/tests/kickstart_tests/basic-ostree.sh
index 349263d..b6fab5b 100755
--- a/tests/kickstart_tests/basic-ostree.sh
+++ b/tests/kickstart_tests/basic-ostree.sh
@@ -19,7 +19,7 @@
# Red Hat Author(s): Chris Lumens <clumens(a)redhat.com>
kernel_args() {
- echo text
+ echo vnc
}
prepare() {
diff --git a/tests/kickstart_tests/groups-and-envs-1.sh b/tests/kickstart_tests/groups-and-envs-1.sh
index 9ebec79..ebbc9f7 100755
--- a/tests/kickstart_tests/groups-and-envs-1.sh
+++ b/tests/kickstart_tests/groups-and-envs-1.sh
@@ -18,7 +18,7 @@
# Red Hat Author(s): Chris Lumens <clumens(a)redhat.com>
kernel_args() {
- echo graphical
+ echo vnc
}
prepare() {
--
1.9.3
9 years, 5 months
[anaconda:master] Patches related to _resizefsUnit (anaconda side)
by Anne Mulhern
Basically updating use of convertTo() to match change in blivet.
mulhern (1):
Updates for new Size.convertTo() spec.
pyanaconda/kickstart.py | 4 ++--
pyanaconda/ui/gui/spokes/custom.py | 4 ++--
tests/gui/outside/__init__.py | 3 ++-
3 files changed, 6 insertions(+), 5 deletions(-)
--
1.9.3
9 years, 5 months
[anaconda][master][PATCH] Update help text for the nodnf option
by Martin Kolman
Signed-off-by: Martin Kolman <mkolman(a)redhat.com>
---
anaconda | 2 +-
data/anaconda_options.txt | 7 ++++---
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/anaconda b/anaconda
index 4ded503..9220653 100755
--- a/anaconda
+++ b/anaconda
@@ -355,7 +355,7 @@ def parseArguments(argv=None, boot_cmdline=None):
ap.add_argument("--nombr", action="store_true", default=False,
help=help_parser.help_text("nombr"))
ap.add_argument("--nodnf", action="store_false", dest="dnf", default=True,
- help=help_parser.help_text("dnf"))
+ help=help_parser.help_text("nodnf"))
ap.add_argument("--mpathfriendlynames", action="store_true", default=True,
help=help_parser.help_text("mpathfriendlynames"))
diff --git a/data/anaconda_options.txt b/data/anaconda_options.txt
index 12a10d9..02dcdb3 100644
--- a/data/anaconda_options.txt
+++ b/data/anaconda_options.txt
@@ -223,9 +223,10 @@ installed OS will be booted. /etc/grub.d/40_custom can be used with
manually created menuentrys which can use configfile to point to the
grub.cfg on the newly installed OS.
-dnf
-Use the experimental DNF package management backend instead of the YUM backend
-that is used by default. For more information about the DNF project see:
+nodnf
+Don't use the DNF package management backend (default since F22) and
+use the legacy YUM backend instead.
+For more information about the DNF project see:
http://dnf.baseurl.org
mpathfriendlynames
--
2.1.0
9 years, 5 months
[PATCH 0/2] Animate screen transitions
by David Shea
Animate the transitions from one screen to another. Hopefully this will ease
the confusion that some users experience with the hub and spoke model.
David Shea (2):
Animate the screen transitions.
Force a background in the main GtkBox in anaconda windows.
pyanaconda/ui/gui/__init__.py | 13 ++++++++++++-
widgets/src/BaseWindow.c | 8 ++++++++
2 files changed, 20 insertions(+), 1 deletion(-)
--
2.1.0
9 years, 5 months
[blivet:master 00/16] Patches related to _resizefsUnit
by Anne Mulhern
Mostly the same as before except:
I ended up combining the revised version of
Do not compare the same two values twice with
Do not calculate Sizes unless they are needed.
I dropped:
Add a new way of specifying Sizes().
Use tuples to construct Sizes() wherever units are known.
since there is a better way of handling how we construct Sizes.
I dropped:
Add _resizefsUnit to TmpFS and use in appropriate places
and I'll be adding it to my other patches related to TmpFS in due course.
The only changed patch is:
Use _resizefsUnit in resizeArgs() method implementations.
so that's the only one I'm sending.
mulhern (16):
Get rid of unnecessary use of long.
Make possiblePhysicalExtents() a bit more direct.
Do not compare the same two values twice.
Avoid using Size constant in FileDevice._create().
Eliminate redundant test.
Comment _prefixTestHelper() and eliminate some redundancies.
Hoist _BINARY_FACTOR * min_value calculation out of loop.
Make _Prefix entries named constants.
Add unitStr() method.
Make _parseUnits() return a unit constant, rather than a number.
Get whole unit tuple in loop when searching for correct units.
Do not even pretend that ReiserFS is resizable.
Change convertTo() and roundToNearest() so each takes a units
specifier.
Use convertTo in humanReadable().
Do not supply a default implementation for the resizeArgs() method.
Use _resizefsUnit in resizeArgs() method implementations.
blivet/devicelibs/lvm.py | 29 ++++-----
blivet/devicelibs/swap.py | 19 +++---
blivet/devices/file.py | 9 ++-
blivet/devices/lvm.py | 16 ++---
blivet/devices/partition.py | 8 +--
blivet/formats/fs.py | 44 +++++++------
blivet/size.py | 130 +++++++++++++++++++-------------------
tests/devicelibs_test/lvm_test.py | 5 --
tests/size_test.py | 92 ++++++++++++---------------
tests/storagetestcase.py | 4 +-
10 files changed, 173 insertions(+), 183 deletions(-)
--
1.9.3
9 years, 5 months