summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/automation/trex_control_plane/client/trex_stateless_client.py246
-rwxr-xr-xscripts/automation/trex_control_plane/console/parsing_opts.py9
-rwxr-xr-xscripts/automation/trex_control_plane/console/trex_console.py150
3 files changed, 268 insertions, 137 deletions
diff --git a/scripts/automation/trex_control_plane/client/trex_stateless_client.py b/scripts/automation/trex_control_plane/client/trex_stateless_client.py
index 011c9426..0df2ac5d 100755
--- a/scripts/automation/trex_control_plane/client/trex_stateless_client.py
+++ b/scripts/automation/trex_control_plane/client/trex_stateless_client.py
@@ -6,6 +6,7 @@ try:
except ImportError:
# support import for Python 3
import client.outer_packages
+
from client_utils.jsonrpc_client import JsonRpcClient, BatchMessage
from client_utils.packet_builder import CTRexPktBuilder
import json
@@ -13,6 +14,8 @@ from common.trex_stats import *
from common.trex_streams import *
from collections import namedtuple
from common.text_opts import *
+import parsing_opts
+import time
from trex_async_client import CTRexAsyncClient
@@ -75,6 +78,66 @@ def RC_ERR (err):
return RC(False, err)
+LoadedStreamList = namedtuple('LoadedStreamList', ['loaded', 'compiled'])
+
+# describes a stream DB
+class CStreamsDB(object):
+
+ def __init__(self):
+ self.stream_packs = {}
+
+ def load_yaml_file (self, filename):
+
+ stream_pack_name = filename
+ if stream_pack_name in self.get_loaded_streams_names():
+ self.remove_stream_packs(stream_pack_name)
+
+ stream_list = CStreamList()
+ loaded_obj = stream_list.load_yaml(filename)
+
+ try:
+ compiled_streams = stream_list.compile_streams()
+ rc = self.load_streams(stream_pack_name,
+ LoadedStreamList(loaded_obj,
+ [StreamPack(v.stream_id, v.stream.dump())
+ for k, v in compiled_streams.items()]))
+
+ except Exception as e:
+ return None
+
+ return self.get_stream_pack(stream_pack_name)
+
+ def load_streams(self, name, LoadedStreamList_obj):
+ if name in self.stream_packs:
+ return False
+ else:
+ self.stream_packs[name] = LoadedStreamList_obj
+ return True
+
+ def remove_stream_packs(self, *names):
+ removed_streams = []
+ for name in names:
+ removed = self.stream_packs.pop(name)
+ if removed:
+ removed_streams.append(name)
+ return removed_streams
+
+ def clear(self):
+ self.stream_packs.clear()
+
+ def get_loaded_streams_names(self):
+ return self.stream_packs.keys()
+
+ def stream_pack_exists (self, name):
+ return name in self.get_loaded_streams_names()
+
+ def get_stream_pack(self, name):
+ if not self.stream_pack_exists(name):
+ return None
+ else:
+ return self.stream_packs.get(name)
+
+
# describes a single port
class Port:
@@ -96,6 +159,9 @@ class Port:
def err (self, msg):
return RC_ERR("port {0} : {1}".format(self.port_id, msg))
+ def ok (self):
+ return RC_OK()
+
# take the port
def acquire (self, force = False):
params = {"port_id": self.port_id,
@@ -106,9 +172,9 @@ class Port:
rc = self.transmit(command.method, command.params)
if rc.success:
self.handler = rc.data
- return RC_OK()
+ return self.ok()
else:
- return RC_ERR(rc.data)
+ return self.err(rc.data)
# release the port
@@ -120,9 +186,9 @@ class Port:
rc = self.transmit(command.method, command.params)
if rc.success:
self.handler = rc.data
- return RC_OK()
+ return self.ok()
else:
- return RC_ERR(rc.data)
+ return self.err(rc.data)
def is_acquired (self):
return (self.handler != None)
@@ -147,7 +213,7 @@ class Port:
else:
raise Exception("port {0}: bad state received from server '{1}'".format(self.port_id, sync_data['state']))
- return RC_OK()
+ return self.ok()
# return TRUE if write commands
@@ -178,7 +244,7 @@ class Port:
# the only valid state now
self.state = self.STATE_STREAMS
- return RC_OK()
+ return self.ok()
# remove stream from port
def remove_stream (self, stream_id):
@@ -197,7 +263,7 @@ class Port:
self.streams[stream_id] = None
- return RC_OK()
+ return self.ok()
# remove all the streams
def remove_all_streams (self):
@@ -211,7 +277,7 @@ class Port:
self.streams = {}
- return RC_OK()
+ return self.ok()
# start traffic
def start (self, mul):
@@ -234,7 +300,7 @@ class Port:
self.state = self.STATE_TX
- return RC_OK()
+ return self.ok()
# stop traffic
# with force ignores the cached state and sends the command
@@ -253,7 +319,7 @@ class Port:
# only valid state after stop
self.state = self.STATE_STREAMS
- return RC_OK()
+ return self.ok()
@@ -273,6 +339,8 @@ class CTRexStatelessClient(object):
self._async_client = CTRexAsyncClient(async_port)
+ self.streams_db = CStreamsDB()
+
self.connected = False
############# helper functions section ##############
@@ -605,15 +673,16 @@ class CTRexStatelessClient(object):
active_ports = list(set(self.get_active_ports()).intersection(port_id_list))
if not active_ports:
- print format_text("No active traffic on porvided ports", 'bold')
- return True
+ msg = "No active traffic on porvided ports"
+ print format_text(msg, 'bold')
+ return RC_ERR(msg)
rc = self.stop_traffic(active_ports)
rc.annotate("Stopping traffic on port(s) {0}:".format(port_id_list))
if rc.bad():
- return False
+ return rc
- return True
+ return RC_OK()
# start cmd
def cmd_start (self, port_id_list, stream_list, mult, force):
@@ -622,31 +691,161 @@ class CTRexStatelessClient(object):
if active_ports:
if not force:
- print format_text("Port(s) {0} are active - please stop them or add '--force'".format(active_ports), 'bold')
- return False
+ msg = "Port(s) {0} are active - please stop them or add '--force'".format(active_ports)
+ print format_text(msg, 'bold')
+ return RC_ERR(msg)
else:
rc = self.cmd_stop(active_ports)
if not rc:
- return False
+ return rc
rc = self.remove_all_streams(port_id_list)
- rc.annotate("Removing all streams from ports {0}:".format(port_id_list))
+ rc.annotate("Removing all streams from port(s) {0}:".format(port_id_list))
if rc.bad():
- return False
+ return rc
rc = self.add_stream_pack(stream_list.compiled, port_id_list)
- rc.annotate("Attaching streams to port {0}:".format(port_id_list))
+ rc.annotate("Attaching streams to port(s) {0}:".format(port_id_list))
if rc.bad():
- return False
+ return rc
# finally, start the traffic
rc = self.start_traffic(mult, port_id_list)
- rc.annotate("Starting traffic on ports {0}:".format(port_id_list))
+ rc.annotate("Starting traffic on port(s) {0}:".format(port_id_list))
if rc.bad():
- return False
+ return rc
+
+ return RC_OK()
+
+ ############## High Level API With Parser ################
+ def cmd_start_line (self, line):
+ '''Start selected traffic in specified ports on TRex\n'''
+ # define a parser
+ parser = parsing_opts.gen_parser(self,
+ "start",
+ self.cmd_start_line.__doc__,
+ parsing_opts.PORT_LIST_WITH_ALL,
+ parsing_opts.FORCE,
+ parsing_opts.STREAM_FROM_PATH_OR_FILE,
+ parsing_opts.DURATION,
+ parsing_opts.MULTIPLIER)
+
+ opts = parser.parse_args(line.split())
+
+ if opts is None:
+ return RC_ERR("bad command line paramters")
+
+ if opts.db:
+ stream_list = self.stream_db.get_stream_pack(opts.db)
+ rc = RC(stream_list != None)
+ rc.annotate("Load stream pack (from DB):")
+ if rc.bad():
+ return RC_ERR("Failed to load stream pack")
+
+ else:
+ # load streams from file
+ stream_list = self.streams_db.load_yaml_file(opts.file[0])
+ rc = RC(stream_list != None)
+ rc.annotate("Load stream pack (from file):")
+ if stream_list == None:
+ return RC_ERR("Failed to load stream pack")
+
+
+ return self.cmd_start(opts.ports, stream_list, opts.mult, opts.force)
+
+ def cmd_stop_line (self, line):
+ '''Stop active traffic in specified ports on TRex\n'''
+ parser = parsing_opts.gen_parser(self,
+ "stop",
+ self.cmd_stop_line.__doc__,
+ parsing_opts.PORT_LIST_WITH_ALL)
+
+ opts = parser.parse_args(line.split())
+ if opts is None:
+ return RC_ERR("bad command line paramters")
+
+ return self.cmd_stop(opts.ports)
+
+
+ def cmd_reset_line (self, line):
+ return self.cmd_reset()
+
+
+ def cmd_exit_line (self, line):
+ print format_text("Exiting\n", 'bold')
+ # a way to exit
+ return RC_ERR("exit")
+
+
+ def cmd_wait_line (self, line):
+ '''wait for a period of time\n'''
+
+ parser = parsing_opts.gen_parser(self,
+ "wait",
+ self.cmd_wait_line.__doc__,
+ parsing_opts.DURATION)
+
+ opts = parser.parse_args(line.split())
+ if opts is None:
+ return RC_ERR("bad command line paramters")
+
+ delay_sec = opts.d if opts.d else 1
+
+ print format_text("Waiting for {0} seconds...\n".format(delay_sec), 'bold')
+ time.sleep(delay_sec)
+
+ return RC_OK()
+
+ # run a script of commands
+ def run_script_file (self, filename):
+
+ print format_text("\nRunning script file '{0}'...".format(filename), 'bold')
+
+ rc = self.cmd_connect()
+ if rc.bad():
+ return
+
+ with open(filename) as f:
+ script_lines = f.readlines()
+
+ cmd_table = {}
+
+ # register all the commands
+ cmd_table['start'] = self.cmd_start_line
+ cmd_table['stop'] = self.cmd_stop_line
+ cmd_table['reset'] = self.cmd_reset_line
+ cmd_table['wait'] = self.cmd_wait_line
+ cmd_table['exit'] = self.cmd_exit_line
+
+ for index, line in enumerate(script_lines):
+ line = line.strip()
+ if line == "":
+ continue
+ if line.startswith("#"):
+ continue
+
+ sp = line.split(' ', 1)
+ cmd = sp[0]
+ if len(sp) == 2:
+ args = sp[1]
+ else:
+ args = ""
+
+ print format_text("Executing line {0} : '{1}'\n".format(index, line))
+
+ if not cmd in cmd_table:
+ print "\n*** Error at line {0} : '{1}'\n".format(index, line)
+ print format_text("unknown command '{0}'\n".format(cmd), 'bold')
+ return False
+
+ rc = cmd_table[cmd](args)
+ if rc.bad():
+ return False
+
+ print format_text("\n[Done]", 'bold')
return True
@@ -710,3 +909,4 @@ class CTRexStatelessClient(object):
if __name__ == "__main__":
pass
+
diff --git a/scripts/automation/trex_control_plane/console/parsing_opts.py b/scripts/automation/trex_control_plane/console/parsing_opts.py
index 0e11df74..c154ce24 100755
--- a/scripts/automation/trex_control_plane/console/parsing_opts.py
+++ b/scripts/automation/trex_control_plane/console/parsing_opts.py
@@ -135,12 +135,13 @@ class CCmdArgParser(argparse.ArgumentParser):
if opts is None:
return None
- if opts.all_ports:
+ if getattr(opts, "all_ports", None):
opts.ports = self.stateless_client.get_port_ids()
- 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))
+ if 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))
return opts
diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py
index 7931dfc9..88e8dede 100755
--- a/scripts/automation/trex_control_plane/console/trex_console.py
+++ b/scripts/automation/trex_control_plane/console/trex_console.py
@@ -30,72 +30,12 @@ import tty, termios
import trex_root_path
from common.trex_streams import *
from client.trex_stateless_client import CTRexStatelessClient
-from client.trex_stateless_client import RpcResponseStatus
from common.text_opts import *
from client_utils.general_utils import user_input, get_current_user
-import parsing_opts
import trex_status
-from collections import namedtuple
-__version__ = "1.0"
-
-LoadedStreamList = namedtuple('LoadedStreamList', ['loaded', 'compiled'])
-
-class CStreamsDB(object):
-
- def __init__(self):
- self.stream_packs = {}
-
- def load_yaml_file (self, filename):
-
- stream_pack_name = filename
- if stream_pack_name in self.get_loaded_streams_names():
- self.remove_stream_packs(stream_pack_name)
-
- stream_list = CStreamList()
- loaded_obj = stream_list.load_yaml(filename)
-
- try:
- compiled_streams = stream_list.compile_streams()
- rc = self.load_streams(stream_pack_name,
- LoadedStreamList(loaded_obj,
- [StreamPack(v.stream_id, v.stream.dump())
- for k, v in compiled_streams.items()]))
-
- except Exception as e:
- return None
-
- return self.get_stream_pack(stream_pack_name)
-
- def load_streams(self, name, LoadedStreamList_obj):
- if name in self.stream_packs:
- return False
- else:
- self.stream_packs[name] = LoadedStreamList_obj
- return True
-
- def remove_stream_packs(self, *names):
- removed_streams = []
- for name in names:
- removed = self.stream_packs.pop(name)
- if removed:
- removed_streams.append(name)
- return removed_streams
-
- def clear(self):
- self.stream_packs.clear()
-
- def get_loaded_streams_names(self):
- return self.stream_packs.keys()
- def stream_pack_exists (self, name):
- return name in self.get_loaded_streams_names()
-
- def get_stream_pack(self, name):
- if not self.stream_pack_exists(name):
- return None
- else:
- return self.stream_packs.get(name)
+__version__ = "1.0"
#
@@ -111,15 +51,11 @@ class TRexConsole(cmd.Cmd):
self.verbose = verbose
self.acquire_all_ports = acquire_all_ports
- self.do_connect("")
-
self.intro = "\n-=TRex Console v{ver}=-\n".format(ver=__version__)
self.intro += "\nType 'help' or '?' for supported actions\n"
self.postcmd(False, "")
- self.streams_db = CStreamsDB()
-
################### internal section ########################
@@ -155,10 +91,21 @@ class TRexConsole(cmd.Cmd):
path = dir
else:
path = "."
+
+
start_string = os.path.basename(text)
- return [x
- for x in os.listdir(path)
- if x.startswith(start_string)]
+
+ targets = []
+
+ for x in os.listdir(path):
+ if x.startswith(start_string):
+ y = os.path.join(path, x)
+ if os.path.isfile(y):
+ targets.append(x + ' ')
+ elif os.path.isdir(y):
+ targets.append(x + '/')
+
+ return targets
# annotation method
@staticmethod
@@ -256,37 +203,7 @@ class TRexConsole(cmd.Cmd):
def do_start(self, line):
'''Start selected traffic in specified ports on TRex\n'''
- # make sure that the user wants to acquire all
- parser = parsing_opts.gen_parser(self.stateless_client,
- "start",
- self.do_start.__doc__,
- parsing_opts.PORT_LIST_WITH_ALL,
- parsing_opts.FORCE,
- parsing_opts.STREAM_FROM_PATH_OR_FILE,
- parsing_opts.DURATION,
- parsing_opts.MULTIPLIER)
-
- opts = parser.parse_args(line.split())
-
- if opts is None:
- return
-
- if opts.db:
- stream_list = self.stream_db.get_stream_pack(opts.db)
- self.annotate("Load stream pack (from DB):", (stream_list != None))
- if stream_list == None:
- return
-
- else:
- # load streams from file
- stream_list = self.streams_db.load_yaml_file(opts.file[0])
- self.annotate("Load stream pack (from file):", (stream_list != None))
- if stream_list == None:
- return
-
-
- self.stateless_client.cmd_start(opts.ports, stream_list, opts.mult, opts.force)
- return
+ self.stateless_client.cmd_start_line(line)
def help_start(self):
@@ -294,18 +211,9 @@ class TRexConsole(cmd.Cmd):
############# stop
def do_stop(self, line):
- '''Stop active traffic in specified ports on TRex\n'''
- parser = parsing_opts.gen_parser(self.stateless_client,
- "stop",
- self.do_stop.__doc__,
- parsing_opts.PORT_LIST_WITH_ALL)
-
- opts = parser.parse_args(line.split())
- if opts is None:
- return
+ self.stateless_client.cmd_stop_line(line)
- self.stateless_client.cmd_stop(opts.ports)
- return
+
def help_stop(self):
self.do_stop("-h")
@@ -373,6 +281,14 @@ class TRexConsole(cmd.Cmd):
do_exit = do_EOF = do_q = do_quit
+#
+def is_valid_file(filename):
+ if not os.path.isfile(filename):
+ raise argparse.ArgumentTypeError("The file '%s' does not exist" % filename)
+
+ return filename
+
+
def setParserOptions():
parser = argparse.ArgumentParser(prog="trex_console.py")
@@ -402,6 +318,12 @@ def setParserOptions():
action="store_false", help="Acquire all ports on connect. Default is: ON.",
default = True)
+ parser.add_argument("--batch", dest="batch",
+ nargs = 1,
+ type = is_valid_file,
+ help = "Run the console in a batch mode with file",
+ default = None)
+
return parser
@@ -411,7 +333,15 @@ def main():
# Stateless client connection
stateless_client = CTRexStatelessClient(options.user, options.server, options.port, options.pub)
+ rc = stateless_client.cmd_connect()
+ if rc.bad():
+ return
+ if options.batch:
+ cont = stateless_client.run_script_file(options.batch[0])
+ if not cont:
+ return
+
# console
try:
console = TRexConsole(stateless_client, options.acquire, options.verbose)