summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2015-12-15 11:40:35 -0500
committerimarom <imarom@cisco.com>2015-12-15 11:40:35 -0500
commit68bf754b96a84c8a2a32bffab30189f8c8e9ad1b (patch)
tree03ed30251c1cc611d888bf62d5c4a8d36566dfd7 /scripts
parent419a25e989c47dcc5e94b9e3bc64252fb5197f10 (diff)
parent7b1796d823b38f7c8c801e19c51a4044bc39b17c (diff)
Merging lastest 'master' to side branch 'vm'
Conflicts: scripts/automation/trex_control_plane/console/trex_console.py
Diffstat (limited to 'scripts')
-rw-r--r--scripts/automation/trex_control_plane/client/trex_async_client.py5
-rwxr-xr-xscripts/automation/trex_control_plane/client/trex_client.py4
-rw-r--r--scripts/automation/trex_control_plane/client/trex_port.py101
-rwxr-xr-xscripts/automation/trex_control_plane/client/trex_stateless_client.py99
-rwxr-xr-xscripts/automation/trex_control_plane/client_utils/jsonrpc_client.py48
-rw-r--r--scripts/automation/trex_control_plane/common/trex_types.py6
-rwxr-xr-xscripts/automation/trex_control_plane/console/trex_console.py25
-rw-r--r--scripts/automation/trex_control_plane/console/trex_tui.py5
-rwxr-xr-xscripts/automation/trex_control_plane/server/trex_server.py2
9 files changed, 166 insertions, 129 deletions
diff --git a/scripts/automation/trex_control_plane/client/trex_async_client.py b/scripts/automation/trex_control_plane/client/trex_async_client.py
index 00304886..459d6915 100644
--- a/scripts/automation/trex_control_plane/client/trex_async_client.py
+++ b/scripts/automation/trex_control_plane/client/trex_async_client.py
@@ -19,6 +19,7 @@ import re
from common.trex_stats import *
from common.trex_streams import *
+from common.trex_types import *
# basic async stats class
class CTRexAsyncStats(object):
@@ -204,9 +205,9 @@ class CTRexAsyncClient():
time.sleep(0.01)
if time.time() > timeout:
self.disconnect()
- return False, "*** [subscriber] - no data flow from server at : " + self.tr
+ return RC_ERR("*** [subscriber] - no data flow from server at : " + self.tr)
- return True, ""
+ return RC_OK()
# disconnect
diff --git a/scripts/automation/trex_control_plane/client/trex_client.py b/scripts/automation/trex_control_plane/client/trex_client.py
index 49807014..a8669011 100755
--- a/scripts/automation/trex_control_plane/client/trex_client.py
+++ b/scripts/automation/trex_control_plane/client/trex_client.py
@@ -88,7 +88,7 @@ class CTRexClient(object):
finally:
self.prompt_verbose_data()
- def start_trex (self, f, d, block_to_success = True, timeout = 30, user = None, trex_development = False, **trex_cmd_options):
+ def start_trex (self, f, d, block_to_success = True, timeout = 40, user = None, trex_development = False, **trex_cmd_options):
"""
Request to start a TRex run on server.
@@ -104,7 +104,7 @@ class CTRexClient(object):
timeout : int
maximum time (in seconds) to wait in blocking state until TRex changes state from 'Starting' to either 'Idle' or 'Running'
- default value: **30**
+ default value: **40**
user : str
the identity of the the run issuer.
trex_cmd_options : key, val
diff --git a/scripts/automation/trex_control_plane/client/trex_port.py b/scripts/automation/trex_control_plane/client/trex_port.py
index 4f82e86a..54b4945e 100644
--- a/scripts/automation/trex_control_plane/client/trex_port.py
+++ b/scripts/automation/trex_control_plane/client/trex_port.py
@@ -3,6 +3,22 @@ from collections import namedtuple
from common.trex_types import *
from common import trex_stats
+
+########## utlity ############
+def mult_to_factor (mult, max_bps, max_pps, line_util):
+ if mult['type'] == 'raw':
+ return mult['value']
+
+ if mult['type'] == 'bps':
+ return mult['value'] / max_bps
+
+ if mult['type'] == 'pps':
+ return mult['value'] / max_pps
+
+ if mult['type'] == 'percentage':
+ return mult['value'] / line_util
+
+
# describes a single port
class Port(object):
STATE_DOWN = 0
@@ -18,7 +34,7 @@ class Port(object):
STATE_PAUSE: "PAUSE"}
- def __init__ (self, port_id, speed, driver, user, comm_link):
+ def __init__ (self, port_id, speed, driver, user, comm_link, session_id):
self.port_id = port_id
self.state = self.STATE_IDLE
self.handler = None
@@ -30,6 +46,7 @@ class Port(object):
self.speed = speed
self.streams = {}
self.profile = None
+ self.session_id = session_id
self.port_stats = trex_stats.CPortStats(self)
@@ -47,15 +64,16 @@ class Port(object):
def acquire(self, force = False):
params = {"port_id": self.port_id,
"user": self.user,
+ "session_id": self.session_id,
"force": force}
command = RpcCmdData("acquire", params)
rc = self.transmit(command.method, command.params)
- if rc.success:
- self.handler = rc.data
+ if rc.good():
+ self.handler = rc.data()
return self.ok()
else:
- return self.err(rc.data)
+ return self.err(rc.err())
# release the port
def release(self):
@@ -66,10 +84,10 @@ class Port(object):
rc = self.transmit(command.method, command.params)
self.handler = None
- if rc.success:
+ if rc.good():
return self.ok()
else:
- return self.err(rc.data)
+ return self.err(rc.err())
def is_acquired(self):
return (self.handler != None)
@@ -89,11 +107,11 @@ class Port(object):
command = RpcCmdData("get_port_status", params)
rc = self.transmit(command.method, command.params)
- if not rc.success:
- return self.err(rc.data)
+ if rc.bad():
+ return self.err(rc.err())
# sync the port
- port_state = rc.data['state']
+ port_state = rc.data()['state']
if port_state == "DOWN":
self.state = self.STATE_DOWN
@@ -128,10 +146,9 @@ class Port(object):
"stream_id": stream_id,
"stream": stream_obj}
- rc, data = self.transmit("add_stream", params)
- if not rc:
- r = self.err(data)
- print r.good()
+ rc = self.transmit("add_stream", params)
+ if rc.bad():
+ return self.err(rc.err())
# add the stream
self.streams[stream_id] = stream_obj
@@ -154,10 +171,11 @@ class Port(object):
cmd = RpcCmdData('add_stream', params)
batch.append(cmd)
- rc, data = self.transmit_batch(batch)
+ rc = self.transmit_batch(batch)
+ if rc.bad():
+ return self.err(rc.err())
- if not rc:
- return self.err(data)
+ # validate that every action succeeded
# add the stream
for stream in streams_list:
@@ -179,9 +197,9 @@ class Port(object):
"stream_id": stream_id}
- rc, data = self.transmit("remove_stream", params)
- if not rc:
- return self.err(data)
+ rc = self.transmit("remove_stream", params)
+ if rc.bad():
+ return self.err(rc.err())
self.streams[stream_id] = None
@@ -195,9 +213,9 @@ class Port(object):
params = {"handler": self.handler,
"port_id": self.port_id}
- rc, data = self.transmit("remove_all_streams", params)
- if not rc:
- return self.err(data)
+ rc = self.transmit("remove_all_streams", params)
+ if rc.bad():
+ return self.err(rc.err())
self.streams = {}
@@ -231,9 +249,9 @@ class Port(object):
"mul": mul,
"duration": duration}
- rc, data = self.transmit("start_traffic", params)
- if not rc:
- return self.err(data)
+ rc = self.transmit("start_traffic", params)
+ if rc.bad():
+ return self.err(rc.err())
self.state = self.STATE_TX
@@ -249,9 +267,9 @@ class Port(object):
params = {"handler": self.handler,
"port_id": self.port_id}
- rc, data = self.transmit("stop_traffic", params)
- if not rc:
- return self.err(data)
+ rc = self.transmit("stop_traffic", params)
+ if rc.bad():
+ return self.err(rc.err())
# only valid state after stop
self.state = self.STATE_STREAMS
@@ -266,9 +284,9 @@ class Port(object):
params = {"handler": self.handler,
"port_id": self.port_id}
- rc, data = self.transmit("pause_traffic", params)
- if not rc:
- return self.err(data)
+ rc = self.transmit("pause_traffic", params)
+ if rc.bad():
+ return self.err(rc.err())
# only valid state after stop
self.state = self.STATE_PAUSE
@@ -284,9 +302,9 @@ class Port(object):
params = {"handler": self.handler,
"port_id": self.port_id}
- rc, data = self.transmit("resume_traffic", params)
- if not rc:
- return self.err(data)
+ rc = self.transmit("resume_traffic", params)
+ if rc.bad():
+ return self.err(rc.err())
# only valid state after stop
self.state = self.STATE_TX
@@ -302,9 +320,9 @@ class Port(object):
"port_id": self.port_id,
"mul": mul}
- rc, data = self.transmit("update_traffic", params)
- if not rc:
- return self.err(data)
+ rc = self.transmit("update_traffic", params)
+ if rc.bad():
+ return self.err(rc.err())
return self.ok()
@@ -320,11 +338,11 @@ class Port(object):
params = {"handler": self.handler,
"port_id": self.port_id}
- rc, data = self.transmit("validate", params)
- if not rc:
- return self.err(data)
+ rc = self.transmit("validate", params)
+ if rc.bad():
+ return self.err(rc.err())
- self.profile = data
+ self.profile = rc.data()
return self.ok()
@@ -409,3 +427,4 @@ class Port(object):
def async_event_forced_acquired (self):
self.handler = None
+
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 899805cf..75c1c06f 100755
--- a/scripts/automation/trex_control_plane/client/trex_stateless_client.py
+++ b/scripts/automation/trex_control_plane/client/trex_stateless_client.py
@@ -26,31 +26,15 @@ from common.trex_types import *
from trex_async_client import CTRexAsyncClient
-########## utlity ############
-def mult_to_factor (mult, max_bps, max_pps, line_util):
- if mult['type'] == 'raw':
- return mult['value']
-
- if mult['type'] == 'bps':
- return mult['value'] / max_bps
-
- if mult['type'] == 'pps':
- return mult['value'] / max_pps
-
- if mult['type'] == 'percentage':
- return mult['value'] / line_util
-
-
-
class CTRexStatelessClient(object):
"""docstring for CTRexStatelessClient"""
# verbose levels
- VERBOSE_SILENCE = 0
+ VERBOSE_QUIET = 0
VERBOSE_REGULAR = 1
VERBOSE_HIGH = 2
- def __init__(self, username, server="localhost", sync_port = 5050, async_port = 4500, virtual=False):
+ def __init__(self, username, server="localhost", sync_port = 5050, async_port = 4500, quiet = False, virtual = False):
super(CTRexStatelessClient, self).__init__()
self.user = username
@@ -58,7 +42,10 @@ class CTRexStatelessClient(object):
self.comm_link = CTRexStatelessClient.CCommLink(server, sync_port, virtual, self.prn_func)
# default verbose level
- self.verbose = self.VERBOSE_REGULAR
+ if not quiet:
+ self.verbose = self.VERBOSE_REGULAR
+ else:
+ self.verbose = self.VERBOSE_QUIET
self.ports = {}
self._connection_info = {"server": server,
@@ -79,7 +66,7 @@ class CTRexStatelessClient(object):
self.events = []
-
+ self.session_id = random.getrandbits(32)
self.read_only = False
self.connected = False
@@ -90,9 +77,15 @@ class CTRexStatelessClient(object):
return self.ports.get(port_id, None)
- def get_server (self):
+ # connection server ip
+ def get_server_ip (self):
return self.comm_link.get_server()
+ # connection server port
+ def get_server_port (self):
+ return self.comm_link.get_port()
+
+
################# events handler ######################
def add_event_log (self, msg, ev_type, show = False):
@@ -107,7 +100,7 @@ class CTRexStatelessClient(object):
if show:
self.prn_func(format_text("\n{:^8} - {:}".format(prefix, format_text(msg, 'bold'))))
-
+
def handle_async_stats_update(self, dump_data):
global_stats = {}
@@ -185,8 +178,16 @@ class CTRexStatelessClient(object):
# port was stolen...
elif (type == 5):
+ session_id = data['session_id']
+
+ # false alarm, its us
+ if session_id == self.session_id:
+ return
+
port_id = int(data['port_id'])
- ev = "Port {0} was forcely taken".format(port_id)
+ who = data['who']
+
+ ev = "Port {0} was forcely taken by '{1}'".format(port_id, who)
# call the handler
self.async_event_port_forced_acquired(port_id)
@@ -300,42 +301,43 @@ class CTRexStatelessClient(object):
self.connected = False
# connect sync channel
- rc, data = self.comm_link.connect()
- if not rc:
- return RC_ERR(data)
+ rc = self.comm_link.connect()
+ if rc.bad():
+ return rc
# connect async channel
- rc, data = self.async_client.connect()
- if not rc:
- return RC_ERR(data)
+ rc = self.async_client.connect()
+ if rc.bad():
+ return rc
# version
- rc, data = self.transmit("get_version")
- if not rc:
- return RC_ERR(data)
+ rc = self.transmit("get_version")
+ if rc.bad():
+ return rc
- self.server_version = data
- self.global_stats.server_version = data
+ self.server_version = rc.data()
+ self.global_stats.server_version = rc.data()
# cache system info
- rc, data = self.transmit("get_system_info")
- if not rc:
- return RC_ERR(data)
- self.system_info = data
+ rc = self.transmit("get_system_info")
+ if rc.bad():
+ return rc
+
+ self.system_info = rc.data()
# cache supported commands
- rc, data = self.transmit("get_supported_cmds")
- if not rc:
- return RC_ERR(data)
+ rc = self.transmit("get_supported_cmds")
+ if rc.bad():
+ return rc
- self.supported_cmds = data
+ self.supported_cmds = rc.data()
# create ports
for port_id in xrange(self.get_port_count()):
speed = self.system_info['ports'][port_id]['speed']
driver = self.system_info['ports'][port_id]['driver']
- self.ports[port_id] = Port(port_id, speed, driver, self.user, self.comm_link)
+ self.ports[port_id] = Port(port_id, speed, driver, self.user, self.comm_link, self.session_id)
# sync the ports
@@ -481,14 +483,12 @@ class CTRexStatelessClient(object):
# ping server
def ping(self):
- rc, info = self.transmit("ping")
- return RC(rc, info)
+ return self.transmit("ping")
def get_global_stats(self):
- rc, info = self.transmit("get_global_stats")
- return RC(rc, info)
+ return self.transmit("get_global_stats")
########## port commands ##############
@@ -688,7 +688,7 @@ class CTRexStatelessClient(object):
# reset
def cmd_reset(self):
-
+ #self.release(self.get_acquired_ports())
rc = self.acquire(force = True)
rc.annotate("Force acquiring all ports:")
@@ -1176,6 +1176,9 @@ class CTRexStatelessClient(object):
def get_server (self):
return self.server
+ def get_port (self):
+ return self.port
+
def set_verbose(self, mode):
self.verbose = mode
return self.rpc_link.set_verbose(mode)
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 ce98fbc6..bdae7bd9 100755
--- a/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py
+++ b/scripts/automation/trex_control_plane/client_utils/jsonrpc_client.py
@@ -7,8 +7,7 @@ import general_utils
import re
from time import sleep
from collections import namedtuple
-
-CmdResponse = namedtuple('CmdResponse', ['success', 'data'])
+from common.trex_types import *
class bcolors:
BLUE = '\033[94m'
@@ -33,15 +32,11 @@ class BatchMessage(object):
def invoke(self, block = False):
if not self.rpc_client.connected:
- return False, "Not connected to server"
+ return RC_ERR("Not connected to server")
msg = json.dumps(self.batch_list)
- rc, resp_list = self.rpc_client.send_raw_msg(msg)
- if len(self.batch_list) == 1:
- return CmdResponse(True, [CmdResponse(rc, resp_list)])
- else:
- return CmdResponse(rc, resp_list)
+ return self.rpc_client.send_raw_msg(msg)
# JSON RPC v2.0 client
@@ -114,7 +109,7 @@ class JsonRpcClient(object):
def invoke_rpc_method (self, method_name, params = {}):
if not self.connected:
- return CmdResponse(False, "Not connected to server")
+ return RC_ERR("Not connected to server")
id, msg = self.create_jsonrpc_v2(method_name, params)
@@ -135,7 +130,7 @@ class JsonRpcClient(object):
tries += 1
if tries > 10:
self.disconnect()
- return CmdResponse(False, "*** [RPC] - Failed to send message to server")
+ return RC_ERR("*** [RPC] - Failed to send message to server")
tries = 0
@@ -147,7 +142,7 @@ class JsonRpcClient(object):
tries += 1
if tries > 10:
self.disconnect()
- return CmdResponse(False, "*** [RPC] - Failed to get server response")
+ return RC_ERR("*** [RPC] - Failed to get server response")
self.verbose_msg("Server Response:\n\n" + self.pretty_json(response) + "\n")
@@ -158,36 +153,35 @@ class JsonRpcClient(object):
response_json = json.loads(response)
if isinstance(response_json, list):
- rc_list = []
+ rc_batch = RC()
for single_response in response_json:
- rc, msg = self.process_single_response(single_response)
- rc_list.append( CmdResponse(rc, msg) )
+ rc = self.process_single_response(single_response)
+ rc_batch.add(rc)
- return CmdResponse(True, rc_list)
+ return rc_batch
else:
- rc, msg = self.process_single_response(response_json)
- return CmdResponse(rc, msg)
+ return self.process_single_response(response_json)
def process_single_response (self, response_json):
if (response_json.get("jsonrpc") != "2.0"):
- return False, "Malformed Response ({0})".format(str(response_json))
+ return RC_ERR("Malformed Response ({0})".format(str(response_json)))
# error reported by server
if ("error" in response_json):
if "specific_err" in response_json["error"]:
- return False, response_json["error"]["specific_err"]
+ return RC_ERR(response_json["error"]["specific_err"])
else:
- return False, response_json["error"]["message"]
+ return RC_ERR(response_json["error"]["message"])
# if no error there should be a result
if ("result" not in response_json):
- return False, "Malformed Response ({0})".format(str(response_json))
+ return RC_ERR("Malformed Response ({0})".format(str(response_json)))
- return True, response_json["result"]
+ return RC_OK(response_json["result"])
@@ -199,9 +193,9 @@ class JsonRpcClient(object):
self.socket.close(linger = 0)
self.context.destroy(linger = 0)
self.connected = False
- return True, ""
+ return RC_OK()
else:
- return False, "Not connected to server"
+ return RC_ERR("Not connected to server")
def connect(self, server = None, port = None, prn_func = None):
@@ -226,14 +220,14 @@ class JsonRpcClient(object):
try:
self.socket.connect(self.transport)
except zmq.error.ZMQError as e:
- return False, "ZMQ Error: Bad server or port name: " + str(e)
+ return RC_ERR("ZMQ Error: Bad server or port name: " + str(e))
self.socket.setsockopt(zmq.SNDTIMEO, 1000)
self.socket.setsockopt(zmq.RCVTIMEO, 1000)
self.connected = True
- return True, ""
+ return RC_OK()
def reconnect(self):
@@ -241,7 +235,7 @@ class JsonRpcClient(object):
return self.connect()
if not self.connected:
- return False, "Not connected to server"
+ return RC_ERR("Not connected to server")
# reconnect
return self.connect(self.server, self.port)
diff --git a/scripts/automation/trex_control_plane/common/trex_types.py b/scripts/automation/trex_control_plane/common/trex_types.py
index 3de36e4c..7c3f04c5 100644
--- a/scripts/automation/trex_control_plane/common/trex_types.py
+++ b/scripts/automation/trex_control_plane/common/trex_types.py
@@ -31,10 +31,12 @@ class RC():
return not self.good()
def data (self):
- return [x.data if x.rc else "" for x in self.rc_list]
+ d = [x.data if x.rc else "" for x in self.rc_list]
+ return (d if len(d) > 1 else d[0])
def err (self):
- return [x.data if not x.rc else "" for x in self.rc_list]
+ e = [x.data if not x.rc else "" for x in self.rc_list]
+ return (e if len(e) > 1 else e[0])
def annotate (self, desc = None, show_status = True):
if desc:
diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py
index f02652d0..1d94afb7 100755
--- a/scripts/automation/trex_control_plane/console/trex_console.py
+++ b/scripts/automation/trex_control_plane/console/trex_console.py
@@ -172,7 +172,7 @@ class TRexConsole(TRexGeneralCmd):
def get_console_identifier(self):
return "{context}_{server}".format(context=self.__class__.__name__,
- server=self.stateless_client.get_server())
+ server=self.stateless_client.get_server_ip())
def register_main_console_methods(self):
main_names = set(self.trex_console.get_names()).difference(set(dir(self.__class__)))
@@ -450,6 +450,7 @@ class TRexConsole(TRexGeneralCmd):
self.stateless_client.clear_events()
print format_text("\n\nEvent log was cleared\n\n")
+
# tui
@verify_connected
def do_tui (self, line):
@@ -465,12 +466,20 @@ class TRexConsole(TRexGeneralCmd):
return
if opts.xterm:
- subprocess.Popen(['xterm', '-geometry', '105x40', '-e', './trex-console', '-t'])
+ exe = ''
+ if os.path.isfile('/usr/bin/wmctrl'):
+ exe += '/usr/bin/wmctrl -r trex_tui -b add,above;'
+
+ exe += './trex-console -t -q -s {0} -p {1}'.format(self.stateless_client.get_server_ip(), self.stateless_client.get_server_port())
+
+ cmd = ['xterm', '-geometry', '105x40', '-title', 'trex_tui', '-e', exe]
+ subprocess.Popen(cmd)
+
return
save_verbose = self.stateless_client.get_verbose()
- self.stateless_client.set_verbose(self.stateless_client.VERBOSE_SILENCE)
+ self.stateless_client.set_verbose(self.stateless_client.VERBOSE_QUIET)
self.tui.show()
self.stateless_client.set_verbose(save_verbose)
@@ -573,6 +582,11 @@ def setParserOptions():
action="store_true", help="Starts with TUI mode",
default = False)
+
+ parser.add_argument("-q", "--quiet", dest="quiet",
+ action="store_true", help="Starts with all outputs suppressed",
+ default = False)
+
return parser
@@ -581,9 +595,10 @@ def main():
options = parser.parse_args()
# Stateless client connection
- stateless_client = CTRexStatelessClient(options.user, options.server, options.port, options.pub)
+ stateless_client = CTRexStatelessClient(options.user, options.server, options.port, options.pub, options.quiet)
- print "\nlogged as {0}".format(format_text(options.user, 'bold'))
+ if not options.quiet:
+ print "\nlogged as {0}".format(format_text(options.user, 'bold'))
# TUI or no acquire will give us READ ONLY mode
if options.tui or not options.acquire:
diff --git a/scripts/automation/trex_control_plane/console/trex_tui.py b/scripts/automation/trex_control_plane/console/trex_tui.py
index 3a89097f..6b0aa50a 100644
--- a/scripts/automation/trex_control_plane/console/trex_tui.py
+++ b/scripts/automation/trex_control_plane/console/trex_tui.py
@@ -392,7 +392,9 @@ class TrexTUI():
def clear_screen (self):
- os.system('clear')
+ #os.system('clear')
+ # maybe this is faster ?
+ sys.stderr.write("\x1b[2J\x1b[H")
@@ -465,3 +467,4 @@ class TrexTUI():
def get_state (self):
return self.state
+
diff --git a/scripts/automation/trex_control_plane/server/trex_server.py b/scripts/automation/trex_control_plane/server/trex_server.py
index 9868d6c8..bf788d35 100755
--- a/scripts/automation/trex_control_plane/server/trex_server.py
+++ b/scripts/automation/trex_control_plane/server/trex_server.py
@@ -259,7 +259,7 @@ class CTRexServer(object):
return False
- def start_trex(self, trex_cmd_options, user, block_to_success = True, timeout = 30):
+ def start_trex(self, trex_cmd_options, user, block_to_success = True, timeout = 40):
with self.start_lock:
logger.info("Processing start_trex() command.")
if self.is_reserved():