summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorDan Klein <danklei@cisco.com>2015-11-07 13:37:31 +0200
committerDan Klein <danklei@cisco.com>2015-11-07 13:37:31 +0200
commit953a250e6cbaea3040920e7441d2d019705efe51 (patch)
tree883740a56dfec7424d28631942444d357f7cca87 /scripts
parent36a9677c0abc038235e7bf706cb2b3dc9e720284 (diff)
Extended line parsing options, didn't apply all changes on console YET
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/automation/trex_control_plane/client/trex_stateless_client.py51
-rw-r--r--scripts/automation/trex_control_plane/console/line_parsing.py50
-rwxr-xr-xscripts/automation/trex_control_plane/console/parsing_opts.py103
-rwxr-xr-xscripts/automation/trex_control_plane/console/trex_console.py111
4 files changed, 222 insertions, 93 deletions
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 aeb25422..dc6e6be2 100755
--- a/scripts/automation/trex_control_plane/client/trex_stateless_client.py
+++ b/scripts/automation/trex_control_plane/client/trex_stateless_client.py
@@ -45,16 +45,57 @@ class CTRexStatelessClient(object):
# ----- decorator methods ----- #
+ def acquired(func):
+ def wrapper_f(self, *args, **kwargs):
+ # print func.__name__
+ # print args
+ # print kwargs
+ port_ids = kwargs.get("port_id")
+ if not port_ids:
+ # print "FROM ARGS!"
+ # print args
+ port_ids = args[0]
+ if isinstance(port_ids, int):
+ # make sure port_ids is a list
+ port_ids = [port_ids]
+ bad_ids = set()
+ # print "============="
+ # print port_ids
+ for port_id in port_ids:
+ port_owned = self._conn_handler.get(port_id)
+ if not port_owned:
+ bad_ids.add(port_id)
+ # elif active_and_owned: # stronger condition than just owned, hence gets precedence
+ # if port_owned and port_id in self._active_ports:
+ # continue
+ # else:
+ # bad_ids.add(port_id)
+ else:
+ continue
+ if bad_ids:
+ # Some port IDs are not according to desires status
+ raise ValueError("The requested method ('{0}') cannot be invoked since port IDs {1} are not "
+ "at allowed states".format(func.__name__, list(bad_ids)))
+ else:
+ return func(self, *args, **kwargs)
+ return wrapper_f
+
def force_status(owned=True, active_and_owned=False):
def wrapper(func):
def wrapper_f(self, *args, **kwargs):
+ # print args
+ # print kwargs
port_ids = kwargs.get("port_id")
if not port_ids:
+ print "FROM ARGS!"
+ print args
port_ids = args[0]
if isinstance(port_ids, int):
# make sure port_ids is a list
port_ids = [port_ids]
bad_ids = set()
+ # print "============="
+ # print port_ids
for port_id in port_ids:
port_owned = self._conn_handler.get(port_id)
if owned and not port_owned:
@@ -271,14 +312,16 @@ class CTRexStatelessClient(object):
"stream_id": stream_id}
return self.transmit("get_stream_list", params)
- @force_status(owned=True)
- def start_traffic(self, port_id=None):
+ @acquired
+ def start_traffic(self, multiplier, port_id=None):
if not self._is_ports_valid(port_id):
raise ValueError("Provided illegal port id input")
if isinstance(port_id, list) or isinstance(port_id, set):
# handle as batch mode
port_ids = set(port_id) # convert to set to avoid duplications
- commands = [RpcCmdData("start_traffic", {"handler": self._conn_handler.get(p_id), "port_id": p_id, "mul": 1.0})
+ commands = [RpcCmdData("start_traffic", {"handler": self._conn_handler.get(p_id),
+ "port_id": p_id,
+ "mul": multiplier})
for p_id in port_ids]
rc, resp_list = self.transmit_batch(commands)
if rc:
@@ -287,7 +330,7 @@ class CTRexStatelessClient(object):
else:
params = {"handler": self._conn_handler.get(port_id),
"port_id": port_id,
- "mul": 1.0}
+ "mul": multiplier}
command = RpcCmdData("start_traffic", params)
return self._handle_start_traffic_response(command,
self.transmit(command.method, command.params),
diff --git a/scripts/automation/trex_control_plane/console/line_parsing.py b/scripts/automation/trex_control_plane/console/line_parsing.py
deleted file mode 100644
index c1227a39..00000000
--- a/scripts/automation/trex_control_plane/console/line_parsing.py
+++ /dev/null
@@ -1,50 +0,0 @@
-import argparse
-from collections import namedtuple
-import sys
-
-ArgumentPack = namedtuple('ArgumentPack', ['name_or_flags', 'options'])
-# class ArgumentPack(namedtuple('ArgumentPack', ['name_or_flags', 'options'])):
-#
-# @property
-# def name_or_flags(self):
-# return self.name_or_flags
-#
-# @name_or_flags.setter
-# def name_or_flags(self, val):
-# print "bla"
-# if not isinstance(val, list):
-# self.name_or_flags = [val]
-# else:
-# self.name_or_flags = val
-
-
-OPTIONS_DB = {'-m': ArgumentPack(['-m', '--multiplier'],
- {'help': "Set multiplier for stream", 'dest':"mult"}),
- 'file_path': ArgumentPack(['file'],
- {'help': "File path to yaml file"})}
-
-
-class CCmdArgParser(argparse.ArgumentParser):
-
- def __init__(self, *args, **kwargs):
- super(CCmdArgParser, self).__init__(*args, **kwargs)
- pass
-
- def error(self, message):
- # self.print_usage(sys.stderr)
- self.print_help()
- return
-
-def gen_parser(op_name, *args):
- parser = CCmdArgParser(prog=op_name, conflict_handler='resolve')
- for param in args:
- try:
- parser.add_argument(*OPTIONS_DB[param].name_or_flags,
- **OPTIONS_DB[param].options)
- except KeyError, e:
- cause = e.args[0]
- raise KeyError("The attribute '{0}' is missing as a field of the {1} option.\n".format(cause, param))
- return parser
-
-if __name__ == "__main__":
- pass \ No newline at end of file
diff --git a/scripts/automation/trex_control_plane/console/parsing_opts.py b/scripts/automation/trex_control_plane/console/parsing_opts.py
new file mode 100755
index 00000000..c94a7461
--- /dev/null
+++ b/scripts/automation/trex_control_plane/console/parsing_opts.py
@@ -0,0 +1,103 @@
+import argparse
+from collections import namedtuple
+import sys
+
+ArgumentPack = namedtuple('ArgumentPack', ['name_or_flags', 'options'])
+ArgumentGroup = namedtuple('ArgumentGroup', ['type', 'args', 'options'])
+
+
+# list of available parsing options
+MULTIPLIER = 1
+PORT_LIST = 2
+ALL_PORTS = 3
+PORT_LIST_WITH_ALL = 4
+FILE_PATH = 5
+FILE_FROM_DB = 6
+STREAM_FROM_PATH_OR_FILE = 7
+
+# list of ArgumentGroup types
+MUTEX = 1
+
+
+
+
+OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
+ {'help': "Set multiplier for stream", 'dest': "mult", 'type': float}),
+ PORT_LIST: ArgumentPack(['--port'],
+ {"nargs": '+',
+ # "action": "store_"
+ 'help': "A list of ports on which to apply the command",
+ 'default': []}),
+ ALL_PORTS: ArgumentPack(['-a'],
+ {"action": "store_true",
+ "dest": "all",
+ 'help': "Set this flag to apply the command on all available ports"}),
+
+ FILE_PATH: ArgumentPack(['-f'],
+ {'help': "File path to YAML file that describes a stream pack"}),
+ FILE_FROM_DB: ArgumentPack(['--db'],
+ {'help': "A stream pack which already loaded into console cache."}),
+ # advanced options
+ PORT_LIST_WITH_ALL: ArgumentGroup(MUTEX, [PORT_LIST,
+ ALL_PORTS],
+ {'required': True}),
+ STREAM_FROM_PATH_OR_FILE: ArgumentGroup(MUTEX, [FILE_PATH,
+ FILE_FROM_DB],
+ {'required': True})
+ }
+
+
+class CCmdArgParser(argparse.ArgumentParser):
+
+ def __init__(self, *args, **kwargs):
+ super(CCmdArgParser, self).__init__(*args, **kwargs)
+ pass
+
+ # def error(self, message):
+ # try:
+ # super(CCmdArgParser, self).error(message) # this will trigger system exit!
+ # except SystemExit:
+ # return -1
+ #
+ # # self.print_usage(sys.stderr)
+ # # print ('%s: error: %s\n') % (self.prog, message)
+ # # self.print_help()
+ # return
+
+ def exit(self, status=0, message=None):
+ try:
+ super(CCmdArgParser, self).exit(status, message) # this will trigger system exit!
+ except SystemExit:
+ return -1
+ return
+
+def gen_parser(op_name, description, *args):
+ parser = CCmdArgParser(prog=op_name, conflict_handler='resolve',
+ # add_help=False,
+ description=description)
+ for param in args:
+ try:
+ argument = OPTIONS_DB[param]
+ if isinstance(argument, ArgumentGroup):
+ if argument.type == MUTEX:
+ # handle as mutually exclusive group
+ group = parser.add_mutually_exclusive_group(**argument.options)
+ for sub_argument in argument.args:
+ group.add_argument(*OPTIONS_DB[sub_argument].name_or_flags,
+ **OPTIONS_DB[sub_argument].options)
+ else:
+ # ignore invalid objects
+ continue
+ elif isinstance(argument, ArgumentPack):
+ parser.add_argument(*argument.name_or_flags,
+ **argument.options)
+ else:
+ # ignore invalid objects
+ continue
+ except KeyError as e:
+ cause = e.args[0]
+ raise KeyError("The attribute '{0}' is missing as a field of the {1} option.\n".format(cause, param))
+ return parser
+
+if __name__ == "__main__":
+ pass \ 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 8a5b29cc..33b4e164 100755
--- a/scripts/automation/trex_control_plane/console/trex_console.py
+++ b/scripts/automation/trex_control_plane/console/trex_console.py
@@ -32,7 +32,7 @@ from common.trex_streams import *
from client.trex_stateless_client import CTRexStatelessClient
from common.text_opts import *
from client_utils.general_utils import user_input, get_current_user
-
+import parsing_opts
import trex_status
from collections import namedtuple
@@ -234,6 +234,9 @@ class TRexConsole(cmd.Cmd):
def extract_port_ids_from_line(self, line):
return {int(x) for x in line.split()}
+ def extract_port_ids_from_list(self, port_list):
+ return {int(x) for x in port_list}
+
def parse_ports_from_line (self, line):
port_list = set()
if line:
@@ -449,42 +452,42 @@ class TRexConsole(cmd.Cmd):
def default(self, line):
print "'{0}' is an unrecognized command. type 'help' or '?' for a list\n".format(line)
- def do_help (self, line):
- '''Shows This Help Screen\n'''
- if line:
- try:
- func = getattr(self, 'help_' + line)
- except AttributeError:
- try:
- doc = getattr(self, 'do_' + line).__doc__
- if doc:
- self.stdout.write("%s\n"%str(doc))
- return
- except AttributeError:
- pass
- self.stdout.write("%s\n"%str(self.nohelp % (line,)))
- return
- func()
- return
-
- print "\nSupported Console Commands:"
- print "----------------------------\n"
-
- cmds = [x[3:] for x in self.get_names() if x.startswith("do_")]
- for cmd in cmds:
- if cmd == "EOF":
- continue
-
- try:
- doc = getattr(self, 'do_' + cmd).__doc__
- if doc:
- help = str(doc)
- else:
- help = "*** Undocumented Function ***\n"
- except AttributeError:
- help = "*** Undocumented Function ***\n"
-
- print "{:<30} {:<30}".format(cmd + " - ", help)
+ # def do_help (self, line):
+ # '''Shows This Help Screen\n'''
+ # if line:
+ # try:
+ # func = getattr(self, 'help_' + line)
+ # except AttributeError:
+ # try:
+ # doc = getattr(self, 'do_' + line).__doc__
+ # if doc:
+ # self.stdout.write("%s\n"%str(doc))
+ # return
+ # except AttributeError:
+ # pass
+ # self.stdout.write("%s\n"%str(self.nohelp % (line,)))
+ # return
+ # func()
+ # return
+ #
+ # print "\nSupported Console Commands:"
+ # print "----------------------------\n"
+ #
+ # cmds = [x[3:] for x in self.get_names() if x.startswith("do_")]
+ # for cmd in cmds:
+ # if cmd == "EOF":
+ # continue
+ #
+ # try:
+ # doc = getattr(self, 'do_' + cmd).__doc__
+ # if doc:
+ # help = str(doc)
+ # else:
+ # help = "*** Undocumented Function ***\n"
+ # except AttributeError:
+ # help = "*** Undocumented Function ***\n"
+ #
+ # print "{:<30} {:<30}".format(cmd + " - ", help)
def do_stream_db_add(self, line):
'''Loads a YAML stream list serialization into user console \n'''
@@ -594,7 +597,7 @@ class TRexConsole(cmd.Cmd):
print "Provided stream list name '{0}' doesn't exists.".format(stream_pack_name)
print format_text("[FAILED]\n", 'red', 'bold')
return
- if args[0] == "all":
+ if args[1] == "all":
ask = ConfirmMenu('Are you sure you want to release all acquired ports? ')
rc = ask.show()
if rc == False:
@@ -698,6 +701,33 @@ class TRexConsole(cmd.Cmd):
def do_start_traffic(self, line):
'''Start pre-submitted traffic in specified ports on TRex\n'''
# make sure that the user wants to acquire all
+ # parser = parsing_opts.gen_parser("start_traffic", self.do_start_traffic.__doc__,
+ # parsing_opts.PORT_LIST_WITH_ALL, parsing_opts.MULTIPLIER)
+ # opts = parser.parse_args(line.split())
+ #
+ # print opts
+ # return
+ # # return
+ # # if not opts.port_list:
+ # # print magenta("Please provide a list of ports separated by spaces, "
+ # # "or specify 'all' to start traffic on all acquired ports")
+ # # return
+ #
+ # if "all" in opts.port_list:
+ # ask = ConfirmMenu('Are you sure you want to start traffic at all acquired ports? ')
+ # rc = ask.show()
+ # if rc == False:
+ # print yellow("[ABORTED]\n")
+ # return
+ # else:
+ # port_list = self.stateless_client.get_acquired_ports()
+ # else:
+ # try:
+ # port_list = self.extract_port_ids_from_list(opts.port_list)
+ # except ValueError as e:
+ # print magenta(e)
+ # return
+
args = line.split()
if len(args) < 1:
print magenta("Please provide a list of ports separated by spaces, "
@@ -715,7 +745,7 @@ class TRexConsole(cmd.Cmd):
port_list = self.extract_port_ids_from_line(line)
try:
- res_ok, log = self.stateless_client.start_traffic(port_list)
+ res_ok, log = self.stateless_client.start_traffic(1.0, port_id=port_list)
self.prompt_response(log)
if not res_ok:
print format_text("[FAILED]\n", 'red', 'bold')
@@ -728,6 +758,9 @@ class TRexConsole(cmd.Cmd):
def complete_start_traffic(self, text, line, begidx, endidx):
return self.port_auto_complete(text, line, begidx, endidx)
+ def help_start_traffic(self):
+ self.do_start_traffic("-h")
+
def do_stop_traffic(self, line):
'''Stop active traffic in specified ports on TRex\n'''
# make sure that the user wants to acquire all