From a2a634fc8b5bac450ea37f29dde521b7d9e740c8 Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Thu, 22 Oct 2015 13:44:25 +0300 Subject: minor updates --- .../automation/trex_control_plane/console/trex_console.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index a9ac040b..0f5c30af 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -17,6 +17,8 @@ See the License for the specific language governing permissions and limitations under the License. """ +__version__ = "1.0" + import cmd import json import ast @@ -38,7 +40,7 @@ LoadedStreamList = namedtuple('LoadedStreamList', ['loaded', 'compiled']) # -def readch (choices = []): +def readch(choices=[]): fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) @@ -119,7 +121,7 @@ class AddStreamMenu(CmdMenu): self.add_menu('Please select ISG', ['d', 'e', 'f']) # main console object -class TrexConsole(cmd.Cmd): +class TRexConsole(cmd.Cmd): """Trex Console""" def __init__(self, rpc_client): @@ -129,7 +131,7 @@ class TrexConsole(cmd.Cmd): self.do_connect("") - self.intro = "\n-=TRex Console V1.0=-\n" + self.intro = "\n-=TRex Console v{ver}=-\n".format(ver=__version__) self.intro += "\nType 'help' or '?' for supported actions\n" self.verbose = False @@ -473,7 +475,7 @@ class TrexConsole(cmd.Cmd): def complete_load_stream_list(self, text, line, begidx, endidx): arg_num = len(line.split()) - 1 if arg_num == 2: - return TrexConsole.tree_autocomplete(line.split()[-1]) + return TRexConsole.tree_autocomplete(line.split()[-1]) else: return [text] @@ -581,7 +583,7 @@ def main (): # console try: - console = TrexConsole(rpc_client) + console = TRexConsole(rpc_client) console.cmdloop() except KeyboardInterrupt as e: print "\n\n*** Caught Ctrl + C... Exiting...\n\n" -- cgit From ebb0b48faca96bad7bfe8da0bf80df7c7c80350d Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Sun, 25 Oct 2015 11:33:48 +0200 Subject: HLTAPI progress... --- scripts/automation/trex_control_plane/console/trex_console.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 0f5c30af..4f9743f4 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -17,7 +17,6 @@ See the License for the specific language governing permissions and limitations under the License. """ -__version__ = "1.0" import cmd import json @@ -36,6 +35,8 @@ from client_utils.jsonrpc_client import TrexStatelessClient import trex_status from collections import namedtuple +__version__ = "1.0" + LoadedStreamList = namedtuple('LoadedStreamList', ['loaded', 'compiled']) # -- cgit From 0c2b3c83f9cc0c25277c39660dce132aad55c3d7 Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Wed, 28 Oct 2015 07:28:37 +0200 Subject: updated more HLTAPI functionality and fixed found bugs. Working: Start/stop traffic, traffic config (semi), connect, clean Missing: stats Next: boost console --- scripts/automation/trex_control_plane/console/trex_console.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 4f9743f4..2ea29473 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -449,10 +449,10 @@ class TRexConsole(cmd.Cmd): try: compiled_streams = stream_list.compile_streams() self.user_streams[name] = LoadedStreamList(loaded_obj, - [StreamPack(v.stream_id, v.stream.dump_compiled()) + [StreamPack(v.stream_id, v.stream.dump()) for k, v in compiled_streams.items()]) - print "Stream '{0}' loaded successfully".format(name) + print "Stream list '{0}' loaded successfully".format(name) except Exception as e: raise return -- cgit From f963facdc949c087c863b8ad81aae537bcf3767b Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Wed, 28 Oct 2015 23:59:11 +0200 Subject: console progress, still SHAKY! --- .../trex_control_plane/console/trex_console.py | 238 ++++++++++++--------- 1 file changed, 132 insertions(+), 106 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 2ea29473..241d46b9 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -29,6 +29,7 @@ import sys import tty, termios import trex_root_path from common.trex_streams import * +from client.trex_stateless_client import CTRexStatelessClient from client_utils.jsonrpc_client import TrexStatelessClient @@ -75,6 +76,25 @@ class YesNoMenu(object): else: return False +class CStreamsDB(object): + + def __init__(self): + self.loaded_streams = {} + + def load_streams(self, name, LoadedStreamList_obj): + if name in self.loaded_streams: + return False + else: + self.loaded_streams[name] = LoadedStreamList_obj + return True + + def remove_streams(self, name): + return self.loaded_streams.pop(name) + + def get_loaded_streams(self): + return self.loaded_streams.keys() + + # multi level cmd menu class CmdMenu(object): def __init__ (self): @@ -125,10 +145,10 @@ class AddStreamMenu(CmdMenu): class TRexConsole(cmd.Cmd): """Trex Console""" - def __init__(self, rpc_client): + def __init__(self, stateless_client, verbose): cmd.Cmd.__init__(self) - self.rpc_client = rpc_client + self.stateless_client = stateless_client self.do_connect("") @@ -140,6 +160,7 @@ class TRexConsole(cmd.Cmd): self.postcmd(False, "") self.user_streams = {} + self.streams_db = CStreamsDB() # a cool hack - i stole this function and added space @@ -155,12 +176,12 @@ class TRexConsole(cmd.Cmd): elif line == "on": self.verbose = True - self.rpc_client.set_verbose(True) + self.stateless_client.set_verbose(True) print "\nverbose set to on\n" elif line == "off": self.verbose = False - self.rpc_client.set_verbose(False) + self.stateless_client.set_verbose(False) print "\nverbose set to off\n" else: @@ -170,7 +191,7 @@ class TRexConsole(cmd.Cmd): def do_query_server(self, line): '''query the RPC server for supported remote commands\n''' - rc, msg = self.rpc_client.query_rpc_server() + rc, msg = self.stateless_client.query_rpc_server() if not rc: print "\n*** " + msg + "\n" return @@ -186,8 +207,8 @@ class TRexConsole(cmd.Cmd): print "\n-> Pinging RPC server" - rc, msg = self.rpc_client.ping_rpc_server() - if rc: + res_ok, msg = self.stateless_client.ping() + if res_ok: print "[SUCCESS]\n" else: print "\n*** " + msg + "\n" @@ -198,13 +219,15 @@ class TRexConsole(cmd.Cmd): self.do_acquire(line, True) + def extract_port_ids_from_line(self, line): + return {int(x) for x in line.split()} + 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.rpc_client.get_port_count()): - print "Please provide a list of ports seperated by spaces between 0 and {0}".format(self.rpc_client.get_port_count() - 1) + 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)) @@ -212,106 +235,86 @@ class TRexConsole(cmd.Cmd): port_list = list(port_list) else: - port_list = [i for i in xrange(0, self.rpc_client.get_port_count())] + port_list = [i for i in xrange(0, self.stateless_client.get_port_count())] return port_list - def do_acquire (self, line, force = False): + def do_acquire (self, line, force=False): '''Acquire ports\n''' # make sure that the user wants to acquire all - if line == "": - ask = YesNoMenu('Do you want to acquire all 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 = YesNoMenu('Are you sure you want to acquire all ports ? ') rc = ask.show() if rc == False: return - - port_list = self.parse_ports_from_line(line) - if not port_list: - return + else: + port_list = self.stateless_client.get_port_ids() + else: + port_list = self.extract_port_ids_from_line(line) print "\nTrying to acquire ports: " + (" ".join(str(x) for x in port_list)) + "\n" - rc, resp_list = self.rpc_client.take_ownership(port_list, force) - - if not rc: - print "\n*** " + resp_list + "\n" + # rc, resp_list = self.stateless_client.take_ownership(port_list, force) + res_ok, log = self.stateless_client.acquire(port_list, force) + self.prompt_response(log) + if not res_ok: + print "[FAILED]\n" return - - for i, rc in enumerate(resp_list): - if rc[0]: - print "Port {0} - Acquired".format(port_list[i]) - else: - print "Port {0} - ".format(port_list[i]) + rc[1] - - print "\n" + print "[SUCCESS]\n" + return def do_release (self, line): '''Release ports\n''' - if line: - port_list = self.parse_ports_from_line(line) - else: - port_list = self.rpc_client.get_owned_ports() - - if not port_list: - return - - rc, resp_list = self.rpc_client.release_ports(port_list) - - - print "\n" - - for i, rc in enumerate(resp_list): - if rc[0]: - print "Port {0} - Released".format(port_list[i]) + # 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 = YesNoMenu('Are you sure you want to release all acquired ports ? ') + rc = ask.show() + if rc == False: + return else: - print "Port {0} - Failed to release port, probably not owned by you or port is under traffic" - - print "\n" - - def do_get_port_stats (self, line): - '''Get ports stats\n''' - - port_list = self.parse_ports_from_line(line) - if not port_list: - return - - rc, resp_list = self.rpc_client.get_port_stats(port_list) + port_list = self.stateless_client.get_acquired_ports() + else: + port_list = self.extract_port_ids_from_line(line) - if not rc: - print "\n*** " + resp_list + "\n" + res_ok, log = self.stateless_client.release(port_list) + self.prompt_response(log) + if not res_ok: + print "[FAILED]\n" return - - for i, rc in enumerate(resp_list): - if rc[0]: - print "\nPort {0} stats:\n{1}\n".format(port_list[i], self.rpc_client.pretty_json(json.dumps(rc[1]))) - else: - print "\nPort {0} - ".format(i) + rc[1] + "\n" - - print "\n" - + print "[SUCCESS]\n" + return def do_connect (self, line): '''Connects to the server\n''' if line == "": - rc, msg = self.rpc_client.connect() + 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 - rc, msg = self.rpc_client.connect(sp[0], sp[1]) + res_ok, msg = self.stateless_client.connect(sp[0], sp[1]) - if rc: + if res_ok: print "[SUCCESS]\n" else: print "\n*** " + msg + "\n" return - self.supported_rpc = self.rpc_client.get_supported_cmds() + self.supported_rpc = self.stateless_client.get_supported_cmds().data def do_rpc (self, line): '''Launches a RPC on the server\n''' @@ -344,9 +347,9 @@ class TRexConsole(cmd.Cmd): print "Example: rpc test_add {'x': 12, 'y': 17}\n" return - rc, msg = self.rpc_client.invoke_rpc_method(method, params) - if rc: - print "\nServer Response:\n\n" + self.rpc_client.pretty_json(json.dumps(msg)) + "\n" + res_ok, msg = self.stateless_client.invoke_rpc_method(method, params) + if res_ok: + print "\nServer Response:\n\n" + self.stateless_client.pretty_json(json.dumps(msg)) + "\n" else: print "\n*** " + msg + "\n" #print "Please try 'reconnect' to reconnect to server" @@ -359,7 +362,7 @@ class TRexConsole(cmd.Cmd): '''Shows a graphical console\n''' self.do_verbose('off') - trex_status.show_trex_status(self.rpc_client) + trex_status.show_trex_status(self.stateless_client) def do_quit(self, line): '''Exit the client\n''' @@ -367,22 +370,22 @@ class TRexConsole(cmd.Cmd): def do_disconnect (self, line): '''Disconnect from the server\n''' - if not self.rpc_client.is_connected(): + if not self.stateless_client.is_connected(): print "Not connected to server\n" return - rc, msg = self.rpc_client.disconnect() - if rc: + res_ok, msg = self.stateless_client.disconnect() + if res_ok: print "[SUCCESS]\n" else: print msg + "\n" def do_whoami (self, line): '''Prints console user name\n''' - print "\n" + self.rpc_client.whoami() + "\n" + print "\n" + self.stateless_client.user + "\n" def postcmd(self, stop, line): - if self.rpc_client.is_connected(): + if self.stateless_client.is_connected(): self.prompt = "TRex > " else: self.supported_rpc = None @@ -430,7 +433,7 @@ class TRexConsole(cmd.Cmd): print "{:<30} {:<30}".format(cmd + " - ", help) - def do_load_stream_list(self, line): + def do_stream_db_add(self, line): '''Loads a YAML stream list serialization into user console \n''' args = line.split() if args >= 2: @@ -442,19 +445,31 @@ class TRexConsole(cmd.Cmd): multiplier = 1 stream_list = CStreamList() loaded_obj = stream_list.load_yaml(yaml_path, multiplier) - # print self.rpc_client.pretty_json(json.dumps(loaded_obj)) - if name in self.user_streams: - print "Picked name already exist. Please pick another name." - else: - try: - compiled_streams = stream_list.compile_streams() - self.user_streams[name] = LoadedStreamList(loaded_obj, - [StreamPack(v.stream_id, v.stream.dump()) - for k, v in compiled_streams.items()]) - + # 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 "Stream list '{0}' loaded successfully".format(name) - except Exception as e: - raise + else: + print "Picked name already exist. Please pick another name." + except Exception as e: + print "adding new stream failed due to the following error:\n", str(e) + + # if name in self.user_streams: + # print "Picked name already exist. Please pick another name." + # else: + # try: + # compiled_streams = stream_list.compile_streams() + # self.user_streams[name] = LoadedStreamList(loaded_obj, + # [StreamPack(v.stream_id, v.stream.dump()) + # for k, v in compiled_streams.items()]) + # + # print "Stream list '{0}' loaded successfully".format(name) + # except Exception as e: + # raise return else: print "please provide load name and YAML path, separated by space.\n" \ @@ -473,7 +488,7 @@ class TRexConsole(cmd.Cmd): if x.startswith(start_string)] - def complete_load_stream_list(self, text, line, begidx, endidx): + 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]) @@ -488,9 +503,9 @@ class TRexConsole(cmd.Cmd): try: stream = self.user_streams[list_name] if len(args) >= 2 and args[1] == "full": - print self.rpc_client.pretty_json(json.dumps(stream.compiled)) + print self.stateless_client.pretty_json(json.dumps(stream.compiled)) else: - print self.rpc_client.pretty_json(json.dumps(stream.loaded)) + print self.stateless_client.pretty_json(json.dumps(stream.loaded)) except KeyError as e: print "Unknown stream list name provided" else: @@ -508,9 +523,9 @@ class TRexConsole(cmd.Cmd): try: stream_list = self.user_streams[args[0]] port_list = self.parse_ports_from_line(' '.join(args[1:])) - owned = set(self.rpc_client.get_owned_ports()) + owned = set(self.stateless_client.get_owned_ports()) if set(port_list).issubset(owned): - rc, resp_list = self.rpc_client.add_stream(port_list, stream_list.compiled) + rc, resp_list = self.stateless_client.add_stream(port_list, stream_list.compiled) if not rc: print "\n*** " + resp_list + "\n" return @@ -528,6 +543,12 @@ class TRexConsole(cmd.Cmd): print "Please provide list name and ports to attach to, or leave empty to attach to all ports." + def prompt_response(self, response_obj): + resp_list = response_obj if isinstance(response_obj, list) else [response_obj] + for response in resp_list: + print response + + @@ -549,9 +570,9 @@ class TRexConsole(cmd.Cmd): stream_id = int(params[1]) packet = [0xFF,0xFF,0xFF] - rc, msg = self.rpc_client.add_stream(port_id = port_id, stream_id = stream_id, isg = 1.1, next_stream_id = -1, packet = packet) + rc, msg = self.stateless_client.add_stream(port_id = port_id, stream_id = stream_id, isg = 1.1, next_stream_id = -1, packet = packet) if rc: - print "\nServer Response:\n\n" + self.rpc_client.pretty_json(json.dumps(msg)) + "\n" + print "\nServer Response:\n\n" + self.stateless_client.pretty_json(json.dumps(msg)) + "\n" else: print "\n*** " + msg + "\n" @@ -573,18 +594,23 @@ def setParserOptions (): default = 'user_' + ''.join(random.choice(string.digits) for _ in range(5)), type = str) + parser.add_argument("--verbose", dest="verbose", + action="store_true", help="Switch ON verbose option. Default is: OFF.", + default = False) + return parser def main (): parser = setParserOptions() - options = parser.parse_args(sys.argv[1:]) + options = parser.parse_args()#sys.argv[1:]) - # RPC client - rpc_client = TrexStatelessClient(options.server, options.port, options.user) + # Stateless client connection + # stateless_client = TrexStatelessClient(options.server, options.port, options.user) + stateless_client = CTRexStatelessClient(options.user, options.server, options.port) # console try: - console = TRexConsole(rpc_client) + console = TRexConsole(stateless_client, options.verbose) console.cmdloop() except KeyboardInterrupt as e: print "\n\n*** Caught Ctrl + C... Exiting...\n\n" -- cgit From aa37a0abb00cbf4cb1611f9c0eefcb1ab850bc45 Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Thu, 29 Oct 2015 11:34:03 +0200 Subject: Console redesign using trex_stateless_client module --- .../trex_control_plane/console/trex_console.py | 234 +++++++++++++++------ 1 file changed, 173 insertions(+), 61 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 241d46b9..d2050f09 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -30,6 +30,8 @@ import tty, termios import trex_root_path from common.trex_streams import * from client.trex_stateless_client import CTRexStatelessClient +from common.text_opts import * +from client_utils.general_utils import user_input from client_utils.jsonrpc_client import TrexStatelessClient @@ -43,7 +45,7 @@ LoadedStreamList = namedtuple('LoadedStreamList', ['loaded', 'compiled']) # def readch(choices=[]): - + fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: @@ -69,30 +71,51 @@ class YesNoMenu(object): ch = readch(choices = ['y', 'Y', 'n', 'N']) if ch == None: return None - - print "\n" + + print "\n" if ch == 'y' or ch == 'Y': return True else: return False +class ConfirmMenu(object): + def __init__ (self, caption): + self.caption = "{cap} [confirm] : ".format(cap=caption) + + def show(self): + sys.stdout.write(self.caption) + + + + class CStreamsDB(object): def __init__(self): - self.loaded_streams = {} + self.stream_packs = {} def load_streams(self, name, LoadedStreamList_obj): - if name in self.loaded_streams: + if name in self.stream_packs: return False else: - self.loaded_streams[name] = LoadedStreamList_obj + self.stream_packs[name] = LoadedStreamList_obj return True - def remove_streams(self, name): - return self.loaded_streams.pop(name) + 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(self): - return self.loaded_streams.keys() + 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 @@ -144,7 +167,7 @@ class AddStreamMenu(CmdMenu): # main console object class TRexConsole(cmd.Cmd): """Trex Console""" - + def __init__(self, stateless_client, verbose): cmd.Cmd.__init__(self) @@ -153,7 +176,7 @@ class TRexConsole(cmd.Cmd): self.do_connect("") self.intro = "\n-=TRex Console v{ver}=-\n".format(ver=__version__) - self.intro += "\nType 'help' or '?' for supported actions\n" + self.intro += "\nType 'help' or '?' for supported actions\n" self.verbose = False @@ -161,7 +184,7 @@ class TRexConsole(cmd.Cmd): self.user_streams = {} self.streams_db = CStreamsDB() - + # a cool hack - i stole this function and added space def completenames(self, text, *ignored): @@ -209,7 +232,7 @@ class TRexConsole(cmd.Cmd): res_ok, msg = self.stateless_client.ping() if res_ok: - print "[SUCCESS]\n" + print format_text("[SUCCESS]\n", 'green', 'bold') else: print "\n*** " + msg + "\n" return @@ -262,9 +285,9 @@ class TRexConsole(cmd.Cmd): res_ok, log = self.stateless_client.acquire(port_list, force) self.prompt_response(log) if not res_ok: - print "[FAILED]\n" + print format_text("[FAILED]\n", 'red', 'bold') return - print "[SUCCESS]\n" + print format_text("[SUCCESS]\n", 'green', 'bold') return def do_release (self, line): @@ -290,9 +313,9 @@ class TRexConsole(cmd.Cmd): res_ok, log = self.stateless_client.release(port_list) self.prompt_response(log) if not res_ok: - print "[FAILED]\n" + print format_text("[FAILED]\n", 'red', 'bold') return - print "[SUCCESS]\n" + print format_text("[SUCCESS]\n", 'green', 'bold') return def do_connect (self, line): @@ -356,7 +379,9 @@ class TRexConsole(cmd.Cmd): def complete_rpc (self, text, line, begidx, endidx): - return [x for x in self.supported_rpc if x.startswith(text)] + return [x + for x in self.supported_rpc + if x.startswith(text)] def do_status (self, line): '''Shows a graphical console\n''' @@ -376,14 +401,14 @@ class TRexConsole(cmd.Cmd): res_ok, msg = self.stateless_client.disconnect() if res_ok: - print "[SUCCESS]\n" + 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 > " @@ -452,11 +477,12 @@ class TRexConsole(cmd.Cmd): [StreamPack(v.stream_id, v.stream.dump()) for k, v in compiled_streams.items()])) if res_ok: - print "Stream list '{0}' loaded successfully".format(name) + print green("Stream list '{0}' loaded and added successfully".format(name)) else: - print "Picked name already exist. Please pick another name." + print magenta("Picked name already exist. Please pick another name.") except Exception as e: print "adding new stream failed due to the following error:\n", str(e) + print format_text("[FAILED]\n", 'red', 'bold') # if name in self.user_streams: # print "Picked name already exist. Please pick another name." @@ -495,71 +521,157 @@ class TRexConsole(cmd.Cmd): else: return [text] - def do_show_stream_list(self, line): + 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.user_streams[list_name] + stream = self.streams_db.get_stream_pack(list_name)#user_streams[list_name] if len(args) >= 2 and args[1] == "full": - print self.stateless_client.pretty_json(json.dumps(stream.compiled)) + print pretty_json(json.dumps(stream.compiled)) else: - print self.stateless_client.pretty_json(json.dumps(stream.loaded)) + print pretty_json(json.dumps(stream.loaded)) except KeyError as e: print "Unknown stream list name provided" else: - print "\nAvailable stream lists:\n{0}".format(', '.join([x - for x in self.user_streams.keys()])) + print "\nAvailable stream lists:\n{0}".format(', '.join(sorted(self.streams_db.get_loaded_streams_names()))) - def complete_show_stream_list(self, text, line, begidx, endidx): + def complete_stream_db_show(self, text, line, begidx, endidx): return [x - for x in self.user_streams.keys() + for x in self.streams_db.get_loaded_streams_names() if x.startswith(text)] - def do_attach(self, line): + def do_stream_db_remove(self, line): args = line.split() - if len(args) >= 1: - try: - stream_list = self.user_streams[args[0]] - port_list = self.parse_ports_from_line(' '.join(args[1:])) - owned = set(self.stateless_client.get_owned_ports()) - if set(port_list).issubset(owned): - rc, resp_list = self.stateless_client.add_stream(port_list, stream_list.compiled) - if not rc: - print "\n*** " + resp_list + "\n" - return - else: - print "Not all desired ports are aquired.\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))) - except KeyError as e: - cause = e.args[0] - print "Provided stream list name '{0}' doesn't exists.".format(cause) + 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 "Please provide list name and ports to attach to, or leave empty to attach to all ports." + print magenta("Please provide stream pack name(s), separated with spaces.") + def do_stream_db_clear(self, line): + self.streams_db.clear() + print format_text("[SUCCESS]\n", 'green', 'bold') - def prompt_response(self, response_obj): - resp_list = response_obj if isinstance(response_obj, list) else [response_obj] - for response in resp_list: - print response + 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): + 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[0] == "all": + ask = YesNoMenu('Are you sure you want to release all acquired ports ? ') + rc = ask.show() + if rc == False: + 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_owned_ports()) + if set(port_list).issubset(owned): + res_ok, log = self.stateless_client.add_stream_pack(port_list, stream_list.compiled) + # 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') + else: + print "Please provide list name and ports to attach to, " \ + "or specify 'all' to attach all owned ports." + + def complete_attach(self, text, line, begidx, endidx): + arg_num = len(line.split()) - 1 + if arg_num == 1: + # return optional streams packs + 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 [x + for x in self.stateless_client.get_acquired_ports() + if str(x).startswith(text)] + 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 green("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 "Please provide a list of ports separated by spaces, " \ + "or specify 'all' to remove from all acquired ports" + if args[0] == "all": + ask = YesNoMenu('Are you sure you want to remove all stream packs from all acquired ports? ') + rc = ask.show() + if rc == False: + return + else: + port_list = self.stateless_client.get_port_ids() + else: + port_list = self.extract_port_ids_from_line(line) + print "\nTrying to remove all streams at ports: " + (" ".join(str(x) for x in port_list)) + "\n" + # rc, resp_list = self.stateless_client.take_ownership(port_list, force) + 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') + return + def complete_remove_all_streams(self, text, line, begidx, endidx): + return [x + for x in self.stateless_client.get_acquired_ports() + if str(x).startswith(text)] # adds a very simple stream - def do_add_simple_stream (self, line): + def do_add_simple_stream(self, line): if line == "": add_stream = AddStreamMenu() add_stream.show() @@ -572,14 +684,14 @@ class TRexConsole(cmd.Cmd): packet = [0xFF,0xFF,0xFF] rc, msg = self.stateless_client.add_stream(port_id = port_id, stream_id = stream_id, isg = 1.1, next_stream_id = -1, packet = packet) if rc: - print "\nServer Response:\n\n" + self.stateless_client.pretty_json(json.dumps(msg)) + "\n" + print "\nServer Response:\n\n" + pretty_json(json.dumps(msg)) + "\n" else: print "\n*** " + msg + "\n" # aliasing do_exit = do_EOF = do_q = do_quit -def setParserOptions (): +def setParserOptions(): parser = argparse.ArgumentParser(prog="trex_console.py") parser.add_argument("-s", "--server", help = "TRex Server [default is localhost]", @@ -600,7 +712,7 @@ def setParserOptions (): return parser -def main (): +def main(): parser = setParserOptions() options = parser.parse_args()#sys.argv[1:]) -- cgit From 13c353b9e4f3f0177458c5bef729de31ec03135d Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Thu, 29 Oct 2015 03:59:43 +0200 Subject: fixed console issues after testsing them --- .../trex_control_plane/console/trex_console.py | 69 +++++++++++++++------- 1 file changed, 47 insertions(+), 22 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index d2050f09..b2eac88e 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -84,10 +84,14 @@ class ConfirmMenu(object): 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): @@ -242,6 +246,9 @@ class TRexConsole(cmd.Cmd): 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()} @@ -262,7 +269,7 @@ class TRexConsole(cmd.Cmd): return port_list - def do_acquire (self, line, force=False): + def do_acquire(self, line, force=False): '''Acquire ports\n''' # make sure that the user wants to acquire all @@ -270,7 +277,7 @@ class TRexConsole(cmd.Cmd): 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 = YesNoMenu('Are you sure you want to acquire all ports ? ') + ask = ConfirmMenu('Are you sure you want to acquire all ports ? ') rc = ask.show() if rc == False: return @@ -290,6 +297,23 @@ class TRexConsole(cmd.Cmd): print format_text("[SUCCESS]\n", 'green', 'bold') return + + def port_auto_complete(self, text, line, begidx, endidx, acquired=True): + if acquired: + 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_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''' @@ -301,7 +325,7 @@ class TRexConsole(cmd.Cmd): 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 = YesNoMenu('Are you sure you want to release all acquired ports ? ') + ask = ConfirmMenu('Are you sure you want to release all acquired ports? ') rc = ask.show() if rc == False: return @@ -318,6 +342,9 @@ class TRexConsole(cmd.Cmd): print format_text("[SUCCESS]\n", 'green', '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''' @@ -332,9 +359,10 @@ class TRexConsole(cmd.Cmd): res_ok, msg = self.stateless_client.connect(sp[0], sp[1]) if res_ok: - print "[SUCCESS]\n" + 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 @@ -477,9 +505,9 @@ class TRexConsole(cmd.Cmd): [StreamPack(v.stream_id, v.stream.dump()) for k, v in compiled_streams.items()])) if res_ok: - print green("Stream list '{0}' loaded and added successfully".format(name)) + print green("Stream pack '{0}' loaded and added successfully\n".format(name)) else: - print magenta("Picked name already exist. Please pick another name.") + 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') @@ -535,7 +563,7 @@ class TRexConsole(cmd.Cmd): except KeyError as e: print "Unknown stream list name provided" else: - print "\nAvailable stream lists:\n{0}".format(', '.join(sorted(self.streams_db.get_loaded_streams_names()))) + 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 @@ -584,9 +612,9 @@ class TRexConsole(cmd.Cmd): 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_owned_ports()) + owned = set(self.stateless_client.get_acquired_ports()) if set(port_list).issubset(owned): - res_ok, log = self.stateless_client.add_stream_pack(port_list, stream_list.compiled) + res_ok, log = self.stateless_client.add_stream_pack(port_list, *stream_list.compiled) # res_ok, msg = self.stateless_client.add_stream(port_list, stream_list.compiled) self.prompt_response(log) if not res_ok: @@ -615,9 +643,7 @@ class TRexConsole(cmd.Cmd): if x.startswith(text)] elif arg_num >= 2: # return optional ports to attach to - return [x - for x in self.stateless_client.get_acquired_ports() - if str(x).startswith(text)] + return self.port_auto_complete(text, line, begidx, endidx) else: return [text] @@ -627,7 +653,7 @@ class TRexConsole(cmd.Cmd): if return_status: return green("OK") else: - return green("fail") + return red("FAIL") for response in resp_list: response_str = "{id:^3} - {msg} ({stat})".format(id=response.id, @@ -642,15 +668,16 @@ class TRexConsole(cmd.Cmd): # make sure that the user wants to acquire all args = line.split() if len(args) < 1: - print "Please provide a list of ports separated by spaces, " \ - "or specify 'all' to remove from all acquired ports" + 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 = YesNoMenu('Are you sure you want to remove all stream packs from all acquired ports? ') + ask = ConfirmMenu('Are you sure you want to remove all stream packs from all acquired ports? ') rc = ask.show() if rc == False: return else: - port_list = self.stateless_client.get_port_ids() + port_list = self.stateless_client.get_acquired_ports() else: port_list = self.extract_port_ids_from_line(line) @@ -666,9 +693,7 @@ class TRexConsole(cmd.Cmd): return def complete_remove_all_streams(self, text, line, begidx, endidx): - return [x - for x in self.stateless_client.get_acquired_ports() - if str(x).startswith(text)] + return self.port_auto_complete(text, line, begidx, endidx) # adds a very simple stream def do_add_simple_stream(self, line): -- cgit From d78150a66de591a77df2496e5de828d3232a931a Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Thu, 29 Oct 2015 06:18:54 +0200 Subject: Awesome working start/stop traffic console Fixed more stability issues :) Ready for merging. --- .../trex_control_plane/console/trex_console.py | 162 ++++++++++++--------- 1 file changed, 95 insertions(+), 67 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index b2eac88e..5c3668c0 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -42,41 +42,6 @@ __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 YesNoMenu(object): - def __init__ (self, caption): - self.caption = caption - - def show (self): - print "{0}".format(self.caption) - sys.stdout.write("[Y/y/N/n] : ") - ch = readch(choices = ['y', 'Y', 'n', 'N']) - if ch == None: - return None - - print "\n" - if ch == 'y' or ch == 'Y': - return True - else: - return False class ConfirmMenu(object): def __init__ (self, caption): @@ -280,14 +245,13 @@ class TRexConsole(cmd.Cmd): 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) - print "\nTrying to acquire ports: " + (" ".join(str(x) for x in port_list)) + "\n" - # rc, resp_list = self.stateless_client.take_ownership(port_list, force) res_ok, log = self.stateless_client.acquire(port_list, force) self.prompt_response(log) @@ -298,11 +262,16 @@ class TRexConsole(cmd.Cmd): return - def port_auto_complete(self, text, line, begidx, endidx, acquired=True): + def port_auto_complete(self, text, line, begidx, endidx, acquired=True, active=False): if acquired: - ret_list = [x - for x in map(str, self.stateless_client.get_acquired_ports()) - if x.startswith(text)] + 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()) @@ -328,19 +297,24 @@ class TRexConsole(cmd.Cmd): 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) - res_ok, log = self.stateless_client.release(port_list) - self.prompt_response(log) - if not res_ok: + 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 - print format_text("[SUCCESS]\n", 'green', 'bold') - return def complete_release(self, text, line, begidx, endidx): return self.port_auto_complete(text, line, begidx, endidx) @@ -489,7 +463,7 @@ class TRexConsole(cmd.Cmd): def do_stream_db_add(self, line): '''Loads a YAML stream list serialization into user console \n''' args = line.split() - if args >= 2: + if len(args) >= 2: name = args[0] yaml_path = args[1] try: @@ -512,22 +486,10 @@ class TRexConsole(cmd.Cmd): print "adding new stream failed due to the following error:\n", str(e) print format_text("[FAILED]\n", 'red', 'bold') - # if name in self.user_streams: - # print "Picked name already exist. Please pick another name." - # else: - # try: - # compiled_streams = stream_list.compile_streams() - # self.user_streams[name] = LoadedStreamList(loaded_obj, - # [StreamPack(v.stream_id, v.stream.dump()) - # for k, v in compiled_streams.items()]) - # - # print "Stream list '{0}' loaded successfully".format(name) - # except Exception as e: - # raise return else: - print "please provide load name and YAML path, separated by space.\n" \ - "Optionally, you may provide a third argument to specify multiplier." + 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): @@ -573,7 +535,7 @@ class TRexConsole(cmd.Cmd): def do_stream_db_remove(self, line): args = line.split() if args: - removed_streams = self.streams_db.remove_stream_packs(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))) @@ -604,9 +566,10 @@ class TRexConsole(cmd.Cmd): print format_text("[FAILED]\n", 'red', 'bold') return if args[0] == "all": - ask = YesNoMenu('Are you sure you want to release all acquired ports ? ') + 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() @@ -631,13 +594,15 @@ class TRexConsole(cmd.Cmd): miss=list(set(port_list).difference(owned))) print format_text("[FAILED]\n", 'red', 'bold') else: - print "Please provide list name and ports to attach to, " \ - "or specify 'all' to attach all owned ports." + 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)] @@ -675,14 +640,13 @@ class TRexConsole(cmd.Cmd): 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) - print "\nTrying to remove all streams at ports: " + (" ".join(str(x) for x in port_list)) + "\n" - # rc, resp_list = self.stateless_client.take_ownership(port_list, force) res_ok, log = self.stateless_client.remove_all_streams(port_list) self.prompt_response(log) @@ -695,6 +659,70 @@ class TRexConsole(cmd.Cmd): def complete_remove_all_streams(self, text, line, begidx, endidx): return self.port_auto_complete(text, line, begidx, endidx) + def do_start_traffic(self, line): + # 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 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(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) + + def do_stop_traffic(self, line): + # 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 stop 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_active_ports() + else: + port_list = self.extract_port_ids_from_line(line) + + try: + res_ok, log = self.stateless_client.stop_traffic(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_stop_traffic(self, text, line, begidx, endidx): + return self.port_auto_complete(text, line, begidx, endidx, active=True) + # adds a very simple stream def do_add_simple_stream(self, line): if line == "": -- cgit From 2636c09cfb74c7981c27d84bcc72d00929fdbbbb Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Thu, 29 Oct 2015 07:14:58 +0200 Subject: Fixed verbose mode More stability fixes removed irrelevand methods --- .../trex_control_plane/console/trex_console.py | 123 ++++++++++++--------- 1 file changed, 69 insertions(+), 54 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 5c3668c0..51a1f8cc 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -43,6 +43,23 @@ __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) @@ -169,30 +186,31 @@ class TRexConsole(cmd.Cmd): elif line == "on": self.verbose = True self.stateless_client.set_verbose(True) - print "\nverbose set to on\n" + print green("\nverbose set to on\n") elif line == "off": self.verbose = False self.stateless_client.set_verbose(False) - print "\nverbose set to off\n" + print green("\nverbose set to off\n") else: - print "\nplease specify 'on' or 'off'\n" + 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''' - rc, msg = self.stateless_client.query_rpc_server() - if not rc: - print "\n*** " + msg + "\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\n" + print "\nRPC server supports the following commands:\n" for func in msg: if func: print func - print "\n" + print '' + print format_text("[SUCCESS]\n", 'green', 'bold') + return def do_ping (self, line): '''Pings the RPC server\n''' @@ -253,13 +271,16 @@ class TRexConsole(cmd.Cmd): port_list = self.extract_port_ids_from_line(line) # rc, resp_list = self.stateless_client.take_ownership(port_list, force) - res_ok, log = self.stateless_client.acquire(port_list, force) - self.prompt_response(log) - if not res_ok: + 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') - return - print format_text("[SUCCESS]\n", 'green', 'bold') - return def port_auto_complete(self, text, line, begidx, endidx, acquired=True, active=False): @@ -533,6 +554,7 @@ class TRexConsole(cmd.Cmd): 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) @@ -546,6 +568,7 @@ class TRexConsole(cmd.Cmd): 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') @@ -557,6 +580,7 @@ class TRexConsole(cmd.Cmd): 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] @@ -576,22 +600,26 @@ class TRexConsole(cmd.Cmd): else: port_list = self.extract_port_ids_from_line(' '.join(args[1:])) owned = set(self.stateless_client.get_acquired_ports()) - if set(port_list).issubset(owned): - res_ok, log = self.stateless_client.add_stream_pack(port_list, *stream_list.compiled) - # 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') + try: + if set(port_list).issubset(owned): + res_ok, log = self.stateless_client.add_stream_pack(port_list, *stream_list.compiled) + # 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 - 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))) + 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, " @@ -648,18 +676,22 @@ class TRexConsole(cmd.Cmd): port_list = self.extract_port_ids_from_line(line) # rc, resp_list = self.stateless_client.take_ownership(port_list, force) - res_ok, log = self.stateless_client.remove_all_streams(port_list) - self.prompt_response(log) - if not res_ok: + 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') - return - print format_text("[SUCCESS]\n", 'green', 'bold') - return def complete_remove_all_streams(self, text, line, begidx, endidx): return self.port_auto_complete(text, line, begidx, endidx) 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 args = line.split() if len(args) < 1: @@ -692,6 +724,7 @@ class TRexConsole(cmd.Cmd): return self.port_auto_complete(text, line, begidx, endidx) def do_stop_traffic(self, line): + '''Stop active traffic in specified ports on TRex\n''' # make sure that the user wants to acquire all args = line.split() if len(args) < 1: @@ -723,24 +756,6 @@ class TRexConsole(cmd.Cmd): def complete_stop_traffic(self, text, line, begidx, endidx): return self.port_auto_complete(text, line, begidx, endidx, active=True) - # adds a very simple stream - def do_add_simple_stream(self, line): - if line == "": - add_stream = AddStreamMenu() - add_stream.show() - return - - params = line.split() - port_id = int(params[0]) - stream_id = int(params[1]) - - packet = [0xFF,0xFF,0xFF] - rc, msg = self.stateless_client.add_stream(port_id = port_id, stream_id = stream_id, isg = 1.1, next_stream_id = -1, packet = packet) - if rc: - print "\nServer Response:\n\n" + pretty_json(json.dumps(msg)) + "\n" - else: - print "\n*** " + msg + "\n" - # aliasing do_exit = do_EOF = do_q = do_quit -- cgit From 7d7767e17b1a4e54a8934ded724f54dc5b6228ce Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 1 Nov 2015 18:03:17 +0200 Subject: added support for a new RPC command : sync_user provides a way to sync a console / GUI to the server for a specific user --- scripts/automation/trex_control_plane/console/trex_console.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 51a1f8cc..ec23eb0c 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -393,9 +393,9 @@ class TRexConsole(cmd.Cmd): print "Example: rpc test_add {'x': 12, 'y': 17}\n" return - res_ok, msg = self.stateless_client.invoke_rpc_method(method, params) + res_ok, msg = self.stateless_client.transmit(method, params) if res_ok: - print "\nServer Response:\n\n" + self.stateless_client.pretty_json(json.dumps(msg)) + "\n" + print "\nServer Response:\n\n" + pretty_json(json.dumps(msg)) + "\n" else: print "\n*** " + msg + "\n" #print "Please try 'reconnect' to reconnect to server" -- cgit From 1586ab131f28c03ea65373d9e702e4051ffb9a56 Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 2 Nov 2015 16:14:02 +0200 Subject: status is back online + ZMQ async stats --- scripts/automation/trex_control_plane/console/trex_console.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index ec23eb0c..bd79cb42 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -34,7 +34,6 @@ from common.text_opts import * from client_utils.general_utils import user_input -from client_utils.jsonrpc_client import TrexStatelessClient import trex_status from collections import namedtuple @@ -177,6 +176,7 @@ class TRexConsole(cmd.Cmd): 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''' @@ -770,6 +770,10 @@ def setParserOptions(): default = 5050, type = int) + parser.add_argument("-z", "--pub", help = "TRex Async Publisher Port [default is 4500]\n", + default = 4500, + type = int) + parser.add_argument("-u", "--user", help = "User Name [default is random generated]\n", default = 'user_' + ''.join(random.choice(string.digits) for _ in range(5)), type = str) @@ -782,11 +786,10 @@ def setParserOptions(): def main(): parser = setParserOptions() - options = parser.parse_args()#sys.argv[1:]) + options = parser.parse_args() # Stateless client connection - # stateless_client = TrexStatelessClient(options.server, options.port, options.user) - stateless_client = CTRexStatelessClient(options.user, options.server, options.port) + stateless_client = CTRexStatelessClient(options.user, options.server, options.port, options.pub) # console try: -- cgit From 3fb4e4c130da10e58af07e1f783f093515e90f96 Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 2 Nov 2015 16:40:34 +0200 Subject: few bug fixes for last commit --- scripts/automation/trex_control_plane/console/trex_console.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index bd79cb42..549262c5 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -409,6 +409,10 @@ class TRexConsole(cmd.Cmd): 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) -- cgit From 0ceddc74c938a023c515be4ed2c37198fd66e87e Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Tue, 3 Nov 2015 09:37:42 +0200 Subject: first commit for advnaced options --- scripts/automation/trex_control_plane/console/trex_console.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 549262c5..e707a9e1 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -31,8 +31,7 @@ import trex_root_path from common.trex_streams import * from client.trex_stateless_client import CTRexStatelessClient from common.text_opts import * -from client_utils.general_utils import user_input - +from client_utils.general_utils import user_input, get_current_user import trex_status from collections import namedtuple @@ -778,8 +777,8 @@ def setParserOptions(): default = 4500, type = int) - parser.add_argument("-u", "--user", help = "User Name [default is random generated]\n", - default = 'user_' + ''.join(random.choice(string.digits) for _ in range(5)), + parser.add_argument("-u", "--user", help = "User Name [default is currently logged in user]\n", + default = get_current_user(), type = str) parser.add_argument("--verbose", dest="verbose", -- cgit From 30b87959dc2d8da7f2f2a471a53485d600d8735a Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 4 Nov 2015 11:31:30 +0200 Subject: some fields were missing from the ZMQ publisher --- scripts/automation/trex_control_plane/console/trex_console.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index e707a9e1..8a5b29cc 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -257,7 +257,9 @@ class TRexConsole(cmd.Cmd): # make sure that the user wants to acquire all 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" + 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() -- cgit From e92507617ed8069b674fa5729b1e6a0c5d4b2662 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 5 Nov 2015 09:55:03 +0200 Subject: bug fixes in status window --- scripts/automation/trex_control_plane/console/trex_console.py | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 8a5b29cc..52effa7e 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -251,6 +251,7 @@ class TRexConsole(cmd.Cmd): return port_list + def do_acquire(self, line, force=False): '''Acquire ports\n''' -- cgit From 953a250e6cbaea3040920e7441d2d019705efe51 Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Sat, 7 Nov 2015 13:37:31 +0200 Subject: Extended line parsing options, didn't apply all changes on console YET --- .../trex_control_plane/console/trex_console.py | 111 +++++++++++++-------- 1 file changed, 72 insertions(+), 39 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 8a5b29cc..33b4e164 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -32,7 +32,7 @@ from common.trex_streams import * from client.trex_stateless_client import CTRexStatelessClient 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 @@ -234,6 +234,9 @@ class TRexConsole(cmd.Cmd): 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: @@ -449,42 +452,42 @@ class TRexConsole(cmd.Cmd): 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_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''' @@ -594,7 +597,7 @@ class TRexConsole(cmd.Cmd): print "Provided stream list name '{0}' doesn't exists.".format(stream_pack_name) print format_text("[FAILED]\n", 'red', 'bold') return - if args[0] == "all": + if args[1] == "all": ask = ConfirmMenu('Are you sure you want to release all acquired ports? ') rc = ask.show() if rc == False: @@ -698,6 +701,33 @@ class TRexConsole(cmd.Cmd): 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 + # # 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 + # + # if "all" in opts.port_list: + # 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: + # try: + # port_list = self.extract_port_ids_from_list(opts.port_list) + # except ValueError as e: + # print magenta(e) + # return + args = line.split() if len(args) < 1: print magenta("Please provide a list of ports separated by spaces, " @@ -715,7 +745,7 @@ class TRexConsole(cmd.Cmd): port_list = self.extract_port_ids_from_line(line) try: - res_ok, log = self.stateless_client.start_traffic(port_list) + 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') @@ -728,6 +758,9 @@ class TRexConsole(cmd.Cmd): def complete_start_traffic(self, text, line, begidx, endidx): return self.port_auto_complete(text, line, begidx, endidx) + def help_start_traffic(self): + self.do_start_traffic("-h") + def do_stop_traffic(self, line): '''Stop active traffic in specified ports on TRex\n''' # make sure that the user wants to acquire all -- cgit From 9c32c36b6006d2a81e1a5658a1fb1616eff650f3 Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 9 Nov 2015 17:10:24 +0200 Subject: moved logic to the port class also implemented the state machine for CP port --- scripts/automation/trex_control_plane/console/trex_console.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index a2c738ab..68050fc0 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -778,6 +778,9 @@ class TRexConsole(cmd.Cmd): return else: port_list = self.stateless_client.get_active_ports() + if not port_list: + print magenta("no active ports - operation aborted\n") + return else: port_list = self.extract_port_ids_from_line(line) -- cgit From d04fb533c0843ebcd3eac5fbefa6f418582db7fc Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Tue, 10 Nov 2015 10:16:28 +0200 Subject: Major progress in parsing, not stable yet Most advanced: start, stop functionality --- .../trex_control_plane/console/trex_console.py | 495 ++++++++++++++++----- 1 file changed, 394 insertions(+), 101 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 68050fc0..a61881a1 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -163,6 +163,7 @@ class TRexConsole(cmd.Cmd): self.intro += "\nType 'help' or '?' for supported actions\n" self.verbose = False + self._silent = True self.postcmd(False, "") @@ -177,7 +178,7 @@ class TRexConsole(cmd.Cmd): # set verbose on / off - def do_verbose (self, line): + def do_verbose(self, line): '''Shows or set verbose mode\n''' if line == "": print "\nverbose is " + ("on\n" if self.verbose else "off\n") @@ -211,7 +212,7 @@ class TRexConsole(cmd.Cmd): print format_text("[SUCCESS]\n", 'green', 'bold') return - def do_ping (self, line): + def do_ping(self, line): '''Pings the RPC server\n''' print "\n-> Pinging RPC server" @@ -223,7 +224,7 @@ class TRexConsole(cmd.Cmd): print "\n*** " + msg + "\n" return - def do_force_acquire (self, line): + def do_force_acquire(self, line): '''Acquires ports by force\n''' self.do_acquire(line, True) @@ -367,49 +368,49 @@ 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_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''' @@ -611,7 +612,7 @@ class TRexConsole(cmd.Cmd): owned = set(self.stateless_client.get_acquired_ports()) try: if set(port_list).issubset(owned): - res_ok, log = self.stateless_client.add_stream_pack(port_list, *stream_list.compiled) + 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: @@ -699,14 +700,302 @@ class TRexConsole(cmd.Cmd): 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()) - # + 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: @@ -714,21 +1003,9 @@ class TRexConsole(cmd.Cmd): # # "or specify 'all' to start traffic on all acquired ports") # # return # - # if "all" in opts.port_list: - # 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: - # try: - # port_list = self.extract_port_ids_from_list(opts.port_list) - # except ValueError as e: - # print magenta(e) - # return + + return args = line.split() if len(args) < 1: print magenta("Please provide a list of ports separated by spaces, " @@ -757,46 +1034,60 @@ class TRexConsole(cmd.Cmd): 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 self.port_auto_complete(text, line, begidx, endidx) + return [text] def help_start_traffic(self): self.do_start_traffic("-h") - def do_stop_traffic(self, line): - '''Stop active traffic in specified ports on TRex\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 stop traffic on all acquired ports") + 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 - 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_active_ports() - if not port_list: - print magenta("no active ports - operation aborted\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: - port_list = self.extract_port_ids_from_line(line) + print "\n*** " + msg + "\n" + #print "Please try 'reconnect' to reconnect to server" - try: - res_ok, log = self.stateless_client.stop_traffic(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_stop_traffic(self, text, line, begidx, endidx): - return self.port_auto_complete(text, line, begidx, endidx, active=True) + 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 @@ -808,12 +1099,13 @@ def setParserOptions(): default = "localhost", type = str) - parser.add_argument("-p", "--port", help = "TRex Server Port [default is 5050]\n", - default = 5050, + parser.add_argument("-p", "--port", help = "TRex Server Port [default is 4505]\n", + default = 4505, type = int) - parser.add_argument("-z", "--pub", help = "TRex Async Publisher Port [default is 4500]\n", - default = 4500, + parser.add_argument("--async_port", help = "TRex ASync Publisher Port [default is 4506]\n", + default = 4506, + dest='pub', type = int) parser.add_argument("-u", "--user", help = "User Name [default is currently logged in user]\n", @@ -826,6 +1118,7 @@ def setParserOptions(): return parser + def main(): parser = setParserOptions() options = parser.parse_args() -- cgit From 467382a7611f478d66cf58c1307f079239f7bac6 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 11 Nov 2015 13:48:02 +0200 Subject: lightweight console --- .../trex_control_plane/console/trex_console.py | 1111 ++++---------------- 1 file changed, 194 insertions(+), 917 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') 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" -- cgit From 45b71cff9d0465b77f82e4cd40b64a9f3183c1c7 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Thu, 12 Nov 2015 15:33:30 +0200 Subject: refactor stream object --- scripts/automation/trex_control_plane/console/trex_console.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 06ae762a..5470e694 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -371,12 +371,12 @@ def setParserOptions(): default = "localhost", type = str) - parser.add_argument("-p", "--port", help = "TRex Server Port [default is 5505]\n", - default = 5505, + parser.add_argument("-p", "--port", help = "TRex Server Port [default is 4501]\n", + default = 4501, type = int) - parser.add_argument("--async_port", help = "TRex ASync Publisher Port [default is 4505]\n", - default = 4505, + parser.add_argument("--async_port", help = "TRex ASync Publisher Port [default is 4500]\n", + default = 4500, dest='pub', type = int) -- cgit From 78c6593c5a2d3d2242be7fc659d15eac6b869358 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 12 Nov 2015 16:33:05 +0200 Subject: DRAFT - only for internal purpose --- .../trex_control_plane/console/trex_console.py | 96 +++++++++++++--------- 1 file changed, 58 insertions(+), 38 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 06ae762a..2be643ab 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -160,7 +160,51 @@ class TRexConsole(cmd.Cmd): for x in os.listdir(path) if x.startswith(start_string)] + # annotation method + @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 + + 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 "" + + 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') + + return False + + else: + print format_text("[SUCCESS]\n", 'green', 'bold') + return True + + ####################### shell commands ####################### + def do_ping (self, line): + '''Ping the server\n''' + + rc = self.stateless_client.ping() + if rc.good(): + print format_text("[SUCCESS]\n", 'green', 'bold') + else: + print "\n*** " + rc.err() + "\n" + print format_text("[FAILED]\n", 'red', 'bold') + return + + def do_test (self, line): + print self.stateless_client.get_acquired_ports() # set verbose on / off def do_verbose(self, line): @@ -171,65 +215,41 @@ class TRexConsole(cmd.Cmd): elif line == "on": self.verbose = True self.stateless_client.set_verbose(True) - print green("\nverbose set to on\n") + print format_text("\nverbose set to on\n", 'green', 'bold') elif line == "off": self.verbose = False self.stateless_client.set_verbose(False) - print green("\nverbose set to off\n") + print format_text("\nverbose set to off\n", 'green', 'bold') else: - print magenta("\nplease specify 'on' or 'off'\n") + print format_text("\nplease specify 'on' or 'off'\n", 'bold') + ############### connect def do_connect (self, line): '''Connects to the server\n''' - res_ok, msg = self.stateless_client.connect() - if res_ok: + rc = self.stateless_client.connect() + if rc.good(): print format_text("[SUCCESS]\n", 'green', 'bold') else: - print "\n*** " + msg + "\n" + print "\n*** " + rc.err() + "\n" print format_text("[FAILED]\n", 'red', 'bold') return - self.supported_rpc = self.stateless_client.get_supported_cmds().data - 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''' - @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" + if not self.stateless_client.is_connected(): + print "Not connected to server\n" return - 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 "" - - 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') - - return False - - else: - print format_text("[SUCCESS]\n", 'green', 'bold') - return True - + self.stateless_client.disconnect() + print format_text("[SUCCESS]\n", 'green', 'bold') + ############### start def complete_start(self, text, line, begidx, endidx): -- cgit From 513581840e5787e73161de049aa59552f23e719d Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 12 Nov 2015 18:28:21 +0200 Subject: modifying stateless client to a simpler lightweight module --- scripts/automation/trex_control_plane/console/trex_console.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 2be643ab..5ba82dcb 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -296,7 +296,7 @@ class TRexConsole(cmd.Cmd): return - self.stateless_client.cmd_start(opts.ports, stream_list, opts.mult, opts.force, self.annotate) + self.stateless_client.cmd_start(opts.ports, stream_list, opts.mult, opts.force) return @@ -315,7 +315,7 @@ class TRexConsole(cmd.Cmd): if opts is None: return - self.stateless_client.cmd_stop(opts.ports, self.annotate) + self.stateless_client.cmd_stop(opts.ports) return def help_stop(self): @@ -324,7 +324,7 @@ class TRexConsole(cmd.Cmd): ########## reset def do_reset (self, line): '''force stop all ports\n''' - self.stateless_client.cmd_reset(self.annotate) + self.stateless_client.cmd_reset() # tui -- cgit From 57e67fd2ae248039951798978cc8c1c219c3d752 Mon Sep 17 00:00:00 2001 From: imarom Date: Fri, 13 Nov 2015 14:21:55 +0200 Subject: few mods few fixes TUI is not working yet... need to fix more stuff a checkpoint for now --- .../trex_control_plane/console/trex_console.py | 25 ++++++---------------- 1 file changed, 7 insertions(+), 18 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 5ba82dcb..bd79479d 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -195,12 +195,8 @@ class TRexConsole(cmd.Cmd): def do_ping (self, line): '''Ping the server\n''' - rc = self.stateless_client.ping() - if rc.good(): - print format_text("[SUCCESS]\n", 'green', 'bold') - else: - print "\n*** " + rc.err() + "\n" - print format_text("[FAILED]\n", 'red', 'bold') + rc = self.stateless_client.cmd_ping() + if rc.bad(): return def do_test (self, line): @@ -230,25 +226,18 @@ class TRexConsole(cmd.Cmd): def do_connect (self, line): '''Connects to the server\n''' - rc = self.stateless_client.connect() - if rc.good(): - print format_text("[SUCCESS]\n", 'green', 'bold') - else: - print "\n*** " + rc.err() + "\n" - print format_text("[FAILED]\n", 'red', 'bold') + rc = self.stateless_client.cmd_connect() + if rc.bad(): return def do_disconnect (self, line): '''Disconnect from the server\n''' - if not self.stateless_client.is_connected(): - print "Not connected to server\n" + rc = self.stateless_client.cmd_disconnect() + if rc.bad(): return - self.stateless_client.disconnect() - print format_text("[SUCCESS]\n", 'green', 'bold') - ############### start @@ -332,7 +321,7 @@ class TRexConsole(cmd.Cmd): '''Shows a graphical console\n''' if not self.stateless_client.is_connected(): - print "Not connected to server\n" + print format_text("\nNot connected to server\n", 'bold') return self.do_verbose('off') -- cgit From 2dee3346a79146b8f042ccb3f105498694fc6c4b Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 15 Nov 2015 14:40:21 +0200 Subject: clean shell / client added script for run --- .../trex_control_plane/console/trex_console.py | 150 ++++++--------------- 1 file changed, 40 insertions(+), 110 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') 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) -- cgit From 56becbc13bc2edc1fe60afb6d788357a70147a43 Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 15 Nov 2015 16:34:16 +0200 Subject: few fixes to ZMQ client (timeout values) --- scripts/automation/trex_control_plane/console/trex_console.py | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 88e8dede..7cb65fa6 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -33,6 +33,7 @@ from client.trex_stateless_client import CTRexStatelessClient from common.text_opts import * from client_utils.general_utils import user_input, get_current_user import trex_status +import parsing_opts __version__ = "1.0" -- cgit From bb6dec2ed238069b6a0c079d2031246704b717c4 Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Mon, 16 Nov 2015 21:59:31 +0200 Subject: created general trex console class added dynamic server async support fixed bugs --- .../trex_control_plane/console/trex_console.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 7cb65fa6..8e8b25ec 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -39,6 +39,24 @@ import parsing_opts __version__ = "1.0" +class TRexGeneralCmd(cmd.Cmd): + def __init__(self): + cmd.Cmd.__init__(self) + + def emptyline(self): + """Called when an empty line is entered in response to the prompt. + + This overriding is such that when empty line is passed, **nothing happens**. + """ + return + + def completenames(self, text, *ignored): + """ + This overriding is such that a space is added to name completion. + """ + dotext = 'do_'+text + return [a[3:]+' ' for a in self.get_names() if a.startswith(dotext)] + # # main console object class TRexConsole(cmd.Cmd): -- cgit From 84e9d7a4a8bbb3afb4861652e2d56bc27097f794 Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Thu, 19 Nov 2015 02:30:48 +0200 Subject: History feature is DONE Fixed bugs Cleaned code, more like PEP8 --- .../trex_control_plane/console/trex_console.py | 52 +++++++++++++++++----- 1 file changed, 42 insertions(+), 10 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 8e8b25ec..ea2f5f12 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -23,6 +23,7 @@ import json import ast import argparse import random +import readline import string import os import sys @@ -36,12 +37,38 @@ import trex_status import parsing_opts -__version__ = "1.0" +__version__ = "1.1" class TRexGeneralCmd(cmd.Cmd): def __init__(self): cmd.Cmd.__init__(self) + # configure history behaviour + self._history_file_dir = "/tmp/trex/console/" + self._history_file = self.get_history_file_full_path() + readline.set_history_length(100) + # load history, if any + self.load_console_history() + + + def get_console_identifier(self): + return self.__class__.__name__ + + def get_history_file_full_path(self): + return "{dir}{filename}.hist".format(dir=self._history_file_dir, + filename=self.get_console_identifier()) + + def load_console_history(self): + if os.path.exists(self._history_file): + readline.read_history_file(self._history_file) + return + + def save_console_history(self): + if not os.path.exists(self._history_file_dir): + os.makedirs(self._history_file_dir) + # os.mknod(self._history_file) + readline.write_history_file(self._history_file) + return def emptyline(self): """Called when an empty line is entered in response to the prompt. @@ -57,15 +84,22 @@ class TRexGeneralCmd(cmd.Cmd): dotext = 'do_'+text return [a[3:]+' ' for a in self.get_names() if a.startswith(dotext)] + def precmd(self, line): + # before doing anything, save history snapshot of the console + # this is done before executing the command in case of ungraceful application exit + self.save_console_history() + return line + + # # main console object -class TRexConsole(cmd.Cmd): +class TRexConsole(TRexGeneralCmd): """Trex Console""" - def __init__(self, stateless_client, acquire_all_ports = True, verbose = False): - cmd.Cmd.__init__(self) - + def __init__(self, stateless_client, acquire_all_ports=True, verbose=False): self.stateless_client = stateless_client + TRexGeneralCmd.__init__(self) + self.verbose = verbose self.acquire_all_ports = acquire_all_ports @@ -78,11 +112,9 @@ class TRexConsole(cmd.Cmd): ################### 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 get_console_identifier(self): + return "{context}_{server}".format(context=self.__class__.__name__, + server=self.stateless_client.get_system_info()['hostname']) def register_main_console_methods(self): main_names = set(self.trex_console.get_names()).difference(set(dir(self.__class__))) -- cgit From 903b855393acd411e85b25e6b2df1158d9fe2856 Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 22 Nov 2015 11:07:40 +0200 Subject: TUI back online --- scripts/automation/trex_control_plane/console/trex_console.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index ea2f5f12..995965fd 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -197,8 +197,6 @@ class TRexConsole(TRexGeneralCmd): if rc.bad(): return - def do_test (self, line): - print self.stateless_client.get_acquired_ports() # set verbose on / off def do_verbose(self, line): @@ -252,7 +250,7 @@ class TRexConsole(TRexGeneralCmd): return TRexConsole.tree_autocomplete(s[l - 1]) def do_start(self, line): - '''Start selected traffic in specified ports on TRex\n''' + '''Start selected traffic in specified port(s) on TRex\n''' self.stateless_client.cmd_start_line(line) @@ -262,6 +260,7 @@ class TRexConsole(TRexGeneralCmd): ############# stop def do_stop(self, line): + '''stops port(s) transmitting traffic\n''' self.stateless_client.cmd_stop_line(line) -- cgit From 54c1f0fc29b3d4580f7a13cffbe625fe88e37b16 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Mon, 23 Nov 2015 14:10:19 +0200 Subject: add pause/resume into the console --- scripts/automation/trex_control_plane/console/trex_console.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 995965fd..c03f2a82 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -263,6 +263,16 @@ class TRexConsole(TRexGeneralCmd): '''stops port(s) transmitting traffic\n''' self.stateless_client.cmd_stop_line(line) + ############# stop + def do_pause(self, line): + '''pause port(s) transmitting traffic\n''' + self.stateless_client.cmd_pause_line(line) + + ############# stop + def do_resume(self, line): + '''resume port(s) transmitting traffic\n''' + self.stateless_client.cmd_resume_line(line) + def help_stop(self): -- cgit From 1e1c11059b7f7fcb5c160dffe2df832a8adf719d Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Tue, 24 Nov 2015 11:41:19 +0200 Subject: minor console fix --- scripts/automation/trex_control_plane/console/trex_console.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index c03f2a82..2a6fd2eb 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -263,12 +263,12 @@ class TRexConsole(TRexGeneralCmd): '''stops port(s) transmitting traffic\n''' self.stateless_client.cmd_stop_line(line) - ############# stop + ############# pause def do_pause(self, line): '''pause port(s) transmitting traffic\n''' self.stateless_client.cmd_pause_line(line) - ############# stop + ############# resume def do_resume(self, line): '''resume port(s) transmitting traffic\n''' self.stateless_client.cmd_resume_line(line) -- cgit From 963da09589fe8376f2750e4d0dc741d48eea6132 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 25 Nov 2015 03:51:37 -0500 Subject: added history command support - you can show the history or execute a previous command --- .../trex_control_plane/console/trex_console.py | 57 +++++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 2a6fd2eb..0dabe2c3 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -70,6 +70,23 @@ class TRexGeneralCmd(cmd.Cmd): readline.write_history_file(self._history_file) return + def print_history (self): + + length = readline.get_current_history_length() + + for i in xrange(1, length + 1): + cmd = readline.get_history_item(i) + print "{:<5} {:}".format(i, cmd) + + def get_history_item (self, index): + length = readline.get_current_history_length() + if index > length: + print format_text("please select an index between {0} and {1}".format(0, length)) + return None + + return readline.get_history_item(index) + + def emptyline(self): """Called when an empty line is entered in response to the prompt. @@ -217,6 +234,41 @@ class TRexConsole(TRexGeneralCmd): else: print format_text("\nplease specify 'on' or 'off'\n", 'bold') + # show history + def help_history (self): + self.do_history("-h") + + def do_history (self, line): + '''Manage the command history\n''' + + item = parsing_opts.ArgumentPack(['item'], + {"nargs": '?', + 'metavar': 'item', + 'type': parsing_opts.check_negative, + 'help': "an history item index", + 'default': 0}) + + parser = parsing_opts.gen_parser(self, + "history", + self.do_history.__doc__, + item) + + opts = parser.parse_args(line.split()) + if opts is None: + return + + if opts.item == 0: + self.print_history() + else: + cmd = self.get_history_item(opts.item) + print cmd + if cmd == None: + return + + print cmd + self.onecmd(cmd) + + ############### connect def do_connect (self, line): @@ -324,7 +376,7 @@ class TRexConsole(TRexGeneralCmd): 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")): + if ( (cmd == "EOF") or (cmd == "q") or (cmd == "exit") or (cmd == "h")): continue try: @@ -338,8 +390,9 @@ class TRexConsole(TRexGeneralCmd): print "{:<30} {:<30}".format(cmd + " - ", help) + # aliases do_exit = do_EOF = do_q = do_quit - + do_h = do_history # def is_valid_file(filename): -- cgit From b0446de90c05d0a129fc38e6aef981dff243ccb7 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 25 Nov 2015 04:11:29 -0500 Subject: removed some garbage prints --- scripts/automation/trex_control_plane/console/trex_console.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 0dabe2c3..dc1515e0 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -261,11 +261,9 @@ class TRexConsole(TRexGeneralCmd): self.print_history() else: cmd = self.get_history_item(opts.item) - print cmd if cmd == None: return - print cmd self.onecmd(cmd) -- cgit From 92dea3787ab7b2c9877af9cd539d42a6957f7da6 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 25 Nov 2015 06:56:04 -0500 Subject: added events log --- scripts/automation/trex_control_plane/console/trex_console.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index dc1515e0..b164af4e 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -334,6 +334,12 @@ class TRexConsole(TRexGeneralCmd): self.stateless_client.cmd_reset() + def do_events (self, line): + '''shows events recieved from server\n''' + events = self.stateless_client.get_events() + for ev in events: + print ev + # tui def do_tui (self, line): '''Shows a graphical console\n''' -- cgit From b6ec2066653319b60385de1d4117165eb88890a1 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 25 Nov 2015 07:39:39 -0500 Subject: fixed a bug with default start command in the console also added clear events and more types of events --- .../trex_control_plane/console/trex_console.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index b164af4e..fc2c845a 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -334,12 +334,34 @@ class TRexConsole(TRexGeneralCmd): self.stateless_client.cmd_reset() + def help_events (self): + self.do_events("-h") + def do_events (self, line): '''shows events recieved from server\n''' + + x = parsing_opts.ArgumentPack(['-c','--clear'], + {'action' : "store_true", + 'default': False, + 'help': "clear the events log"}) + + parser = parsing_opts.gen_parser(self, + "events", + self.do_events.__doc__, + x) + + opts = parser.parse_args(line.split()) + if opts is None: + return + events = self.stateless_client.get_events() for ev in events: print ev + if opts.clear: + self.stateless_client.clear_events() + print format_text("\n\nEvent log was cleared\n\n") + # tui def do_tui (self, line): '''Shows a graphical console\n''' -- cgit From d9a11302236095e055247295021bdfce6c988802 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 26 Nov 2015 02:30:03 -0500 Subject: added support for 'update' --- .../trex_control_plane/console/trex_console.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index fc2c845a..9e44daac 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -313,6 +313,17 @@ class TRexConsole(TRexGeneralCmd): '''stops port(s) transmitting traffic\n''' self.stateless_client.cmd_stop_line(line) + def help_stop(self): + self.do_stop("-h") + + ############# update + def do_update(self, line): + '''update speed of port(s)currently transmitting traffic\n''' + self.stateless_client.cmd_update_line(line) + + def help_update (self): + self.do_update("-h") + ############# pause def do_pause(self, line): '''pause port(s) transmitting traffic\n''' @@ -323,10 +334,7 @@ class TRexConsole(TRexGeneralCmd): '''resume port(s) transmitting traffic\n''' self.stateless_client.cmd_resume_line(line) - - - def help_stop(self): - self.do_stop("-h") + ########## reset def do_reset (self, line): -- cgit From 91f6c24f45cbb0cbf8568a9938059a1a934e6ae6 Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Thu, 26 Nov 2015 13:06:36 +0200 Subject: Initial implementation of stats prompting --- scripts/automation/trex_control_plane/console/trex_console.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index c03f2a82..7d4f3c27 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -33,8 +33,9 @@ from common.trex_streams import * from client.trex_stateless_client import CTRexStatelessClient from common.text_opts import * from client_utils.general_utils import user_input, get_current_user +from client_utils import parsing_opts import trex_status -import parsing_opts + __version__ = "1.1" @@ -283,6 +284,14 @@ class TRexConsole(TRexGeneralCmd): '''force stop all ports\n''' self.stateless_client.cmd_reset() + def do_stats(self, line): + '''Fetch statistics from TRex server by port\n''' + self.stateless_client.cmd_stats_line(line) + pass + + def help_stats(self): + self.do_stats("-h") + # tui def do_tui (self, line): -- cgit From 27a7103d501e9a0bf005d657cb3f7c51a72eca6b Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 26 Nov 2015 09:00:58 -0500 Subject: when connection is lost - identify this on the console --- .../trex_control_plane/console/trex_console.py | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 9e44daac..e537c306 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -210,6 +210,10 @@ class TRexConsole(TRexGeneralCmd): def do_ping (self, line): '''Ping the server\n''' + if not self.stateless_client.is_connected(): + print format_text("\nNot connected to server\n", 'bold') + return + rc = self.stateless_client.cmd_ping() if rc.bad(): return @@ -302,6 +306,10 @@ class TRexConsole(TRexGeneralCmd): def do_start(self, line): '''Start selected traffic in specified port(s) on TRex\n''' + if not self.stateless_client.is_connected(): + print format_text("\nNot connected to server\n", 'bold') + return + self.stateless_client.cmd_start_line(line) @@ -311,6 +319,11 @@ class TRexConsole(TRexGeneralCmd): ############# stop def do_stop(self, line): '''stops port(s) transmitting traffic\n''' + + if not self.stateless_client.is_connected(): + print format_text("\nNot connected to server\n", 'bold') + return + self.stateless_client.cmd_stop_line(line) def help_stop(self): @@ -319,6 +332,11 @@ class TRexConsole(TRexGeneralCmd): ############# update def do_update(self, line): '''update speed of port(s)currently transmitting traffic\n''' + + if not self.stateless_client.is_connected(): + print format_text("\nNot connected to server\n", 'bold') + return + self.stateless_client.cmd_update_line(line) def help_update (self): @@ -327,11 +345,21 @@ class TRexConsole(TRexGeneralCmd): ############# pause def do_pause(self, line): '''pause port(s) transmitting traffic\n''' + + if not self.stateless_client.is_connected(): + print format_text("\nNot connected to server\n", 'bold') + return + self.stateless_client.cmd_pause_line(line) ############# resume def do_resume(self, line): '''resume port(s) transmitting traffic\n''' + + if not self.stateless_client.is_connected(): + print format_text("\nNot connected to server\n", 'bold') + return + self.stateless_client.cmd_resume_line(line) @@ -339,6 +367,11 @@ class TRexConsole(TRexGeneralCmd): ########## reset def do_reset (self, line): '''force stop all ports\n''' + + if not self.stateless_client.is_connected(): + print format_text("\nNot connected to server\n", 'bold') + return + self.stateless_client.cmd_reset() -- cgit From a609111bc37ef88f14d4f2ebf7cd186b04b86402 Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Sun, 29 Nov 2015 00:25:07 +0200 Subject: Supports all desired stats option, plus clearing option --- scripts/automation/trex_control_plane/console/trex_console.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 3ddfd8c6..9236ce98 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -350,6 +350,13 @@ class TRexConsole(TRexGeneralCmd): def help_stats(self): self.do_stats("-h") + def do_clear(self, line): + '''Clear cached local statistics\n''' + self.stateless_client.cmd_clear_line(line) + + def help_clear(self): + self.do_clear("-h") + def help_events (self): self.do_events("-h") -- cgit From a48cd6471a2d82e5d78e8abe85b065f66a388e11 Mon Sep 17 00:00:00 2001 From: imarom Date: Tue, 1 Dec 2015 03:46:21 -0500 Subject: 1. fixed ZMQ message limitation 2. added some scale yamls for IMIX (300 streams, 1000 streams) 3. return objects are always complex objects (not strings) - for backward compatability 4. some minor adjustments to ZMQ socket timeouts --- scripts/automation/trex_control_plane/console/trex_console.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index e537c306..be8fb70e 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -372,7 +372,7 @@ class TRexConsole(TRexGeneralCmd): print format_text("\nNot connected to server\n", 'bold') return - self.stateless_client.cmd_reset() + self.stateless_client.cmd_reset_line(line) def help_events (self): -- cgit From a6af2a8e624c62d9a347215321c6562f28879d97 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 3 Dec 2015 06:07:20 -0500 Subject: various fixes (each one is a minor one) --- .../trex_control_plane/console/trex_console.py | 65 ++++++++++------------ 1 file changed, 30 insertions(+), 35 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index be8fb70e..73f4f612 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -35,7 +35,7 @@ from common.text_opts import * from client_utils.general_utils import user_input, get_current_user import trex_status import parsing_opts - +from functools import wraps __version__ = "1.1" @@ -128,6 +128,18 @@ class TRexConsole(TRexGeneralCmd): ################### internal section ######################## + def verify_connected(f): + @wraps(f) + def wrap(*args): + inst = args[0] + if not inst.stateless_client.is_connected(): + print format_text("\nNot connected to server\n", 'bold') + return + + ret = f(*args) + return ret + + return wrap def get_console_identifier(self): return "{context}_{server}".format(context=self.__class__.__name__, @@ -207,13 +219,9 @@ class TRexConsole(TRexGeneralCmd): ####################### shell commands ####################### + @verify_connected def do_ping (self, line): '''Ping the server\n''' - - if not self.stateless_client.is_connected(): - print format_text("\nNot connected to server\n", 'bold') - return - rc = self.stateless_client.cmd_ping() if rc.bad(): return @@ -303,13 +311,10 @@ class TRexConsole(TRexGeneralCmd): if (l > 2) and (s[l - 2] in file_flags): return TRexConsole.tree_autocomplete(s[l - 1]) + @verify_connected def do_start(self, line): '''Start selected traffic in specified port(s) on TRex\n''' - if not self.stateless_client.is_connected(): - print format_text("\nNot connected to server\n", 'bold') - return - self.stateless_client.cmd_start_line(line) @@ -317,64 +322,57 @@ class TRexConsole(TRexGeneralCmd): self.do_start("-h") ############# stop + @verify_connected def do_stop(self, line): '''stops port(s) transmitting traffic\n''' - if not self.stateless_client.is_connected(): - print format_text("\nNot connected to server\n", 'bold') - return - self.stateless_client.cmd_stop_line(line) def help_stop(self): self.do_stop("-h") ############# update + @verify_connected def do_update(self, line): '''update speed of port(s)currently transmitting traffic\n''' - if not self.stateless_client.is_connected(): - print format_text("\nNot connected to server\n", 'bold') - return - self.stateless_client.cmd_update_line(line) def help_update (self): self.do_update("-h") ############# pause + @verify_connected def do_pause(self, line): '''pause port(s) transmitting traffic\n''' - if not self.stateless_client.is_connected(): - print format_text("\nNot connected to server\n", 'bold') - return - self.stateless_client.cmd_pause_line(line) ############# resume + @verify_connected def do_resume(self, line): '''resume port(s) transmitting traffic\n''' - if not self.stateless_client.is_connected(): - print format_text("\nNot connected to server\n", 'bold') - return - self.stateless_client.cmd_resume_line(line) ########## reset + @verify_connected def do_reset (self, line): '''force stop all ports\n''' - if not self.stateless_client.is_connected(): - print format_text("\nNot connected to server\n", 'bold') - return - self.stateless_client.cmd_reset_line(line) - + + ######### validate + @verify_connected + def do_validate (self, line): + '''validates port(s) stream configuration\n''' + + self.stateless_client.cmd_validate_line(line) + + def help_events (self): self.do_events("-h") @@ -404,13 +402,10 @@ class TRexConsole(TRexGeneralCmd): print format_text("\n\nEvent log was cleared\n\n") # tui + @verify_connected def do_tui (self, line): '''Shows a graphical console\n''' - if not self.stateless_client.is_connected(): - print format_text("\nNot connected to server\n", 'bold') - return - self.do_verbose('off') trex_status.show_trex_status(self.stateless_client) -- cgit From 026f949fbafbb00fd7a21f3d84a632f5745003ea Mon Sep 17 00:00:00 2001 From: imarom Date: Sun, 6 Dec 2015 08:11:42 -0500 Subject: ZMQ bug - connect / disconnect fron another thread on pyhton (not safe !) fixed and more hardening --- scripts/automation/trex_control_plane/console/trex_console.py | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 73f4f612..9d855f98 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -153,6 +153,7 @@ class TRexConsole(TRexGeneralCmd): self.__dict__[name] = getattr(self.trex_console, name) def postcmd(self, stop, line): + if self.stateless_client.is_connected(): self.prompt = "TRex > " else: -- cgit From feb152b7d5eb531d439a4950d27cbc44031daf92 Mon Sep 17 00:00:00 2001 From: imarom Date: Tue, 8 Dec 2015 07:43:24 -0500 Subject: text based TUI (does not use ncurses) --- scripts/automation/trex_control_plane/console/trex_console.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index e187c8c2..8d52b2a4 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -34,8 +34,7 @@ from client.trex_stateless_client import CTRexStatelessClient from common.text_opts import * from client_utils.general_utils import user_input, get_current_user from client_utils import parsing_opts -import trex_status -import parsing_opts +import trex_tui from functools import wraps @@ -119,6 +118,7 @@ class TRexConsole(TRexGeneralCmd): self.stateless_client = stateless_client TRexGeneralCmd.__init__(self) + self.tui = trex_tui.TrexTUI(stateless_client) self.verbose = verbose self.acquire_all_ports = acquire_all_ports @@ -425,7 +425,7 @@ class TRexConsole(TRexGeneralCmd): '''Shows a graphical console\n''' self.do_verbose('off') - trex_status.show_trex_status(self.stateless_client) + self.tui.show() # quit function def do_quit(self, line): -- cgit From 1355327e97e6d5ce5800fa4d6f879695922e8637 Mon Sep 17 00:00:00 2001 From: imarom Date: Tue, 8 Dec 2015 11:42:59 -0500 Subject: some modifications to the tables added clear stats as well --- scripts/automation/trex_control_plane/console/trex_console.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 8d52b2a4..9140977a 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -238,12 +238,12 @@ class TRexConsole(TRexGeneralCmd): elif line == "on": self.verbose = True - self.stateless_client.set_verbose(True) + self.stateless_client.set_verbose(self.stateless_client.VERBOSE_HIGH) print format_text("\nverbose set to on\n", 'green', 'bold') elif line == "off": self.verbose = False - self.stateless_client.set_verbose(False) + self.stateless_client.set_verbose(self.stateless_client.VERBOSE_REGULAR) print format_text("\nverbose set to off\n", 'green', 'bold') else: @@ -424,8 +424,11 @@ class TRexConsole(TRexGeneralCmd): def do_tui (self, line): '''Shows a graphical console\n''' - self.do_verbose('off') + save_verbose = self.stateless_client.get_verbose() + + self.stateless_client.set_verbose(self.stateless_client.VERBOSE_SILENCE) self.tui.show() + self.stateless_client.set_verbose(save_verbose) # quit function def do_quit(self, line): -- cgit From 95c2405d6373ca3c6b69efc3faf293cd41a55c76 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 9 Dec 2015 15:01:25 -0500 Subject: read only support --- .../trex_control_plane/console/trex_console.py | 78 +++++++++++++++++----- 1 file changed, 62 insertions(+), 16 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 9140977a..495e1c22 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -130,12 +130,17 @@ class TRexConsole(TRexGeneralCmd): ################### internal section ######################## + def verify_connected(f): @wraps(f) def wrap(*args): inst = args[0] + func_name = f.__name__ + if func_name.startswith("do_"): + func_name = func_name[3:] + if not inst.stateless_client.is_connected(): - print format_text("\nNot connected to server\n", 'bold') + print format_text("\n'{0}' cannot be executed on offline mode\n".format(func_name), 'bold') return ret = f(*args) @@ -143,9 +148,32 @@ class TRexConsole(TRexGeneralCmd): return wrap + # TODO: remove this ugly duplication + def verify_connected_and_rw (f): + @wraps(f) + def wrap(*args): + inst = args[0] + func_name = f.__name__ + if func_name.startswith("do_"): + func_name = func_name[3:] + + if not inst.stateless_client.is_connected(): + print format_text("\n'{0}' cannot be executed on offline mode\n".format(func_name), 'bold') + return + + if inst.stateless_client.is_read_only(): + print format_text("\n'{0}' cannot be executed on read only mode\n".format(func_name), 'bold') + return + + ret = f(*args) + return ret + + return wrap + + def get_console_identifier(self): return "{context}_{server}".format(context=self.__class__.__name__, - server=self.stateless_client.get_system_info()['hostname']) + server=self.stateless_client.get_server()) def register_main_console_methods(self): main_names = set(self.trex_console.get_names()).difference(set(dir(self.__class__))) @@ -156,11 +184,17 @@ class TRexConsole(TRexGeneralCmd): def postcmd(self, stop, line): - if self.stateless_client.is_connected(): - self.prompt = "TRex > " - else: - self.supported_rpc = None + if not self.stateless_client.is_connected(): self.prompt = "TRex (offline) > " + self.supported_rpc = None + return stop + + if self.stateless_client.is_read_only(): + self.prompt = "TRex (read only) > " + return stop + + + self.prompt = "TRex > " return stop @@ -287,7 +321,7 @@ class TRexConsole(TRexGeneralCmd): def do_connect (self, line): '''Connects to the server\n''' - rc = self.stateless_client.cmd_connect() + rc = self.stateless_client.cmd_connect_line(line) if rc.bad(): return @@ -314,7 +348,7 @@ class TRexConsole(TRexGeneralCmd): if (l > 2) and (s[l - 2] in file_flags): return TRexConsole.tree_autocomplete(s[l - 1]) - @verify_connected + @verify_connected_and_rw def do_start(self, line): '''Start selected traffic in specified port(s) on TRex\n''' @@ -325,7 +359,7 @@ class TRexConsole(TRexGeneralCmd): self.do_start("-h") ############# stop - @verify_connected + @verify_connected_and_rw def do_stop(self, line): '''stops port(s) transmitting traffic\n''' @@ -335,7 +369,7 @@ class TRexConsole(TRexGeneralCmd): self.do_stop("-h") ############# update - @verify_connected + @verify_connected_and_rw def do_update(self, line): '''update speed of port(s)currently transmitting traffic\n''' @@ -345,14 +379,14 @@ class TRexConsole(TRexGeneralCmd): self.do_update("-h") ############# pause - @verify_connected + @verify_connected_and_rw def do_pause(self, line): '''pause port(s) transmitting traffic\n''' self.stateless_client.cmd_pause_line(line) ############# resume - @verify_connected + @verify_connected_and_rw def do_resume(self, line): '''resume port(s) transmitting traffic\n''' @@ -361,7 +395,7 @@ class TRexConsole(TRexGeneralCmd): ########## reset - @verify_connected + @verify_connected_and_rw def do_reset (self, line): '''force stop all ports\n''' self.stateless_client.cmd_reset_line(line) @@ -375,6 +409,7 @@ class TRexConsole(TRexGeneralCmd): self.stateless_client.cmd_validate_line(line) + @verify_connected def do_stats(self, line): '''Fetch statistics from TRex server by port\n''' self.stateless_client.cmd_stats_line(line) @@ -383,6 +418,7 @@ class TRexConsole(TRexGeneralCmd): def help_stats(self): self.do_stats("-h") + @verify_connected def do_clear(self, line): '''Clear cached local statistics\n''' self.stateless_client.cmd_clear_line(line) @@ -529,9 +565,17 @@ def main(): # Stateless client connection stateless_client = CTRexStatelessClient(options.user, options.server, options.port, options.pub) - rc = stateless_client.cmd_connect() + + print "\nlogged as {0}".format(format_text(options.user, 'bold')) + rc = stateless_client.connect() + + # error can be either no able to connect or a read only if rc.bad(): - return + if not stateless_client.is_connected(): + rc.annotate() + else: + rc.annotate(show_status = False) + if options.batch: cont = stateless_client.run_script_file(options.batch[0]) @@ -544,7 +588,9 @@ def main(): console.cmdloop() except KeyboardInterrupt as e: print "\n\n*** Caught Ctrl + C... Exiting...\n\n" - return + + finally: + stateless_client.shutdown() if __name__ == '__main__': main() -- cgit From 7567166ca52bd136ce08c06dcbd48c0dfd67210f Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 10 Dec 2015 03:43:55 -0500 Subject: removed session id - not necessary --- scripts/automation/trex_control_plane/console/trex_console.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 495e1c22..e8f90186 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -575,6 +575,7 @@ def main(): rc.annotate() else: rc.annotate(show_status = False) + print format_text("Switching to read only mode - only few commands will be available", 'bold') if options.batch: @@ -590,7 +591,7 @@ def main(): print "\n\n*** Caught Ctrl + C... Exiting...\n\n" finally: - stateless_client.shutdown() + stateless_client.disconnect() if __name__ == '__main__': main() -- cgit From fc4b8bddcb4550cbf8d06e414b82a1d082d1d996 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 10 Dec 2015 06:56:17 -0500 Subject: added a "--tui" feature to the console it opens in read only mode and runs the TUI --- .../trex_control_plane/console/trex_console.py | 40 +++++++++++++--------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index e8f90186..0ecfce9c 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -114,14 +114,13 @@ class TRexGeneralCmd(cmd.Cmd): class TRexConsole(TRexGeneralCmd): """Trex Console""" - def __init__(self, stateless_client, acquire_all_ports=True, verbose=False): + def __init__(self, stateless_client, verbose=False): self.stateless_client = stateless_client TRexGeneralCmd.__init__(self) self.tui = trex_tui.TrexTUI(stateless_client) self.verbose = verbose - self.acquire_all_ports = acquire_all_ports self.intro = "\n-=TRex Console v{ver}=-\n".format(ver=__version__) self.intro += "\nType 'help' or '?' for supported actions\n" @@ -321,17 +320,13 @@ class TRexConsole(TRexGeneralCmd): def do_connect (self, line): '''Connects to the server\n''' - rc = self.stateless_client.cmd_connect_line(line) - if rc.bad(): - return + self.stateless_client.cmd_connect_line(line) def do_disconnect (self, line): '''Disconnect from the server\n''' - rc = self.stateless_client.cmd_disconnect() - if rc.bad(): - return + self.stateless_client.cmd_disconnect() ############### start @@ -556,6 +551,10 @@ def setParserOptions(): help = "Run the console in a batch mode with file", default = None) + parser.add_argument("-t", "--tui", dest="tui", + action="store_true", help="Starts with TUI mode", + default = False) + return parser @@ -567,17 +566,20 @@ def main(): stateless_client = CTRexStatelessClient(options.user, options.server, options.port, options.pub) print "\nlogged as {0}".format(format_text(options.user, 'bold')) - rc = stateless_client.connect() - # error can be either no able to connect or a read only + # TUI or no acquire will give us READ ONLY mode + if options.tui or not options.acquire: + rc = stateless_client.connect("RO") + else: + rc = stateless_client.connect("RW") + + # unable to connect - bye if rc.bad(): - if not stateless_client.is_connected(): - rc.annotate() - else: - rc.annotate(show_status = False) - print format_text("Switching to read only mode - only few commands will be available", 'bold') + rc.annotate() + return + # a script mode if options.batch: cont = stateless_client.run_script_file(options.batch[0]) if not cont: @@ -585,8 +587,12 @@ def main(): # console try: - console = TRexConsole(stateless_client, options.acquire, options.verbose) - console.cmdloop() + console = TRexConsole(stateless_client, options.verbose) + if options.tui: + console.do_tui("") + else: + console.cmdloop() + except KeyboardInterrupt as e: print "\n\n*** Caught Ctrl + C... Exiting...\n\n" -- cgit