[PATCH] Fix config_only action
by Jan Tluka
The config_only action did not work correctly since deconfigure
parameter of NetTestController::_cleanup_slaves() has not been used
for bypassing deconfiguration of configured interfaces at all. This
patch fixes this behavior.
Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
---
lnst/Controller/Machine.py | 7 ++++---
lnst/Controller/NetTestController.py | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/lnst/Controller/Machine.py b/lnst/Controller/Machine.py
index 2ae008c..d4348e2 100644
--- a/lnst/Controller/Machine.py
+++ b/lnst/Controller/Machine.py
@@ -150,9 +150,10 @@ class Machine(object):
self._rpc_call("kill_cmds")
- for iface in reversed(self._interfaces):
- iface.deconfigure()
- iface.cleanup()
+ if deconfigure:
+ for iface in reversed(self._interfaces):
+ iface.deconfigure()
+ iface.cleanup()
self._rpc_call("bye")
self._msg_dispatcher.disconnect_slave(self.get_id())
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index ae2a78a..88d3156 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -171,7 +171,7 @@ class NetTestController:
for machine_id, machine in self._machines.iteritems():
if machine.is_configured():
- machine.cleanup()
+ machine.cleanup(deconfigure)
#clean-up slave logger
self._log_ctl.remove_slave(machine_id)
--
1.8.1.4
10 years, 5 months
[lnst trac] #73: Coloured output to terminal
by fedora-badges
#73: Coloured output to terminal
-------------------------+-----------------------------
Reporter: rpazdera | Owner: rpazdera
Type: enhancement | Status: new
Priority: minor | Milestone: Stable Release
Component: lnst-ctl | Version: git
Keywords: | Blocked By:
Blocking: |
-------------------------+-----------------------------
It would be nice, if the terminal output of LNST was coloured. LNST prints
out lots of messages and colouring would make them much easier to read.
--
Ticket URL: <https://fedorahosted.org/lnst/ticket/73>
lnst <https://fedorahosted.org/lnst/>
Linux Network Stack Test
10 years, 5 months
[lnst] lnst-ctl, lnst-slave: Disabling colours
by Jiří Pírko
commit 6c2b04cabb541bddeaef1f25f6351aa532e9ef7d
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Fri Jun 28 18:51:44 2013 +0200
lnst-ctl, lnst-slave: Disabling colours
This patch adds a possibility to lnst-ctl and lnst-slave to disable the
output colouring by a CLI options. Either -m or --no-colour can be used.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst-ctl | 10 +++++++---
lnst-slave | 11 ++++++++---
lnst/Common/Logs.py | 4 ++--
3 files changed, 17 insertions(+), 8 deletions(-)
---
diff --git a/lnst-ctl b/lnst-ctl
index f4fc31d..3e9b62b 100755
--- a/lnst-ctl
+++ b/lnst-ctl
@@ -37,6 +37,7 @@ def usage():
" network communication during\n" \
" the test"
print " -h, --help print this message"
+ print " -m, --no-colours disable coloured terminal output"
print " -o, --disable-pool-checks don't check the availability of\n"\
" machines in the pool"
print " -c, --cleanup perform config cleanup\n" \
@@ -85,9 +86,9 @@ def main():
try:
opts, args = getopt.getopt(
sys.argv[1:],
- "dhr:cx:po",
+ "dhr:cx:pom",
["debug", "help", "recipe=", "cleanup", "result=",
- "packet-capture", "disable-pool-checks"]
+ "packet-capture", "disable-pool-checks", "no-colours"]
)
except getopt.GetoptError as err:
print str(err)
@@ -117,6 +118,7 @@ def main():
result_path = None
packet_capture = False
pool_checks = True
+ coloured_output = not config.get_option("colours", "disable_colours")
for opt, arg in opts:
if opt in ("-d", "--debug"):
debug += 1
@@ -130,13 +132,15 @@ def main():
packet_capture = True
elif opt in ("-o", "--disable-pool-checks"):
pool_checks = False
+ elif opt in ("-m", "--no-colours"):
+ coloured_output = False
load_presets_from_config(config)
date = datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S")
log_ctl = LoggingCtl(debug,
log_dir=config.get_option('environment', 'log_dir'),
- log_subdir=date)
+ log_subdir=date, colours=coloured_output)
action = args.pop()
diff --git a/lnst-slave b/lnst-slave
index 91f257c..996cd32 100755
--- a/lnst-slave
+++ b/lnst-slave
@@ -30,6 +30,7 @@ def usage():
print " -h, --help print this message"
print " -e, --daemonize go to background after init"
print " -i, --pidfile file to write daemonized process pid"
+ print " -m, --no-colours disable coloured terminal output"
print " -p, --port xmlrpc port to listen on"
sys.exit()
@@ -40,8 +41,8 @@ def main():
try:
opts = getopt.getopt(
sys.argv[1:],
- "dhei:p:",
- ["debug", "help", "daemonize", "pidfile", "port"]
+ "dhei:p:m",
+ ["debug", "help", "daemonize", "pidfile", "port", "no-colours"]
)[0]
except getopt.GetoptError as err:
print str(err)
@@ -60,6 +61,7 @@ def main():
daemon = False
pidfile = "lnst-slave.pid"
port = None
+ coloured_output = not config.get_option("colours", "disable_colours")
for opt, arg in opts:
if opt in ("-d", "--debug"):
debug = True
@@ -71,9 +73,12 @@ def main():
pidfile = arg
elif opt in ("-p", "--port"):
port = int(arg)
+ elif opt in ("-m", "--no-colours"):
+ coloured_output = False
log_ctl = LoggingCtl(debug,
- log_dir=config.get_option('environment', 'log_dir'))
+ log_dir=config.get_option('environment', 'log_dir'),
+ colours=coloured_output)
logging.info("Started")
if port:
diff --git a/lnst/Common/Logs.py b/lnst/Common/Logs.py
index 73989f5..33a43a7 100644
--- a/lnst/Common/Logs.py
+++ b/lnst/Common/Logs.py
@@ -94,7 +94,7 @@ class LoggingCtl:
slaves = {}
transmit_handler = None
- def __init__(self, debug=False, log_dir=None, log_subdir=""):
+ def __init__(self, debug=False, log_dir=None, log_subdir="", colours=True):
if log_dir != None:
self.log_folder = os.path.abspath(os.path.join(log_dir, log_subdir))
else:
@@ -107,7 +107,7 @@ class LoggingCtl:
#the display_handler will display logs in the terminal
self.display_handler = logging.StreamHandler(sys.stdout)
- self.display_handler.setFormatter(MultilineFormatter(coloured=True))
+ self.display_handler.setFormatter(MultilineFormatter(colours))
if not debug:
self.display_handler.setLevel(logging.INFO)
else:
10 years, 5 months
[lnst] NetTestResultSerializer: Coloured summary
by Jiří Pírko
commit 6b9ad78cc29adbac04e5f185b0e685d8ab8b5332
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Fri Jun 28 18:51:43 2013 +0200
NetTestResultSerializer: Coloured summary
This patch contains several modifications of the summary. It is now
coloured in case it is printed to a terminal.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Controller/NetTestResultSerializer.py | 29 ++++++++++++++++++++-------
1 files changed, 21 insertions(+), 8 deletions(-)
---
diff --git a/lnst/Controller/NetTestResultSerializer.py b/lnst/Controller/NetTestResultSerializer.py
index b41ac39..b0bca12 100644
--- a/lnst/Controller/NetTestResultSerializer.py
+++ b/lnst/Controller/NetTestResultSerializer.py
@@ -11,9 +11,10 @@ __author__ = """
jpirko(a)redhat.com (Jiri Pirko)
"""
+import logging
from xml.dom.minidom import getDOMImplementation
from lnst.Common.NetTestCommand import str_command
-import logging
+from lnst.Common.Colours import decorate_string, decorate_with_preset
def serialize_obj(obj, dom, el, upper_name="unnamed"):
if isinstance(obj, dict):
@@ -227,18 +228,30 @@ class NetTestResultSerializer:
if len(right) > max_right:
max_right = len(right)
- full_length = max_left + max_right
+ # +1 for the alignment of " PASS" or " FAIL"
+ # +2 for spacing aroun the whole block
+ full_length = max_left + max_right + 1 + 2
+
if full_length % 2:
- full_length = full_length+2
+ full_length = full_length + 2
else:
- full_length = full_length+1
+ full_length = full_length + 1
+
+ header = " SUMMARY ".center(full_length, "=")
+ coloured_summary = decorate_with_preset("SUMMARY", "highlight")
+ logging.info(header.replace("SUMMARY", coloured_summary))
- logging.info("="*((full_length-9)/2) + " SUMMARY " + "="*((full_length-9)/2))
for left, right in output_pairs:
if right != "":
- space_fill = full_length - len(left) - len(right)
+ space_fill = full_length - len(left) - len(right) - 1 - 2
+ if right == "PASS":
+ right = decorate_with_preset(right, "pass")
+ elif right == "FAIL":
+ right = decorate_with_preset(right, "fail")
+ right = " %s" % right
+
output = left + (space_fill)*" " + right
else:
- output = left
- logging.info(output)
+ output = left + " "
+ logging.info(" %s " % output)
logging.info("="*(full_length))
10 years, 5 months
[lnst] Colouring: Make the colour presets configurable
by Jiří Pírko
commit b0e9f55ef89e64db1517776e0851d9bcc6e99582
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Fri Jun 28 18:51:42 2013 +0200
Colouring: Make the colour presets configurable
This patch adds support for a new set of configuration options to allow
the user to change the colour presets. The predefined colour presets are
the following:
faded for debugging output
alert for important messages
highlight highlighted text
pass PASS colour
fail FAIL colour
info the INFO label
debug the DEBUG label
warning the WARNING label
error the ERROR label
log_header the date and ip address in each log message
You can override these values on both the controller and the slave by
addint a [colours] section to your conf file and setting different
values for these presets. For example:
[colours]
faded = yellow default false
alert = red default true
Each colour preset comprises of three values:
(foreground colour, background colour, bold flag)
You can use one of the 16 standard colours or (if your terminal supports
it) use the extended palette. The standard colours are:
black, red, green, yellow, blue, magenta, cyan,
light-gray, dark-gray, light-red, light-green,
light-yellow, light-blue, light-magenta, light-cyan,
white
The colours from the extended palette can be accessed by their index
as follows (256 colours are available):
extended(0)
extended(5)
...
extended(255)
The complete palette can be found here:
http://misc.flogisoft.com/bash/tip_colors_and_formatting
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst-ctl | 3 +++
lnst/Common/Config.py | 31 +++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 0 deletions(-)
---
diff --git a/lnst-ctl b/lnst-ctl
index 210c6dc..f4fc31d 100755
--- a/lnst-ctl
+++ b/lnst-ctl
@@ -19,6 +19,7 @@ import re
import datetime
from lnst.Common.Logs import LoggingCtl, log_exc_traceback
from lnst.Common.Config import Config
+from lnst.Common.Colours import load_presets_from_config
from lnst.Controller.NetTestController import NetTestController, NetTestError
from lnst.Controller.NetTestResultSerializer import NetTestResultSerializer
@@ -130,6 +131,8 @@ def main():
elif opt in ("-o", "--disable-pool-checks"):
pool_checks = False
+ load_presets_from_config(config)
+
date = datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S")
log_ctl = LoggingCtl(debug,
log_dir=config.get_option('environment', 'log_dir'),
diff --git a/lnst/Common/Config.py b/lnst/Common/Config.py
index 3d65048..6e0deae 100644
--- a/lnst/Common/Config.py
+++ b/lnst/Common/Config.py
@@ -15,6 +15,7 @@ import sys
import logging
import re
from ConfigParser import ConfigParser
+from lnst.Common.Utils import bool_it
from lnst.Common.NetUtils import verify_ip_address, verify_mac_address
DefaultRPCPort = 9999
@@ -73,6 +74,8 @@ class Config():
"action" : self.optionPath,
"name" : "log_dir"}
+ self.colours_scheme()
+
def slave_scheme(self):
self.options['environment'] = dict()
self.options['environment']['log_dir'] = {\
@@ -96,6 +99,21 @@ class Config():
"action" : self.optionTimeval,
"name" : "expiration_period"}
+ self.colours_scheme()
+
+ def colours_scheme(self):
+ self.options['colours'] = dict()
+ for preset in ["default", "faded", "alert", "highlight",
+ "pass", "fail", "error", "info", "debug", "warning",
+ "log_header"]:
+ self.options['colours'][preset] = {\
+ "value" : None, "additive" : False,
+ "action" : self.optionColour, "name" : preset}
+
+ self.options['colours']["disable_colours"] = {\
+ "value" : False, "additive" : False,
+ "action" : self.optionBool, "name" : "disable_colours"}
+
def get_config(self):
return self.options
@@ -226,6 +244,19 @@ class Config():
return timeval
+ def optionColour(self, option, cfg_path):
+ colour = option.split()
+ if len(colour) != 3:
+ msg = "Colour must be specified by 3"\
+ " values (foreground, background, bold)"\
+ " sepparated by whitespace."
+ raise ConfigError(msg)
+
+ return colour
+
+ def optionBool(self, option, cfg_path):
+ return bool_it(option)
+
def dump_config(self):
string = ""
for section in self.options:
10 years, 5 months
[lnst] Logs: Adding support for terminal output colouring
by Jiří Pírko
commit cad208b187531f3db5fbe4f303e4bb5028f642fc
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Fri Jun 28 18:51:41 2013 +0200
Logs: Adding support for terminal output colouring
In this patch, the MultilineFormatter was reimplemented to support
output colouring using the lnst.Common.Colours module.
In case output to terminal is detected, it will add the colouring escape
sequences to the string, so different parts of the logs are printed in
different colours.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Common/Logs.py | 116 ++++++++++++++++++++++++++------------------------
1 files changed, 60 insertions(+), 56 deletions(-)
---
diff --git a/lnst/Common/Logs.py b/lnst/Common/Logs.py
index 379405c..73989f5 100644
--- a/lnst/Common/Logs.py
+++ b/lnst/Common/Logs.py
@@ -15,69 +15,79 @@ import logging.handlers
import traceback
from lnst.Common.LoggingHandler import LogBuffer
from lnst.Common.LoggingHandler import TransmitHandler
+from lnst.Common.Colours import decorate_with_preset, strip_colours
def log_exc_traceback():
cmd_type, value, tb = sys.exc_info()
exception = traceback.format_exception(cmd_type, value, tb)
logging.debug(''.join(exception))
+class MultilineFormatter(Formatter): # addr:17 level:7
+ _ADDR_WIDTH = 17
+ _LEVEL_WIDTH = 7
+ _coloured = False
+
+ def __init__(self, coloured=False):
+ fmt = "%(asctime)s %(address)s %(levelname)s: %(message)s"
+ datefmt = "%Y-%m-%d %H:%M:%S"
+ self.linefmt = " "
+ self._coloured = coloured
-class MultilineFormater(Formatter):
- """
- Better formating of multiline logs.
- """
- def __init__(self, fmt=None, datefmt=None, linefmt=None):
Formatter.__init__(self, fmt, datefmt)
- if linefmt:
- self.linefmt = linefmt
+
+ def _decorate_value(self, string, preset):
+ value = strip_colours(string)
+ if sys.stdout.isatty() and self._coloured:
+ return decorate_with_preset(value, preset)
else:
- self.linefmt = ""
+ return value
- def format(self, record):
- """
- Format the specified record as text.
-
- The record's attribute dictionary is used as the operand to a
- string formatting operation which yields the returned string.
- Before formatting the dictionary, a couple of preparatory steps
- are carried out. The message attribute of the record is computed
- using LogRecord.getMessage(). If the formatting string uses the
- time (as determined by a call to usesTime(), formatTime() is
- called to format the event time. If there is exception information,
- it is formatted using formatException() and appended to the message.
- """
- record.message = record.getMessage()
+ def _format_addr(self, record):
if not "address" in record.__dict__:
- record.address = "(127.0.0.1)"
- if self._fmt.find("%(asctime)") >= 0:
- record.asctime = self.formatTime(record, self.datefmt)
- lines = record.__dict__["message"].split("\n")
- s = ""
+ addr = "(127.0.0.1)".rjust(17)
+ else:
+ addr = record.address.rjust(17)
+
+ just = " " * (self._ADDR_WIDTH - len(addr))
+ return just + self._decorate_value(addr, "log_header")
+
+ def _format_level(self, record):
+ level = record.levelname
+
+ just = " " * (self._LEVEL_WIDTH - len(level))
+ return just + self._decorate_value(level, level.lower())
+
+ def format(self, record):
+ values = {}
+
+ asctime = self.formatTime(record, self.datefmt)
+ values["asctime"] = self._decorate_value(asctime, "log_header")
+
+ values["address"] = self._format_addr(record)
+ values["levelname"] = self._format_level(record)
+
+ msg = ""
+ level = record.levelname
+ lines = record.getMessage().split("\n")
if len(lines) > 1:
- record.__dict__['message'] = ""
for line in lines:
- s += "\n" + self.linefmt + line
- s = self._fmt % record.__dict__ + s
- if record.exc_info:
- # Cache the traceback text to avoid converting it multiple times
- # (it's constant anyway)
- if not record.exc_text:
- record.exc_text = self.formatException(record.exc_info)
- if record.exc_text:
- if s[-1:] != "\n":
- s = s + "\n"
- try:
- s = s + record.exc_text
- except UnicodeError:
- # Sometimes filenames have non-ASCII chars, which can lead
- # to errors when s is Unicode and record.exc_text is str
- # See issue 8924
- s = s + record.exc_text.decode(sys.getfilesystemencoding())
- return s
+ if level == "DEBUG":
+ line = self._decorate_value(line, "faded")
+ msg += "\n" + self.linefmt + line
+ values["message"] = msg
+ else:
+ if level == "DEBUG":
+ values["message"] = self._decorate_value(lines[0], "faded")
+ else:
+ if sys.stdout.isatty() and self._coloured:
+ values["message"] = lines[0]
+ else:
+ values["message"] = strip_colours(lines[0])
+
+ return self._fmt % values
class LoggingCtl:
log_folder = ""
- formatter = None
display_handler = None
recipe_handlers = (None,None)
recipe_log_path = ""
@@ -95,15 +105,9 @@ class LoggingCtl:
if not os.path.isdir(self.log_folder):
self._clean_folder(self.log_folder)
-
- self.formatter = MultilineFormater(
- '%(asctime)s| %(address)17.17s| %(levelname)7.7s: '
- '%(message)s', '%Y-%m-%d %H:%M:%S', " "*4)
-
-
#the display_handler will display logs in the terminal
self.display_handler = logging.StreamHandler(sys.stdout)
- self.display_handler.setFormatter(self.formatter)
+ self.display_handler.setFormatter(MultilineFormatter(coloured=True))
if not debug:
self.display_handler.setLevel(logging.INFO)
else:
@@ -210,11 +214,11 @@ class LoggingCtl:
def _create_file_handler(self, folder_path):
file_debug = logging.FileHandler(os.path.join(folder_path, 'debug'))
- file_debug.setFormatter(self.formatter)
+ file_debug.setFormatter(MultilineFormatter())
file_debug.setLevel(logging.DEBUG)
file_info = logging.FileHandler(os.path.join(folder_path, 'info'))
- file_info.setFormatter(self.formatter)
+ file_info.setFormatter(MultilineFormatter())
file_info.setLevel(logging.INFO)
return (file_debug, file_info)
10 years, 5 months
[lnst] NetTestSlave: Removing double exception handling
by Jiří Pírko
commit b65cb9fd368a5240dc79f3e38d12bd862ea4c425
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Mon Jun 24 15:49:26 2013 +0200
NetTestSlave: Removing double exception handling
Due to several changes in the communication channel between controller
and the slaves, the NetTestSlave class was handling (and logging)
exceptions twice.
This patch removes the first unnecessary processing, so only a single
traceback is logged.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Slave/NetTestSlave.py | 44 ++++++++++++++++++--------------------------
1 files changed, 18 insertions(+), 26 deletions(-)
---
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index d2dd484..f3a321a 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -211,32 +211,24 @@ class SlaveMethods:
return True
def run_command(self, command):
- try:
- cmd = NetTestCommand(self._command_context, command,
- self._resource_table, self._log_ctl)
- self._command_context.add_cmd(cmd)
-
- res = cmd.run()
- if not cmd.forked():
- self._command_context.del_cmd(cmd)
-
- if command["type"] == "system_config":
- if res["passed"]:
- self._update_system_config(res["res_data"]["options"],
- command["persistent"])
- else:
- err = "Error occured while setting system "\
- "configuration (%s)" % res["err_msg"]
- logging.error(err)
-
- return res
- except:
- log_exc_traceback()
- cmd_type = command["type"]
- m_id = command["machine_id"]
- msg = "Execution of %s command on machine %s failed" \
- % (cmd_type, m_id)
- raise CommandException(msg)
+ cmd = NetTestCommand(self._command_context, command,
+ self._resource_table, self._log_ctl)
+ self._command_context.add_cmd(cmd)
+
+ res = cmd.run()
+ if not cmd.forked():
+ self._command_context.del_cmd(cmd)
+
+ if command["type"] == "system_config":
+ if res["passed"]:
+ self._update_system_config(res["res_data"]["options"],
+ command["persistent"])
+ else:
+ err = "Error occured while setting system "\
+ "configuration (%s)" % res["err_msg"]
+ logging.error(err)
+
+ return res
def machine_cleanup(self):
NetConfigDeviceAllCleanup()
10 years, 5 months