summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xscripts/automation/trex_control_plane/stl/console/trex_console.py43
-rw-r--r--scripts/automation/trex_control_plane/stl/console/trex_tui.py50
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py130
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py31
4 files changed, 144 insertions, 110 deletions
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 9e3f2600..41a04617 100755
--- a/scripts/automation/trex_control_plane/stl/console/trex_console.py
+++ b/scripts/automation/trex_control_plane/stl/console/trex_console.py
@@ -241,20 +241,7 @@ class TRexConsole(TRexGeneralCmd):
def postcmd(self, stop, line):
-
- if not self.stateless_client.is_connected():
- self.prompt = "trex(offline)>"
- self.supported_rpc = None
-
- elif not self.stateless_client.get_acquired_ports():
- self.prompt = "trex(read-only)>"
-
- elif self.stateless_client.is_all_ports_acquired():
- self.prompt = "trex>"
-
- else:
- self.prompt = "trex {0}>".format(self.stateless_client.get_acquired_ports())
-
+ self.prompt = self.stateless_client.generate_prompt(prefix = 'trex')
return stop
@@ -316,25 +303,21 @@ class TRexConsole(TRexGeneralCmd):
self.do_history("-h")
def do_shell (self, line):
- return self.do_history(line)
+ self.do_history(line)
def do_push (self, line):
'''Push a local PCAP file\n'''
- return self.stateless_client.push_line(line)
-
- #def do_push_remote (self, line):
- # '''Push a remote accessible PCAP file\n'''
- # return self.stateless_client.push_remote_line(line)
+ self.stateless_client.push_line(line)
def help_push (self):
- return self.do_push("-h")
+ self.do_push("-h")
def do_portattr (self, line):
'''Change/show port(s) attributes\n'''
- return self.stateless_client.set_port_attr_line(line)
+ self.stateless_client.set_port_attr_line(line)
def help_portattr (self):
- return self.do_portattr("-h")
+ self.do_portattr("-h")
@verify_connected
def do_map (self, line):
@@ -548,7 +531,7 @@ class TRexConsole(TRexGeneralCmd):
def do_events (self, line):
'''shows events recieved from server\n'''
- return self.stateless_client.get_events_line(line)
+ self.stateless_client.get_events_line(line)
def complete_profile(self, text, line, begidx, endidx):
@@ -562,7 +545,6 @@ class TRexConsole(TRexGeneralCmd):
@verify_connected
def do_tui (self, line):
'''Shows a graphical console\n'''
-
parser = parsing_opts.gen_parser(self,
"tui",
self.do_tui.__doc__,
@@ -581,16 +563,19 @@ class TRexConsole(TRexGeneralCmd):
info = self.stateless_client.get_connection_info()
exe = './trex-console --top -t -q -s {0} -p {1} --async_port {2}'.format(info['server'], info['sync_port'], info['async_port'])
- cmd = ['/usr/bin/xterm', '-geometry', '111x49', '-sl', '0', '-title', 'trex_tui', '-e', exe]
+ cmd = ['/usr/bin/xterm', '-geometry', '{0}x{1}'.format(self.tui.MIN_COLS, self.tui.MIN_ROWS), '-sl', '0', '-title', 'trex_tui', '-e', exe]
# detach child
self.terminal = subprocess.Popen(cmd, preexec_fn = os.setpgrp)
return
-
- with self.stateless_client.logger.supress():
- self.tui.show(self.stateless_client, locked = opts.locked)
+
+ try:
+ with self.stateless_client.logger.supress():
+ self.tui.show(self.stateless_client, locked = opts.locked)
+ except self.tui.ScreenSizeException as e:
+ print(format_text(str(e) + "\n", 'bold'))
def help_tui (self):
diff --git a/scripts/automation/trex_control_plane/stl/console/trex_tui.py b/scripts/automation/trex_control_plane/stl/console/trex_tui.py
index 385cd098..2e26fdfc 100644
--- a/scripts/automation/trex_control_plane/stl/console/trex_tui.py
+++ b/scripts/automation/trex_control_plane/stl/console/trex_tui.py
@@ -5,6 +5,7 @@ import time
from collections import OrderedDict, deque
import datetime
import readline
+from texttable import ansi_len
if sys.version_info > (3,0):
from io import StringIO
@@ -449,6 +450,17 @@ class TrexTUI():
STATE_RECONNECT = 2
is_graph = False
+ MIN_ROWS = 50
+ MIN_COLS = 111
+
+ class ScreenSizeException(Exception):
+ def __init__ (self, cols, rows):
+ msg = "TUI requires console screen size of at least {0}x{1}, current is {2}x{3}".format(TrexTUI.MIN_COLS,
+ TrexTUI.MIN_ROWS,
+ cols,
+ rows)
+ super(TrexTUI.ScreenSizeException, self).__init__(msg)
+
def __init__ (self, stateless_client):
self.stateless_client = stateless_client
@@ -472,6 +484,11 @@ class TrexTUI():
def show (self, client, show_log = False, locked = False):
+
+ rows, cols = os.popen('stty size', 'r').read().split()
+ if (int(rows) < TrexTUI.MIN_ROWS) or (int(cols) < TrexTUI.MIN_COLS):
+ raise self.ScreenSizeException(rows = rows, cols = cols)
+
with AsyncKeys(client, locked) as async_keys:
sys.stdout.write("\x1bc")
self.async_keys = async_keys
@@ -691,16 +708,22 @@ class AsyncKeysEngineConsole:
self.async = async
self.lines = deque(maxlen = 100)
- self.ac = {'start' : client.start_line,
- 'stop' : client.stop_line,
- 'pause' : client.pause_line,
- 'resume': client.resume_line,
- 'update': client.update_line,
- 'quit' : self.action_quit,
- 'q' : self.action_quit,
- 'exit' : self.action_quit,
- 'help' : self.action_help,
- '?' : self.action_help}
+ self.generate_prompt = client.generate_prompt
+
+ self.ac = {'start' : client.start_line,
+ 'stop' : client.stop_line,
+ 'pause' : client.pause_line,
+ 'resume' : client.resume_line,
+ 'update' : client.update_line,
+ 'connect' : client.connect_line,
+ 'disconnect' : client.disconnect_line,
+ 'acquire' : client.acquire_line,
+ 'release' : client.release_line,
+ 'quit' : self.action_quit,
+ 'q' : self.action_quit,
+ 'exit' : self.action_quit,
+ 'help' : self.action_help,
+ '?' : self.action_help}
# fetch readline history and add relevants
for i in range(0, readline.get_current_history_length()):
@@ -916,6 +939,7 @@ class AsyncKeysEngineConsole:
line.invalidate()
assert(self.lines[0].modified == False)
+ color = None
if not func:
self.last_status = "unknown command: '{0}'".format(format_text(cmd.split()[0], 'bold'))
else:
@@ -923,12 +947,16 @@ class AsyncKeysEngineConsole:
self.last_status = func_rc
else:
self.last_status = format_text("[OK]", 'green') if func_rc else format_text(str(func_rc).replace('\n', ''), 'red')
+ color = 'red'
+ # trim too long lines
+ if ansi_len(self.last_status) > 100:
+ self.last_status = format_text(self.last_status[:100] + "...", color, 'bold')
def draw (self):
sys.stdout.write("\nPress 'ESC' for navigation panel...\n")
sys.stdout.write("status: \x1b[0K{0}\n".format(self.last_status))
- sys.stdout.write("\ntui>\x1b[0K")
+ sys.stdout.write("\n{0}\x1b[0K".format(self.generate_prompt(prefix = 'tui')))
self.lines[self.line_index].draw()
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 7c8a5fbf..a4f26f69 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
@@ -2442,7 +2442,7 @@ class STLClient(object):
def ping_line (self, line):
'''pings the server'''
self.ping()
- return True
+ return RC_OK()
@__console
def connect_line (self, line):
@@ -2454,14 +2454,13 @@ class STLClient(object):
parsing_opts.FORCE)
opts = parser.parse_args(line.split(), default_ports = self.get_all_ports())
- if opts is None:
- return
+ if not opts:
+ return opts
self.connect()
self.acquire(ports = opts.ports, force = opts.force)
- # true means print time
- return True
+ return RC_OK()
@__console
@@ -2476,19 +2475,19 @@ class STLClient(object):
parsing_opts.FORCE)
opts = parser.parse_args(line.split(), default_ports = self.get_all_ports())
- if opts is None:
- return
+ if not opts:
+ return opts
# filter out all the already owned ports
ports = list_difference(opts.ports, self.get_acquired_ports())
if not ports:
- self.logger.log("acquire - all port(s) {0} are already acquired".format(opts.ports))
- return
+ msg = "acquire - all of port(s) {0} are already acquired".format(opts.ports)
+ self.logger.log(format_text(msg, 'bold'))
+ return RC_ERR(msg)
self.acquire(ports = ports, force = opts.force)
- # true means print time
- return True
+ return RC_OK()
#
@@ -2502,23 +2501,24 @@ class STLClient(object):
parsing_opts.PORT_LIST_WITH_ALL)
opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports())
- if opts is None:
- return
+ if not opts:
+ return opts
ports = list_intersect(opts.ports, self.get_acquired_ports())
if not ports:
if not opts.ports:
- self.logger.log("release - no acquired ports")
- return
+ msg = "release - no acquired ports"
+ self.logger.log(format_text(msg, 'bold'))
+ return RC_ERR(msg)
else:
- self.logger.log("release - none of port(s) {0} are acquired".format(opts.ports))
- return
+ msg = "release - none of port(s) {0} are acquired".format(opts.ports)
+ self.logger.log(format_text(msg, 'bold'))
+ return RC_ERR(msg)
self.release(ports = ports)
- # true means print time
- return True
+ return RC_OK()
@__console
@@ -2530,23 +2530,23 @@ class STLClient(object):
self.reacquire_line.__doc__)
opts = parser.parse_args(line.split())
- if opts is None:
- return
+ if not opts:
+ return opts
# find all the on-owned ports under your name
my_unowned_ports = list_difference([k for k, v in self.ports.items() if v.get_owner() == self.username], self.get_acquired_ports())
if not my_unowned_ports:
- self.logger.log("reacquire - no unowned ports under '{0}'".format(self.username))
- return
+ msg = "reacquire - no unowned ports under '{0}'".format(self.username)
+ self.logger.log(msg)
+ return RC_ERR(msg)
self.acquire(ports = my_unowned_ports, force = True)
- return True
+ return RC_OK()
@__console
def disconnect_line (self, line):
self.disconnect()
-
@__console
@@ -2559,13 +2559,12 @@ class STLClient(object):
parsing_opts.PORT_LIST_WITH_ALL)
opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports(), verify_acquired = True)
- if opts is None:
- return
+ if not opts:
+ return opts
self.reset(ports = opts.ports)
- # true means print time
- return True
+ return RC_OK()
@@ -2586,8 +2585,8 @@ class STLClient(object):
parsing_opts.DRY_RUN)
opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports(), verify_acquired = True)
- if opts is None:
- return RC_ERR("invalid arguments for 'start'")
+ if not opts:
+ return opts
active_ports = list_intersect(self.get_active_ports(), opts.ports)
if active_ports:
@@ -2663,8 +2662,8 @@ class STLClient(object):
parsing_opts.PORT_LIST_WITH_ALL)
opts = parser.parse_args(line.split(), default_ports = self.get_active_ports(), verify_acquired = True)
- if opts is None:
- return RC_ERR("invalid arguments for 'stop'")
+ if not opts:
+ return opts
# find the relevant ports
@@ -2681,7 +2680,6 @@ class STLClient(object):
# call API
self.stop(ports)
- # true means print time
return RC_OK()
@@ -2697,8 +2695,8 @@ class STLClient(object):
parsing_opts.FORCE)
opts = parser.parse_args(line.split(), default_ports = self.get_active_ports(), verify_acquired = True)
- if opts is None:
- return RC_ERR("invalid arguments for 'update'")
+ if not opts:
+ return opts
# find the relevant ports
@@ -2714,7 +2712,6 @@ class STLClient(object):
self.update(ports, opts.mult, opts.total, opts.force)
- # true means print time
return RC_OK()
@@ -2727,8 +2724,8 @@ class STLClient(object):
parsing_opts.PORT_LIST_WITH_ALL)
opts = parser.parse_args(line.split(), default_ports = self.get_transmitting_ports(), verify_acquired = True)
- if opts is None:
- return RC_ERR("invalid arguments for 'pause'")
+ if not opts:
+ return opts
# check for already paused case
if opts.ports and is_sub_list(opts.ports, self.get_paused_ports()):
@@ -2749,7 +2746,6 @@ class STLClient(object):
self.pause(ports)
- # true means print time
return RC_OK()
@@ -2762,8 +2758,8 @@ class STLClient(object):
parsing_opts.PORT_LIST_WITH_ALL)
opts = parser.parse_args(line.split(), default_ports = self.get_paused_ports(), verify_acquired = True)
- if opts is None:
- return RC_ERR("invalid arguments for 'resume'")
+ if not opts:
+ return opts
# find the relevant ports
ports = list_intersect(opts.ports, self.get_paused_ports())
@@ -2794,8 +2790,8 @@ class STLClient(object):
opts = parser.parse_args(line.split())
- if opts is None:
- return
+ if not opts:
+ return opts
self.clear_stats(opts.ports)
@@ -2814,8 +2810,8 @@ class STLClient(object):
opts = parser.parse_args(line.split())
- if opts is None:
- return
+ if not opts:
+ return opts
# determine stats mask
mask = self.__get_mask_keys(**self.__filter_namespace_args(opts, trex_stl_stats.ALL_STATS_OPTS))
@@ -2845,8 +2841,8 @@ class STLClient(object):
opts = parser.parse_args(line.split())
- if opts is None:
- return
+ if not opts:
+ return opts
streams = self._get_streams(opts.ports, set(opts.streams))
if not streams:
@@ -2872,8 +2868,8 @@ class STLClient(object):
parsing_opts.PORT_LIST_WITH_ALL)
opts = parser.parse_args(line.split())
- if opts is None:
- return
+ if not opts:
+ return opts
self.validate(opts.ports)
@@ -2897,8 +2893,8 @@ class STLClient(object):
parsing_opts.FORCE)
opts = parser.parse_args(line.split())
- if opts is None:
- return
+ if not opts:
+ return opts
active_ports = list(set(self.get_active_ports()).intersection(opts.ports))
@@ -2906,7 +2902,7 @@ class STLClient(object):
if not opts.force:
msg = "Port(s) {0} are active - please stop them or add '--force'\n".format(active_ports)
self.logger.log(format_text(msg, 'bold'))
- return
+ return RC_ERR(msg)
else:
self.stop(active_ports)
@@ -2930,7 +2926,7 @@ class STLClient(object):
- return True
+ return RC_OK()
@@ -2945,8 +2941,8 @@ class STLClient(object):
parsing_opts.PROMISCUOUS_SWITCH)
opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports(), verify_acquired = True)
- if opts is None:
- return
+ if not opts:
+ return opts
# if no attributes - fall back to printing the status
if opts.prom is None:
@@ -2954,7 +2950,7 @@ class STLClient(object):
return
self.set_port_attr(opts.ports, opts.prom)
-
+ return RC_OK()
@__console
@@ -2967,8 +2963,8 @@ class STLClient(object):
parsing_opts.FILE_PATH)
opts = parser.parse_args(line.split())
- if opts is None:
- return
+ if not opts:
+ return opts
info = STLProfile.get_info(opts.file[0])
@@ -3024,8 +3020,8 @@ class STLClient(object):
*x)
opts = parser.parse_args(line.split())
- if opts is None:
- return
+ if not opts:
+ return opts
ev_type_filter = []
@@ -3046,3 +3042,15 @@ class STLClient(object):
if opts.clear:
self.clear_events()
+ def generate_prompt (self, prefix = 'trex'):
+ if not self.is_connected():
+ return "{0}(offline)>".format(prefix)
+
+ elif not self.get_acquired_ports():
+ return "{0}(read-only)>".format(prefix)
+
+ elif self.is_all_ports_acquired():
+ return "{0}>".format(prefix)
+
+ else:
+ return "{0} {1}>".format(prefix, self.get_acquired_ports())
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 caa5aea8..8be154af 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
@@ -1,6 +1,9 @@
import argparse
from collections import namedtuple
from .common import list_intersect, list_difference
+from .text_opts import format_text
+from ..trex_stl_types import *
+
import sys
import re
import os
@@ -400,6 +403,11 @@ class CCmdArgParser(argparse.ArgumentParser):
def _print_message(self, message, file=None):
self.stateless_client.logger.log(message)
+ def error(self, message):
+ self.print_usage()
+ self._print_message(('%s: error: %s\n') % (self.prog, message))
+ raise ValueError(message)
+
def has_ports_cfg (self, opts):
return hasattr(opts, "all_ports") or hasattr(opts, "ports")
@@ -407,7 +415,7 @@ class CCmdArgParser(argparse.ArgumentParser):
try:
opts = super(CCmdArgParser, self).parse_args(args, namespace)
if opts is None:
- return None
+ return RC_ERR("'{0}' - invalid arguments".format(self.cmd_name))
if not self.has_ports_cfg(opts):
return opts
@@ -422,8 +430,9 @@ class CCmdArgParser(argparse.ArgumentParser):
# so maybe we have ports configured
invalid_ports = list_difference(opts.ports, self.stateless_client.get_all_ports())
if invalid_ports:
- self.stateless_client.logger.log("{0}: port(s) {1} are not valid port IDs".format(self.cmd_name, invalid_ports))
- return None
+ msg = "{0}: port(s) {1} are not valid port IDs".format(self.cmd_name, invalid_ports)
+ self.stateless_client.logger.log(format_text(msg, 'bold'))
+ return RC_ERR(msg)
# verify acquired ports
if verify_acquired:
@@ -431,21 +440,25 @@ class CCmdArgParser(argparse.ArgumentParser):
diff = list_difference(opts.ports, acquired_ports)
if diff:
- self.stateless_client.logger.log("{0} - port(s) {1} are not acquired".format(self.cmd_name, diff))
- return None
+ msg = "{0} - port(s) {1} are not acquired".format(self.cmd_name, diff)
+ self.stateless_client.logger.log(format_text(msg, 'bold'))
+ return RC_ERR(msg)
# no acquire ports at all
if not acquired_ports:
- self.stateless_client.logger.log("{0} - no acquired ports".format(self.cmd_name))
- return None
-
+ msg = "{0} - no acquired ports".format(self.cmd_name)
+ self.stateless_client.logger.log(format_text(msg, 'bold'))
+ return RC_ERR(msg)
return opts
+ except ValueError as e:
+ return RC_ERR("'{0}' - {1}".format(self.cmd_name, str(e)))
+
except SystemExit:
# recover from system exit scenarios, such as "help", or bad arguments.
- return None
+ return RC_ERR("'{0}' - {1}".format(self.cmd_name, "no action"))
def get_flags (opt):