diff options
author | 2015-11-09 11:20:28 +0200 | |
---|---|---|
committer | 2015-11-09 11:20:28 +0200 | |
commit | 82280f7c87fabed60d83643bd9ec2c79cac34668 (patch) | |
tree | 62916038bc3650e161c53bc1f9a44df02dca8fe3 /scripts/automation/trex_control_plane/console/trex_status.py | |
parent | 7c9355cc198ee897de9cd2d60e88a232ce1fa405 (diff) | |
parent | c6d2cb0554ebc39142fb433040a968714a7ec24f (diff) |
Merge branch 'rpc_intg1'
Diffstat (limited to 'scripts/automation/trex_control_plane/console/trex_status.py')
-rw-r--r-- | scripts/automation/trex_control_plane/console/trex_status.py | 447 |
1 files changed, 253 insertions, 194 deletions
diff --git a/scripts/automation/trex_control_plane/console/trex_status.py b/scripts/automation/trex_control_plane/console/trex_status.py index 2c5a648f..2b97d7d3 100644 --- a/scripts/automation/trex_control_plane/console/trex_status.py +++ b/scripts/automation/trex_control_plane/console/trex_status.py @@ -11,22 +11,27 @@ import datetime g_curses_active = False +################### utils ################# + # simple percetange show def percentage (a, total): x = int ((float(a) / total) * 100) return str(x) + "%" -# simple float to human readable -def float_to_human_readable (size, suffix = "bps"): - for unit in ['','K','M','G']: - if abs(size) < 1024.0: - return "%3.1f %s%s" % (size, unit, suffix) - size /= 1024.0 - return "NaN" +################### panels ################# # panel object class TrexStatusPanel(object): - def __init__ (self, h, l, y, x, headline): + def __init__ (self, h, l, y, x, headline, status_obj): + + self.status_obj = status_obj + + self.log = status_obj.log + self.stateless_client = status_obj.stateless_client + + self.stats = status_obj.stats + self.general_stats = status_obj.general_stats + self.h = h self.l = l self.y = y @@ -53,64 +58,26 @@ class TrexStatusPanel(object): return self.win -# total stats (ports + global) -class Stats(): - def __init__ (self, rpc_client, port_list, interval = 100): - - self.rpc_client = rpc_client - - self.port_list = port_list - self.port_stats = {} - - self.interval = interval - self.delay_count = 0 - - def get_port_stats (self, port_id): - if self.port_stats.get(port_id): - return self.port_stats[port_id] - else: - return None - - def query_sync (self): - self.delay_count += 1 - if self.delay_count < self.interval: - return - - self.delay_count = 0 - - # query global stats - - # query port stats - - rc, resp_list = self.rpc_client.get_port_stats(self.port_list) - if not rc: - return - - for i, rc in enumerate(resp_list): - if rc[0]: - self.port_stats[self.port_list[i]] = rc[1] - - # various kinds of panels # Server Info Panel class ServerInfoPanel(TrexStatusPanel): def __init__ (self, h, l, y, x, status_obj): - super(ServerInfoPanel, self).__init__(h, l, y ,x ,"Server Info:") - - self.status_obj = status_obj + super(ServerInfoPanel, self).__init__(h, l, y ,x ,"Server Info:", status_obj) def draw (self): - if self.status_obj.server_version == None: + if not self.status_obj.server_version : + return + + if not self.status_obj.server_sys_info: return - self.clear() - connection_details = self.status_obj.rpc_client.get_connection_details() + self.clear() - self.getwin().addstr(3, 2, "{:<30} {:30}".format("Server:",self.status_obj.server_sys_info["hostname"] + ":" + str(connection_details['port']))) + self.getwin().addstr(3, 2, "{:<30} {:30}".format("Server:",self.status_obj.server_sys_info["hostname"] + ":" + str(self.stateless_client.get_connection_port()))) self.getwin().addstr(4, 2, "{:<30} {:30}".format("Version:", self.status_obj.server_version["version"])) self.getwin().addstr(5, 2, "{:<30} {:30}".format("Build:", self.status_obj.server_version["build_date"] + " @ " + @@ -123,7 +90,7 @@ class ServerInfoPanel(TrexStatusPanel): self.getwin().addstr(9, 2, "{:<30} {:<30}".format("Ports Count:", self.status_obj.server_sys_info["port_count"])) - ports_owned = " ".join(str(x) for x in self.status_obj.rpc_client.get_owned_ports()) + ports_owned = " ".join(str(x) for x in self.status_obj.owned_ports_list) if not ports_owned: ports_owned = "None" @@ -134,92 +101,123 @@ class ServerInfoPanel(TrexStatusPanel): class GeneralInfoPanel(TrexStatusPanel): def __init__ (self, h, l, y, x, status_obj): - super(GeneralInfoPanel, self).__init__(h, l, y ,x ,"General Info:") - - self.status_obj = status_obj + super(GeneralInfoPanel, self).__init__(h, l, y ,x ,"General Info:", status_obj) def draw (self): - pass + self.clear() + + if not self.general_stats.is_online(): + self.getwin().addstr(3, 2, "No Published Data From TRex Server") + return + + self.getwin().addstr(3, 2, "{:<30} {:0.2f} %".format("CPU util.:", self.general_stats.get("m_cpu_util"))) + + self.getwin().addstr(6, 2, "{:<30} {:} / {:}".format("Total Tx. rate:", + self.general_stats.get("m_tx_bps", format = True, suffix = "bps"), + self.general_stats.get("m_tx_pps", format = True, suffix = "pps"))) + + + self.getwin().addstr(8, 2, "{:<30} {:} / {:}".format("Total Tx:", + self.general_stats.get_rel("m_total_tx_bytes", format = True, suffix = "B"), + self.general_stats.get_rel("m_total_tx_pkts", format = True, suffix = "pkts"))) + + self.getwin().addstr(11, 2, "{:<30} {:} / {:}".format("Total Rx. rate:", + self.general_stats.get("m_rx_bps", format = True, suffix = "bps"), + self.general_stats.get("m_rx_pps", format = True, suffix = "pps"))) + + + self.getwin().addstr(13, 2, "{:<30} {:} / {:}".format("Total Rx:", + self.general_stats.get_rel("m_total_rx_bytes", format = True, suffix = "B"), + self.general_stats.get_rel("m_total_rx_pkts", format = True, suffix = "pkts"))) # all ports stats class PortsStatsPanel(TrexStatusPanel): def __init__ (self, h, l, y, x, status_obj): - super(PortsStatsPanel, self).__init__(h, l, y ,x ,"Trex Ports:") + super(PortsStatsPanel, self).__init__(h, l, y ,x ,"Trex Ports:", status_obj) - self.status_obj = status_obj def draw (self): self.clear() - owned_ports = self.status_obj.rpc_client.get_owned_ports() + owned_ports = self.status_obj.owned_ports_list if not owned_ports: self.getwin().addstr(3, 2, "No Owned Ports - Please Acquire One Or More Ports") return # table header - self.getwin().addstr(3, 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format( - "Port ID", "Tx [pps]", "Tx [bps]", "Tx [bytes]", "Rx [pps]", "Rx [bps]", "Rx [bytes]")) + self.getwin().addstr(3, 2, "{:^15} {:^30} {:^30} {:^30}".format( + "Port ID", "Tx Rate [bps/pps]", "Rx Rate [bps/pps]", "Total Bytes [tx/rx]")) + - # port loop - self.status_obj.stats.query_sync() for i, port_index in enumerate(owned_ports): port_stats = self.status_obj.stats.get_port_stats(port_index) if port_stats: - self.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^15,.2f} {:^15,.2f} {:^15,} {:^15,.2f} {:^15,.2f} {:^15,}".format( + self.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^30} {:^30} {:^30}".format( "{0} ({1})".format(str(port_index), self.status_obj.server_sys_info["ports"][port_index]["speed"]), - port_stats["tx_pps"], - port_stats["tx_bps"], - port_stats["total_tx_bytes"], - port_stats["rx_pps"], - port_stats["rx_bps"], - port_stats["total_rx_bytes"])) - + "{0} / {1}".format(port_stats.get("m_total_tx_bps", format = True, suffix = "bps"), + port_stats.get("m_total_tx_pps", format = True, suffix = "pps")), + + "{0} / {1}".format(port_stats.get("m_total_rx_bps", format = True, suffix = "bps"), + port_stats.get("m_total_rx_pps", format = True, suffix = "pps")), + "{0} / {1}".format(port_stats.get_rel("obytes", format = True, suffix = "B"), + port_stats.get_rel("ibytes", format = True, suffix = "B")))) + else: - self.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format( + self.getwin().addstr(5 + (i * 4), 2, 2, "{:^15} {:^30} {:^30} {:^30}".format( "{0} ({1})".format(str(port_index), self.status_obj.server_sys_info["ports"][port_index]["speed"]), "N/A", "N/A", "N/A", - "N/A", - "N/A", "N/A")) + + # old format +# if port_stats: +# self.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format( +# "{0} ({1})".format(str(port_index), self.status_obj.server_sys_info["ports"][port_index]["speed"]), +# port_stats.get("m_total_tx_pps", format = True, suffix = "pps"), +# port_stats.get("m_total_tx_bps", format = True, suffix = "bps"), +# port_stats.get_rel("obytes", format = True, suffix = "B"), +# port_stats.get("m_total_rx_pps", format = True, suffix = "pps"), +# port_stats.get("m_total_rx_bps", format = True, suffix = "bps"), +# port_stats.get_rel("ibytes", format = True, suffix = "B"))) +# +# else: +# self.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format( +# "{0} ({1})".format(str(port_index), self.status_obj.server_sys_info["ports"][port_index]["speed"]), +# "N/A", +# "N/A", +# "N/A", +# "N/A", +# "N/A", +# "N/A")) + # control panel class ControlPanel(TrexStatusPanel): def __init__ (self, h, l, y, x, status_obj): - super(ControlPanel, self).__init__(h, l, y, x, "") + super(ControlPanel, self).__init__(h, l, y, x, "", status_obj) - self.status_obj = status_obj def draw (self): self.clear() self.getwin().addstr(1, 2, "'g' - general, '0-{0}' - specific port, 'f' - freeze, 'c' - clear stats, 'p' - ping server, 'q' - quit" - .format(self.status_obj.rpc_client.get_port_count() - 1)) + .format(self.status_obj.stateless_client.get_port_count() - 1)) - index = 3 - - cut = len(self.status_obj.log) - 4 - if cut < 0: - cut = 0 - - for l in self.status_obj.log[cut:]: - self.getwin().addstr(index, 2, l) - index += 1 + self.log.draw(self.getwin(), 2, 3) # specific ports panels class SinglePortPanel(TrexStatusPanel): def __init__ (self, h, l, y, x, status_obj, port_id): - super(SinglePortPanel, self).__init__(h, l, y, x, "Port {0}".format(port_id)) + super(SinglePortPanel, self).__init__(h, l, y, x, "Port {0}".format(port_id), status_obj) - self.status_obj = status_obj self.port_id = port_id def draw (self): @@ -227,7 +225,7 @@ class SinglePortPanel(TrexStatusPanel): self.clear() - if not self.port_id in self.status_obj.rpc_client.get_owned_ports(): + if not self.port_id in self.status_obj.owned_ports_list: self.getwin().addstr(y, 2, "Port {0} is not owned by you, please acquire the port for more info".format(self.port_id)) return @@ -241,16 +239,19 @@ class SinglePortPanel(TrexStatusPanel): y += 2 # streams - if 'streams' in self.status_obj.snapshot[self.port_id]: - for stream_id, stream in self.status_obj.snapshot[self.port_id]['streams'].iteritems(): + + if 'streams' in self.status_obj.owned_ports[str(self.port_id)]: + stream_info = self.status_obj.owned_ports[str(self.port_id)]['streams'] + + for stream_id, stream in sorted(stream_info.iteritems(), key=operator.itemgetter(0)): self.getwin().addstr(y, 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format( stream_id, - ("True" if stream['stream']['enabled'] else "False"), - stream['stream']['mode']['type'], - ("True" if stream['stream']['self_start'] else "False"), - stream['stream']['isg'], - (stream['stream']['next_stream_id'] if stream['stream']['next_stream_id'] != -1 else "None"), - ("{0} instr.".format(len(stream['stream']['vm'])) if stream['stream']['vm'] else "None"))) + ("True" if stream['enabled'] else "False"), + stream['mode']['type'], + ("True" if stream['self_start'] else "False"), + stream['isg'], + (stream['next_stream_id'] if stream['next_stream_id'] != -1 else "None"), + ("{0} instr.".format(len(stream['vm'])) if stream['vm'] else "None"))) y += 1 @@ -260,128 +261,180 @@ class SinglePortPanel(TrexStatusPanel): self.getwin().addstr(y, 2, "Traffic:", curses.A_UNDERLINE) y += 2 - self.status_obj.stats.query_sync() - port_stats = self.status_obj.stats.get_port_stats(self.port_id) - # table header - self.getwin().addstr(y, 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format( - "Port ID", "Tx [pps]", "Tx [bps]", "Tx [bytes]", "Rx [pps]", "Rx [bps]", "Rx [bytes]")) + # table header + self.getwin().addstr(y, 2, "{:^15} {:^30} {:^30} {:^30}".format( + "Port ID", "Tx Rate [bps/pps]", "Rx Rate [bps/pps]", "Total Bytes [tx/rx]")) + y += 2 - if port_stats: - self.getwin().addstr(y, 2, "{:^15} {:^15,} {:^15,} {:^15,} {:^15,} {:^15,} {:^15,}".format( - "{0} ({1})".format(str(self.port_id), self.status_obj.server_sys_info["ports"][self.port_id]["speed"]), - port_stats["tx_pps"], - port_stats["tx_bps"], - port_stats["total_tx_bytes"], - port_stats["rx_pps"], - port_stats["rx_bps"], - port_stats["total_rx_bytes"])) + port_stats = self.status_obj.stats.get_port_stats(self.port_id) + if port_stats: + self.getwin().addstr(y, 2, "{:^15} {:^30} {:^30} {:^30}".format( + "{0} ({1})".format(str(self.port_id), self.status_obj.server_sys_info["ports"][self.port_id]["speed"]), + "{0} / {1}".format(port_stats.get("m_total_tx_bps", format = True, suffix = "bps"), + port_stats.get("m_total_tx_pps", format = True, suffix = "pps")), + + "{0} / {1}".format(port_stats.get("m_total_rx_bps", format = True, suffix = "bps"), + port_stats.get("m_total_rx_pps", format = True, suffix = "pps")), + "{0} / {1}".format(port_stats.get_rel("obytes", format = True, suffix = "B"), + port_stats.get_rel("ibytes", format = True, suffix = "B")))) + else: - self.getwin().addstr(y, 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format( + self.getwin().addstr(y + (i * 4), 2, 2, "{:^15} {:^30} {:^30} {:^30}".format( "{0} ({1})".format(str(self.port_id), self.status_obj.server_sys_info["ports"][self.port_id]["speed"]), "N/A", "N/A", "N/A", - "N/A", - "N/A", "N/A")) - y += 2 -# status object -class TrexStatus(): - def __init__ (self, stdscr, rpc_client): - self.stdscr = stdscr +################### main objects ################# + +# status log +class TrexStatusLog(): + def __init__ (self): self.log = [] - self.rpc_client = rpc_client - self.snapshot = self.rpc_client.snapshot() + def add_event (self, msg): + self.log.append("[{0}] {1}".format(str(datetime.datetime.now().time()), msg)) - # fetch server info - self.get_server_info() + def draw (self, window, x, y, max_lines = 4): + index = y + + cut = len(self.log) - max_lines + if cut < 0: + cut = 0 + + for msg in self.log[cut:]: + window.addstr(index, x, msg) + index += 1 + +# status commands +class TrexStatusCommands(): + def __init__ (self, status_object): - # create stats objects - self.stats = Stats(rpc_client, self.rpc_client.get_owned_ports()) + self.status_object = status_object + + self.stateless_client = status_object.stateless_client + self.log = self.status_object.log - # register actions self.actions = {} - self.actions[ord('q')] = self.action_quit - self.actions[ord('p')] = self.action_ping - self.actions[ord('f')] = self.action_freeze + self.actions[ord('q')] = self._quit + self.actions[ord('p')] = self._ping + self.actions[ord('f')] = self._freeze - self.actions[ord('g')] = self.action_show_ports_stats + self.actions[ord('g')] = self._show_ports_stats - for port_id in xrange(0, self.rpc_client.get_port_count()): - self.actions[ord('0') + port_id] = self.action_show_port_generator(port_id) + # register all the available ports shortcuts + for port_id in xrange(0, self.stateless_client.get_port_count()): + self.actions[ord('0') + port_id] = self._show_port_generator(port_id) + + + # handle a key pressed + def handle (self, ch): + if ch in self.actions: + return self.actions[ch]() + else: + self.log.add_event("Unknown key pressed, please see legend") + return True + + # show all ports + def _show_ports_stats (self): + self.log.add_event("Switching to all ports view") + self.status_object.stats_panel = self.status_object.ports_stats_panel - - # all ports stats - def action_show_ports_stats (self): - self.add_log_event("Switching to all ports view") - self.stats_panel = self.ports_stats_panel - return True - # function generator for different ports requests - def action_show_port_generator (self, port_id): - def action_show_port(): - self.add_log_event("Switching panel to port {0}".format(port_id)) - self.stats_panel = self.ports_panels[port_id] + + # function generator for different ports requests + def _show_port_generator (self, port_id): + def _show_port(): + self.log.add_event("Switching panel to port {0}".format(port_id)) + self.status_object.stats_panel = self.status_object.ports_panels[port_id] return True - return action_show_port + return _show_port - def action_freeze (self): - self.update_active = not self.update_active - self.add_log_event("Update continued" if self.update_active else "Update stopped") + def _freeze (self): + self.status_object.update_active = not self.status_object.update_active + self.log.add_event("Update continued" if self.status_object.update_active else "Update stopped") return True - def action_quit(self): + def _quit(self): return False - def action_ping (self): - self.add_log_event("Pinging RPC server") + def _ping (self): + self.log.add_event("Pinging RPC server") - rc, msg = self.rpc_client.ping_rpc_server() + rc, msg = self.stateless_client.ping() if rc: - self.add_log_event("Server replied: '{0}'".format(msg)) + self.log.add_event("Server replied: '{0}'".format(msg)) else: - self.add_log_event("Failed to get reply") + self.log.add_event("Failed to get reply") return True - def get_server_info (self): +# status object +# +# +# +class TrexStatus(): + def __init__ (self, stdscr, stateless_client): + self.stdscr = stdscr - self.server_version = self.rpc_client.get_rpc_server_version() - self.server_sys_info = self.rpc_client.get_system_info() + self.stateless_client = stateless_client + self.log = TrexStatusLog() + self.cmds = TrexStatusCommands(self) - def add_log_event (self, msg): - self.log.append("[{0}] {1}".format(str(datetime.datetime.now().time()), msg)) + self.stats = stateless_client.get_stats_async() + self.general_stats = stateless_client.get_stats_async().get_general_stats() - # control panel - def update_control (self): - self.control_panel.clear() + # fetch server info + rc, self.server_sys_info = self.stateless_client.get_system_info() + if not rc: + return - self.control_panel.getwin().addstr(1, 2, "'g' - general, '0-{0}' - specific port, 'f' - freeze, 'c' - clear stats, 'p' - ping server, 'q' - quit" - .format(self.rpc_client.get_port_count() - 1)) + rc, self.server_version = self.stateless_client.get_version() + if not rc: + return - index = 3 + # list of owned ports + self.owned_ports_list = self.stateless_client.get_acquired_ports() + + # data per port + self.owned_ports = {} - cut = len(self.log) - 4 - if cut < 0: - cut = 0 + for port_id in self.owned_ports_list: + self.owned_ports[str(port_id)] = {} + self.owned_ports[str(port_id)]['streams'] = {} - for l in self.log[cut:]: - self.control_panel.getwin().addstr(index, 2, l) - index += 1 + rc, stream_list = self.stateless_client.get_all_streams(port_id) + if not rc: + raise Exception("unable to get streams") + self.owned_ports[str(port_id)] = stream_list + + + try: + curses.curs_set(0) + except: + pass + + curses.use_default_colors() + self.stdscr.nodelay(1) + curses.nonl() + curses.noecho() + + self.generate_layout() + + def generate_layout (self): self.max_y = self.stdscr.getmaxyx()[0] self.max_x = self.stdscr.getmaxyx()[1] @@ -394,7 +447,7 @@ class TrexStatus(): self.ports_stats_panel = PortsStatsPanel(int(self.max_y * 0.8), self.max_x / 2, 0, 0, self) self.ports_panels = {} - for i in xrange(0, self.rpc_client.get_port_count()): + for i in xrange(0, self.stateless_client.get_port_count()): self.ports_panels[i] = SinglePortPanel(int(self.max_y * 0.8), self.max_x / 2, 0, 0, self, i) # at start time we point to the main one @@ -411,28 +464,27 @@ class TrexStatus(): # no key , continue if ch == curses.ERR: return True - - # check for registered function - if ch in self.actions: - return self.actions[ch]() - else: - self.add_log_event("Unknown key pressed, please see legend") - - return True + + return self.cmds.handle(ch) # main run entry point def run (self): - try: - curses.curs_set(0) - except: - pass - curses.use_default_colors() - self.stdscr.nodelay(1) - curses.nonl() - curses.noecho() + # list of owned ports + self.owned_ports_list = self.stateless_client.get_acquired_ports() - self.generate_layout() + # data per port + self.owned_ports = {} + + for port_id in self.owned_ports_list: + self.owned_ports[str(port_id)] = {} + self.owned_ports[str(port_id)]['streams'] = {} + + rc, stream_list = self.stateless_client.get_all_streams(port_id) + if not rc: + raise Exception("unable to get streams") + + self.owned_ports[str(port_id)] = stream_list self.update_active = True while (True): @@ -454,14 +506,21 @@ class TrexStatus(): sleep(0.01) -def show_trex_status_internal (stdscr, rpc_client): - trex_status = TrexStatus(stdscr, rpc_client) +# global container +trex_status = None + +def show_trex_status_internal (stdscr, stateless_client): + global trex_status + + if trex_status == None: + trex_status = TrexStatus(stdscr, stateless_client) + trex_status.run() -def show_trex_status (rpc_client): +def show_trex_status (stateless_client): try: - curses.wrapper(show_trex_status_internal, rpc_client) + curses.wrapper(show_trex_status_internal, stateless_client) except KeyboardInterrupt: curses.endwin() |