From 30c686d5de018612cf404520d139a9b5a021ea32 Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 21 Sep 2015 13:46:33 +0300 Subject: checkpoint - added stats and some python code --- .../trex_control_plane/console/trex_console.py | 100 +++++++++++++++++++-- 1 file changed, 93 insertions(+), 7 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 6514a51c..4ce6127e 100644 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -4,9 +4,13 @@ import cmd import json import ast import argparse +import random +import string + import sys import trex_root_path -from client_utils.jsonrpc_client import JsonRpcClient + +from client_utils.jsonrpc_client import TrexStatelessClient import trex_status class TrexConsole(cmd.Cmd): @@ -34,7 +38,7 @@ class TrexConsole(cmd.Cmd): # set verbose on / off def do_verbose (self, line): - '''shows or set verbose mode\n''' + '''Shows or set verbose mode\n''' if line == "": print "\nverbose is " + ("on\n" if self.verbose else "off\n") @@ -78,6 +82,81 @@ class TrexConsole(cmd.Cmd): print "\n*** " + msg + "\n" return + def do_force_acquire (self, line): + '''Acquires ports by force\n''' + + self.do_acquire(line, True) + + def parse_ports_from_line (self, line): + port_list = set() + + if line: + for port_id in line.split(' '): + if (not port_id.isdigit()) or (int(port_id) < 0) or (int(port_id) >= self.rpc_client.get_port_count()): + print "Please provide a list of ports seperated by spaces between 0 and {0}".format(self.rpc_client.get_port_count() - 1) + return None + + port_list.add(int(port_id)) + + port_list = list(port_list) + + else: + port_list = [i for i in xrange(0, self.rpc_client.get_port_count())] + + return port_list + + def do_acquire (self, line, force = False): + '''Acquire ports\n''' + + port_list = self.parse_ports_from_line(line) + if not port_list: + return + + print "\nTrying to acquire ports: " + (" ".join(str(x) for x in port_list)) + "\n" + + rc, resp_list = self.rpc_client.take_ownership(port_list, force) + + if not rc: + print "\n*** " + resp_list + "\n" + return + + for i, rc in enumerate(resp_list): + if rc[0]: + print "Port {0} - Acquired".format(port_list[i]) + else: + print "Port {0} - ".format(port_list[i]) + rc[1] + + print "\n" + + def do_release (self, line): + '''Release ports\n''' + + port_list = self.parse_ports_from_line(line) + if not port_list: + return + + def do_get_port_stats (self, line): + '''Get ports stats\n''' + + port_list = self.parse_ports_from_line(line) + if not port_list: + return + + rc, resp_list = self.rpc_client.get_port_stats(port_list) + + if not rc: + print "\n*** " + resp_list + "\n" + return + + for i, rc in enumerate(resp_list): + if rc[0]: + print "\nPort {0} stats:\n{1}\n".format(port_list[i], self.rpc_client.pretty_json(json.dumps(rc[1]))) + else: + print "\nPort {0} - ".format(i) + rc[1] + "\n" + + print "\n" + + def do_connect (self, line): '''Connects to the server\n''' @@ -97,8 +176,7 @@ class TrexConsole(cmd.Cmd): print "\n*** " + msg + "\n" return - rc, msg = self.rpc_client.query_rpc_server() - + rc, msg = self.rpc_client.get_supported_cmds() if rc: self.supported_rpc = [str(x) for x in msg if x] @@ -135,7 +213,7 @@ class TrexConsole(cmd.Cmd): rc, msg = self.rpc_client.invoke_rpc_method(method, params) if rc: - print "\nServer Response:\n\n" + json.dumps(msg) + "\n" + print "\nServer Response:\n\n" + self.rpc_client.pretty_json(json.dumps(msg)) + "\n" else: print "\n*** " + msg + "\n" #print "Please try 'reconnect' to reconnect to server" @@ -151,7 +229,7 @@ class TrexConsole(cmd.Cmd): trex_status.show_trex_status(self.rpc_client) def do_quit(self, line): - '''exit the client\n''' + '''Exit the client\n''' return True def do_disconnect (self, line): @@ -166,6 +244,10 @@ class TrexConsole(cmd.Cmd): else: print msg + "\n" + def do_whoami (self, line): + '''Prints console user name\n''' + print "\n" + self.rpc_client.whoami() + "\n" + def postcmd(self, stop, line): if self.rpc_client.is_connected(): self.prompt = "TRex > " @@ -230,6 +312,10 @@ def setParserOptions (): default = 5050, type = int) + parser.add_argument("-u", "--user", help = "User Name [default is random generated]\n", + default = 'user_' + ''.join(random.choice(string.digits) for _ in range(5)), + type = str) + return parser def main (): @@ -237,7 +323,7 @@ def main (): options = parser.parse_args(sys.argv[1:]) # RPC client - rpc_client = JsonRpcClient(options.server, options.port) + rpc_client = TrexStatelessClient(options.server, options.port, options.user) # console try: -- cgit 1.2.3-korg From 3f4249b20c0edfb6902d1e4b5ebd13244f5a17b7 Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 21 Sep 2015 16:13:27 +0300 Subject: some python console modifications --- .../client_utils/jsonrpc_client.py | 63 +++- .../trex_control_plane/console/trex_console.py | 23 +- .../trex_control_plane/console/trex_status.py | 350 ++++++++++++++------- 3 files changed, 301 insertions(+), 135 deletions(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py b/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py index 96a4154b..0d46ba11 100644 --- a/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py +++ b/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py @@ -250,7 +250,11 @@ class TrexStatelessClient(JsonRpcClient): self.user = user self.port_handlers = {} - self.system_info = None + + self.supported_cmds = [] + self.system_info = None + self.server_version = None + def whoami (self): return self.user @@ -260,13 +264,13 @@ class TrexStatelessClient(JsonRpcClient): return self.invoke_rpc_method("ping", block = False) def get_rpc_server_version (self): - return self.invoke_rpc_method("get_version") + return self.server_version def get_system_info (self): - return self.invoke_rpc_method("get_system_info") + return self.system_info def get_supported_cmds(self): - return self.invoke_rpc_method("get_supported_cmds") + return self.supported_cmds def get_port_count (self): if not self.system_info: @@ -274,27 +278,27 @@ class TrexStatelessClient(JsonRpcClient): return self.system_info["port_count"] - def connect (self): - rc, err = super(TrexStatelessClient, self).connect() - if not rc: - return rc, err + # refresh the client for transient data + def refresh (self): - # ping the server - rc, msg = self.ping_rpc_server() + # get server versionrc, msg = self.get_supported_cmds() + rc, msg = self.invoke_rpc_method("get_version") if not rc: self.disconnect() return rc, msg + self.server_version = msg + # get supported commands - rc, msg = self.get_supported_cmds() + rc, msg = self.invoke_rpc_method("get_supported_cmds") if not rc: self.disconnect() return rc, msg - self.supported_rpc = [str(x) for x in msg if x] + self.supported_cmds = [str(x) for x in msg if x] # get system info - rc, msg = self.get_system_info() + rc, msg = self.invoke_rpc_method("get_system_info") if not rc: self.disconnect() return rc, msg @@ -303,6 +307,14 @@ class TrexStatelessClient(JsonRpcClient): return True, "" + def connect (self): + rc, err = super(TrexStatelessClient, self).connect() + if not rc: + return rc, err + + return self.refresh() + + # take ownership over ports def take_ownership (self, port_id_array, force = False): if not self.connected: @@ -324,6 +336,30 @@ class TrexStatelessClient(JsonRpcClient): return True, resp_list + def release_ports (self, port_id_array): + batch = self.create_batch() + + for port_id in port_id_array: + + # let the server handle un-acquired errors + if self.port_handlers.get(port_id): + handler = self.port_handlers[port_id] + else: + handler = "" + + batch.add("release", params = {"port_id":port_id, "handler":handler}) + + + rc, resp_list = batch.invoke() + if not rc: + return rc, resp_list + + for i, rc in enumerate(resp_list): + if rc[0]: + self.port_handlers.pop(port_id_array[i]) + + return True, resp_list + def get_owned_ports (self): return self.port_handlers.keys() @@ -353,3 +389,4 @@ class TrexStatelessClient(JsonRpcClient): return rc, resp_list + \ No newline at end of file diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 4ce6127e..509ec3ee 100644 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -131,10 +131,27 @@ class TrexConsole(cmd.Cmd): def do_release (self, line): '''Release ports\n''' - port_list = self.parse_ports_from_line(line) + if line: + port_list = self.parse_ports_from_line(line) + else: + port_list = self.rpc_client.get_owned_ports() + if not port_list: return + rc, resp_list = self.rpc_client.release_ports(port_list) + + + print "\n" + + for i, rc in enumerate(resp_list): + if rc[0]: + print "Port {0} - Released".format(port_list[i]) + else: + print "Port {0} - Failed to release port, probably not owned by you or port is under traffic" + + print "\n" + def do_get_port_stats (self, line): '''Get ports stats\n''' @@ -176,9 +193,7 @@ class TrexConsole(cmd.Cmd): print "\n*** " + msg + "\n" return - rc, msg = self.rpc_client.get_supported_cmds() - if rc: - self.supported_rpc = [str(x) for x in msg if x] + self.supported_rpc = self.rpc_client.get_supported_cmds() def do_rpc (self, line): '''Launches a RPC on the server\n''' diff --git a/scripts/automation/trex_control_plane/console/trex_status.py b/scripts/automation/trex_control_plane/console/trex_status.py index b01bc3e7..301b71f5 100644 --- a/scripts/automation/trex_control_plane/console/trex_status.py +++ b/scripts/automation/trex_control_plane/console/trex_status.py @@ -11,13 +11,21 @@ import datetime g_curses_active = False -# +# 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" + # panel object -class TrexStatusPanel(): +class TrexStatusPanel(object): def __init__ (self, h, l, y, x, headline): self.h = h self.l = l @@ -44,13 +52,6 @@ class TrexStatusPanel(): def getwin (self): return self.win -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" - # total stats (ports + global) class Stats(): @@ -90,115 +91,87 @@ class Stats(): self.port_stats[self.port_list[i]] = rc[1] +# various kinds of panels -# status object -class TrexStatus(): - def __init__ (self, stdscr, rpc_client): - self.stdscr = stdscr - self.log = [] - self.rpc_client = rpc_client - - self.get_server_info() - - self.stats = Stats(rpc_client, self.rpc_client.get_owned_ports()) - - self.actions = {} - self.actions[ord('q')] = self.action_quit - self.actions[ord('p')] = self.action_ping +# Server Info Panel +class ServerInfoPanel(TrexStatusPanel): + def __init__ (self, h, l, y, x, status_obj): - def action_quit(self): - return False + super(ServerInfoPanel, self).__init__(h, l, y ,x ,"Server Info:") - def action_ping (self): - self.add_log_event("Pinging RPC server") - rc, msg = self.rpc_client.ping_rpc_server() - if rc: - self.add_log_event("Server replied: '{0}'".format(msg)) - else: - self.add_log_event("Failed to get reply") - return True + self.status_obj = status_obj - def get_server_info (self): - rc, msg = self.rpc_client.get_rpc_server_version() + def draw (self): - if rc: - self.server_version = msg - else: - self.server_version = None + if self.status_obj.server_version == None: + return - rc, msg = self.rpc_client.get_system_info() + self.clear() - if rc: - self.server_sys_info = msg - else: - self.server_sys_info = None + connection_details = self.status_obj.rpc_client.get_connection_details() + self.getwin().addstr(3, 2, "{:<30} {:30}".format("Server:",self.status_obj.server_sys_info["hostname"] + ":" + str(connection_details['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"] + " @ " + + self.status_obj.server_version["build_time"] + " by " + + self.status_obj.server_version["built_by"])) - def add_log_event (self, msg): - self.log.append("[{0}] {1}".format(str(datetime.datetime.now().time()), msg)) + self.getwin().addstr(6, 2, "{:<30} {:30}".format("Server Uptime:", self.status_obj.server_sys_info["uptime"])) + self.getwin().addstr(7, 2, "{:<30} {:<3} / {:<30}".format("DP Cores:", str(self.status_obj.server_sys_info["dp_core_count"]) + + " cores", self.status_obj.server_sys_info["core_type"])) - def add_panel (self, h, l, y, x, headline): - win = curses.newwin(h, l, y, x) - win.erase() - win.box() + self.getwin().addstr(9, 2, "{:<30} {:<30}".format("Ports Count:", self.status_obj.server_sys_info["port_count"])) - win.addstr(1, 2, headline) - win.refresh() + ports_owned = " ".join(str(x) for x in self.status_obj.rpc_client.get_owned_ports()) - panel.new_panel(win) - panel1 = panel.new_panel(win) - panel1.top() + if not ports_owned: + ports_owned = "None" - return win, panel1 + self.getwin().addstr(10, 2, "{:<30} {:<30}".format("Ports Owned:", ports_owned)) - # static info panel - def update_info (self): - if self.server_version == None: - return +# general info panel +class GeneralInfoPanel(TrexStatusPanel): + def __init__ (self, h, l, y, x, status_obj): - self.info_panel.clear() + super(GeneralInfoPanel, self).__init__(h, l, y ,x ,"General Info:") - connection_details = self.rpc_client.get_connection_details() + self.status_obj = status_obj - self.info_panel.getwin().addstr(3, 2, "{:<30} {:30}".format("Server:",self.server_sys_info["hostname"] + ":" + str(connection_details['port']))) - self.info_panel.getwin().addstr(4, 2, "{:<30} {:30}".format("Version:", self.server_version["version"])) - self.info_panel.getwin().addstr(5, 2, "{:<30} {:30}".format("Build:", - self.server_version["build_date"] + " @ " + self.server_version["build_time"] + " by " + self.server_version["built_by"])) + def draw (self): + pass - self.info_panel.getwin().addstr(6, 2, "{:<30} {:30}".format("Server Uptime:", self.server_sys_info["uptime"])) - self.info_panel.getwin().addstr(7, 2, "{:<30} {:<3} / {:<30}".format("DP Cores:", str(self.server_sys_info["dp_core_count"]) + " cores", self.server_sys_info["core_type"])) - self.info_panel.getwin().addstr(9, 2, "{:<30} {:<30}".format("Ports Count:", self.server_sys_info["port_count"])) +# all ports stats +class PortsStatsPanel(TrexStatusPanel): + def __init__ (self, h, l, y, x, status_obj): - ports_owned = " ".join(str(x) for x in self.rpc_client.get_owned_ports()) - if not ports_owned: - ports_owned = "None" - self.info_panel.getwin().addstr(10, 2, "{:<30} {:<30}".format("Ports Owned:", ports_owned)) + super(PortsStatsPanel, self).__init__(h, l, y ,x ,"Trex Ports:") + self.status_obj = status_obj - # general stats - def update_ports_stats (self): + def draw (self): - self.ports_stats_panel.clear() + self.clear() - owned_ports = self.rpc_client.get_owned_ports() + owned_ports = self.status_obj.rpc_client.get_owned_ports() if not owned_ports: - self.ports_stats_panel.getwin().addstr(3, 2, "No Owned Ports - Please Acquire One Or More Ports") + self.getwin().addstr(3, 2, "No Owned Ports - Please Acquire One Or More Ports") return # table header - self.ports_stats_panel.getwin().addstr(3, 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format( + 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]")) # port loop - self.stats.query_sync() + self.status_obj.stats.query_sync() for i, port_index in enumerate(owned_ports): - port_stats = self.stats.get_port_stats(port_index) + port_stats = self.status_obj.stats.get_port_stats(port_index) if port_stats: - self.ports_stats_panel.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^15,} {:^15,} {:^15,} {:^15,} {:^15,} {:^15,}".format( - "{0} ({1})".format(str(port_index), self.server_sys_info["ports"][port_index]["speed"]), + 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["tx_pps"], port_stats["tx_bps"], port_stats["total_tx_bytes"], @@ -207,8 +180,8 @@ class TrexStatus(): port_stats["total_rx_bytes"])) else: - self.ports_stats_panel.getwin().addstr(5 + (i * 4), 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format( - "{0} ({1})".format(str(port_index), self.server_sys_info["ports"][port_index]["speed"]), + 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", @@ -216,6 +189,160 @@ class TrexStatus(): "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, "") + + 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)) + + 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 + +# 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)) + + self.status_obj = status_obj + self.port_id = port_id + + def draw (self): + y = 3 + + self.clear() + + if not self.port_id in self.status_obj.rpc_client.get_owned_ports(): + self.getwin().addstr(y, 2, "Port {0} is not owned by you, please acquire the port for more info".format(self.port_id)) + return + + # streams + self.getwin().addstr(y, 2, "Streams:", curses.A_UNDERLINE) + y += 2 + + y += 2 + + 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]")) + + 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"])) + + else: + 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"]), + "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 + self.log = [] + self.rpc_client = rpc_client + + # fetch server info + self.get_server_info() + + # create stats objects + self.stats = Stats(rpc_client, self.rpc_client.get_owned_ports()) + + # 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('g')] = self.action_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) + + + # 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] + + return True + + return action_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") + + return True + + def action_quit(self): + return False + + def action_ping (self): + self.add_log_event("Pinging RPC server") + + rc, msg = self.rpc_client.ping_rpc_server() + if rc: + self.add_log_event("Server replied: '{0}'".format(msg)) + else: + self.add_log_event("Failed to get reply") + + return True + + def get_server_info (self): + + self.server_version = self.rpc_client.get_rpc_server_version() + self.server_sys_info = self.rpc_client.get_system_info() + + + def add_log_event (self, msg): + self.log.append("[{0}] {1}".format(str(datetime.datetime.now().time()), msg)) + # control panel def update_control (self): self.control_panel.clear() @@ -237,16 +364,24 @@ class TrexStatus(): self.max_y = self.stdscr.getmaxyx()[0] self.max_x = self.stdscr.getmaxyx()[1] - # create cls panel - self.ports_stats_panel = TrexStatusPanel(int(self.max_y * 0.8), self.max_x / 2, 0,0, "Trex Ports:") + self.server_info_panel = ServerInfoPanel(int(self.max_y * 0.3), self.max_x / 2, int(self.max_y * 0.5), self.max_x /2, self) + self.general_info_panel = GeneralInfoPanel(int(self.max_y * 0.5), self.max_x / 2, 0, self.max_x /2, self) + self.control_panel = ControlPanel(int(self.max_y * 0.2), self.max_x , int(self.max_y * 0.8), 0, self) - self.general_panel = TrexStatusPanel(int(self.max_y * 0.5), self.max_x / 2, 0, self.max_x /2, "General Statistics:") + # those can be switched on the same place + self.ports_stats_panel = PortsStatsPanel(int(self.max_y * 0.8), self.max_x / 2, 0, 0, self) - self.info_panel = TrexStatusPanel(int(self.max_y * 0.3), self.max_x / 2, int(self.max_y * 0.5), self.max_x /2, "Server Info:") + self.ports_panels = {} + for i in xrange(0, self.rpc_client.get_port_count()): + self.ports_panels[i] = SinglePortPanel(int(self.max_y * 0.8), self.max_x / 2, 0, 0, self, i) - self.control_panel = TrexStatusPanel(int(self.max_y * 0.2), self.max_x , int(self.max_y * 0.8), 0, "") + # at start time we point to the main one + self.stats_panel = self.ports_stats_panel + self.stats_panel.panel.top() panel.update_panels(); self.stdscr.refresh() + return + def wait_for_key_input (self): ch = self.stdscr.getch() @@ -263,31 +398,6 @@ class TrexStatus(): return True - if (ch != curses.ERR): - # stop/start status - if (ch == ord('f')): - self.update_active = not self.update_active - self.add_log_event("Update continued" if self.update_active else "Update stopped") - - elif (ch == ord('p')): - self.add_log_event("Pinging RPC server") - rc, msg = self.rpc_client.ping_rpc_server() - if rc: - self.add_log_event("Server replied: '{0}'".format(msg)) - else: - self.add_log_event("Failed to get reply") - - # c - clear stats - elif (ch == ord('c')): - self.add_log_event("Statistics cleared") - - elif (ch == ord('q')): - return False - else: - self.add_log_event("Unknown key pressed, please see legend") - - return True - # main run entry point def run (self): try: @@ -309,9 +419,13 @@ class TrexStatus(): if not rc: break - self.update_control() - self.update_info() - self.update_ports_stats() + self.server_info_panel.draw() + self.general_info_panel.draw() + self.control_panel.draw() + + # can be different kinds of panels + self.stats_panel.panel.top() + self.stats_panel.draw() panel.update_panels(); self.stdscr.refresh() -- cgit 1.2.3-korg From d9e1cc14540431aa8baf8480625aa54c2a7c7175 Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 21 Sep 2015 18:27:02 +0300 Subject: more refinments on the console --- .../client_utils/jsonrpc_client.py | 58 +++++++++++++++++++++- .../trex_control_plane/console/trex_console.py | 7 +++ .../trex_control_plane/console/trex_status.py | 22 ++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) (limited to 'scripts/automation/trex_control_plane/console/trex_console.py') diff --git a/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py b/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py index 0d46ba11..893fd5e3 100644 --- a/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py +++ b/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py @@ -389,4 +389,60 @@ class TrexStatelessClient(JsonRpcClient): return rc, resp_list - \ No newline at end of file + # snapshot will take a snapshot of all your owned ports for streams and etc. + def snapshot(self): + + + if len(self.get_owned_ports()) == 0: + return {} + + snap = {} + + batch = self.create_batch() + + for port_id in self.get_owned_ports(): + + batch.add("get_port_stats", params = {"port_id": port_id, "handler": self.port_handlers[port_id]}) + batch.add("get_stream_list", params = {"port_id": port_id, "handler": self.port_handlers[port_id]}) + + rc, resp_list = batch.invoke() + if not rc: + return rc, resp_list + + # split the list to 2s + index = 0 + for port_id in self.get_owned_ports(): + if not resp_list[index] or not resp_list[index + 1]: + snap[port_id] = None + continue + + # fetch the first two + stats = resp_list[index][1] + stream_list = resp_list[index + 1][1] + + port = {} + port['status'] = stats['status'] + port['stream_list'] = [] + + # get all the streams + if len(stream_list) > 0: + batch = self.create_batch() + for stream_id in stream_list: + batch.add("get_stream", params = {"port_id": port_id, "stream_id": stream_id, "handler": self.port_handlers[port_id]}) + + rc, stream_resp_list = batch.invoke() + if not rc: + port = {} + + port['streams'] = {} + for i, resp in enumerate(stream_resp_list): + if resp[0]: + port['streams'][stream_list[i]] = resp[1] + + snap[port_id] = port + + # move to next one + index += 2 + + + return snap \ No newline at end of file diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 509ec3ee..3aeab901 100644 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -313,6 +313,13 @@ class TrexConsole(cmd.Cmd): print "{:<30} {:<30}".format(cmd + " - ", help) + # do + #def do_snapshot (self, line): + + #for key, value in self.rpc_client.snapshot()[1]['streams'].iteritems(): + #print str(key) + " " + str(value) + + # aliasing do_exit = do_EOF = do_q = do_quit diff --git a/scripts/automation/trex_control_plane/console/trex_status.py b/scripts/automation/trex_control_plane/console/trex_status.py index 301b71f5..b881f9f5 100644 --- a/scripts/automation/trex_control_plane/console/trex_status.py +++ b/scripts/automation/trex_control_plane/console/trex_status.py @@ -235,6 +235,26 @@ class SinglePortPanel(TrexStatusPanel): self.getwin().addstr(y, 2, "Streams:", curses.A_UNDERLINE) y += 2 + # stream table header + self.getwin().addstr(y, 2, "{:^15} {:^15} {:^15} {:^15} {:^15} {:^15} {:^15}".format( + "Stream ID", "Enabled", "Type", "Self Start", "ISG", "Next Stream", "VM")) + 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(): + 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"))) + + y += 1 + + # new section - traffic y += 2 self.getwin().addstr(y, 2, "Traffic:", curses.A_UNDERLINE) @@ -279,6 +299,8 @@ class TrexStatus(): self.log = [] self.rpc_client = rpc_client + self.snapshot = self.rpc_client.snapshot() + # fetch server info self.get_server_info() -- cgit 1.2.3-korg