From d04fb533c0843ebcd3eac5fbefa6f418582db7fc Mon Sep 17 00:00:00 2001
From: Dan Klein <danklein10@gmail.com>
Date: Tue, 10 Nov 2015 10:16:28 +0200
Subject: Major progress in parsing, not stable yet Most advanced: start, stop
 functionality

---
 .../client/trex_stateless_client.py                |  31 +-
 .../trex_control_plane/console/parsing_opts.py     |  92 +++-
 .../trex_control_plane/console/trex_console.py     | 495 ++++++++++++++++-----
 3 files changed, 488 insertions(+), 130 deletions(-)

(limited to 'scripts/automation')

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,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