summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2015-09-21 16:13:27 +0300
committerimarom <imarom@cisco.com>2015-09-21 16:13:27 +0300
commit3f4249b20c0edfb6902d1e4b5ebd13244f5a17b7 (patch)
treedc21c07a537e4d980398ba1d4065701d65648523 /scripts
parent30c686d5de018612cf404520d139a9b5a021ea32 (diff)
some python console modifications
Diffstat (limited to 'scripts')
-rw-r--r--scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py63
-rw-r--r--scripts/automation/trex_control_plane/console/trex_console.py23
-rw-r--r--scripts/automation/trex_control_plane/console/trex_status.py350
3 files changed, 301 insertions, 135 deletions
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()