From cc75f3f75e026bc17e526577c463ab5b524ebf22 Mon Sep 17 00:00:00 2001 From: imarom Date: Thu, 21 Jan 2016 10:05:18 -0500 Subject: phase 4 --- .../trex_control_plane/client/trex_port.py | 10 +- .../client/trex_stateless_client.py | 404 +++++++++------------ .../client_utils/parsing_opts.py | 5 +- .../trex_control_plane/common/trex_stats.py | 45 ++- .../trex_control_plane/console/trex_console.py | 76 ++-- .../trex_control_plane/console/trex_tui.py | 127 +++---- 6 files changed, 325 insertions(+), 342 deletions(-) (limited to 'scripts/automation/trex_control_plane') diff --git a/scripts/automation/trex_control_plane/client/trex_port.py b/scripts/automation/trex_control_plane/client/trex_port.py index 7e5942d4..94240f2a 100644 --- a/scripts/automation/trex_control_plane/client/trex_port.py +++ b/scripts/automation/trex_control_plane/client/trex_port.py @@ -56,7 +56,7 @@ class Port(object): def err(self, msg): return RC_ERR("port {0} : {1}".format(self.port_id, msg)) - def ok(self, data = "ACK"): + def ok(self, data = ""): return RC_OK(data) def get_speed_bps (self): @@ -283,8 +283,12 @@ class Port(object): if not self.is_acquired(): return self.err("port is not owned") - if (not force) and (self.state != self.STATE_TX) and (self.state != self.STATE_PAUSE): - return self.err("port is not transmitting") + # port is already stopped + if not force: + if (self.state == self.STATE_IDLE) or (self.state == self.state == self.STATE_STREAMS): + return self.ok() + + params = {"handler": self.handler, "port_id": self.port_id} 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 69cc9838..c5d7e053 100755 --- a/scripts/automation/trex_control_plane/client/trex_stateless_client.py +++ b/scripts/automation/trex_control_plane/client/trex_stateless_client.py @@ -67,7 +67,7 @@ class STLArgumentError(STLError): if extended: self.msg += "\n{0}".format(extended) - +# raised when timeout occurs class STLTimeoutError(STLError): def __init__ (self, timeout): self.msg = "Timeout: operation took more than '{0}' seconds".format(timeout) @@ -660,7 +660,7 @@ class CTRexStatelessClient(object): return rc - def __validate (self, port_id_list = None): + def __validate_traffic (self, port_id_list = None): port_id_list = self.__ports(port_id_list) rc = RC() @@ -821,17 +821,8 @@ class CTRexStatelessClient(object): # stop cmd def __stop (self, port_id_list): - # find the relveant ports - active_ports = list(set(self.get_active_ports()).intersection(port_id_list)) - - if not active_ports: - msg = "No active traffic on provided ports" - self.logger.log(format_text(msg, 'bold')) - return RC_WARN(msg) - - self.logger.pre_cmd("Stopping traffic on port(s) {0}:".format(port_id_list)) - rc = self.__stop_traffic(active_ports) + rc = self.__stop_traffic(port_id_list) self.logger.post_cmd(rc) if not rc: @@ -842,16 +833,8 @@ class CTRexStatelessClient(object): #update cmd def __update (self, port_id_list, mult): - # find the relevant ports - active_ports = list(set(self.get_active_ports()).intersection(port_id_list)) - - if not active_ports: - msg = "No active traffic on provided ports" - self.logger.log(format_text(msg, 'bold')) - return RC_WARN(msg) - self.logger.pre_cmd("Updating traffic on port(s) {0}:".format(port_id_list)) - rc = self.__update_traffic(mult, active_ports) + rc = self.__update_traffic(mult, port_id_list) self.logger.post_cmd(rc) return rc @@ -860,16 +843,8 @@ class CTRexStatelessClient(object): # pause cmd def __pause (self, port_id_list): - # find the relevant ports - active_ports = list(set(self.get_active_ports()).intersection(port_id_list)) - - if not active_ports: - msg = "No active traffic on provided ports" - self.logger.log(format_text(msg, 'bold')) - return RC_WARN(msg) - self.logger.pre_cmd("Pausing traffic on port(s) {0}:".format(port_id_list)) - rc = self.__pause_traffic(active_ports) + rc = self.__pause_traffic(port_id_list) self.logger.post_cmd(rc) return rc @@ -878,16 +853,17 @@ class CTRexStatelessClient(object): # resume cmd def __resume (self, port_id_list): - # find the relveant ports - active_ports = list(set(self.get_active_ports()).intersection(port_id_list)) + self.logger.pre_cmd("Resume traffic on port(s) {0}:".format(port_id_list)) + rc = self.__resume_traffic(port_id_list) + self.logger.post_cmd(rc) - if not active_ports: - msg = "No active traffic on porvided ports" - self.logger.log(format_text(msg, 'bold')) - return RC_WARN(msg) + return rc - self.logger.pre_cmd("Resume traffic on port(s) {0}:".format(port_id_list)) - rc = self.__resume_traffic(active_ports) + + # validate port(s) profile + def __validate (self, port_id_list): + self.logger.pre_cmd("Validating streams on port(s) {0}:".format(port_id_list)) + rc = self.__validate_traffic(port_id_list) self.logger.post_cmd(rc) return rc @@ -985,52 +961,8 @@ class CTRexStatelessClient(object): def _transmit_batch(self, batch_list): return self.comm_link.transmit_batch(batch_list) - ############# helper functions section ############## - - - ########## port commands ############## - - ######################### Console (high level) API ######################### - - - - # clear stats - def cmd_clear(self, port_id_list): - - for port_id in port_id_list: - self.ports[port_id].clear_stats() - - self.global_stats.clear_stats() - - return RC_OK() - - - def cmd_invalidate (self, port_id_list): - for port_id in port_id_list: - self.ports[port_id].invalidate_stats() - - self.global_stats.invalidate() - - return RC_OK() - - - - - - - - - # validate port(s) profile - def cmd_validate (self, port_id_list): - self.logger.pre_cmd("Validating streams on port(s) {0}:".format(port_id_list)) - rc = self.__validate(port_id_list) - self.logger.post_cmd(rc) - - return rc - - # stats - def cmd_stats(self, port_id_list, stats_mask=set()): + def _get_formatted_stats(self, port_id_list, stats_mask=set()): stats_opts = trex_stats.ALL_STATS_OPTS.intersection(stats_mask) stats_obj = {} @@ -1038,15 +970,24 @@ class CTRexStatelessClient(object): stats_obj.update(self.stats_generator.generate_single_statistic(port_id_list, stats_type)) return stats_obj - def cmd_streams(self, port_id_list, streams_mask=set()): + def _get_streams(self, port_id_list, streams_mask=set()): streams_obj = self.stats_generator.generate_streams_info(port_id_list, streams_mask) return streams_obj - ############## High Level API With Parser ################ + def _invalidate_stats (self, port_id_list): + for port_id in port_id_list: + self.ports[port_id].invalidate_stats() + + self.global_stats.invalidate() + + return RC_OK() + + + ################################# # ------ private methods ------ # @@ -1089,6 +1030,7 @@ class CTRexStatelessClient(object): ############################ ############################# def __enter__ (self): self.connect(mode = "RWF") + self.reset() return self def __exit__ (self, type, value, traceback): @@ -1174,6 +1116,34 @@ class CTRexStatelessClient(object): if port_obj.is_transmitting()] + # get stats + def get_stats (self, ports = None, async_barrier = True): + # by default use all ports + if ports == None: + ports = self.get_all_ports() + + # verify valid port id list + rc = self._validate_port_list(ports) + if not rc: + raise STLArgumentError('ports', ports, valid_values = self.get_all_ports()) + + # check async barrier + if not type(async_barrier) is bool: + raise STLArgumentError('async_barrier', async_barrier) + + + # if the user requested a barrier - use it + if async_barrier: + rc = self.async_client.barrier() + if not rc: + raise STLError(rc) + + return self.__get_stats(ports) + + # return all async events + def get_events (self): + return self.event_handler.get_events() + ############################ Commands ############################# ############################ ############################# ############################ ############################# @@ -1252,7 +1222,6 @@ class CTRexStatelessClient(object): if not rc: raise STLError(rc) - return rc # teardown - call after test is done @@ -1282,7 +1251,6 @@ class CTRexStatelessClient(object): if not rc: raise STLError(rc) - return rc # reset the server by performing @@ -1315,8 +1283,7 @@ class CTRexStatelessClient(object): if not rc: raise STLError(rc) - # TODO: clear stats - return RC_OK() + self.clear_stats() # start cmd @@ -1333,7 +1300,7 @@ class CTRexStatelessClient(object): # by default use all ports if ports == None: - ports = self.get_all_ports() + ports = self.get_acquired_ports() # verify valid port id list rc = self._validate_port_list(ports) @@ -1380,9 +1347,10 @@ class CTRexStatelessClient(object): # stop traffic on ports @__api_check(True) def stop (self, ports = None): - # by default use all ports + + # by default the user means all the active ports if ports == None: - ports = self.get_all_ports() + ports = self.get_active_ports() # verify valid port id list rc = self._validate_port_list(ports) @@ -1399,16 +1367,15 @@ class CTRexStatelessClient(object): @__api_check(True) def update (self, ports = None, mult = "1", total = False): - # by default use all ports + # by default the user means all the active ports if ports == None: - ports = self.get_all_ports() + ports = self.get_active_ports() # verify valid port id list rc = self._validate_port_list(ports) if not rc: raise STLArgumentError('ports', ports, valid_values = self.get_all_ports()) - # verify multiplier mult_obj = parsing_opts.decode_multiplier(mult, allow_update = True, @@ -1426,15 +1393,15 @@ class CTRexStatelessClient(object): if not rc: raise STLError(rc) - return rc # pause traffic on ports @__api_check(True) def pause (self, ports = None): - # by default use all ports + + # by default the user means all the TX ports if ports == None: - ports = self.get_all_ports() + ports = self.get_transmitting_ports() # verify valid port id list rc = self._validate_port_list(ports) @@ -1445,15 +1412,15 @@ class CTRexStatelessClient(object): if not rc: raise STLError(rc) - return rc # resume traffic on ports @__api_check(True) def resume (self, ports = None): - # by default use all ports + + # by default the user means all the paused ports if ports == None: - ports = self.get_all_ports() + ports = self.get_paused_ports() # verify valid port id list rc = self._validate_port_list(ports) @@ -1464,63 +1431,55 @@ class CTRexStatelessClient(object): if not rc: raise STLError(rc) - return rc - - # clear stats - @__api_check(False) - def clear_stats (self, ports = None, clear_global = True): - # by default use all ports + @__api_check(True) + def validate (self, ports = None): if ports == None: - ports = self.get_all_ports() + ports = self.get_acquired_ports() # verify valid port id list rc = self._validate_port_list(ports) if not rc: raise STLArgumentError('ports', ports, valid_values = self.get_all_ports()) - # verify clear global - if not type(clear_global) is bool: - raise STLArgumentError('clear_global', clear_global) - - - rc = self.__clear_stats(ports, clear_global) + rc = self.__validate(ports) if not rc: raise STLError(rc) - # get stats + # clear stats @__api_check(False) - def get_stats (self, ports = None, async_barrier = True): + def clear_stats (self, ports = None, clear_global = True): + # by default use all ports if ports == None: - ports = self.get_all_ports() + ports = self.get_acquired_ports() # verify valid port id list rc = self._validate_port_list(ports) if not rc: raise STLArgumentError('ports', ports, valid_values = self.get_all_ports()) - # check async barrier - if not type(async_barrier) is bool: - raise STLArgumentError('async_barrier', async_barrier) + # verify clear global + if not type(clear_global) is bool: + raise STLArgumentError('clear_global', clear_global) - # if the user requested a barrier - use it - if async_barrier: - rc = self.async_client.barrier() - if not rc: - raise STLError(rc) + rc = self.__clear_stats(ports, clear_global) + if not rc: + raise STLError(rc) - return self.__get_stats(ports) + + # wait while traffic is on, on timeout throw STLTimeoutError @__api_check(True) def wait_on_traffic (self, ports = None, timeout = 60): - # by default use all ports + + # by default use all acquired ports if ports == None: - ports = self.get_all_ports() + ports = self.get_acquired_ports() # verify valid port id list rc = self._validate_port_list(ports) @@ -1536,7 +1495,9 @@ class CTRexStatelessClient(object): raise STLTimeoutError(timeout) - + # clear all async events + def clear_events (self): + self.event_handler.clear_events() ############################ Line ############################# ############################ Commands ############################# @@ -1554,16 +1515,11 @@ class CTRexStatelessClient(object): client.logger.log("Log:\n" + format_text(e.brief() + "\n", 'bold')) return - # don't want to print on error - if not rc or rc.warn(): - return rc + # if got true - print time + if rc: + delta = time.time() - time1 + client.logger.log(format_time(delta) + "\n") - delta = time.time() - time1 - - - client.logger.log(format_time(delta) + "\n") - - return rc return wrap @@ -1583,19 +1539,24 @@ class CTRexStatelessClient(object): return # call the API - mode = "RWF" if opts.force else "RW" - self.connect(mode) + self.connect("RWF" if opts.force else "RW") + # true means print time + return True @__console def disconnect_line (self, line): self.disconnect() + @__console def reset_line (self, line): self.reset() + # true means print time + return True + @__console def start_line (self, line): @@ -1629,6 +1590,9 @@ class CTRexStatelessClient(object): opts.dry, opts.total) + # true means print time + return True + @__console @@ -1643,7 +1607,17 @@ class CTRexStatelessClient(object): if opts is None: return - self.stop(opts.ports) + # find the relevant ports + ports = list(set(self.get_active_ports()).intersection(opts.ports)) + + if not ports: + self.logger.log(format_text("No active traffic on provided ports\n", 'bold')) + return + + self.stop(ports) + + # true means print time + return True @__console @@ -1660,7 +1634,17 @@ class CTRexStatelessClient(object): if opts is None: return - self.update(opts.ports, opts.mult, opts.total) + # find the relevant ports + ports = list(set(self.get_active_ports()).intersection(opts.ports)) + + if not ports: + self.logger.log(format_text("No ports in valid state to update\n", 'bold')) + return + + self.update(ports, opts.mult, opts.total) + + # true means print time + return True @__console @@ -1675,7 +1659,17 @@ class CTRexStatelessClient(object): if opts is None: return - self.pause(opts.ports) + # find the relevant ports + ports = list(set(self.get_transmitting_ports()).intersection(opts.ports)) + + if not ports: + self.logger.log(format_text("No ports in valid state to pause\n", 'bold')) + return + + self.pause(ports) + + # true means print time + return True @__console @@ -1690,7 +1684,17 @@ class CTRexStatelessClient(object): if opts is None: return - return self.resume(opts.ports) + # find the relevant ports + ports = list(set(self.get_paused_ports()).intersection(opts.ports)) + + if not ports: + self.logger.log(format_text("No ports in valid state to resume\n", 'bold')) + return + + return self.resume(ports) + + # true means print time + return True @__console @@ -1711,8 +1715,9 @@ class CTRexStatelessClient(object): + @__console - def print_formatted_stats_line (self, line): + def show_stats_line (self, line): '''Fetch statistics from TRex server by port\n''' # define a parser parser = parsing_opts.gen_parser(self, @@ -1724,7 +1729,7 @@ class CTRexStatelessClient(object): opts = parser.parse_args(line.split()) if opts is None: - return None + return # determine stats mask mask = self.__get_mask_keys(**self.__filter_namespace_args(opts, trex_stats.ALL_STATS_OPTS)) @@ -1732,137 +1737,60 @@ class CTRexStatelessClient(object): # set to show all stats if no filter was given mask = trex_stats.ALL_STATS_OPTS - - self.print_formatted_stats() - stats = self.get_stats(opts.ports, mask) + stats_opts = trex_stats.ALL_STATS_OPTS.intersection(mask) + + stats = self._get_formatted_stats(opts.ports, mask) + # print stats to screen for stat_type, stat_data in stats.iteritems(): text_tables.print_table_with_header(stat_data.text_table, stat_type) - return RC_OK() - def cmd_streams_line(self, line): + @__console + def show_streams_line(self, line): '''Fetch streams statistics from TRex server by port\n''' # define a parser parser = parsing_opts.gen_parser(self, "streams", - self.cmd_streams_line.__doc__, + self.show_streams_line.__doc__, parsing_opts.PORT_LIST_WITH_ALL, - parsing_opts.STREAMS_MASK)#, - #parsing_opts.FULL_OUTPUT) + parsing_opts.STREAMS_MASK) opts = parser.parse_args(line.split()) if opts is None: - return RC_ERR("bad command line parameters") + return - streams = self.cmd_streams(opts.ports, set(opts.streams)) + streams = self._get_streams(opts.ports, set(opts.streams)) if not streams: - # we got no streams running - self.logger.log(format_text("No streams found with desired filter.\n", "bold", "magenta")) - return RC_ERR("No streams found with desired filter.") + else: # print stats to screen for stream_hdr, port_streams_data in streams.iteritems(): text_tables.print_table_with_header(port_streams_data.text_table, header= stream_hdr.split(":")[0] + ":", untouched_header= stream_hdr.split(":")[1]) - return RC_OK() @__console - def cmd_validate_line (self, line): + def validate_line (self, line): '''validates port(s) stream configuration\n''' parser = parsing_opts.gen_parser(self, "validate", - self.cmd_validate_line.__doc__, + self.validate_line.__doc__, parsing_opts.PORT_LIST_WITH_ALL) opts = parser.parse_args(line.split()) if opts is None: - return RC_ERR("bad command line paramters") - - rc = self.cmd_validate(opts.ports) - return rc - - - def cmd_exit_line (self, line): - self.logger.log(format_text("Exiting\n", 'bold')) - # a way to exit - return RC_ERR("exit") - - - def cmd_wait_line (self, line): - '''wait for a period of time\n''' - - parser = parsing_opts.gen_parser(self, - "wait", - self.cmd_wait_line.__doc__, - parsing_opts.DURATION) - - opts = parser.parse_args(line.split()) - if opts is None: - return RC_ERR("bad command line parameters") - - delay_sec = opts.duration if (opts.duration > 0) else 1 - - self.logger.log(format_text("Waiting for {0} seconds...\n".format(delay_sec), 'bold')) - time.sleep(delay_sec) - - return RC_OK() - - # run a script of commands - def run_script_file (self, filename): - - self.logger.log(format_text("\nRunning script file '{0}'...".format(filename), 'bold')) - - rc = self.cmd_connect() - if rc.bad(): return - with open(filename) as f: - script_lines = f.readlines() - - cmd_table = {} - - # register all the commands - cmd_table['start'] = self.cmd_start_line - cmd_table['stop'] = self.cmd_stop_line - cmd_table['reset'] = self.cmd_reset_line - cmd_table['wait'] = self.cmd_wait_line - cmd_table['exit'] = self.cmd_exit_line - - for index, line in enumerate(script_lines, start = 1): - line = line.strip() - if line == "": - continue - if line.startswith("#"): - continue - - sp = line.split(' ', 1) - cmd = sp[0] - if len(sp) == 2: - args = sp[1] - else: - args = "" - - self.logger.log(format_text("Executing line {0} : '{1}'\n".format(index, line))) - - if not cmd in cmd_table: - print "\n*** Error at line {0} : '{1}'\n".format(index, line) - self.logger.log(format_text("unknown command '{0}'\n".format(cmd), 'bold')) - return False + self.validate(opts.ports) - rc = cmd_table[cmd](args) - if rc.bad(): - return False - - self.logger.log(format_text("\n[Done]", 'bold')) - return True + \ No newline at end of file diff --git a/scripts/automation/trex_control_plane/client_utils/parsing_opts.py b/scripts/automation/trex_control_plane/client_utils/parsing_opts.py index 3cc32b1d..ba60c191 100755 --- a/scripts/automation/trex_control_plane/client_utils/parsing_opts.py +++ b/scripts/automation/trex_control_plane/client_utils/parsing_opts.py @@ -156,7 +156,7 @@ def decode_multiplier(val, allow_update = False, divide_count = 1): def match_multiplier(val): '''match some val against multiplier shortcut inputs ''' - result = decode_multiplier(val, allow_update = False) + result = decode_multiplier(val, allow_update = True) if not result: raise argparse.ArgumentTypeError(match_multiplier_help) @@ -165,7 +165,7 @@ def match_multiplier(val): def match_multiplier_strict(val): '''match some val against multiplier shortcut inputs ''' - result = decode_multiplier(val, allow_update = True) + result = decode_multiplier(val, allow_update = False) if not result: raise argparse.ArgumentTypeError(match_multiplier_help) @@ -252,6 +252,7 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'], 'default': False, 'help': "Starts TUI in xterm window"}), + FULL_OUTPUT: ArgumentPack(['--full'], {'action': 'store_true', 'help': "Prompt full info in a JSON format"}), diff --git a/scripts/automation/trex_control_plane/common/trex_stats.py b/scripts/automation/trex_control_plane/common/trex_stats.py index 3d6ece7c..9c2cd7f1 100755 --- a/scripts/automation/trex_control_plane/common/trex_stats.py +++ b/scripts/automation/trex_control_plane/common/trex_stats.py @@ -260,7 +260,7 @@ class CTRexStats(object): def __init__(self): self.reference_stats = None - self.latest_stats = {} + self.latest_stats = None self.last_update_ts = time.time() self.history = deque(maxlen = 10) @@ -314,13 +314,11 @@ class CTRexStats(object): self.last_update_ts = time.time() - def get_stats (self): - # copy and return - return dict(self.latest_stats) def clear_stats(self): self.reference_stats = self.latest_stats + def invalidate (self): self.latest_stats = {} @@ -337,6 +335,10 @@ class CTRexStats(object): return "N/A" if not format: + if not field in self.reference_stats: + print "REF: " + str(self.reference_stats) + print "BASE: " + str(self.latest_stats) + return (self.latest_stats[field] - self.reference_stats[field]) else: return format_num(self.latest_stats[field] - self.reference_stats[field], suffix) @@ -403,6 +405,24 @@ class CGlobalStats(CTRexStats): self.server_version = server_version self._ports_dict = ports_dict_ref + def get_stats (self): + stats = {} + + # absolute + stats['cpu_util'] = self.get("m_cpu_util") + stats['tx_bps'] = self.get("m_tx_bps") + stats['tx_pps'] = self.get("m_tx_pps") + + stats['rx_bps'] = self.get("m_rx_bps") + stats['rx_pps'] = self.get("m_rx_pps") + stats['rx_drop_bps'] = self.get("m_rx_drop_bps") + + # relatives + stats['queue_full'] = self.get_rel("m_total_queue_full") + + return stats + + def generate_stats(self): return OrderedDict([("connection", "{host}, Port {port}".format(host=self.connection_info.get("server"), port=self.connection_info.get("sync_port"))), @@ -475,6 +495,23 @@ class CPortStats(CTRexStats): return self + # for port we need to do something smarter + def get_stats (self): + stats = {} + + stats['opackets'] = self.get_rel("opackets") + stats['ipackets'] = self.get_rel("ipackets") + stats['obytes'] = self.get_rel("obytes") + stats['ibytes'] = self.get_rel("ibytes") + stats['oerrors'] = self.get_rel("oerrors") + stats['ierrors'] = self.get_rel("ierrors") + stats['tx_bps'] = self.get("m_total_tx_bps") + stats['tx_pps'] = self.get("m_total_tx_pps") + stats['rx_bps'] = self.get("m_total_rx_bps") + stats['rx_pps'] = self.get("m_total_rx_pps") + + return stats + def generate_stats(self): diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 3ecbca06..34494561 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -438,13 +438,13 @@ class TRexConsole(TRexGeneralCmd): def do_validate (self, line): '''validates port(s) stream configuration\n''' - self.stateless_client.cmd_validate_line(line) + self.stateless_client.validate_line(line) @verify_connected def do_stats(self, line): '''Fetch statistics from TRex server by port\n''' - self.stateless_client.stats_line(line) + self.stateless_client.show_stats_line(line) def help_stats(self): @@ -523,13 +523,8 @@ class TRexConsole(TRexGeneralCmd): return - set_window_always_on_top('trex_tui') - - save_verbose = self.stateless_client.get_verbose() - - self.stateless_client.set_verbose(self.stateless_client.logger.VERBOSE_QUIET) - self.tui.show() - self.stateless_client.set_verbose(save_verbose) + with self.stateless_client.logger.supress(): + self.tui.show() def help_tui (self): @@ -601,6 +596,51 @@ class TRexConsole(TRexGeneralCmd): do_h = do_history +# run a script of commands +def run_script_file (self, filename, stateless_client): + + self.logger.log(format_text("\nRunning script file '{0}'...".format(filename), 'bold')) + + with open(filename) as f: + script_lines = f.readlines() + + cmd_table = {} + + # register all the commands + cmd_table['start'] = stateless_client.start_line + cmd_table['stop'] = stateless_client.stop_line + cmd_table['reset'] = stateless_client.reset_line + + for index, line in enumerate(script_lines, start = 1): + line = line.strip() + if line == "": + continue + if line.startswith("#"): + continue + + sp = line.split(' ', 1) + cmd = sp[0] + if len(sp) == 2: + args = sp[1] + else: + args = "" + + stateless_client.logger.log(format_text("Executing line {0} : '{1}'\n".format(index, line))) + + if not cmd in cmd_table: + print "\n*** Error at line {0} : '{1}'\n".format(index, line) + stateless_client.logger.log(format_text("unknown command '{0}'\n".format(cmd), 'bold')) + return False + + rc = cmd_table[cmd](args) + if rc.bad(): + return False + + stateless_client.logger.log(format_text("\n[Done]", 'bold')) + + return True + + # def is_valid_file(filename): if not os.path.isfile(filename): @@ -609,6 +649,7 @@ def is_valid_file(filename): return filename + def setParserOptions(): parser = argparse.ArgumentParser(prog="trex_console.py") @@ -691,33 +732,20 @@ def main(): logger.log("Log:\n" + format_text(e.brief() + "\n", 'bold')) logger.log(format_text("\nSwitching to read only mode - only few commands will be available", 'bold')) - - # if options.tui or not options.acquire: - # rc = stateless_client.connect("RO") - # else: - # try: - # rc = stateless_client.connect("RW") - # except STLError as e: - # logger.log(format_text("Switching to read only mode - only few commands will be available", 'bold')) - # - # with logger.supress(): - # rc = stateless_client.connect("RO") - - # a script mode if options.batch: - cont = stateless_client.run_script_file(options.batch[0]) + cont = run_script_file(options.batch[0], stateless_client) if not cont: return # console - try: console = TRexConsole(stateless_client, options.verbose) logger.prompt_redraw = console.prompt_redraw if options.tui: + set_window_always_on_top('trex_tui') console.do_tui("") else: console.start() diff --git a/scripts/automation/trex_control_plane/console/trex_tui.py b/scripts/automation/trex_control_plane/console/trex_tui.py index 9e66a984..1e22b005 100644 --- a/scripts/automation/trex_control_plane/console/trex_tui.py +++ b/scripts/automation/trex_control_plane/console/trex_tui.py @@ -8,6 +8,7 @@ from client_utils import text_tables from collections import OrderedDict import datetime from cStringIO import StringIO +from client.trex_stateless_client import STLError class SimpleBar(object): def __init__ (self, desc, pattern): @@ -60,7 +61,7 @@ class TrexTUIDashBoard(TrexTUIPanel): def show (self): - stats = self.stateless_client.cmd_stats(self.ports, trex_stats.COMPACT) + stats = self.stateless_client._get_formatted_stats(self.ports, trex_stats.COMPACT) # print stats to screen for stat_type, stat_data in stats.iteritems(): text_tables.print_table_with_header(stat_data.text_table, stat_type) @@ -88,64 +89,44 @@ class TrexTUIDashBoard(TrexTUIPanel): ######### actions def action_pause (self): - rc = self.stateless_client.pause_traffic(self.mng.ports) + try: + rc = self.stateless_client.pause(ports = self.mng.ports) + except STLError: + pass - ports_succeeded = [] - for rc_single, port_id in zip(rc.rc_list, self.mng.ports): - if rc_single.rc: - ports_succeeded.append(port_id) + return "" - if len(ports_succeeded) > 0: - return "paused traffic on port(s): {0}".format(ports_succeeded) - else: - return "" def action_resume (self): - rc = self.stateless_client.resume_traffic(self.mng.ports) - - ports_succeeded = [] - for rc_single, port_id in zip(rc.rc_list, self.mng.ports): - if rc_single.rc: - ports_succeeded.append(port_id) + try: + self.stateless_client.resume(ports = self.mng.ports) + except STLError: + pass - if len(ports_succeeded) > 0: - return "resumed traffic on port(s): {0}".format(ports_succeeded) - else: - return "" + return "" def action_raise (self): - mul = {'type': 'percentage', 'value': 5, 'op': 'add'} - rc = self.stateless_client.update_traffic(mul, self.mng.ports) + try: + self.stateless_client.update(mult = "5%+", ports = self.mng.ports) + except STLError: + pass - ports_succeeded = [] - for rc_single, port_id in zip(rc.rc_list, self.mng.ports): - if rc_single.rc: - ports_succeeded.append(port_id) + return "" - if len(ports_succeeded) > 0: - return "raised B/W by %5 on port(s): {0}".format(ports_succeeded) - else: - return "" def action_lower (self): - mul = {'type': 'percentage', 'value': 5, 'op': 'sub'} - rc = self.stateless_client.update_traffic(mul, self.mng.ports) - - ports_succeeded = [] - for rc_single, port_id in zip(rc.rc_list, self.mng.ports): - if rc_single.rc: - ports_succeeded.append(port_id) + try: + self.stateless_client.update(mult = "5%-", ports = self.mng.ports) + except STLError: + pass - if len(ports_succeeded) > 0: - return "lowered B/W by %5 on port(s): {0}".format(ports_succeeded) - else: - return "" + return "" def action_clear (self): - self.stateless_client.cmd_clear(self.mng.ports) + self.stateless_client.clear_stats(self.mng.ports) return "cleared all stats" @@ -167,7 +148,7 @@ class TrexTUIPort(TrexTUIPanel): def show (self): - stats = self.stateless_client.cmd_stats([self.port_id], trex_stats.COMPACT) + stats = self.stateless_client._get_formatted_stats([self.port_id], trex_stats.COMPACT) # print stats to screen for stat_type, stat_data in stats.iteritems(): text_tables.print_table_with_header(stat_data.text_table, stat_type) @@ -194,39 +175,44 @@ class TrexTUIPort(TrexTUIPanel): # actions def action_pause (self): - rc = self.stateless_client.pause_traffic([self.port_id]) - if rc.good(): - return "port {0}: paused traffic".format(self.port_id) - else: - return "" + try: + self.stateless_client.pause(ports = [self.port_id]) + except STLError: + pass + + return "" def action_resume (self): - rc = self.stateless_client.resume_traffic([self.port_id]) - if rc.good(): - return "port {0}: resumed traffic".format(self.port_id) - else: - return "" + try: + self.stateless_client.resume(ports = [self.port_id]) + except STLError: + pass + + return "" + def action_raise (self): - mul = {'type': 'percentage', 'value': 5, 'op': 'add'} - rc = self.stateless_client.update_traffic(mul, [self.port_id]) + mult = {'type': 'percentage', 'value': 5, 'op': 'add'} - if rc.good(): - return "port {0}: raised B/W by 5%".format(self.port_id) - else: - return "" + try: + self.stateless_client.update(mult = mult, ports = [self.port_id]) + except STLError: + pass + + return "" def action_lower (self): - mul = {'type': 'percentage', 'value': 5, 'op': 'sub'} - rc = self.stateless_client.update_traffic(mul, [self.port_id]) + mult = {'type': 'percentage', 'value': 5, 'op': 'sub'} - if rc.good(): - return "port {0}: lowered B/W by 5%".format(self.port_id) - else: - return "" + try: + self.stateless_client.update(mult = mult, ports = [self.port_id]) + except STLError: + pass + + return "" def action_clear (self): - self.stateless_client.cmd_clear([self.port_id]) + self.stateless_client.clear_stats([self.port_id]) return "port {0}: cleared stats".format(self.port_id) # log @@ -423,7 +409,7 @@ class TrexTUI(): if self.state == self.STATE_ACTIVE: # if no connectivity - move to lost connecitivty if not self.stateless_client.async_client.is_alive(): - self.stateless_client.cmd_invalidate(self.pm.ports) + self.stateless_client._invalidate_stats(self.pm.ports) self.state = self.STATE_LOST_CONT @@ -438,11 +424,10 @@ class TrexTUI(): # restored connectivity - try to reconnect elif self.state == self.STATE_RECONNECT: - rc = self.stateless_client.connect("RO") - if rc.good(): + try: + self.stateless_client.connect("RO") self.state = self.STATE_ACTIVE - else: - # maybe we lost it again + except STLError: self.state = self.STATE_LOST_CONT -- cgit 1.2.3-korg