summaryrefslogtreecommitdiffstats
path: root/scripts/automation/trex_control_plane/stl
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2017-01-18 13:08:41 +0200
committerimarom <imarom@cisco.com>2017-01-18 13:08:41 +0200
commit951b09ef1b892594840f091f861f11ad274541ec (patch)
tree1fe935fb6cdbf22308971b081e7685fdb1f185bb /scripts/automation/trex_control_plane/stl
parent9f72a19a6bb0edf7ad54129f7ad06e8e288a61d7 (diff)
many capture modes in Python console
Signed-off-by: imarom <imarom@cisco.com>
Diffstat (limited to 'scripts/automation/trex_control_plane/stl')
-rw-r--r--scripts/automation/trex_control_plane/stl/console/trex_capture.py163
-rwxr-xr-xscripts/automation/trex_control_plane/stl/console/trex_console.py26
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py172
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py29
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_opts.py16
5 files changed, 250 insertions, 156 deletions
diff --git a/scripts/automation/trex_control_plane/stl/console/trex_capture.py b/scripts/automation/trex_control_plane/stl/console/trex_capture.py
index 922497db..e5708e9b 100644
--- a/scripts/automation/trex_control_plane/stl/console/trex_capture.py
+++ b/scripts/automation/trex_control_plane/stl/console/trex_capture.py
@@ -1,7 +1,7 @@
from trex_stl_lib.api import *
from trex_stl_lib.utils import parsing_opts, text_tables
import threading
-
+import tempfile
class CaptureMonitorWriter(object):
def init (self):
@@ -27,7 +27,7 @@ class CaptureMonitorWriterStdout(CaptureMonitorWriter):
def init (self):
self.logger.log(format_text("\nStarting capture monitor on selected ports", 'bold'))
self.logger.log(format_text("*** any captured packet will be displayed on screen ***\n"))
- self.logger.log(format_text("('capture monitor --stop' to abort capturing...)\n", 'bold'))
+ self.logger.log(format_text("('capture monitor stop' to abort capturing...)\n", 'bold'))
def deinit (self):
@@ -81,18 +81,42 @@ class CaptureMonitorWriterPipe(CaptureMonitorWriter):
self.logger = logger
def init (self):
- self.fifo_name = '/tmp/out.fif'
- if os.path.exists(self.fifo_name):
- os.unlink(self.fifo_name)
+ self.fifo_name = tempfile.mktemp()
+
+ try:
+ os.mkfifo(self.fifo_name)
+
+ self.logger.log(format_text("\nPlease run 'wireshark -k -i {0}'".format(self.fifo_name), 'bold'))
+ self.logger.log('\nWaiting for Wireshark connection...')
+
+ self.fifo = os.open(self.fifo_name, os.O_WRONLY)
+ self.logger.log('Successfuly connected to Wireshark...')
+ self.logger.log(format_text('\n*** Capture monitoring started ***\n', 'bold'))
- os.mkfifo(self.fifo_name)
- self.fifo = os.open(self.fifo_name, os.O_WRONLY)
+ self.writer = RawPcapWriter(self.fifo_name, linktype = 1, sync = True)
+ self.writer._write_header(None)
+
+ except KeyboardInterrupt as e:
+ os.unlink(self.fifo_name)
+ raise STLError("*** pipe monitor aborted...cleaning up")
+
+ except OSError as e:
+ os.unlink(self.fifo_name)
+ raise STLError("failed to create pipe {0}\n{1}".format(self.fifo_name, str(e)))
+
+
+ def deinit (self):
+ os.unlink(self.fifo_name)
+
- self.writer = RawPcapWriter(self.fifo_name, linktype = 1, sync = True)
- self.writer._write_header(None)
-
def handle_pkts (self, pkts):
- pass
+ for pkt in pkts:
+ pkt_bin = base64.b64decode(pkt['binary'])
+ try:
+ self.writer._write_packet(pkt_bin, sec = 0, usec = 0)
+ except IOError:
+ klgjdf
+
class CaptureMonitor(object):
@@ -127,14 +151,14 @@ class CaptureMonitor(object):
raise STLError('unknown writer type')
- self.writer.init()
-
with self.logger.supress():
self.capture_id = self.client.start_capture(tx_port_list, rx_port_list, limit = rate_pps)
self.tx_port_list = tx_port_list
self.rx_port_list = rx_port_list
+ self.writer.init()
+
self.t = threading.Thread(target = self.__thread_cb)
self.t.setDaemon(True)
@@ -154,6 +178,7 @@ class CaptureMonitor(object):
self.client.stop_capture(self.capture_id, None)
self.capture_id = -1
self.writer.deinit()
+
def get_mon_row (self):
if not self.is_active():
@@ -215,7 +240,7 @@ class CaptureMonitor(object):
pkts = rc.data()['pkts']
if not pkts:
continue
-
+
self.writer.handle_pkts(pkts)
@@ -232,33 +257,50 @@ class CaptureManager(object):
# install parsers
self.parser = parsing_opts.gen_parser(self, "capture", self.parse_line_internal.__doc__)
- subparsers = self.parser.add_subparsers(title = "commands", dest="commands")
+ self.subparsers = self.parser.add_subparsers(title = "commands", dest="commands")
+
+ self.install_record_parser()
+ self.install_monitor_parser()
+
+ # show
+ self.show_parser = self.subparsers.add_parser('show', help = "show all active captures")
+
+ # reset
+ self.clear_parser = self.subparsers.add_parser('clear', help = "remove all active captures")
+
+ # register handlers
+ self.cmds = {'record': self.parse_record, 'monitor' : self.parse_monitor, 'clear': self.parse_clear, 'show' : self.parse_show}
+
+
+ def install_record_parser (self):
+ # recording
+ self.record_parser = self.subparsers.add_parser('record', help = "PCAP recording")
+ record_sub = self.record_parser.add_subparsers(title = 'commands', dest = 'record_cmd')
+ self.record_start_parser = record_sub.add_parser('start', help = "starts a new buffered capture")
+ self.record_stop_parser = record_sub.add_parser('stop', help = "stops an active buffered capture")
# start
- self.start_parser = subparsers.add_parser('start', help = "starts a new buffered capture")
- self.start_parser.add_arg_list(parsing_opts.TX_PORT_LIST,
- parsing_opts.RX_PORT_LIST,
- parsing_opts.LIMIT)
+ self.record_start_parser.add_arg_list(parsing_opts.TX_PORT_LIST,
+ parsing_opts.RX_PORT_LIST,
+ parsing_opts.LIMIT)
# stop
- self.stop_parser = subparsers.add_parser('stop', help = "stops an active capture")
- self.stop_parser.add_arg_list(parsing_opts.CAPTURE_ID,
- parsing_opts.OUTPUT_FILENAME)
-
- # show
- self.show_parser = subparsers.add_parser('show', help = "show all active captures")
+ self.record_stop_parser.add_arg_list(parsing_opts.CAPTURE_ID,
+ parsing_opts.OUTPUT_FILENAME)
+
+
+ def install_monitor_parser (self):
# monitor
- self.monitor_parser = subparsers.add_parser('monitor', help = "attach a constant monitor to port(s)")
- self.monitor_parser.add_arg_list(parsing_opts.TX_PORT_LIST,
- parsing_opts.RX_PORT_LIST,
- parsing_opts.MONITOR_TYPE)
+ self.monitor_parser = self.subparsers.add_parser('monitor', help = 'live monitoring')
+ monitor_sub = self.monitor_parser.add_subparsers(title = 'commands', dest = 'mon_cmd')
+ self.monitor_start_parser = monitor_sub.add_parser('start', help = 'starts a monitor')
+ self.monitor_stop_parser = monitor_sub.add_parser('stop', help = 'stops an active monitor')
+
+ self.monitor_start_parser.add_arg_list(parsing_opts.TX_PORT_LIST,
+ parsing_opts.RX_PORT_LIST,
+ parsing_opts.MONITOR_TYPE)
- # reset
- self.clear_parser = subparsers.add_parser('clear', help = "remove all active captures")
-
- # register handlers
- self.cmds = {'start': self.parse_start, 'stop' : self.parse_stop, 'clear': self.parse_clear, 'monitor': self.parse_monitor, 'show' : self.parse_show}
def stop (self):
@@ -289,22 +331,48 @@ class CaptureManager(object):
self.cmds[opts.commands](opts)
- def parse_start (self, opts):
+ # record methods
+ def parse_record (self, opts):
+ if opts.record_cmd == 'start':
+ self.parse_record_start(opts)
+ elif opts.record_cmd == 'stop':
+ self.parse_record_stop(opts)
+ else:
+ assert(0)
+
+ def parse_record_start (self, opts):
if not opts.tx_port_list and not opts.rx_port_list:
- self.start_parser.formatted_error('please provide either --tx or --rx')
+ self.record_start_parser.formatted_error('please provide either --tx or --rx')
return
self.c.start_capture(opts.tx_port_list, opts.rx_port_list, opts.limit)
- def parse_stop (self, opts):
- if self.monitor.is_active() and self.monitor.get_capture_id() == opts.capture_id:
- self.monitor.stop()
- else:
- self.c.stop_capture(opts.capture_id, opts.output_filename)
+ def parse_record_stop (self, opts):
+ captures = self.c.get_capture_status()
+ ids = [c['id'] for c in captures]
+
+ if opts.capture_id == self.monitor.get_capture_id():
+ self.record_stop_parser.formatted_error("'{0}' is a monitor, please use 'capture monitor stop'".format(opts.capture_id))
+ return
+
+ if opts.capture_id not in ids:
+ self.record_stop_parser.formatted_error("'{0}' is not an active capture ID".format(opts.capture_id))
+ return
+
+ self.c.stop_capture(opts.capture_id, opts.output_filename)
+ # monitor methods
def parse_monitor (self, opts):
+ if opts.mon_cmd == 'start':
+ self.parse_monitor_start(opts)
+ elif opts.mon_cmd == 'stop':
+ self.parse_monitor_stop(opts)
+ else:
+ assert(0)
+
+ def parse_monitor_start (self, opts):
mon_type = 'compact'
if opts.verbose:
@@ -312,10 +380,15 @@ class CaptureManager(object):
elif opts.pipe:
mon_type = 'pipe'
-
+ if not opts.tx_port_list and not opts.rx_port_list:
+ self.monitor_start_parser.formatted_error('please provide either --tx or --rx')
+ return
+
self.monitor.stop()
- self.monitor.start(opts.tx_port_list, opts.rx_port_list, 10, mon_type)
+ self.monitor.start(opts.tx_port_list, opts.rx_port_list, 100, mon_type)
+ def parse_monitor_stop (self, opts):
+ self.monitor.stop()
def parse_clear (self, opts):
self.monitor.stop()
@@ -357,9 +430,9 @@ class CaptureManager(object):
mon_table.header(['ID', 'Packets Seen', 'Bytes Seen', 'TX Ports', 'RX Ports'])
if cap_table._rows:
- text_tables.print_table_with_header(cap_table, "Buffers")
+ text_tables.print_table_with_header(cap_table, '\nActive Recorders')
if mon_table._rows:
- text_tables.print_table_with_header(mon_table, "Monitors")
+ text_tables.print_table_with_header(mon_table, '\nActive Monitor')
diff --git a/scripts/automation/trex_control_plane/stl/console/trex_console.py b/scripts/automation/trex_control_plane/stl/console/trex_console.py
index b0ab70e0..bf543045 100755
--- a/scripts/automation/trex_control_plane/stl/console/trex_console.py
+++ b/scripts/automation/trex_control_plane/stl/console/trex_console.py
@@ -29,6 +29,8 @@ import string
import os
import sys
import tty, termios
+from threading import Lock
+import threading
try:
import stl_path
@@ -39,6 +41,7 @@ from trex_stl_lib.api import *
from trex_stl_lib.utils.text_opts import *
from trex_stl_lib.utils.common import user_input, get_current_user
from trex_stl_lib.utils import parsing_opts
+from .trex_capture import CaptureManager
try:
import trex_tui
@@ -172,6 +175,8 @@ class TRexConsole(TRexGeneralCmd):
def __init__(self, stateless_client, verbose = False):
+ self.cmd_lock = Lock()
+
self.stateless_client = stateless_client
TRexGeneralCmd.__init__(self)
@@ -184,8 +189,11 @@ class TRexConsole(TRexGeneralCmd):
self.intro = "\n-=TRex Console v{ver}=-\n".format(ver=__version__)
self.intro += "\nType 'help' or '?' for supported actions\n"
+ self.cap_mngr = CaptureManager(stateless_client, self.cmd_lock)
+
self.postcmd(False, "")
+
################### internal section ########################
@@ -231,6 +239,7 @@ class TRexConsole(TRexGeneralCmd):
lines = line.split(';')
try:
+ self.cmd_lock.acquire()
for line in lines:
stop = self.onecmd(line)
stop = self.postcmd(stop, line)
@@ -238,10 +247,15 @@ class TRexConsole(TRexGeneralCmd):
return "quit"
return ""
+
except STLError as e:
print(e)
return ''
+ finally:
+ self.cmd_lock.release()
+
+
def postcmd(self, stop, line):
self.prompt = self.stateless_client.generate_prompt(prefix = 'trex')
@@ -349,7 +363,7 @@ class TRexConsole(TRexGeneralCmd):
@verify_connected
def do_capture (self, line):
'''Manage PCAP captures'''
- self.stateless_client.capture_line(line)
+ self.cap_mngr.parse_line(line)
def help_capture (self):
self.do_capture("-h")
@@ -443,7 +457,9 @@ class TRexConsole(TRexGeneralCmd):
def do_disconnect (self, line):
'''Disconnect from the server\n'''
-
+
+ # stop any monitors before disconnecting
+ self.cap_mngr.stop()
self.stateless_client.disconnect_line(line)
@@ -688,6 +704,7 @@ class TRexConsole(TRexGeneralCmd):
l=help.splitlines()
print("{:<30} {:<30}".format(cmd + " - ",l[0] ))
+
# a custorm cmdloop wrapper
def start(self):
while True:
@@ -702,6 +719,9 @@ class TRexConsole(TRexGeneralCmd):
self.intro = None
continue
+ finally:
+ self.cap_mngr.stop()
+
if self.terminal:
self.terminal.kill()
@@ -934,6 +954,8 @@ def main():
with stateless_client.logger.supress():
stateless_client.disconnect(stop_traffic = False)
+
+
if __name__ == '__main__':
main()
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py
index d75c554e..c632ad7c 100755
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py
@@ -17,10 +17,12 @@ from .utils.text_opts import *
from functools import wraps
from texttable import ansi_len
+
from collections import namedtuple
from yaml import YAMLError
import time
import datetime
+import threading
import re
import random
import json
@@ -601,7 +603,7 @@ class STLClient(object):
self.util_stats,
self.xstats,
self.async_client.monitor)
-
+
############# private functions - used by the class itself ###########
@@ -2981,7 +2983,7 @@ class STLClient(object):
self.logger.post_cmd(rc)
if verbose:
- for x in filter(bool, rc.data()):
+ for x in filter(bool, listify(rc.data())):
self.logger.log(format_text("{0}".format(x), 'bold'))
if not rc:
@@ -2999,6 +3001,10 @@ class STLClient(object):
tx_ports - on which ports to capture TX
rx_ports - on which ports to capture RX
limit - limit how many packets will be written
+
+ :returns:
+ the new capture_id
+
:raises:
+ :exe:'STLError'
@@ -3018,7 +3024,7 @@ class STLClient(object):
non_service_ports = list_difference(set(tx_ports + rx_ports), self.get_service_enabled_ports())
if non_service_ports:
- raise STLError("Port(s) {0} are not under service mode. PCAP capturing requires all ports to be in service mode")
+ raise STLError("Port(s) {0} are not under service mode. PCAP capturing requires all ports to be in service mode".format(non_service_ports))
self.logger.pre_cmd("Starting PCAP capturing up to {0} packets".format(limit))
@@ -3030,8 +3036,39 @@ class STLClient(object):
if not rc:
raise STLError(rc)
+ return rc.data()['capture_id']
+
+
+ def __fetch_capture_packets (self, capture_id, output_filename, pkt_count):
+ self.logger.pre_cmd("Writing {0} packets to '{1}'".format(pkt_count, output_filename))
+
+ # create a PCAP file
+ writer = RawPcapWriter(output_filename, linktype = 1)
+ writer._write_header(None)
+
+ # fetch
+ pending = pkt_count
+ rc = RC_OK()
+ while pending > 0:
+ rc = self._transmit("capture", params = {'command': 'fetch', 'capture_id': capture_id, 'pkt_limit': 50})
+ if not rc:
+ self.logger.post_cmd(rc)
+ raise STLError(rc)
+
+ pkts = rc.data()['pkts']
+ for pkt in pkts:
+ ts = pkt['ts']
+ pkt_bin = base64.b64decode(pkt['binary'])
+ writer._write_packet(pkt_bin, sec = 0, usec = 0)
+
+ pending = rc.data()['pending']
+
+
+ self.logger.post_cmd(rc)
+
+
@__api_check(True)
def stop_capture (self, capture_id, output_filename):
"""
@@ -3045,8 +3082,6 @@ class STLClient(object):
+ :exe:'STLError'
"""
-
-
# stopping a capture requires:
# 1. stopping
@@ -3063,36 +3098,19 @@ class STLClient(object):
# pkt count
pkt_count = rc.data()['pkt_count']
-
- if not output_filename or pkt_count == 0:
- return
- self.logger.pre_cmd("Writing {0} packets to '{1}'".format(pkt_count, output_filename))
-
- # create a PCAP file
- writer = RawPcapWriter(output_filename, linktype = 1)
- writer._write_header(None)
-
- # fetch
- while True:
- rc = self._transmit("capture", params = {'command': 'fetch', 'capture_id': capture_id, 'pkt_limit': 50})
- if not rc:
- self.logger.post_cmd(rc)
- raise STLError(rc)
-
- pkts = rc.data()['pkts']
- for pkt in pkts:
- ts = pkt['ts']
- pkt_bin = base64.b64decode(pkt['binary'])
- writer._write_packet(pkt_bin, sec = 0, usec = 0)
-
- if rc.data()['pending'] == 0:
- break
+ # fetch packets
+ if output_filename:
+ self.__fetch_capture_packets(capture_id, output_filename, pkt_count)
+ # remove
+ self.logger.pre_cmd("Removing PCAP capture {0} from server".format(capture_id))
+ rc = self._transmit("capture", params = {'command': 'remove', 'capture_id': capture_id})
self.logger.post_cmd(rc)
+ if not rc:
+ raise STLError(rc)
- # get capture status
@__api_check(True)
def get_capture_status (self):
"""
@@ -3109,7 +3127,25 @@ class STLClient(object):
return rc.data()
-
+ @__api_check(True)
+ def remove_all_captures (self):
+ """
+ Removes any existing captures
+ """
+ captures = self.get_capture_status()
+
+ self.logger.pre_cmd("Removing all PCAP captures from server")
+
+ for c in captures:
+ # remove
+ rc = self._transmit("capture", params = {'command': 'remove', 'capture_id': c['id']})
+ if not rc:
+ raise STLError(rc)
+
+ self.logger.post_cmd(RC_OK())
+
+
+
@__api_check(True)
def set_rx_queue (self, ports = None, size = 1000):
"""
@@ -3230,6 +3266,7 @@ class STLClient(object):
return wrap
+
@__console
def ping_line (self, line):
'''pings the server / specific IP'''
@@ -3820,77 +3857,9 @@ class STLClient(object):
opts.link,
opts.led,
opts.flow_ctrl)
+
+
-
-
-
- @__console
- def capture_line (self, line):
- '''Manage PCAP recorders'''
-
- # default
- if not line:
- line = "show"
-
- parser = parsing_opts.gen_parser(self, "capture", self.capture_line.__doc__)
- subparsers = parser.add_subparsers(title = "commands", dest="commands")
-
- # start
- start_parser = subparsers.add_parser('start', help = "starts a new capture")
- start_parser.add_arg_list(parsing_opts.TX_PORT_LIST,
- parsing_opts.RX_PORT_LIST,
- parsing_opts.LIMIT)
-
- # stop
- stop_parser = subparsers.add_parser('stop', help = "stops an active capture")
- stop_parser.add_arg_list(parsing_opts.CAPTURE_ID,
- parsing_opts.OUTPUT_FILENAME)
-
- # show
- show_parser = subparsers.add_parser('show', help = "show all active captures")
-
- opts = parser.parse_args(line.split())
-
- if not opts:
- return opts
-
- # start
- if opts.commands == 'start':
- if not opts.tx_port_list and not opts.rx_port_list:
- start_parser.formatted_error('please provide either --tx or --rx')
- return
-
- self.start_capture(opts.tx_port_list, opts.rx_port_list, opts.limit)
-
- # stop
- elif opts.commands == 'stop':
- self.stop_capture(opts.capture_id, opts.output_filename)
-
- # show
- else:
- data = self.get_capture_status()
-
- stats_table = text_tables.TRexTextTable()
- stats_table.set_cols_align(["c"] * 6)
- stats_table.set_cols_width([15] * 6)
-
- for elem in data:
- row = [elem['id'],
- elem['state'],
- '[{0}/{1}]'.format(elem['count'], elem['limit']),
- format_num(elem['bytes'], suffix = 'B'),
- bitfield_to_str(elem['filter']['tx']),
- bitfield_to_str(elem['filter']['rx'])]
-
- stats_table.add_rows([row], header=False)
-
- stats_table.header(['ID', 'Status', 'Count', 'Bytes', 'TX Ports', 'RX Ports'])
- text_tables.print_table_with_header(stats_table, "Captures")
-
-
- return RC_OK()
-
-
@__console
def resolve_line (self, line):
@@ -4089,3 +4058,4 @@ class STLClient(object):
self.set_service_mode(ports = opts.ports, enabled = opts.enabled)
+
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py
index cb594ef4..8d3aedbe 100755
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py
@@ -85,6 +85,10 @@ STREAMS_MASK
CORE_MASK_GROUP
CAPTURE_PORTS_GROUP
+MONITOR_TYPE_VERBOSE
+MONITOR_TYPE_PIPE
+MONITOR_TYPE
+
# ALL_STREAMS
# STREAM_LIST_WITH_ALL
@@ -606,6 +610,7 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
'help': 'A list of ports to capture on the TX side',
'default': []}),
+
RX_PORT_LIST: ArgumentPack(['--rx'],
{'nargs': '+',
'dest':'rx_port_list',
@@ -614,7 +619,21 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
'type': int,
'help': 'A list of ports to capture on the RX side',
'default': []}),
-
+
+
+ MONITOR_TYPE_VERBOSE: ArgumentPack(['-v', '--verbose'],
+ {'action': 'store_true',
+ 'dest': 'verbose',
+ 'default': False,
+ 'help': 'output to screen as verbose'}),
+
+ MONITOR_TYPE_PIPE: ArgumentPack(['-p', '--pipe'],
+ {'action': 'store_true',
+ 'dest': 'pipe',
+ 'default': False,
+ 'help': 'forward packets to a pipe'}),
+
+
CAPTURE_ID: ArgumentPack(['-i', '--id'],
{'help': "capture ID to remove",
'dest': "capture_id",
@@ -646,6 +665,12 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
{'required': False}),
CAPTURE_PORTS_GROUP: ArgumentGroup(NON_MUTEX, [TX_PORT_LIST, RX_PORT_LIST], {}),
+
+
+ MONITOR_TYPE: ArgumentGroup(MUTEX, [MONITOR_TYPE_VERBOSE,
+ MONITOR_TYPE_PIPE],
+ {'required': False}),
+
}
class _MergeAction(argparse._AppendAction):
@@ -760,7 +785,7 @@ class CCmdArgParser(argparse.ArgumentParser):
def formatted_error (self, msg):
self.print_usage()
- self.stateless_client.logger.log(msg)
+ self._print_message(('%s: error: %s\n') % (self.prog, msg))
def get_flags (opt):
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_opts.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_opts.py
index 63b05bf4..3ffd07e2 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_opts.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/text_opts.py
@@ -133,12 +133,16 @@ def underline(text):
# apply attribute on each non-empty line
def text_attribute(text, attribute):
- return '\n'.join(['{start}{txt}{end}'.format(
- start = TEXT_CODES[attribute]['start'],
- txt = line,
- end = TEXT_CODES[attribute]['end'])
- if line else '' for line in ('%s' % text).split('\n')])
-
+ if isinstance(text, str):
+ return "{start}{txt}{stop}".format(start=TEXT_CODES[attribute]['start'],
+ txt=text,
+ stop=TEXT_CODES[attribute]['end'])
+ elif isinstance(text, unicode):
+ return u"{start}{txt}{stop}".format(start=TEXT_CODES[attribute]['start'],
+ txt=text,
+ stop=TEXT_CODES[attribute]['end'])
+ else:
+ raise Exception("not a string")
FUNC_DICT = {'blue': blue,
'bold': bold,