summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2015-11-11 13:48:02 +0200
committerimarom <imarom@cisco.com>2015-11-11 13:48:02 +0200
commit467382a7611f478d66cf58c1307f079239f7bac6 (patch)
tree6652a456f6e67fa462a5a2ec44bffabc9a05406a
parenta7983ed267e02a9c6a39c898c58e96b5d878e3f2 (diff)
lightweight console
-rwxr-xr-xscripts/automation/trex_control_plane/client/trex_stateless_client.py102
-rw-r--r--scripts/automation/trex_control_plane/console/old_console.py946
-rwxr-xr-xscripts/automation/trex_control_plane/console/parsing_opts.py74
-rwxr-xr-xscripts/automation/trex_control_plane/console/trex_console.py1111
-rw-r--r--scripts/automation/trex_control_plane/console/trex_status.py5
-rw-r--r--src/rpc-server/trex_rpc_req_resp_server.h2
-rw-r--r--src/stateless/cp/trex_stateless_port.cpp4
7 files changed, 1288 insertions, 956 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 11728965..168853b3 100755
--- a/scripts/automation/trex_control_plane/client/trex_stateless_client.py
+++ b/scripts/automation/trex_control_plane/client/trex_stateless_client.py
@@ -232,7 +232,6 @@ class CTRexStatelessClient(object):
self.transmit(command.method, command.params),
self.ack_success_test)
- # @force_status(owned=True)
@acquired
def add_stream(self, stream_id, stream_obj, port_id=None):
if not self._is_ports_valid(port_id):
@@ -244,7 +243,6 @@ class CTRexStatelessClient(object):
"stream": stream_obj.dump()}
return self.transmit("add_stream", params)
- # @force_status(owned=True)
@acquired
def add_stream_pack(self, stream_pack_list, port_id=None):
if not self._is_ports_valid(port_id):
@@ -262,9 +260,11 @@ class CTRexStatelessClient(object):
for p_id in port_ids]
)
res_ok, resp_list = self.transmit_batch(commands)
- if res_ok:
- return self._process_batch_result(commands, resp_list, self._handle_add_stream_response,
- success_test=self.ack_success_test)
+ if not res_ok:
+ return res_ok, resp_list
+
+ return self._process_batch_result(commands, resp_list, self._handle_add_stream_response,
+ success_test=self.ack_success_test)
@force_status(owned=True)
def remove_stream(self, stream_id, port_id=None):
@@ -275,8 +275,6 @@ class CTRexStatelessClient(object):
"stream_id": stream_id}
return self.transmit("remove_stream", params)
- # @force_status(owned=True)
- @acquired
def remove_all_streams(self, port_id=None):
if not self._is_ports_valid(port_id):
raise ValueError("Provided illegal port id input")
@@ -326,7 +324,6 @@ class CTRexStatelessClient(object):
"get_pkt": get_pkt}
return self.transmit("get_stream_list", params)
- @acquired
def start_traffic(self, multiplier, port_id=None):
if not self._is_ports_valid(port_id):
raise ValueError("Provided illegal port id input")
@@ -350,8 +347,6 @@ class CTRexStatelessClient(object):
self.transmit(command.method, command.params),
self.ack_success_test)
- # @force_status(owned=False, active_and_owned=True)
- @acquired
def stop_traffic(self, port_id=None):
if not self._is_ports_valid(port_id):
raise ValueError("Provided illegal port id input")
@@ -371,7 +366,7 @@ class CTRexStatelessClient(object):
params = {"handler": self._conn_handler.get(port_id),
"port_id": port_id}
command = RpcCmdData("stop_traffic", params)
- return self._handle_start_traffic_response(command,
+ return self._handle_stop_traffic_response(command,
self.transmit(command.method, command.params),
self.ack_success_test)
@@ -471,6 +466,88 @@ class CTRexStatelessClient(object):
return False
+ ######################### Console (high level) API #########################
+
+ # reset
+ # acquire, stop, remove streams and clear stats
+ #
+ #
+ def cmd_reset (self, annotate_func):
+
+ ports = self.get_port_ids()
+
+ # sync with the server
+ rc, log = self._init_sync()
+ annotate_func("Syncing with the server:", rc, log)
+ if not rc:
+ return False
+
+
+ # force acquire all ports
+ rc, log = self.acquire(ports, force = True)
+ annotate_func("Force acquiring all ports:", rc, log)
+ if not rc:
+ return False
+
+ # force stop
+ rc, log = self.stop_traffic(ports)
+ annotate_func("Stop traffic on all ports:", rc, log)
+ if not rc:
+ return False
+
+ # remove all streams
+ rc, log = self.remove_all_streams(ports)
+ annotate_func("Removing all streams from all ports:", rc, log)
+ if not rc:
+ return False
+
+ # TODO: clear stats
+ return True
+
+
+ # stop cmd
+ def cmd_stop (self, ports, annotate_func):
+
+ # find the relveant ports
+ active_ports = set(self.get_active_ports()).intersection(ports)
+ if not active_ports:
+ annotate_func("No active traffic on porivded ports")
+ return True
+
+ rc, log = self.stop_traffic(active_ports)
+ annotate_func("Stopping traffic on ports {0}:".format([port for port in active_ports]), rc, log)
+ if not rc:
+ return False
+
+ return True
+
+ # start cmd
+ def cmd_start (self, ports, stream_list, mult, force, annotate_func):
+
+ if force:
+ rc = self.cmd_stop(ports, annotate_func)
+ if not rc:
+ return False
+
+ rc, log = self.remove_all_streams(ports)
+ annotate_func("Removing all streams from ports {0}:".format([port for port in ports]), rc, log,
+ "Please either retry with --force or stop traffic")
+ if not rc:
+ return False
+
+ rc, log = self.add_stream_pack(stream_list.compiled, port_id= ports)
+ annotate_func("Attaching streams to port {0}:".format([port for port in ports]), rc, log)
+ if not rc:
+ return False
+
+ # finally, start the traffic
+ rc, log = self.start_traffic(mult, ports)
+ annotate_func("Starting traffic on ports {0}:".format([port for port in ports]), rc, log)
+ if not rc:
+ return False
+
+ return True
+
# ----- handler internal methods ----- #
def _handle_general_response(self, request, response, msg, success_test=None):
port_id = request.params.get("port_id")
@@ -525,7 +602,8 @@ class CTRexStatelessClient(object):
def _handle_stop_traffic_response(self, request, response, success_test):
port_id = request.params.get("port_id")
if success_test(response):
- self._active_ports.remove(port_id)
+ if port_id in self._active_ports:
+ self._active_ports.remove(port_id)
return RpcResponseStatus(True, port_id, "Traffic stopped")
else:
return RpcResponseStatus(False, port_id, response.data)
diff --git a/scripts/automation/trex_control_plane/console/old_console.py b/scripts/automation/trex_control_plane/console/old_console.py
new file mode 100644
index 00000000..93c7e3f4
--- /dev/null
+++ b/scripts/automation/trex_control_plane/console/old_console.py
@@ -0,0 +1,946 @@
+
+# main console object
+class TRexConsole1(cmd.Cmd):
+ """Trex Console"""
+
+ def __init__(self, stateless_client, verbose):
+ cmd.Cmd.__init__(self)
+
+ self.stateless_client = stateless_client
+
+ self.do_connect("")
+
+ self.intro = "\n-=TRex Console v{ver}=-\n".format(ver=__version__)
+ self.intro += "\nType 'help' or '?' for supported actions\n"
+
+ self.verbose = False
+ self._silent = True
+
+ self.postcmd(False, "")
+
+ self.user_streams = {}
+ self.streams_db = CStreamsDB()
+
+
+ # a cool hack - i stole this function and added space
+ def completenames(self, text, *ignored):
+ dotext = 'do_'+text
+ return [a[3:]+' ' for a in self.get_names() if a.startswith(dotext)]
+
+
+ # set verbose on / off
+ def do_verbose(self, line):
+ '''Shows or set verbose mode\n'''
+ if line == "":
+ print "\nverbose is " + ("on\n" if self.verbose else "off\n")
+
+ elif line == "on":
+ self.verbose = True
+ self.stateless_client.set_verbose(True)
+ print green("\nverbose set to on\n")
+
+ elif line == "off":
+ self.verbose = False
+ self.stateless_client.set_verbose(False)
+ print green("\nverbose set to off\n")
+
+ else:
+ print magenta("\nplease specify 'on' or 'off'\n")
+
+ # query the server for registered commands
+ def do_query_server(self, line):
+ '''query the RPC server for supported remote commands\n'''
+
+ res_ok, msg = self.stateless_client.get_supported_cmds()
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ print "\nRPC server supports the following commands:\n"
+ for func in msg:
+ if func:
+ print func
+ print ''
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ return
+
+ def do_ping(self, line):
+ '''Pings the RPC server\n'''
+
+ print "\n-> Pinging RPC server"
+
+ res_ok, msg = self.stateless_client.ping()
+ if res_ok:
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ else:
+ print "\n*** " + msg + "\n"
+ return
+
+ def do_force_acquire(self, line):
+ '''Acquires ports by force\n'''
+
+ self.do_acquire(line, True)
+
+ def complete_force_acquire(self, text, line, begidx, endidx):
+ return self.port_auto_complete(text, line, begidx, endidx, acquired=False)
+
+ def extract_port_ids_from_line(self, line):
+ return {int(x) for x in line.split()}
+
+ def extract_port_ids_from_list(self, port_list):
+ return {int(x) for x in port_list}
+
+ def parse_ports_from_line (self, line):
+ port_list = set()
+ if line:
+ for port_id in line.split(' '):
+ if (not port_id.isdigit()) or (int(port_id) < 0) or (int(port_id) >= self.stateless_client.get_port_count()):
+ print "Please provide a list of ports separated by spaces between 0 and {0}".format(self.stateless_client.get_port_count() - 1)
+ return None
+
+ port_list.add(int(port_id))
+
+ port_list = list(port_list)
+
+ else:
+ port_list = [i for i in xrange(0, self.stateless_client.get_port_count())]
+
+ return port_list
+
+
+ def do_acquire(self, line, force=False):
+ '''Acquire ports\n'''
+
+ # make sure that the user wants to acquire all
+ args = line.split()
+ if len(args) < 1:
+ print magenta("Please provide a list of ports separated by spaces, or specify 'all' to acquire all available ports")
+ return
+
+ if args[0] == "all":
+ ask = ConfirmMenu('Are you sure you want to acquire all ports ? ')
+ rc = ask.show()
+ if rc == False:
+ print yellow("[ABORTED]\n")
+ return
+ else:
+ port_list = self.stateless_client.get_port_ids()
+ else:
+ port_list = self.extract_port_ids_from_line(line)
+
+ # rc, resp_list = self.stateless_client.take_ownership(port_list, force)
+ try:
+ res_ok, log = self.stateless_client.acquire(port_list, force)
+ self.prompt_response(log)
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ except ValueError as e:
+ print magenta(str(e))
+ print format_text("[FAILED]\n", 'red', 'bold')
+
+
+ def port_auto_complete(self, text, line, begidx, endidx, acquired=True, active=False):
+ if acquired:
+ if not active:
+ ret_list = [x
+ for x in map(str, self.stateless_client.get_acquired_ports())
+ if x.startswith(text)]
+ else:
+ ret_list = [x
+ for x in map(str, self.stateless_client.get_active_ports())
+ if x.startswith(text)]
+ else:
+ ret_list = [x
+ for x in map(str, self.stateless_client.get_port_ids())
+ if x.startswith(text)]
+ ret_list.append("all")
+ return ret_list
+
+
+ def complete_acquire(self, text, line, begidx, endidx):
+ return self.port_auto_complete(text, line, begidx, endidx, acquired=False)
+
+ def do_release (self, line):
+ '''Release ports\n'''
+
+ # if line:
+ # port_list = self.parse_ports_from_line(line)
+ # else:
+ # port_list = self.stateless_client.get_owned_ports()
+ args = line.split()
+ if len(args) < 1:
+ print "Please provide a list of ports separated by spaces, or specify 'all' to acquire all available ports"
+ if args[0] == "all":
+ ask = ConfirmMenu('Are you sure you want to release all acquired ports? ')
+ rc = ask.show()
+ if rc == False:
+ print yellow("[ABORTED]\n")
+ return
+ else:
+ port_list = self.stateless_client.get_acquired_ports()
+ else:
+ port_list = self.extract_port_ids_from_line(line)
+
+ try:
+ res_ok, log = self.stateless_client.release(port_list)
+ self.prompt_response(log)
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ except ValueError as e:
+ print magenta(str(e))
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+
+ def complete_release(self, text, line, begidx, endidx):
+ return self.port_auto_complete(text, line, begidx, endidx)
+
+ def do_connect (self, line):
+ '''Connects to the server\n'''
+
+ if line == "":
+ res_ok, msg = self.stateless_client.connect()
+ else:
+ sp = line.split()
+ if (len(sp) != 2):
+ print "\n[usage] connect [server] [port] or without parameters\n"
+ return
+
+ res_ok, msg = self.stateless_client.connect(sp[0], sp[1])
+
+ if res_ok:
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ else:
+ print "\n*** " + msg + "\n"
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+
+ self.supported_rpc = self.stateless_client.get_supported_cmds().data
+
+ # def do_rpc (self, line):
+ # '''Launches a RPC on the server\n'''
+ #
+ # if line == "":
+ # print "\nUsage: [method name] [param dict as string]\n"
+ # print "Example: rpc test_add {'x': 12, 'y': 17}\n"
+ # return
+ #
+ # sp = line.split(' ', 1)
+ # method = sp[0]
+ #
+ # params = None
+ # bad_parse = False
+ # if len(sp) > 1:
+ #
+ # try:
+ # params = ast.literal_eval(sp[1])
+ # if not isinstance(params, dict):
+ # bad_parse = True
+ #
+ # except ValueError as e1:
+ # bad_parse = True
+ # except SyntaxError as e2:
+ # bad_parse = True
+ #
+ # if bad_parse:
+ # print "\nValue should be a valid dict: '{0}'".format(sp[1])
+ # print "\nUsage: [method name] [param dict as string]\n"
+ # print "Example: rpc test_add {'x': 12, 'y': 17}\n"
+ # return
+ #
+ # res_ok, msg = self.stateless_client.transmit(method, params)
+ # if res_ok:
+ # print "\nServer Response:\n\n" + pretty_json(json.dumps(msg)) + "\n"
+ # else:
+ # print "\n*** " + msg + "\n"
+ # #print "Please try 'reconnect' to reconnect to server"
+ #
+ #
+ # def complete_rpc (self, text, line, begidx, endidx):
+ # return [x
+ # for x in self.supported_rpc
+ # if x.startswith(text)]
+
+ def do_status (self, line):
+ '''Shows a graphical console\n'''
+
+ if not self.stateless_client.is_connected():
+ print "Not connected to server\n"
+ return
+
+ self.do_verbose('off')
+ trex_status.show_trex_status(self.stateless_client)
+
+ def do_quit(self, line):
+ '''Exit the client\n'''
+ return True
+
+ def do_disconnect (self, line):
+ '''Disconnect from the server\n'''
+ if not self.stateless_client.is_connected():
+ print "Not connected to server\n"
+ return
+
+ res_ok, msg = self.stateless_client.disconnect()
+ if res_ok:
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ else:
+ print msg + "\n"
+
+ def do_whoami (self, line):
+ '''Prints console user name\n'''
+ print "\n" + self.stateless_client.user + "\n"
+
+ def postcmd(self, stop, line):
+ if self.stateless_client.is_connected():
+ self.prompt = "TRex > "
+ else:
+ self.supported_rpc = None
+ self.prompt = "TRex (offline) > "
+
+ return stop
+
+ def default(self, line):
+ print "'{0}' is an unrecognized command. type 'help' or '?' for a list\n".format(line)
+
+ # def do_help (self, line):
+ # '''Shows This Help Screen\n'''
+ # if line:
+ # try:
+ # func = getattr(self, 'help_' + line)
+ # except AttributeError:
+ # try:
+ # doc = getattr(self, 'do_' + line).__doc__
+ # if doc:
+ # self.stdout.write("%s\n"%str(doc))
+ # return
+ # except AttributeError:
+ # pass
+ # self.stdout.write("%s\n"%str(self.nohelp % (line,)))
+ # return
+ # func()
+ # return
+ #
+ # print "\nSupported Console Commands:"
+ # print "----------------------------\n"
+ #
+ # cmds = [x[3:] for x in self.get_names() if x.startswith("do_")]
+ # for cmd in cmds:
+ # if cmd == "EOF":
+ # continue
+ #
+ # try:
+ # doc = getattr(self, 'do_' + cmd).__doc__
+ # if doc:
+ # help = str(doc)
+ # else:
+ # help = "*** Undocumented Function ***\n"
+ # except AttributeError:
+ # help = "*** Undocumented Function ***\n"
+ #
+ # print "{:<30} {:<30}".format(cmd + " - ", help)
+
+ def do_stream_db_add(self, line):
+ '''Loads a YAML stream list serialization into user console \n'''
+ args = line.split()
+ if len(args) >= 2:
+ name = args[0]
+ yaml_path = args[1]
+ try:
+ multiplier = args[2]
+ except IndexError:
+ multiplier = 1
+ stream_list = CStreamList()
+ loaded_obj = stream_list.load_yaml(yaml_path, multiplier)
+ # print self.stateless_client.pretty_json(json.dumps(loaded_obj))
+ try:
+ compiled_streams = stream_list.compile_streams()
+ res_ok = self.streams_db.load_streams(name, LoadedStreamList(loaded_obj,
+ [StreamPack(v.stream_id, v.stream.dump())
+ for k, v in compiled_streams.items()]))
+ if res_ok:
+ print green("Stream pack '{0}' loaded and added successfully\n".format(name))
+ else:
+ print magenta("Picked name already exist. Please pick another name.\n")
+ except Exception as e:
+ print "adding new stream failed due to the following error:\n", str(e)
+ print format_text("[FAILED]\n", 'red', 'bold')
+
+ return
+ else:
+ print magenta("please provide load name and YAML path, separated by space.\n"
+ "Optionally, you may provide a third argument to specify multiplier.\n")
+
+ @staticmethod
+ def tree_autocomplete(text):
+ dir = os.path.dirname(text)
+ if dir:
+ path = dir
+ else:
+ path = "."
+ start_string = os.path.basename(text)
+ return [x
+ for x in os.listdir(path)
+ if x.startswith(start_string)]
+
+
+ def complete_stream_db_add(self, text, line, begidx, endidx):
+ arg_num = len(line.split()) - 1
+ if arg_num == 2:
+ return TRexConsole.tree_autocomplete(line.split()[-1])
+ else:
+ return [text]
+
+ def do_stream_db_show(self, line):
+ '''Shows the loaded stream list named [name] \n'''
+ args = line.split()
+ if args:
+ list_name = args[0]
+ try:
+ stream = self.streams_db.get_stream_pack(list_name)#user_streams[list_name]
+ if len(args) >= 2 and args[1] == "full":
+ print pretty_json(json.dumps(stream.compiled))
+ else:
+ print pretty_json(json.dumps(stream.loaded))
+ except KeyError as e:
+ print "Unknown stream list name provided"
+ else:
+ print "Available stream packs:\n{0}".format(', '.join(sorted(self.streams_db.get_loaded_streams_names())))
+
+ def complete_stream_db_show(self, text, line, begidx, endidx):
+ return [x
+ for x in self.streams_db.get_loaded_streams_names()
+ if x.startswith(text)]
+
+ def do_stream_db_remove(self, line):
+ '''Removes a single loaded stream packs from loaded stream pack repository\n'''
+ args = line.split()
+ if args:
+ removed_streams = self.streams_db.remove_stream_packs(*args)
+ if removed_streams:
+ print green("The following stream packs were removed:")
+ print bold(", ".join(sorted(removed_streams)))
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ else:
+ print red("No streams were removed. Make sure to provide valid stream pack names.")
+ else:
+ print magenta("Please provide stream pack name(s), separated with spaces.")
+
+ def do_stream_db_clear(self, line):
+ '''Clears all loaded stream packs from loaded stream pack repository\n'''
+ self.streams_db.clear()
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+
+
+ def complete_stream_db_remove(self, text, line, begidx, endidx):
+ return [x
+ for x in self.streams_db.get_loaded_streams_names()
+ if x.startswith(text)]
+
+
+ def do_attach(self, line):
+ '''Assign loaded stream pack into specified ports on TRex\n'''
+ args = line.split()
+ if len(args) >= 2:
+ stream_pack_name = args[0]
+ stream_list = self.streams_db.get_stream_pack(stream_pack_name) #user_streams[args[0]]
+ if not stream_list:
+ print "Provided stream list name '{0}' doesn't exists.".format(stream_pack_name)
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ if args[1] == "all":
+ ask = ConfirmMenu('Are you sure you want to release all acquired ports? ')
+ rc = ask.show()
+ if rc == False:
+ print yellow("[ABORTED]\n")
+ return
+ else:
+ port_list = self.stateless_client.get_acquired_ports()
+ else:
+ port_list = self.extract_port_ids_from_line(' '.join(args[1:]))
+ owned = set(self.stateless_client.get_acquired_ports())
+ try:
+ if set(port_list).issubset(owned):
+ res_ok, log = self.stateless_client.add_stream_pack(stream_list.compiled, port_id=port_list)
+ # res_ok, msg = self.stateless_client.add_stream(port_list, stream_list.compiled)
+ self.prompt_response(log)
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ return
+ else:
+ print "Not all desired ports are acquired.\n" \
+ "Acquired ports are: {acq}\n" \
+ "Requested ports: {req}\n" \
+ "Missing ports: {miss}".format(acq=list(owned),
+ req=port_list,
+ miss=list(set(port_list).difference(owned)))
+ print format_text("[FAILED]\n", 'red', 'bold')
+ except ValueError as e:
+ print magenta(str(e))
+ print format_text("[FAILED]\n", 'red', 'bold')
+ else:
+ print magenta("Please provide list name and ports to attach to, "
+ "or specify 'all' to attach all owned ports.\n")
+
+ def complete_attach(self, text, line, begidx, endidx):
+ arg_num = len(line.split()) - 1
+ if arg_num == 1:
+ # return optional streams packs
+ if line.endswith(" "):
+ return self.port_auto_complete(text, line, begidx, endidx)
+ return [x
+ for x in self.streams_db.get_loaded_streams_names()
+ if x.startswith(text)]
+ elif arg_num >= 2:
+ # return optional ports to attach to
+ return self.port_auto_complete(text, line, begidx, endidx)
+ else:
+ return [text]
+
+ def prompt_response(self, response_obj):
+ resp_list = response_obj if isinstance(response_obj, list) else [response_obj]
+ def format_return_status(return_status):
+ if return_status:
+ return green("OK")
+ else:
+ return red("FAIL")
+
+ for response in resp_list:
+ response_str = "{id:^3} - {msg} ({stat})".format(id=response.id,
+ msg=response.msg,
+ stat=format_return_status(response.success))
+ print response_str
+ return
+
+ def do_remove_all_streams(self, line):
+ '''Acquire ports\n'''
+
+ # make sure that the user wants to acquire all
+ args = line.split()
+ if len(args) < 1:
+ print magenta("Please provide a list of ports separated by spaces, "
+ "or specify 'all' to remove from all acquired ports")
+ return
+ if args[0] == "all":
+ ask = ConfirmMenu('Are you sure you want to remove all stream packs from all acquired ports? ')
+ rc = ask.show()
+ if rc == False:
+ print yellow("[ABORTED]\n")
+ return
+ else:
+ port_list = self.stateless_client.get_acquired_ports()
+ else:
+ port_list = self.extract_port_ids_from_line(line)
+
+ # rc, resp_list = self.stateless_client.take_ownership(port_list, force)
+ try:
+ res_ok, log = self.stateless_client.remove_all_streams(port_list)
+ self.prompt_response(log)
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ except ValueError as e:
+ print magenta(str(e))
+ print format_text("[FAILED]\n", 'red', 'bold')
+
+ def complete_remove_all_streams(self, text, line, begidx, endidx):
+ return self.port_auto_complete(text, line, begidx, endidx)
+
+ 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("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:
+ # avoid further processing in this command
+ return
+ # print opts
+ port_list = self.extract_port_list(opts)
+ # print port_list
+ if opts.force:
+ # stop all active ports, if any
+ res_ok = self.stop_traffic(set(self.stateless_client.get_active_ports()).intersection(port_list))
+ if not res_ok:
+ print yellow("[ABORTED]\n")
+ return
+ # remove all traffic from ports
+ res_ok = self.remove_all_streams(port_list)
+ if not res_ok:
+ print yellow("[ABORTED]\n")
+ return
+ # decide which traffic to use
+ stream_pack_name = None
+ if opts.db:
+ # use pre-loaded traffic
+ print format_text('{:<30}'.format("Load stream pack (from DB):"), 'bold'),
+ if opts.db not in self.streams_db.get_loaded_streams_names():
+ print format_text("[FAILED]\n", 'red', 'bold')
+ print yellow("[ABORTED]\n")
+ return
+ else:
+ stream_pack_name = opts.db
+ else:
+ # try loading a YAML file
+ print format_text('{:<30}'.format("Load stream pack (from file):"), 'bold'),
+ stream_list = CStreamList()
+ loaded_obj = stream_list.load_yaml(opts.file[0])
+ # print self.stateless_client.pretty_json(json.dumps(loaded_obj))
+ try:
+ compiled_streams = stream_list.compile_streams()
+ res_ok = self.streams_db.load_streams(opts.file[1],
+ LoadedStreamList(loaded_obj,
+ [StreamPack(v.stream_id, v.stream.dump())
+ for k, v in compiled_streams.items()]))
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ print yellow("[ABORTED]\n")
+ return
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ stream_pack_name = opts.file[1]
+ except Exception as e:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ print yellow("[ABORTED]\n")
+ res_ok = self.attach_to_port(stream_pack_name, port_list)
+ if not res_ok:
+ print yellow("[ABORTED]\n")
+ return
+ # finally, start the traffic
+ res_ok = self.start_traffic(opts.mult, port_list)
+ if not res_ok:
+ print yellow("[ABORTED]\n")
+ return
+ return
+
+ def help_start(self):
+ self.do_start("-h")
+
+ def do_stop(self, line):
+ '''Stop active traffic in specified ports on TRex\n'''
+ parser = parsing_opts.gen_parser("stop", self.do_stop.__doc__,
+ parsing_opts.PORT_LIST_WITH_ALL)
+ opts = parser.parse_args(line.split())
+ if opts is None:
+ # avoid further processing in this command
+ return
+ port_list = self.extract_port_list(opts)
+ res_ok = self.stop_traffic(port_list)
+ return
+
+
+ def help_stop(self):
+ self.do_stop("-h")
+
+
+ def do_debug(self, line):
+ '''Enter DEBUG mode of the console to invoke smaller building blocks with server'''
+ i = DebugTRexConsole(self)
+ i.prompt = self.prompt[:-3] + ':' + blue('debug') + ' > '
+ i.cmdloop()
+
+ # aliasing
+ do_exit = do_EOF = do_q = do_quit
+
+ # ----- utility methods ----- #
+
+ def start_traffic(self, multiplier, port_list):#, silent=True):
+ print format_text('{:<30}'.format("Start traffic:"), 'bold'),
+ try:
+ res_ok, log = self.stateless_client.start_traffic(multiplier, port_id=port_list)
+ if not self._silent:
+ print ''
+ self.prompt_response(log)
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return False
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ return True
+ except ValueError as e:
+ print ''
+ print magenta(str(e))
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return False
+
+ def attach_to_port(self, stream_pack_name, port_list):
+ print format_text('{:<30}'.format("Attaching traffic to ports:"), 'bold'),
+ stream_list = self.streams_db.get_stream_pack(stream_pack_name) #user_streams[args[0]]
+ if not stream_list:
+ print "Provided stream list name '{0}' doesn't exists.".format(stream_pack_name)
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ try:
+ res_ok, log = self.stateless_client.add_stream_pack(stream_list.compiled, port_id=port_list)
+ if not self._silent:
+ print ''
+ self.prompt_response(log)
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return False
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ return True
+ except ValueError as e:
+ print ''
+ print magenta(str(e))
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return False
+
+ def stop_traffic(self, port_list):
+ print format_text('{:<30}'.format("Stop traffic:"), 'bold'),
+ try:
+ res_ok, log = self.stateless_client.stop_traffic(port_id=port_list)
+ if not self._silent:
+ print ''
+ self.prompt_response(log)
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ return True
+ except ValueError as e:
+ print ''
+ print magenta(str(e))
+ print format_text("[FAILED]\n", 'red', 'bold')
+
+ def remove_all_streams(self, port_list):
+ '''Remove all streams from given port_list'''
+ print format_text('{:<30}'.format("Remove all streams:"), 'bold'),
+ try:
+ res_ok, log = self.stateless_client.remove_all_streams(port_id=port_list)
+ if not self._silent:
+ print ''
+ self.prompt_response(log)
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ return True
+ except ValueError as e:
+ print ''
+ print magenta(str(e))
+ print format_text("[FAILED]\n", 'red', 'bold')
+
+
+
+
+
+ def extract_port_list(self, opts):
+ if opts.all_ports or "all" in opts.ports:
+ # handling all ports
+ port_list = self.stateless_client.get_acquired_ports()
+ else:
+ port_list = self.extract_port_ids_from_list(opts.ports)
+ return port_list
+
+ def decode_multiplier(self, opts_mult):
+ pass
+
+
+class DebugTRexConsole(cmd.Cmd):
+
+ def __init__(self, trex_main_console):
+ cmd.Cmd.__init__(self)
+ self.trex_console = trex_main_console
+ self.stateless_client = self.trex_console.stateless_client
+ self.streams_db = self.trex_console.streams_db
+ self.register_main_console_methods()
+ self.do_silent("on")
+ pass
+
+ # ----- super methods overriding ----- #
+ def completenames(self, text, *ignored):
+ dotext = 'do_'+text
+ return [a[3:]+' ' for a in self.get_names() if a.startswith(dotext)]
+
+ def get_names(self):
+ result = cmd.Cmd.get_names(self)
+ result += self.trex_console.get_names()
+ return list(set(result))
+
+ def register_main_console_methods(self):
+ main_names = set(self.trex_console.get_names()).difference(set(dir(self.__class__)))
+ for name in main_names:
+ for prefix in 'do_', 'help_', 'complete_':
+ if name.startswith(prefix):
+ self.__dict__[name] = getattr(self.trex_console, name)
+
+ # if (name[:3] == 'do_') or (name[:5] == 'help_') or (name[:9] == 'complete_'):
+ # chosen.append(name)
+ # self.__dict__[name] = getattr(self.trex_console, name)
+ # # setattr(self, name, classmethod(getattr(self.trex_console, name)))
+
+ # print chosen
+ # self.get_names()
+
+ # return result
+
+
+ # ----- DEBUGGING methods ----- #
+ # set silent on / off
+ def do_silent(self, line):
+ '''Shows or set silent mode\n'''
+ if line == "":
+ print "\nsilent mode is " + ("on\n" if self.trex_console._silent else "off\n")
+
+ elif line == "on":
+ self.verbose = True
+ self.stateless_client.set_verbose(True)
+ print green("\nsilent set to on\n")
+
+ elif line == "off":
+ self.verbose = False
+ self.stateless_client.set_verbose(False)
+ print green("\nsilent set to off\n")
+
+ else:
+ print magenta("\nplease specify 'on' or 'off'\n")
+
+ def do_quit(self, line):
+ '''Exit the debug client back to main console\n'''
+ self.do_silent("off")
+ return True
+
+ def do_start_traffic(self, line):
+ '''Start pre-submitted traffic in specified ports on TRex\n'''
+ # make sure that the user wants to acquire all
+ parser = parsing_opts.gen_parser("start_traffic", self.do_start_traffic.__doc__,
+ parsing_opts.PORT_LIST_WITH_ALL, parsing_opts.MULTIPLIER)
+ opts = parser.parse_args(line.split())
+ # print opts
+ # return
+ if opts is None:
+ # avoid further processing in this command
+ return
+ try:
+ port_list = self.trex_console.extract_port_list(opts)
+ return self.trex_console.start_traffic(opts.mult, port_list)
+ except Exception as e:
+ print e
+ return
+
+ def do_stop_traffic(self, line):
+ '''Stop active traffic in specified ports on TRex\n'''
+ parser = parsing_opts.gen_parser("stop_traffic", self.do_stop_traffic.__doc__,
+ parsing_opts.PORT_LIST_WITH_ALL)
+ opts = parser.parse_args(line.split())
+ # print opts
+ # return
+ if opts is None:
+ # avoid further processing in this command
+ return
+ try:
+ port_list = self.trex_console.extract_port_list(opts)
+ return self.trex_console.stop_traffic(port_list)
+ except Exception as e:
+ print e
+ return
+
+
+ def complete_stop_traffic(self, text, line, begidx, endidx):
+ return self.port_auto_complete(text, line, begidx, endidx, active=True)
+
+ # return
+ # # return
+ # # if not opts.port_list:
+ # # print magenta("Please provide a list of ports separated by spaces, "
+ # # "or specify 'all' to start traffic on all acquired ports")
+ # # return
+ #
+
+
+ return
+ args = line.split()
+ if len(args) < 1:
+ print magenta("Please provide a list of ports separated by spaces, "
+ "or specify 'all' to start traffic on all acquired ports")
+ return
+ if args[0] == "all":
+ ask = ConfirmMenu('Are you sure you want to start traffic at all acquired ports? ')
+ rc = ask.show()
+ if rc == False:
+ print yellow("[ABORTED]\n")
+ return
+ else:
+ port_list = self.stateless_client.get_acquired_ports()
+ else:
+ port_list = self.extract_port_ids_from_line(line)
+
+ try:
+ res_ok, log = self.stateless_client.start_traffic(1.0, port_id=port_list)
+ self.prompt_response(log)
+ if not res_ok:
+ print format_text("[FAILED]\n", 'red', 'bold')
+ return
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ except ValueError as e:
+ print magenta(str(e))
+ print format_text("[FAILED]\n", 'red', 'bold')
+
+ def complete_start_traffic(self, text, line, begidx, endidx):
+ # return self.port_auto_complete(text, line, begidx, endidx)
+ return [text]
+
+ def help_start_traffic(self):
+ self.do_start_traffic("-h")
+
+ def help_stop_traffic(self):
+ self.do_stop_traffic("-h")
+
+ # def do_help(self):
+
+ def do_rpc (self, line):
+ '''Launches a RPC on the server\n'''
+
+ if line == "":
+ print "\nUsage: [method name] [param dict as string]\n"
+ print "Example: rpc test_add {'x': 12, 'y': 17}\n"
+ return
+
+ sp = line.split(' ', 1)
+ method = sp[0]
+
+ params = None
+ bad_parse = False
+ if len(sp) > 1:
+
+ try:
+ params = ast.literal_eval(sp[1])
+ if not isinstance(params, dict):
+ bad_parse = True
+
+ except ValueError as e1:
+ bad_parse = True
+ except SyntaxError as e2:
+ bad_parse = True
+
+ if bad_parse:
+ print "\nValue should be a valid dict: '{0}'".format(sp[1])
+ print "\nUsage: [method name] [param dict as string]\n"
+ print "Example: rpc test_add {'x': 12, 'y': 17}\n"
+ return
+
+ res_ok, msg = self.stateless_client.transmit(method, params)
+ if res_ok:
+ print "\nServer Response:\n\n" + pretty_json(json.dumps(msg)) + "\n"
+ else:
+ print "\n*** " + msg + "\n"
+ #print "Please try 'reconnect' to reconnect to server"
+
+
+ def complete_rpc (self, text, line, begidx, endidx):
+ return [x
+ for x in self.trex_console.supported_rpc
+ if x.startswith(text)]
+
+ # aliasing
+ do_exit = do_EOF = do_q = do_quit
+
+#
diff --git a/scripts/automation/trex_control_plane/console/parsing_opts.py b/scripts/automation/trex_control_plane/console/parsing_opts.py
index e701b7db..f983d837 100755
--- a/scripts/automation/trex_control_plane/console/parsing_opts.py
+++ b/scripts/automation/trex_control_plane/console/parsing_opts.py
@@ -2,6 +2,7 @@ import argparse
from collections import namedtuple
import sys
import re
+import os
ArgumentPack = namedtuple('ArgumentPack', ['name_or_flags', 'options'])
ArgumentGroup = namedtuple('ArgumentGroup', ['type', 'args', 'options'])
@@ -14,9 +15,10 @@ ALL_PORTS = 3
PORT_LIST_WITH_ALL = 4
FILE_PATH = 5
FILE_FROM_DB = 6
-STREAM_FROM_PATH_OR_FILE = 7
-DURATION = 8
-FORCE = 9
+SERVER_IP = 7
+STREAM_FROM_PATH_OR_FILE = 8
+DURATION = 9
+FORCE = 10
# list of ArgumentGroup types
MUTEX = 1
@@ -61,20 +63,27 @@ def match_multiplier(val):
+def is_valid_file(filename):
+ if not os.path.isfile(filename):
+ raise argparse.ArgumentTypeError("The file '%s' does not exist" % filename)
+
+ return filename
+
OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
{'help': "Set multiplier for stream",
'dest': "mult",
'default': 1.0,
'type': match_multiplier}),
+
PORT_LIST: ArgumentPack(['--port'],
{"nargs": '+',
- # "action": "store_"
'dest':'ports',
'metavar': 'PORTS',
- # 'type': int,
+ 'type': int,
'help': "A list of ports on which to apply the command",
'default': []}),
+
ALL_PORTS: ArgumentPack(['-a'],
{"action": "store_true",
"dest": "all_ports",
@@ -88,15 +97,22 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
{"action": "store_true",
'default': False,
'help': "Set if you want to stop active ports before applying new TRex run on them."}),
+
FILE_PATH: ArgumentPack(['-f'],
- {'metavar': ('FILE', 'DB_NAME'),
+ {'metavar': 'FILE',
'dest': 'file',
- 'nargs': 2,
- 'help': "File path to YAML file that describes a stream pack. "
- "Second argument is a name to store the loaded yaml file into db."}),
+ 'nargs': 1,
+ 'type': is_valid_file,
+ 'help': "File path to YAML file that describes a stream pack. "}),
+
FILE_FROM_DB: ArgumentPack(['--db'],
{'metavar': 'LOADED_STREAM_PACK',
'help': "A stream pack which already loaded into console cache."}),
+
+ SERVER_IP: ArgumentPack(['--server'],
+ {'metavar': 'SERVER',
+ 'help': "server IP"}),
+
# advanced options
PORT_LIST_WITH_ALL: ArgumentGroup(MUTEX, [PORT_LIST,
ALL_PORTS],
@@ -109,33 +125,44 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
class CCmdArgParser(argparse.ArgumentParser):
- def __init__(self, *args, **kwargs):
+ def __init__(self, stateless_client, *args, **kwargs):
super(CCmdArgParser, self).__init__(*args, **kwargs)
-
- # def exit(self, status=0, message=None):
- # try:
- # return super(CCmdArgParser, self).exit(status, message) # this will trigger system exit!
- # except SystemExit:
- # print "Caught system exit!!"
- # return -1
- # # return
+ self.stateless_client = stateless_client
def parse_args(self, args=None, namespace=None):
try:
- return super(CCmdArgParser, self).parse_args(args, namespace)
+ opts = super(CCmdArgParser, self).parse_args(args, namespace)
+ if opts is None:
+ return None
+
+ if opts.all_ports:
+ opts.ports = self.stateless_client.get_port_ids()
+
+ for port in opts.ports:
+ if not self.stateless_client._is_ports_valid(port):
+ self.error("port id {0} is not a valid\n".format(port))
+
+ return opts
+
except SystemExit:
# recover from system exit scenarios, such as "help", or bad arguments.
return None
+def get_flags (opt):
+ return OPTIONS_DB[opt].name_or_flags
-def gen_parser(op_name, description, *args):
- parser = CCmdArgParser(prog=op_name, conflict_handler='resolve',
- # add_help=False,
+def gen_parser(stateless_client, op_name, description, *args):
+ parser = CCmdArgParser(stateless_client, prog=op_name, conflict_handler='resolve',
description=description)
for param in args:
try:
- argument = OPTIONS_DB[param]
+
+ if isinstance(param, int):
+ argument = OPTIONS_DB[param]
+ else:
+ argument = param
+
if isinstance(argument, ArgumentGroup):
if argument.type == MUTEX:
# handle as mutually exclusive group
@@ -157,5 +184,6 @@ def gen_parser(op_name, description, *args):
raise KeyError("The attribute '{0}' is missing as a field of the {1} option.\n".format(cause, param))
return parser
+
if __name__ == "__main__":
pass \ No newline at end of file
diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py
index a61881a1..06ae762a 100755
--- a/scripts/automation/trex_control_plane/console/trex_console.py
+++ b/scripts/automation/trex_control_plane/console/trex_console.py
@@ -30,6 +30,7 @@ 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
@@ -40,43 +41,32 @@ __version__ = "1.0"
LoadedStreamList = namedtuple('LoadedStreamList', ['loaded', 'compiled'])
-
-def readch(choices=[]):
-
- fd = sys.stdin.fileno()
- old_settings = termios.tcgetattr(fd)
- try:
- tty.setraw(sys.stdin.fileno())
- while True:
- ch = sys.stdin.read(1)
- if (ord(ch) == 3) or (ord(ch) == 4):
- return None
- if ch in choices:
- return ch
- finally:
- termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
-
- return None
-
-class ConfirmMenu(object):
- def __init__ (self, caption):
- self.caption = "{cap} [confirm] : ".format(cap=caption)
-
- def show(self):
- sys.stdout.write(self.caption)
- input = user_input()
- if input:
- return False
- else:
- # user hit Enter
- return True
-
-
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
@@ -98,84 +88,79 @@ class CStreamsDB(object):
def get_loaded_streams_names(self):
return self.stream_packs.keys()
- def get_stream_pack(self, name):
- return self.stream_packs.get(name)
-
-
-# multi level cmd menu
-class CmdMenu(object):
- def __init__ (self):
- self.menus = []
-
-
- def add_menu (self, caption, options):
- menu = {}
- menu['caption'] = caption
- menu['options'] = options
- self.menus.append(menu)
-
- def show (self):
- cur_level = 0
- print "\n"
-
- selected_path = []
- for menu in self.menus:
- # show all the options
- print "{0}\n".format(menu['caption'])
- for i, option in enumerate(menu['options']):
- print "{0}. {1}".format(i + 1, option)
-
- #print "\nPlease select an option: "
-
- choices = range(0, len(menu['options']))
- choices = [ chr(x + 48) for x in choices]
-
- print ""
- ch = readch(choices)
- print ""
-
- if ch == None:
- return None
-
- selected_path.append(int(ch) - 1)
-
- return selected_path
+ 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)
-class AddStreamMenu(CmdMenu):
- def __init__ (self):
- super(AddStreamMenu, self).__init__()
- self.add_menu('Please select type of stream', ['a', 'b', 'c'])
- self.add_menu('Please select ISG', ['d', 'e', 'f'])
+#
# main console object
class TRexConsole(cmd.Cmd):
"""Trex Console"""
- def __init__(self, stateless_client, verbose):
+ def __init__(self, stateless_client, acquire_all_ports = True, verbose = False):
cmd.Cmd.__init__(self)
self.stateless_client = stateless_client
+ 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.verbose = False
- self._silent = True
-
self.postcmd(False, "")
- self.user_streams = {}
self.streams_db = CStreamsDB()
+ ################### internal section ########################
+
# a cool hack - i stole this function and added space
def completenames(self, text, *ignored):
dotext = 'do_'+text
return [a[3:]+' ' for a in self.get_names() if a.startswith(dotext)]
+
+ def register_main_console_methods(self):
+ main_names = set(self.trex_console.get_names()).difference(set(dir(self.__class__)))
+ for name in main_names:
+ for prefix in 'do_', 'help_', 'complete_':
+ if name.startswith(prefix):
+ self.__dict__[name] = getattr(self.trex_console, name)
+
+ def postcmd(self, stop, line):
+ if self.stateless_client.is_connected():
+ self.prompt = "TRex > "
+ else:
+ self.supported_rpc = None
+ self.prompt = "TRex (offline) > "
+
+ return stop
+
+ def default(self, line):
+ print "'{0}' is an unrecognized command. type 'help' or '?' for a list\n".format(line)
+
+ @staticmethod
+ def tree_autocomplete(text):
+ dir = os.path.dirname(text)
+ if dir:
+ path = dir
+ else:
+ path = "."
+ start_string = os.path.basename(text)
+ return [x
+ for x in os.listdir(path)
+ if x.startswith(start_string)]
+
+ ####################### shell commands #######################
# set verbose on / off
def do_verbose(self, line):
@@ -196,169 +181,11 @@ class TRexConsole(cmd.Cmd):
else:
print magenta("\nplease specify 'on' or 'off'\n")
- # query the server for registered commands
- def do_query_server(self, line):
- '''query the RPC server for supported remote commands\n'''
-
- res_ok, msg = self.stateless_client.get_supported_cmds()
- if not res_ok:
- print format_text("[FAILED]\n", 'red', 'bold')
- return
- print "\nRPC server supports the following commands:\n"
- for func in msg:
- if func:
- print func
- print ''
- print format_text("[SUCCESS]\n", 'green', 'bold')
- return
-
- def do_ping(self, line):
- '''Pings the RPC server\n'''
-
- print "\n-> Pinging RPC server"
-
- res_ok, msg = self.stateless_client.ping()
- if res_ok:
- print format_text("[SUCCESS]\n", 'green', 'bold')
- else:
- print "\n*** " + msg + "\n"
- return
-
- def do_force_acquire(self, line):
- '''Acquires ports by force\n'''
-
- self.do_acquire(line, True)
-
- def complete_force_acquire(self, text, line, begidx, endidx):
- return self.port_auto_complete(text, line, begidx, endidx, acquired=False)
-
- def extract_port_ids_from_line(self, line):
- return {int(x) for x in line.split()}
-
- def extract_port_ids_from_list(self, port_list):
- return {int(x) for x in port_list}
-
- def parse_ports_from_line (self, line):
- port_list = set()
- if line:
- for port_id in line.split(' '):
- if (not port_id.isdigit()) or (int(port_id) < 0) or (int(port_id) >= self.stateless_client.get_port_count()):
- print "Please provide a list of ports separated by spaces between 0 and {0}".format(self.stateless_client.get_port_count() - 1)
- return None
-
- port_list.add(int(port_id))
-
- port_list = list(port_list)
-
- else:
- port_list = [i for i in xrange(0, self.stateless_client.get_port_count())]
-
- return port_list
-
-
- def do_acquire(self, line, force=False):
- '''Acquire ports\n'''
-
- # make sure that the user wants to acquire all
- args = line.split()
- if len(args) < 1:
- print magenta("Please provide a list of ports separated by spaces, or specify 'all' to acquire all available ports")
- return
-
- if args[0] == "all":
- ask = ConfirmMenu('Are you sure you want to acquire all ports ? ')
- rc = ask.show()
- if rc == False:
- print yellow("[ABORTED]\n")
- return
- else:
- port_list = self.stateless_client.get_port_ids()
- else:
- port_list = self.extract_port_ids_from_line(line)
-
- # rc, resp_list = self.stateless_client.take_ownership(port_list, force)
- try:
- res_ok, log = self.stateless_client.acquire(port_list, force)
- self.prompt_response(log)
- if not res_ok:
- print format_text("[FAILED]\n", 'red', 'bold')
- return
- print format_text("[SUCCESS]\n", 'green', 'bold')
- except ValueError as e:
- print magenta(str(e))
- print format_text("[FAILED]\n", 'red', 'bold')
-
-
- def port_auto_complete(self, text, line, begidx, endidx, acquired=True, active=False):
- if acquired:
- if not active:
- ret_list = [x
- for x in map(str, self.stateless_client.get_acquired_ports())
- if x.startswith(text)]
- else:
- ret_list = [x
- for x in map(str, self.stateless_client.get_active_ports())
- if x.startswith(text)]
- else:
- ret_list = [x
- for x in map(str, self.stateless_client.get_port_ids())
- if x.startswith(text)]
- ret_list.append("all")
- return ret_list
-
-
- def complete_acquire(self, text, line, begidx, endidx):
- return self.port_auto_complete(text, line, begidx, endidx, acquired=False)
-
- def do_release (self, line):
- '''Release ports\n'''
-
- # if line:
- # port_list = self.parse_ports_from_line(line)
- # else:
- # port_list = self.stateless_client.get_owned_ports()
- args = line.split()
- if len(args) < 1:
- print "Please provide a list of ports separated by spaces, or specify 'all' to acquire all available ports"
- if args[0] == "all":
- ask = ConfirmMenu('Are you sure you want to release all acquired ports? ')
- rc = ask.show()
- if rc == False:
- print yellow("[ABORTED]\n")
- return
- else:
- port_list = self.stateless_client.get_acquired_ports()
- else:
- port_list = self.extract_port_ids_from_line(line)
-
- try:
- res_ok, log = self.stateless_client.release(port_list)
- self.prompt_response(log)
- if not res_ok:
- print format_text("[FAILED]\n", 'red', 'bold')
- return
- print format_text("[SUCCESS]\n", 'green', 'bold')
- except ValueError as e:
- print magenta(str(e))
- print format_text("[FAILED]\n", 'red', 'bold')
- return
-
- def complete_release(self, text, line, begidx, endidx):
- return self.port_auto_complete(text, line, begidx, endidx)
-
+ ############### connect
def do_connect (self, line):
'''Connects to the server\n'''
- if line == "":
- res_ok, msg = self.stateless_client.connect()
- else:
- sp = line.split()
- if (len(sp) != 2):
- print "\n[usage] connect [server] [port] or without parameters\n"
- return
-
- res_ok, msg = self.stateless_client.connect(sp[0], sp[1])
-
+ res_ok, msg = self.stateless_client.connect()
if res_ok:
print format_text("[SUCCESS]\n", 'green', 'bold')
else:
@@ -368,730 +195,175 @@ class TRexConsole(cmd.Cmd):
self.supported_rpc = self.stateless_client.get_supported_cmds().data
- # def do_rpc (self, line):
- # '''Launches a RPC on the server\n'''
- #
- # if line == "":
- # print "\nUsage: [method name] [param dict as string]\n"
- # print "Example: rpc test_add {'x': 12, 'y': 17}\n"
- # return
- #
- # sp = line.split(' ', 1)
- # method = sp[0]
- #
- # params = None
- # bad_parse = False
- # if len(sp) > 1:
- #
- # try:
- # params = ast.literal_eval(sp[1])
- # if not isinstance(params, dict):
- # bad_parse = True
- #
- # except ValueError as e1:
- # bad_parse = True
- # except SyntaxError as e2:
- # bad_parse = True
- #
- # if bad_parse:
- # print "\nValue should be a valid dict: '{0}'".format(sp[1])
- # print "\nUsage: [method name] [param dict as string]\n"
- # print "Example: rpc test_add {'x': 12, 'y': 17}\n"
- # return
- #
- # res_ok, msg = self.stateless_client.transmit(method, params)
- # if res_ok:
- # print "\nServer Response:\n\n" + pretty_json(json.dumps(msg)) + "\n"
- # else:
- # print "\n*** " + msg + "\n"
- # #print "Please try 'reconnect' to reconnect to server"
- #
- #
- # def complete_rpc (self, text, line, begidx, endidx):
- # return [x
- # for x in self.supported_rpc
- # if x.startswith(text)]
-
- def do_status (self, line):
- '''Shows a graphical console\n'''
-
- if not self.stateless_client.is_connected():
- print "Not connected to server\n"
- return
-
- self.do_verbose('off')
- trex_status.show_trex_status(self.stateless_client)
-
- def do_quit(self, line):
- '''Exit the client\n'''
- return True
+ if self.acquire_all_ports:
+ res_ok, log = self.stateless_client.acquire(self.stateless_client.get_port_ids())
+ if not res_ok:
+ print "\n*** Failed to acquire all ports... exiting..."""
- def do_disconnect (self, line):
- '''Disconnect from the server\n'''
- if not self.stateless_client.is_connected():
- print "Not connected to server\n"
+ @staticmethod
+ def annotate (desc, rc = None, err_log = None, ext_err_msg = None):
+ print format_text('\n{:<40}'.format(desc), 'bold'),
+ if rc == None:
+ print "\n"
return
- res_ok, msg = self.stateless_client.disconnect()
- if res_ok:
- print format_text("[SUCCESS]\n", 'green', 'bold')
- else:
- print msg + "\n"
-
- def do_whoami (self, line):
- '''Prints console user name\n'''
- print "\n" + self.stateless_client.user + "\n"
-
- def postcmd(self, stop, line):
- if self.stateless_client.is_connected():
- self.prompt = "TRex > "
- else:
- self.supported_rpc = None
- self.prompt = "TRex (offline) > "
-
- return stop
-
- def default(self, line):
- print "'{0}' is an unrecognized command. type 'help' or '?' for a list\n".format(line)
+ if rc == False:
+ # do we have a complex log object ?
+ if isinstance(err_log, list):
+ print ""
+ for func in err_log:
+ if func:
+ print func
+ print ""
- # def do_help (self, line):
- # '''Shows This Help Screen\n'''
- # if line:
- # try:
- # func = getattr(self, 'help_' + line)
- # except AttributeError:
- # try:
- # doc = getattr(self, 'do_' + line).__doc__
- # if doc:
- # self.stdout.write("%s\n"%str(doc))
- # return
- # except AttributeError:
- # pass
- # self.stdout.write("%s\n"%str(self.nohelp % (line,)))
- # return
- # func()
- # return
- #
- # print "\nSupported Console Commands:"
- # print "----------------------------\n"
- #
- # cmds = [x[3:] for x in self.get_names() if x.startswith("do_")]
- # for cmd in cmds:
- # if cmd == "EOF":
- # continue
- #
- # try:
- # doc = getattr(self, 'do_' + cmd).__doc__
- # if doc:
- # help = str(doc)
- # else:
- # help = "*** Undocumented Function ***\n"
- # except AttributeError:
- # help = "*** Undocumented Function ***\n"
- #
- # print "{:<30} {:<30}".format(cmd + " - ", help)
-
- def do_stream_db_add(self, line):
- '''Loads a YAML stream list serialization into user console \n'''
- args = line.split()
- if len(args) >= 2:
- name = args[0]
- yaml_path = args[1]
- try:
- multiplier = args[2]
- except IndexError:
- multiplier = 1
- stream_list = CStreamList()
- loaded_obj = stream_list.load_yaml(yaml_path, multiplier)
- # print self.stateless_client.pretty_json(json.dumps(loaded_obj))
- try:
- compiled_streams = stream_list.compile_streams()
- res_ok = self.streams_db.load_streams(name, LoadedStreamList(loaded_obj,
- [StreamPack(v.stream_id, v.stream.dump())
- for k, v in compiled_streams.items()]))
- if res_ok:
- print green("Stream pack '{0}' loaded and added successfully\n".format(name))
- else:
- print magenta("Picked name already exist. Please pick another name.\n")
- except Exception as e:
- print "adding new stream failed due to the following error:\n", str(e)
- print format_text("[FAILED]\n", 'red', 'bold')
-
- return
- else:
- print magenta("please provide load name and YAML path, separated by space.\n"
- "Optionally, you may provide a third argument to specify multiplier.\n")
-
- @staticmethod
- def tree_autocomplete(text):
- dir = os.path.dirname(text)
- if dir:
- path = dir
- else:
- path = "."
- start_string = os.path.basename(text)
- return [x
- for x in os.listdir(path)
- if x.startswith(start_string)]
+ elif isinstance(err_log, str):
+ print "\n" + err_log + "\n"
+ print format_text("[FAILED]\n", 'red', 'bold')
+ if ext_err_msg:
+ print format_text(ext_err_msg + "\n", 'blue', 'bold')
- def complete_stream_db_add(self, text, line, begidx, endidx):
- arg_num = len(line.split()) - 1
- if arg_num == 2:
- return TRexConsole.tree_autocomplete(line.split()[-1])
- else:
- return [text]
-
- def do_stream_db_show(self, line):
- '''Shows the loaded stream list named [name] \n'''
- args = line.split()
- if args:
- list_name = args[0]
- try:
- stream = self.streams_db.get_stream_pack(list_name)#user_streams[list_name]
- if len(args) >= 2 and args[1] == "full":
- print pretty_json(json.dumps(stream.compiled))
- else:
- print pretty_json(json.dumps(stream.loaded))
- except KeyError as e:
- print "Unknown stream list name provided"
- else:
- print "Available stream packs:\n{0}".format(', '.join(sorted(self.streams_db.get_loaded_streams_names())))
+ return False
- def complete_stream_db_show(self, text, line, begidx, endidx):
- return [x
- for x in self.streams_db.get_loaded_streams_names()
- if x.startswith(text)]
-
- def do_stream_db_remove(self, line):
- '''Removes a single loaded stream packs from loaded stream pack repository\n'''
- args = line.split()
- if args:
- removed_streams = self.streams_db.remove_stream_packs(*args)
- if removed_streams:
- print green("The following stream packs were removed:")
- print bold(", ".join(sorted(removed_streams)))
- print format_text("[SUCCESS]\n", 'green', 'bold')
- else:
- print red("No streams were removed. Make sure to provide valid stream pack names.")
else:
- print magenta("Please provide stream pack name(s), separated with spaces.")
-
- def do_stream_db_clear(self, line):
- '''Clears all loaded stream packs from loaded stream pack repository\n'''
- self.streams_db.clear()
- print format_text("[SUCCESS]\n", 'green', 'bold')
+ print format_text("[SUCCESS]\n", 'green', 'bold')
+ return True
- def complete_stream_db_remove(self, text, line, begidx, endidx):
- return [x
- for x in self.streams_db.get_loaded_streams_names()
- if x.startswith(text)]
-
-
- def do_attach(self, line):
- '''Assign loaded stream pack into specified ports on TRex\n'''
- args = line.split()
- if len(args) >= 2:
- stream_pack_name = args[0]
- stream_list = self.streams_db.get_stream_pack(stream_pack_name) #user_streams[args[0]]
- if not stream_list:
- print "Provided stream list name '{0}' doesn't exists.".format(stream_pack_name)
- print format_text("[FAILED]\n", 'red', 'bold')
- return
- if args[1] == "all":
- ask = ConfirmMenu('Are you sure you want to release all acquired ports? ')
- rc = ask.show()
- if rc == False:
- print yellow("[ABORTED]\n")
- return
- else:
- port_list = self.stateless_client.get_acquired_ports()
- else:
- port_list = self.extract_port_ids_from_line(' '.join(args[1:]))
- owned = set(self.stateless_client.get_acquired_ports())
- try:
- if set(port_list).issubset(owned):
- res_ok, log = self.stateless_client.add_stream_pack(stream_list.compiled, port_id=port_list)
- # res_ok, msg = self.stateless_client.add_stream(port_list, stream_list.compiled)
- self.prompt_response(log)
- if not res_ok:
- print format_text("[FAILED]\n", 'red', 'bold')
- return
- print format_text("[SUCCESS]\n", 'green', 'bold')
- return
- else:
- print "Not all desired ports are acquired.\n" \
- "Acquired ports are: {acq}\n" \
- "Requested ports: {req}\n" \
- "Missing ports: {miss}".format(acq=list(owned),
- req=port_list,
- miss=list(set(port_list).difference(owned)))
- print format_text("[FAILED]\n", 'red', 'bold')
- except ValueError as e:
- print magenta(str(e))
- print format_text("[FAILED]\n", 'red', 'bold')
- else:
- print magenta("Please provide list name and ports to attach to, "
- "or specify 'all' to attach all owned ports.\n")
-
- def complete_attach(self, text, line, begidx, endidx):
- arg_num = len(line.split()) - 1
- if arg_num == 1:
- # return optional streams packs
- if line.endswith(" "):
- return self.port_auto_complete(text, line, begidx, endidx)
- return [x
- for x in self.streams_db.get_loaded_streams_names()
- if x.startswith(text)]
- elif arg_num >= 2:
- # return optional ports to attach to
- return self.port_auto_complete(text, line, begidx, endidx)
- else:
- return [text]
-
- def prompt_response(self, response_obj):
- resp_list = response_obj if isinstance(response_obj, list) else [response_obj]
- def format_return_status(return_status):
- if return_status:
- return green("OK")
- else:
- return red("FAIL")
-
- for response in resp_list:
- response_str = "{id:^3} - {msg} ({stat})".format(id=response.id,
- msg=response.msg,
- stat=format_return_status(response.success))
- print response_str
- return
+ ############### start
- def do_remove_all_streams(self, line):
- '''Acquire ports\n'''
+ def complete_start(self, text, line, begidx, endidx):
+ s = line.split()
+ l = len(s)
- # make sure that the user wants to acquire all
- args = line.split()
- if len(args) < 1:
- print magenta("Please provide a list of ports separated by spaces, "
- "or specify 'all' to remove from all acquired ports")
- return
- if args[0] == "all":
- ask = ConfirmMenu('Are you sure you want to remove all stream packs from all acquired ports? ')
- rc = ask.show()
- if rc == False:
- print yellow("[ABORTED]\n")
- return
- else:
- port_list = self.stateless_client.get_acquired_ports()
- else:
- port_list = self.extract_port_ids_from_line(line)
+ file_flags = parsing_opts.get_flags(parsing_opts.FILE_PATH)
- # rc, resp_list = self.stateless_client.take_ownership(port_list, force)
- try:
- res_ok, log = self.stateless_client.remove_all_streams(port_list)
- self.prompt_response(log)
- if not res_ok:
- print format_text("[FAILED]\n", 'red', 'bold')
- return
- print format_text("[SUCCESS]\n", 'green', 'bold')
- except ValueError as e:
- print magenta(str(e))
- print format_text("[FAILED]\n", 'red', 'bold')
+ if (l > 1) and (s[l - 1] in file_flags):
+ return TRexConsole.tree_autocomplete("")
- def complete_remove_all_streams(self, text, line, begidx, endidx):
- return self.port_auto_complete(text, line, begidx, endidx)
+ if (l > 2) and (s[l - 2] in file_flags):
+ return TRexConsole.tree_autocomplete(s[l - 1])
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("start", self.do_start.__doc__,
+ 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:
- # avoid further processing in this command
- return
- # print opts
- port_list = self.extract_port_list(opts)
- # print port_list
- if opts.force:
- # stop all active ports, if any
- res_ok = self.stop_traffic(set(self.stateless_client.get_active_ports()).intersection(port_list))
- if not res_ok:
- print yellow("[ABORTED]\n")
- return
- # remove all traffic from ports
- res_ok = self.remove_all_streams(port_list)
- if not res_ok:
- print yellow("[ABORTED]\n")
return
- # decide which traffic to use
- stream_pack_name = None
+
if opts.db:
- # use pre-loaded traffic
- print format_text('{:<30}'.format("Load stream pack (from DB):"), 'bold'),
- if opts.db not in self.streams_db.get_loaded_streams_names():
- print format_text("[FAILED]\n", 'red', 'bold')
- print yellow("[ABORTED]\n")
+ 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:
- stream_pack_name = opts.db
+
else:
- # try loading a YAML file
- print format_text('{:<30}'.format("Load stream pack (from file):"), 'bold'),
- stream_list = CStreamList()
- loaded_obj = stream_list.load_yaml(opts.file[0])
- # print self.stateless_client.pretty_json(json.dumps(loaded_obj))
- try:
- compiled_streams = stream_list.compile_streams()
- res_ok = self.streams_db.load_streams(opts.file[1],
- LoadedStreamList(loaded_obj,
- [StreamPack(v.stream_id, v.stream.dump())
- for k, v in compiled_streams.items()]))
- if not res_ok:
- print format_text("[FAILED]\n", 'red', 'bold')
- print yellow("[ABORTED]\n")
- return
- print format_text("[SUCCESS]\n", 'green', 'bold')
- stream_pack_name = opts.file[1]
- except Exception as e:
- print format_text("[FAILED]\n", 'red', 'bold')
- print yellow("[ABORTED]\n")
- res_ok = self.attach_to_port(stream_pack_name, port_list)
- if not res_ok:
- print yellow("[ABORTED]\n")
- return
- # finally, start the traffic
- res_ok = self.start_traffic(opts.mult, port_list)
- if not res_ok:
- print yellow("[ABORTED]\n")
- return
+ # 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, self.annotate)
return
+
def help_start(self):
self.do_start("-h")
+ ############# stop
def do_stop(self, line):
'''Stop active traffic in specified ports on TRex\n'''
- parser = parsing_opts.gen_parser("stop", self.do_stop.__doc__,
+ 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:
- # avoid further processing in this command
return
- port_list = self.extract_port_list(opts)
- res_ok = self.stop_traffic(port_list)
- return
+ self.stateless_client.cmd_stop(opts.ports, self.annotate)
+ return
def help_stop(self):
self.do_stop("-h")
+ ########## reset
+ def do_reset (self, line):
+ '''force stop all ports\n'''
+ self.stateless_client.cmd_reset(self.annotate)
- def do_debug(self, line):
- '''Enter DEBUG mode of the console to invoke smaller building blocks with server'''
- i = DebugTRexConsole(self)
- i.prompt = self.prompt[:-3] + ':' + blue('debug') + ' > '
- i.cmdloop()
-
- # aliasing
- do_exit = do_EOF = do_q = do_quit
-
- # ----- utility methods ----- #
-
- def start_traffic(self, multiplier, port_list):#, silent=True):
- print format_text('{:<30}'.format("Start traffic:"), 'bold'),
- try:
- res_ok, log = self.stateless_client.start_traffic(multiplier, port_id=port_list)
- if not self._silent:
- print ''
- self.prompt_response(log)
- if not res_ok:
- print format_text("[FAILED]\n", 'red', 'bold')
- return False
- print format_text("[SUCCESS]\n", 'green', 'bold')
- return True
- except ValueError as e:
- print ''
- print magenta(str(e))
- print format_text("[FAILED]\n", 'red', 'bold')
- return False
+
+ # tui
+ def do_tui (self, line):
+ '''Shows a graphical console\n'''
- def attach_to_port(self, stream_pack_name, port_list):
- print format_text('{:<30}'.format("Attaching traffic to ports:"), 'bold'),
- stream_list = self.streams_db.get_stream_pack(stream_pack_name) #user_streams[args[0]]
- if not stream_list:
- print "Provided stream list name '{0}' doesn't exists.".format(stream_pack_name)
- print format_text("[FAILED]\n", 'red', 'bold')
+ if not self.stateless_client.is_connected():
+ print "Not connected to server\n"
return
- try:
- res_ok, log = self.stateless_client.add_stream_pack(stream_list.compiled, port_id=port_list)
- if not self._silent:
- print ''
- self.prompt_response(log)
- if not res_ok:
- print format_text("[FAILED]\n", 'red', 'bold')
- return False
- print format_text("[SUCCESS]\n", 'green', 'bold')
- return True
- except ValueError as e:
- print ''
- print magenta(str(e))
- print format_text("[FAILED]\n", 'red', 'bold')
- return False
-
- def stop_traffic(self, port_list):
- print format_text('{:<30}'.format("Stop traffic:"), 'bold'),
- try:
- res_ok, log = self.stateless_client.stop_traffic(port_id=port_list)
- if not self._silent:
- print ''
- self.prompt_response(log)
- if not res_ok:
- print format_text("[FAILED]\n", 'red', 'bold')
- return
- print format_text("[SUCCESS]\n", 'green', 'bold')
- return True
- except ValueError as e:
- print ''
- print magenta(str(e))
- print format_text("[FAILED]\n", 'red', 'bold')
-
- def remove_all_streams(self, port_list):
- '''Remove all streams from given port_list'''
- print format_text('{:<30}'.format("Remove all streams:"), 'bold'),
- try:
- res_ok, log = self.stateless_client.remove_all_streams(port_id=port_list)
- if not self._silent:
- print ''
- self.prompt_response(log)
- if not res_ok:
- print format_text("[FAILED]\n", 'red', 'bold')
- return
- print format_text("[SUCCESS]\n", 'green', 'bold')
- return True
- except ValueError as e:
- print ''
- print magenta(str(e))
- print format_text("[FAILED]\n", 'red', 'bold')
-
-
-
-
-
- def extract_port_list(self, opts):
- if opts.all_ports or "all" in opts.ports:
- # handling all ports
- port_list = self.stateless_client.get_acquired_ports()
- else:
- port_list = self.extract_port_ids_from_list(opts.ports)
- return port_list
-
- def decode_multiplier(self, opts_mult):
- pass
-
-
-class DebugTRexConsole(cmd.Cmd):
-
- def __init__(self, trex_main_console):
- cmd.Cmd.__init__(self)
- self.trex_console = trex_main_console
- self.stateless_client = self.trex_console.stateless_client
- self.streams_db = self.trex_console.streams_db
- self.register_main_console_methods()
- self.do_silent("on")
- pass
-
- # ----- super methods overriding ----- #
- def completenames(self, text, *ignored):
- dotext = 'do_'+text
- return [a[3:]+' ' for a in self.get_names() if a.startswith(dotext)]
- def get_names(self):
- result = cmd.Cmd.get_names(self)
- result += self.trex_console.get_names()
- return list(set(result))
-
- def register_main_console_methods(self):
- main_names = set(self.trex_console.get_names()).difference(set(dir(self.__class__)))
- for name in main_names:
- for prefix in 'do_', 'help_', 'complete_':
- if name.startswith(prefix):
- self.__dict__[name] = getattr(self.trex_console, name)
-
- # if (name[:3] == 'do_') or (name[:5] == 'help_') or (name[:9] == 'complete_'):
- # chosen.append(name)
- # self.__dict__[name] = getattr(self.trex_console, name)
- # # setattr(self, name, classmethod(getattr(self.trex_console, name)))
-
- # print chosen
- # self.get_names()
-
- # return result
-
-
- # ----- DEBUGGING methods ----- #
- # set silent on / off
- def do_silent(self, line):
- '''Shows or set silent mode\n'''
- if line == "":
- print "\nsilent mode is " + ("on\n" if self.trex_console._silent else "off\n")
-
- elif line == "on":
- self.verbose = True
- self.stateless_client.set_verbose(True)
- print green("\nsilent set to on\n")
-
- elif line == "off":
- self.verbose = False
- self.stateless_client.set_verbose(False)
- print green("\nsilent set to off\n")
-
- else:
- print magenta("\nplease specify 'on' or 'off'\n")
+ self.do_verbose('off')
+ trex_status.show_trex_status(self.stateless_client)
+ # quit function
def do_quit(self, line):
- '''Exit the debug client back to main console\n'''
- self.do_silent("off")
+ '''Exit the client\n'''
return True
- def do_start_traffic(self, line):
- '''Start pre-submitted traffic in specified ports on TRex\n'''
- # make sure that the user wants to acquire all
- parser = parsing_opts.gen_parser("start_traffic", self.do_start_traffic.__doc__,
- parsing_opts.PORT_LIST_WITH_ALL, parsing_opts.MULTIPLIER)
- opts = parser.parse_args(line.split())
- # print opts
- # return
- if opts is None:
- # avoid further processing in this command
- return
- try:
- port_list = self.trex_console.extract_port_list(opts)
- return self.trex_console.start_traffic(opts.mult, port_list)
- except Exception as e:
- print e
- return
-
- def do_stop_traffic(self, line):
- '''Stop active traffic in specified ports on TRex\n'''
- parser = parsing_opts.gen_parser("stop_traffic", self.do_stop_traffic.__doc__,
- parsing_opts.PORT_LIST_WITH_ALL)
- opts = parser.parse_args(line.split())
- # print opts
- # return
- if opts is None:
- # avoid further processing in this command
- return
- try:
- port_list = self.trex_console.extract_port_list(opts)
- return self.trex_console.stop_traffic(port_list)
- except Exception as e:
- print e
- return
-
-
- def complete_stop_traffic(self, text, line, begidx, endidx):
- return self.port_auto_complete(text, line, begidx, endidx, active=True)
-
- # return
- # # return
- # # if not opts.port_list:
- # # print magenta("Please provide a list of ports separated by spaces, "
- # # "or specify 'all' to start traffic on all acquired ports")
- # # return
- #
-
-
- return
- args = line.split()
- if len(args) < 1:
- print magenta("Please provide a list of ports separated by spaces, "
- "or specify 'all' to start traffic on all acquired ports")
- return
- if args[0] == "all":
- ask = ConfirmMenu('Are you sure you want to start traffic at all acquired ports? ')
- rc = ask.show()
- if rc == False:
- print yellow("[ABORTED]\n")
- return
- else:
- port_list = self.stateless_client.get_acquired_ports()
- else:
- port_list = self.extract_port_ids_from_line(line)
-
- try:
- res_ok, log = self.stateless_client.start_traffic(1.0, port_id=port_list)
- self.prompt_response(log)
- if not res_ok:
- print format_text("[FAILED]\n", 'red', 'bold')
- return
- print format_text("[SUCCESS]\n", 'green', 'bold')
- except ValueError as e:
- print magenta(str(e))
- print format_text("[FAILED]\n", 'red', 'bold')
-
- def complete_start_traffic(self, text, line, begidx, endidx):
- # return self.port_auto_complete(text, line, begidx, endidx)
- return [text]
-
- def help_start_traffic(self):
- self.do_start_traffic("-h")
-
- def help_stop_traffic(self):
- self.do_stop_traffic("-h")
-
- # def do_help(self):
-
- def do_rpc (self, line):
- '''Launches a RPC on the server\n'''
+
+ def do_help (self, line):
+ '''Shows This Help Screen\n'''
+ if line:
+ try:
+ func = getattr(self, 'help_' + line)
+ except AttributeError:
+ try:
+ doc = getattr(self, 'do_' + line).__doc__
+ if doc:
+ self.stdout.write("%s\n"%str(doc))
+ return
+ except AttributeError:
+ pass
+ self.stdout.write("%s\n"%str(self.nohelp % (line,)))
+ return
+ func()
+ return
+
+ print "\nSupported Console Commands:"
+ print "----------------------------\n"
+
+ cmds = [x[3:] for x in self.get_names() if x.startswith("do_")]
+ for cmd in cmds:
+ if ( (cmd == "EOF") or (cmd == "q") or (cmd == "exit")):
+ continue
+
+ try:
+ doc = getattr(self, 'do_' + cmd).__doc__
+ if doc:
+ help = str(doc)
+ else:
+ help = "*** Undocumented Function ***\n"
+ except AttributeError:
+ help = "*** Undocumented Function ***\n"
+
+ print "{:<30} {:<30}".format(cmd + " - ", help)
- if line == "":
- print "\nUsage: [method name] [param dict as string]\n"
- print "Example: rpc test_add {'x': 12, 'y': 17}\n"
- return
-
- sp = line.split(' ', 1)
- method = sp[0]
-
- params = None
- bad_parse = False
- if len(sp) > 1:
-
- try:
- params = ast.literal_eval(sp[1])
- if not isinstance(params, dict):
- bad_parse = True
-
- except ValueError as e1:
- bad_parse = True
- except SyntaxError as e2:
- bad_parse = True
-
- if bad_parse:
- print "\nValue should be a valid dict: '{0}'".format(sp[1])
- print "\nUsage: [method name] [param dict as string]\n"
- print "Example: rpc test_add {'x': 12, 'y': 17}\n"
- return
-
- res_ok, msg = self.stateless_client.transmit(method, params)
- if res_ok:
- print "\nServer Response:\n\n" + pretty_json(json.dumps(msg)) + "\n"
- else:
- print "\n*** " + msg + "\n"
- #print "Please try 'reconnect' to reconnect to server"
-
-
- def complete_rpc (self, text, line, begidx, endidx):
- return [x
- for x in self.trex_console.supported_rpc
- if x.startswith(text)]
-
- # aliasing
do_exit = do_EOF = do_q = do_quit
+
def setParserOptions():
parser = argparse.ArgumentParser(prog="trex_console.py")
@@ -1099,12 +371,12 @@ def setParserOptions():
default = "localhost",
type = str)
- parser.add_argument("-p", "--port", help = "TRex Server Port [default is 4505]\n",
- default = 4505,
+ parser.add_argument("-p", "--port", help = "TRex Server Port [default is 5505]\n",
+ default = 5505,
type = int)
- parser.add_argument("--async_port", help = "TRex ASync Publisher Port [default is 4506]\n",
- default = 4506,
+ parser.add_argument("--async_port", help = "TRex ASync Publisher Port [default is 4505]\n",
+ default = 4505,
dest='pub',
type = int)
@@ -1116,6 +388,11 @@ def setParserOptions():
action="store_true", help="Switch ON verbose option. Default is: OFF.",
default = False)
+
+ parser.add_argument("--no_acquire", dest="acquire",
+ action="store_false", help="Acquire all ports on connect. Default is: ON.",
+ default = True)
+
return parser
@@ -1128,7 +405,7 @@ def main():
# console
try:
- console = TRexConsole(stateless_client, options.verbose)
+ console = TRexConsole(stateless_client, options.acquire, options.verbose)
console.cmdloop()
except KeyboardInterrupt as e:
print "\n\n*** Caught Ctrl + C... Exiting...\n\n"
diff --git a/scripts/automation/trex_control_plane/console/trex_status.py b/scripts/automation/trex_control_plane/console/trex_status.py
index 2b97d7d3..a54b718e 100644
--- a/scripts/automation/trex_control_plane/console/trex_status.py
+++ b/scripts/automation/trex_control_plane/console/trex_status.py
@@ -168,7 +168,8 @@ class PortsStatsPanel(TrexStatusPanel):
port_stats.get_rel("ibytes", format = True, suffix = "B"))))
else:
- self.getwin().addstr(5 + (i * 4), 2, 2, "{:^15} {:^30} {:^30} {:^30}".format(
+
+ self.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^30} {:^30} {:^30}".format(
"{0} ({1})".format(str(port_index), self.status_obj.server_sys_info["ports"][port_index]["speed"]),
"N/A",
"N/A",
@@ -284,7 +285,7 @@ class SinglePortPanel(TrexStatusPanel):
port_stats.get_rel("ibytes", format = True, suffix = "B"))))
else:
- self.getwin().addstr(y + (i * 4), 2, 2, "{:^15} {:^30} {:^30} {:^30}".format(
+ self.getwin().addstr(y, 2, "{:^15} {:^30} {:^30} {:^30}".format(
"{0} ({1})".format(str(self.port_id), self.status_obj.server_sys_info["ports"][self.port_id]["speed"]),
"N/A",
"N/A",
diff --git a/src/rpc-server/trex_rpc_req_resp_server.h b/src/rpc-server/trex_rpc_req_resp_server.h
index 1f638adf..bc38c0ef 100644
--- a/src/rpc-server/trex_rpc_req_resp_server.h
+++ b/src/rpc-server/trex_rpc_req_resp_server.h
@@ -43,7 +43,7 @@ private:
void handle_request(const std::string &request);
void handle_server_error(const std::string &specific_err);
- static const int RPC_MAX_MSG_SIZE = (20 * 1024);
+ static const int RPC_MAX_MSG_SIZE = (200 * 1024);
void *m_context;
void *m_socket;
uint8_t m_msg_buffer[RPC_MAX_MSG_SIZE];
diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp
index b9206775..907b9cf4 100644
--- a/src/stateless/cp/trex_stateless_port.cpp
+++ b/src/stateless/cp/trex_stateless_port.cpp
@@ -122,7 +122,9 @@ TrexStatelessPort::start_traffic(double mul) {
void
TrexStatelessPort::stop_traffic(void) {
- verify_state(PORT_STATE_TX);
+ if (m_port_state != PORT_STATE_TX) {
+ return;
+ }
/* generate a message to all the relevant DP cores to start transmitting */
TrexStatelessCpToDpMsgBase *stop_msg = new TrexStatelessDpStop(m_port_id);