diff options
author | Dan Klein <danklein10@gmail.com> | 2015-11-10 10:16:28 +0200 |
---|---|---|
committer | Dan Klein <danklein10@gmail.com> | 2015-11-10 10:21:52 +0200 |
commit | d04fb533c0843ebcd3eac5fbefa6f418582db7fc (patch) | |
tree | 7df9e69736440a05ce153afa28ff52fb31b6214f /scripts/automation | |
parent | 6394039f728bc73918f9c0c1bb8ba5dcc85c5cb1 (diff) |
Major progress in parsing, not stable yet
Most advanced: start, stop functionality
Diffstat (limited to 'scripts/automation')
3 files changed, 488 insertions, 130 deletions
diff --git a/scripts/automation/trex_control_plane/client/trex_stateless_client.py b/scripts/automation/trex_control_plane/client/trex_stateless_client.py index 627c3365..11728965 100755 --- a/scripts/automation/trex_control_plane/client/trex_stateless_client.py +++ b/scripts/automation/trex_control_plane/client/trex_stateless_client.py @@ -51,10 +51,10 @@ class CTRexStatelessClient(object): # print args # print kwargs port_ids = kwargs.get("port_id") - if not port_ids: - # print "FROM ARGS!" - # print args - port_ids = args[0] + # if not port_ids: + # # print "FROM ARGS!" + # # print args + # port_ids = args[0] if isinstance(port_ids, int): # make sure port_ids is a list port_ids = [port_ids] @@ -74,8 +74,8 @@ class CTRexStatelessClient(object): continue if bad_ids: # Some port IDs are not according to desires status - raise ValueError("The requested method ('{0}') cannot be invoked since port IDs {1} are not " - "at allowed states".format(func.__name__, list(bad_ids))) + raise ValueError("The requested method ('{0}') cannot be invoked since port IDs {1} aren't " + "acquired".format(func.__name__, list(bad_ids))) else: return func(self, *args, **kwargs) return wrapper_f @@ -232,7 +232,8 @@ class CTRexStatelessClient(object): self.transmit(command.method, command.params), self.ack_success_test) - @force_status(owned=True) + # @force_status(owned=True) + @acquired def add_stream(self, stream_id, stream_obj, port_id=None): if not self._is_ports_valid(port_id): raise ValueError("Provided illegal port id input") @@ -243,15 +244,16 @@ class CTRexStatelessClient(object): "stream": stream_obj.dump()} return self.transmit("add_stream", params) - @force_status(owned=True) - def add_stream_pack(self, port_id=None, *stream_packs): + # @force_status(owned=True) + @acquired + def add_stream_pack(self, stream_pack_list, port_id=None): if not self._is_ports_valid(port_id): raise ValueError("Provided illegal port id input") # since almost every run contains more than one transaction with server, handle all as batch mode port_ids = set(port_id) # convert to set to avoid duplications commands = [] - for stream_pack in stream_packs: + for stream_pack in stream_pack_list: commands.extend([RpcCmdData("add_stream", {"port_id": p_id, "handler": self._conn_handler.get(p_id), "stream_id": stream_pack.stream_id, @@ -273,7 +275,8 @@ class CTRexStatelessClient(object): "stream_id": stream_id} return self.transmit("remove_stream", params) - @force_status(owned=True) + # @force_status(owned=True) + @acquired def remove_all_streams(self, port_id=None): if not self._is_ports_valid(port_id): raise ValueError("Provided illegal port id input") @@ -347,13 +350,17 @@ class CTRexStatelessClient(object): self.transmit(command.method, command.params), self.ack_success_test) - @force_status(owned=False, active_and_owned=True) + # @force_status(owned=False, active_and_owned=True) + @acquired def stop_traffic(self, port_id=None): if not self._is_ports_valid(port_id): raise ValueError("Provided illegal port id input") if isinstance(port_id, list) or isinstance(port_id, set): # handle as batch mode port_ids = set(port_id) # convert to set to avoid duplications + if not port_ids: + # don't invoke if port ids is empty + return True, [] commands = [RpcCmdData("stop_traffic", {"handler": self._conn_handler.get(p_id), "port_id": p_id}) for p_id in port_ids] rc, resp_list = self.transmit_batch(commands) diff --git a/scripts/automation/trex_control_plane/console/parsing_opts.py b/scripts/automation/trex_control_plane/console/parsing_opts.py index c94a7461..e701b7db 100755 --- a/scripts/automation/trex_control_plane/console/parsing_opts.py +++ b/scripts/automation/trex_control_plane/console/parsing_opts.py @@ -1,6 +1,7 @@ import argparse from collections import namedtuple import sys +import re ArgumentPack = namedtuple('ArgumentPack', ['name_or_flags', 'options']) ArgumentGroup = namedtuple('ArgumentGroup', ['type', 'args', 'options']) @@ -14,29 +15,88 @@ PORT_LIST_WITH_ALL = 4 FILE_PATH = 5 FILE_FROM_DB = 6 STREAM_FROM_PATH_OR_FILE = 7 +DURATION = 8 +FORCE = 9 # list of ArgumentGroup types MUTEX = 1 +def match_time_unit(val): + '''match some val against time shortcut inputs ''' + match = re.match("^(\d+)([m|h]?)$", val) + if match: + digit = int(match.group(1)) + unit = match.group(2) + if not unit: + return digit + elif unit == 'm': + return digit*60 + else: + return digit*60*60 + else: + raise argparse.ArgumentTypeError("Duration should be passed in the following format: \n" + "-d 100 : in sec \n" + "-d 10m : in min \n" + "-d 1h : in hours") + +def match_multiplier(val): + '''match some val against multiplier shortcut inputs ''' + match = re.match("^(\d+)(gb|kpps|%?)$", val) + if match: + digit = int(match.group(1)) + unit = match.group(2) + if not unit: + return digit + elif unit == 'gb': + raise NotImplementedError("gb units are not supported yet") + else: + raise NotImplementedError("kpps units are not supported yet") + else: + raise argparse.ArgumentTypeError("Multiplier should be passed in the following format: \n" + "-m 100 : multiply stream file by this factor \n" + "-m 10gb : from graph calculate the maximum rate as this bandwidth (for each port)\n" + "-m 10kpps : from graph calculate the maximum rate as this pps (for each port)\n" + "-m 40% : from graph calculate the maximum rate as this percent from total port (for each port)") + + OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], - {'help': "Set multiplier for stream", 'dest': "mult", 'type': float}), + {'help': "Set multiplier for stream", + 'dest': "mult", + 'default': 1.0, + 'type': match_multiplier}), PORT_LIST: ArgumentPack(['--port'], {"nargs": '+', # "action": "store_" + 'dest':'ports', + 'metavar': 'PORTS', + # 'type': int, 'help': "A list of ports on which to apply the command", 'default': []}), ALL_PORTS: ArgumentPack(['-a'], {"action": "store_true", - "dest": "all", + "dest": "all_ports", 'help': "Set this flag to apply the command on all available ports"}), - + DURATION: ArgumentPack(['-d'], + {"action": "store", + 'metavar': 'TIME', + "type": match_time_unit, + 'help': "Set duration time for TRex."}), + FORCE: ArgumentPack(['--force'], + {"action": "store_true", + 'default': False, + 'help': "Set if you want to stop active ports before applying new TRex run on them."}), FILE_PATH: ArgumentPack(['-f'], - {'help': "File path to YAML file that describes a stream pack"}), + {'metavar': ('FILE', 'DB_NAME'), + 'dest': 'file', + 'nargs': 2, + 'help': "File path to YAML file that describes a stream pack. " + "Second argument is a name to store the loaded yaml file into db."}), FILE_FROM_DB: ArgumentPack(['--db'], - {'help': "A stream pack which already loaded into console cache."}), + {'metavar': 'LOADED_STREAM_PACK', + 'help': "A stream pack which already loaded into console cache."}), # advanced options PORT_LIST_WITH_ALL: ArgumentGroup(MUTEX, [PORT_LIST, ALL_PORTS], @@ -51,25 +111,23 @@ class CCmdArgParser(argparse.ArgumentParser): def __init__(self, *args, **kwargs): super(CCmdArgParser, self).__init__(*args, **kwargs) - pass - # def error(self, message): + # def exit(self, status=0, message=None): # try: - # super(CCmdArgParser, self).error(message) # this will trigger system exit! + # return super(CCmdArgParser, self).exit(status, message) # this will trigger system exit! # except SystemExit: + # print "Caught system exit!!" # return -1 - # - # # self.print_usage(sys.stderr) - # # print ('%s: error: %s\n') % (self.prog, message) - # # self.print_help() - # return + # # return - def exit(self, status=0, message=None): + def parse_args(self, args=None, namespace=None): try: - super(CCmdArgParser, self).exit(status, message) # this will trigger system exit! + return super(CCmdArgParser, self).parse_args(args, namespace) except SystemExit: - return -1 - return + # recover from system exit scenarios, such as "help", or bad arguments. + return None + + def gen_parser(op_name, description, *args): parser = CCmdArgParser(prog=op_name, conflict_handler='resolve', 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,36 +700,312 @@ 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: # # 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 + + 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() |