summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xscripts/automation/trex_control_plane/stl/console/trex_console.py47
-rw-r--r--scripts/automation/trex_control_plane/stl/console/trex_tui.py33
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py143
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/common.py5
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py42
5 files changed, 178 insertions, 92 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 e5539b2b..2b53b7ec 100755
--- a/scripts/automation/trex_control_plane/stl/console/trex_console.py
+++ b/scripts/automation/trex_control_plane/stl/console/trex_console.py
@@ -212,29 +212,7 @@ class TRexConsole(TRexGeneralCmd):
return wrap
- # TODO: remove this ugly duplication
- def verify_connected_and_rw (f):
- @wraps(f)
- def wrap(*args):
- inst = args[0]
- func_name = f.__name__
- if func_name.startswith("do_"):
- func_name = func_name[3:]
-
- if not inst.stateless_client.is_connected():
- print(format_text("\n'{0}' cannot be executed on offline mode\n".format(func_name), 'bold'))
- return
-
- if not inst.stateless_client.get_acquired_ports():
- print(format_text("\n'{0}' cannot be executed on read only mode\n".format(func_name), 'bold'))
- return
-
- rc = f(*args)
- return rc
-
- return wrap
-
-
+
def get_console_identifier(self):
return "{context}_{server}".format(context=get_current_user(),
server=self.stateless_client.get_connection_info()['server'])
@@ -431,19 +409,22 @@ class TRexConsole(TRexGeneralCmd):
self.stateless_client.disconnect_line(line)
+ @verify_connected
def do_acquire (self, line):
'''Acquire ports\n'''
self.stateless_client.acquire_line(line)
-
- def help_acquire (self):
- self.do_acquire("-h")
+
+ @verify_connected
def do_release (self, line):
'''Release ports\n'''
-
self.stateless_client.release_line(line)
+
+ def help_acquire (self):
+ self.do_acquire("-h")
+
def help_release (self):
self.do_release("-h")
@@ -462,7 +443,7 @@ class TRexConsole(TRexGeneralCmd):
return TRexConsole.tree_autocomplete(s[l - 1])
- @verify_connected_and_rw
+ @verify_connected
def do_start(self, line):
'''Start selected traffic in specified port(s) on TRex\n'''
@@ -475,7 +456,7 @@ class TRexConsole(TRexGeneralCmd):
self.do_start("-h")
############# stop
- @verify_connected_and_rw
+ @verify_connected
def do_stop(self, line):
'''stops port(s) transmitting traffic\n'''
@@ -485,7 +466,7 @@ class TRexConsole(TRexGeneralCmd):
self.do_stop("-h")
############# update
- @verify_connected_and_rw
+ @verify_connected
def do_update(self, line):
'''update speed of port(s)currently transmitting traffic\n'''
@@ -495,14 +476,14 @@ class TRexConsole(TRexGeneralCmd):
self.do_update("-h")
############# pause
- @verify_connected_and_rw
+ @verify_connected
def do_pause(self, line):
'''pause port(s) transmitting traffic\n'''
self.stateless_client.pause_line(line)
############# resume
- @verify_connected_and_rw
+ @verify_connected
def do_resume(self, line):
'''resume port(s) transmitting traffic\n'''
@@ -511,7 +492,7 @@ class TRexConsole(TRexGeneralCmd):
########## reset
- @verify_connected_and_rw
+ @verify_connected
def do_reset (self, line):
'''force stop all ports\n'''
self.stateless_client.reset_line(line)
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 a842e172..331baec9 100644
--- a/scripts/automation/trex_control_plane/stl/console/trex_tui.py
+++ b/scripts/automation/trex_control_plane/stl/console/trex_tui.py
@@ -48,12 +48,17 @@ class TrexTUIPanel(object):
def get_key_actions (self):
raise NotImplementedError("must implement this")
+
def get_name (self):
return self.name
# dashboard panel
class TrexTUIDashBoard(TrexTUIPanel):
+
+ FILTER_ACQUIRED = 1
+ FILTER_ALL = 2
+
def __init__ (self, mng):
super(TrexTUIDashBoard, self).__init__(mng, "dashboard")
@@ -65,11 +70,23 @@ class TrexTUIDashBoard(TrexTUIPanel):
self.key_actions['+'] = {'action': self.action_raise, 'legend': 'up 5%', 'show': True}
self.key_actions['-'] = {'action': self.action_lower, 'legend': 'low 5%', 'show': True}
- self.ports = self.stateless_client.get_all_ports()
+ self.key_actions['o'] = {'action': self.action_show_owned, 'legend': 'owned ports', 'show': True}
+ self.key_actions['a'] = {'action': self.action_show_all, 'legend': 'all ports', 'show': True}
+
+ self.ports_filter = self.FILTER_ACQUIRED
+
+
+ def get_ports (self):
+ if self.ports_filter == self.FILTER_ACQUIRED:
+ return self.stateless_client.get_acquired_ports()
+ elif self.ports_filter == self.FILTER_ALL:
+ return self.stateless_client.get_all_ports()
+
+ assert(0)
def show (self):
- stats = self.stateless_client._get_formatted_stats(self.ports)
+ stats = self.stateless_client._get_formatted_stats(self.get_ports())
# print stats to screen
for stat_type, stat_data in stats.items():
text_tables.print_table_with_header(stat_data.text_table, stat_type)
@@ -79,8 +96,10 @@ class TrexTUIDashBoard(TrexTUIPanel):
allowed = OrderedDict()
allowed['c'] = self.key_actions['c']
+ allowed['o'] = self.key_actions['o']
+ allowed['a'] = self.key_actions['a']
- if self.stateless_client.is_all_ports_acquired():
+ if self.ports_filter == self.FILTER_ALL:
return allowed
if len(self.stateless_client.get_transmitting_ports()) > 0:
@@ -133,6 +152,14 @@ class TrexTUIDashBoard(TrexTUIPanel):
return ""
+ def action_show_owned (self):
+ self.ports_filter = self.FILTER_ACQUIRED
+ return ""
+
+ def action_show_all (self):
+ self.ports_filter = self.FILTER_ALL
+ return ""
+
def action_clear (self):
self.stateless_client.clear_stats(self.mng.ports)
return "cleared all stats"
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 98f3fe3a..aa95f037 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
@@ -12,6 +12,7 @@ from .trex_stl_types import *
from .trex_stl_async_client import CTRexAsyncClient
from .utils import parsing_opts, text_tables, common
+from .utils.common import list_intersect, list_difference, is_sub_list
from .utils.text_opts import *
from functools import wraps
@@ -1141,23 +1142,39 @@ class STLClient(object):
if port_obj.is_acquired()]
# get all active ports (TX or pause)
- def get_active_ports(self):
- return [port_id
- for port_id, port_obj in self.ports.items()
- if port_obj.is_active()]
+ def get_active_ports(self, owned = True):
+ if owned:
+ return [port_id
+ for port_id, port_obj in self.ports.items()
+ if port_obj.is_active() and port_obj.is_acquired()]
+ else:
+ return [port_id
+ for port_id, port_obj in self.ports.items()
+ if port_obj.is_active()]
# get paused ports
- def get_paused_ports (self):
- return [port_id
- for port_id, port_obj in self.ports.items()
- if port_obj.is_paused()]
+ def get_paused_ports (self, owned = True):
+ if owned:
+ return [port_id
+ for port_id, port_obj in self.ports.items()
+ if port_obj.is_paused() and port_obj.is_acquired()]
+ else:
+ return [port_id
+ for port_id, port_obj in self.ports.items()
+ if port_obj.is_paused()]
+
# get all TX ports
- def get_transmitting_ports (self):
- return [port_id
- for port_id, port_obj in self.ports.items()
- if port_obj.is_transmitting()]
+ def get_transmitting_ports (self, owned = True):
+ if owned:
+ return [port_id
+ for port_id, port_obj in self.ports.items()
+ if port_obj.is_transmitting() and port_obj.is_acquired()]
+ else:
+ return [port_id
+ for port_id, port_obj in self.ports.items()
+ if port_obj.is_transmitting()]
# get stats
@@ -2031,8 +2048,7 @@ class STLClient(object):
parsing_opts.PORT_LIST_WITH_ALL,
parsing_opts.FORCE)
- opts = parser.parse_args(line.split())
-
+ opts = parser.parse_args(line.split(), default_ports = self.get_all_ports())
if opts is None:
return
@@ -2042,6 +2058,7 @@ class STLClient(object):
# true means print time
return True
+
@__console
def acquire_line (self, line):
'''Acquire ports\n'''
@@ -2053,15 +2070,14 @@ class STLClient(object):
parsing_opts.PORT_LIST_WITH_ALL,
parsing_opts.FORCE)
- opts = parser.parse_args(line.split())
-
+ opts = parser.parse_args(line.split(), default_ports = self.get_all_ports())
if opts is None:
return
- # call the API
- ports = [x for x in opts.ports if x not in self.get_acquired_ports()]
+ # filter out all the already owned ports
+ ports = list_difference(opts.ports, self.get_acquired_ports())
if not ports:
- self.logger.log("Port(s) {0} are already acquired\n".format(opts.ports))
+ self.logger.log("acquire - all port(s) {0} are already acquired".format(opts.ports))
return
self.acquire(ports = ports, force = opts.force)
@@ -2080,22 +2096,26 @@ class STLClient(object):
self.release_line.__doc__,
parsing_opts.PORT_LIST_WITH_ALL)
- opts = parser.parse_args(line.split())
-
+ opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports())
if opts is None:
return
- # call the API
- ports = [x for x in opts.ports if x in self.get_acquired_ports()]
+ ports = list_intersect(opts.ports, self.get_acquired_ports())
if not ports:
- self.logger.log("Port(s) {0} are not owned by you\n".format(opts.ports))
- return
+ if not opts.ports:
+ self.logger.log("release - no acquired ports")
+ return
+ else:
+ self.logger.log("release - none of port(s) {0} are acquired".format(opts.ports))
+ return
+
self.release(ports = ports)
# true means print time
return True
+
@__console
def disconnect_line (self, line):
self.disconnect()
@@ -2104,12 +2124,24 @@ class STLClient(object):
@__console
def reset_line (self, line):
- self.reset()
+ '''Reset ports - if no ports are provided all acquired ports will be reset'''
+
+ parser = parsing_opts.gen_parser(self,
+ "reset",
+ self.reset_line.__doc__,
+ 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
+
+ self.reset(ports = opts.ports)
# true means print time
return True
+
@__console
def start_line (self, line):
'''Start selected traffic on specified ports on TRex\n'''
@@ -2126,15 +2158,11 @@ class STLClient(object):
parsing_opts.MULTIPLIER_STRICT,
parsing_opts.DRY_RUN)
- opts = parser.parse_args(line.split())
-
-
+ opts = parser.parse_args(line.split(), default_ports = self.get_acquired_ports(), verify_acquired = True)
if opts is None:
return
-
- active_ports = list(set(self.get_active_ports()).intersection(opts.ports))
-
+ active_ports = list_intersect(self.get_active_ports(), opts.ports)
if active_ports:
if not opts.force:
msg = "Port(s) {0} are active - please stop them or add '--force'\n".format(active_ports)
@@ -2205,17 +2233,21 @@ class STLClient(object):
self.stop_line.__doc__,
parsing_opts.PORT_LIST_WITH_ALL)
- opts = parser.parse_args(line.split())
+ opts = parser.parse_args(line.split(), default_ports = self.get_active_ports(), verify_acquired = True)
if opts is None:
return
- # find the relevant ports
- ports = list(set(self.get_active_ports()).intersection(opts.ports))
+ # find the relevant ports
+ ports = list_intersect(opts.ports, self.get_active_ports())
if not ports:
- self.logger.log(format_text("No active traffic on provided ports\n", 'bold'))
+ if not opts.ports:
+ self.logger.log('stop - no active ports')
+ else:
+ self.logger.log('stop - no active traffic on ports {0}'.format(opts.ports))
return
+ # call API
self.stop(ports)
# true means print time
@@ -2233,15 +2265,18 @@ class STLClient(object):
parsing_opts.TOTAL,
parsing_opts.FORCE)
- opts = parser.parse_args(line.split())
+ opts = parser.parse_args(line.split(), default_ports = self.get_active_ports(), verify_acquired = True)
if opts is None:
return
- # find the relevant ports
- ports = list(set(self.get_active_ports()).intersection(opts.ports))
+ # find the relevant ports
+ ports = list_intersect(opts.ports, self.get_active_ports())
if not ports:
- self.logger.log(format_text("No ports in valid state to update\n", 'bold'))
+ if not opts.ports:
+ self.logger.log('update - no active ports')
+ else:
+ self.logger.log('update - no active traffic on ports {0}'.format(opts.ports))
return
self.update(ports, opts.mult, opts.total, opts.force)
@@ -2258,15 +2293,22 @@ class STLClient(object):
self.pause_line.__doc__,
parsing_opts.PORT_LIST_WITH_ALL)
- opts = parser.parse_args(line.split())
+ opts = parser.parse_args(line.split(), default_ports = self.get_transmitting_ports(), verify_acquired = True)
if opts is None:
return
- # find the relevant ports
- ports = list(set(self.get_transmitting_ports()).intersection(opts.ports))
+ # check for already paused case
+ if opts.ports and is_sub_list(opts.ports, self.get_paused_ports()):
+ self.logger.log('pause - all of port(s) {0} are already paused'.format(opts.ports))
+ return
+ # find the relevant ports
+ ports = list_intersect(opts.ports, self.get_transmitting_ports())
if not ports:
- self.logger.log(format_text("No ports in valid state to pause\n", 'bold'))
+ if not opts.ports:
+ self.logger.log('pause - no transmitting ports')
+ else:
+ self.logger.log('pause - none of ports {0} are transmitting'.format(opts.ports))
return
self.pause(ports)
@@ -2283,18 +2325,21 @@ class STLClient(object):
self.resume_line.__doc__,
parsing_opts.PORT_LIST_WITH_ALL)
- opts = parser.parse_args(line.split())
+ opts = parser.parse_args(line.split(), default_ports = self.get_paused_ports(), verify_acquired = True)
if opts is None:
return
# find the relevant ports
- ports = list(set(self.get_paused_ports()).intersection(opts.ports))
-
+ ports = list_intersect(opts.ports, self.get_paused_ports())
if not ports:
- self.logger.log(format_text("No ports in valid state to resume\n", 'bold'))
+ if not opts.ports:
+ self.logger.log('resume - no paused ports')
+ else:
+ self.logger.log('resume - none of ports {0} are paused'.format(opts.ports))
return
- return self.resume(ports)
+
+ self.resume(ports)
# true means print time
return True
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/common.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/common.py
index e176ca99..b4903e81 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/common.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/common.py
@@ -59,3 +59,8 @@ def get_number(input):
def list_intersect(l1, l2):
return list(filter(lambda x: x in l2, l1))
+def list_difference (l1, l2):
+ return list(filter(lambda x: x not in l2, l1))
+
+def is_sub_list (l1, l2):
+ return set(l1) <= set(l2)
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 c4f2b358..ad46625b 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,5 +1,6 @@
import argparse
from collections import namedtuple
+from .common import list_intersect, list_difference
import sys
import re
import os
@@ -262,7 +263,7 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
'action': "store_false"}),
- PORT_LIST: ArgumentPack(['--port'],
+ PORT_LIST: ArgumentPack(['--port', '-p'],
{"nargs": '+',
'dest':'ports',
'metavar': 'PORTS',
@@ -374,22 +375,49 @@ class CCmdArgParser(argparse.ArgumentParser):
def __init__(self, stateless_client, *args, **kwargs):
super(CCmdArgParser, self).__init__(*args, **kwargs)
self.stateless_client = stateless_client
+ self.cmd_name = kwargs.get('prog')
- def parse_args(self, args=None, namespace=None):
+
+ def has_ports_cfg (self, opts):
+ return hasattr(opts, "all_ports") or hasattr(opts, "ports")
+
+ def parse_args(self, args=None, namespace=None, default_ports=None, verify_acquired=False):
try:
opts = super(CCmdArgParser, self).parse_args(args, namespace)
if opts is None:
return None
+ if not self.has_ports_cfg(opts):
+ return opts
+
# if all ports are marked or
if (getattr(opts, "all_ports", None) == True) or (getattr(opts, "ports", None) == []):
- opts.ports = self.stateless_client.get_all_ports()
+ if default_ports is None:
+ opts.ports = self.stateless_client.get_acquired_ports()
+ else:
+ opts.ports = default_ports
# so maybe we have ports configured
- elif getattr(opts, "ports", None):
- for port in opts.ports:
- if not self.stateless_client._validate_port_list(port):
- self.error("port id '{0}' is not a valid port id\n".format(port))
+ 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
+
+ # verify acquired ports
+ if verify_acquired:
+ acquired_ports = self.stateless_client.get_acquired_ports()
+
+ 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
+
+ # no acquire ports at all
+ if not acquired_ports:
+ self.stateless_client.logger.log("{0} - no acquired ports".format(self.cmd_name))
+ return None
+
+
return opts