summaryrefslogtreecommitdiffstats
path: root/scripts/automation/trex_control_plane/console/trex_console.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/automation/trex_control_plane/console/trex_console.py')
-rwxr-xr-x[-rw-r--r--]scripts/automation/trex_control_plane/console/trex_console.py248
1 files changed, 240 insertions, 8 deletions
diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py
index 3aeab901..a9ac040b 100644..100755
--- a/scripts/automation/trex_control_plane/console/trex_console.py
+++ b/scripts/automation/trex_control_plane/console/trex_console.py
@@ -1,18 +1,124 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
+
+"""
+Dan Klein, Itay Marom
+Cisco Systems, Inc.
+
+Copyright (c) 2015-2015 Cisco Systems, Inc.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+"""
+
import cmd
import json
import ast
import argparse
import random
import string
-
+import os
import sys
+import tty, termios
import trex_root_path
+from common.trex_streams import *
+
from client_utils.jsonrpc_client import TrexStatelessClient
import trex_status
+from collections import namedtuple
+
+LoadedStreamList = namedtuple('LoadedStreamList', ['loaded', 'compiled'])
+
+#
+
+def readch (choices = []):
+
+ fd = sys.stdin.fileno()
+ old_settings = termios.tcgetattr(fd)
+ try:
+ tty.setraw(sys.stdin.fileno())
+ while True:
+ ch = sys.stdin.read(1)
+ if (ord(ch) == 3) or (ord(ch) == 4):
+ return None
+ if ch in choices:
+ return ch
+ finally:
+ termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
+
+ return None
+
+class YesNoMenu(object):
+ def __init__ (self, caption):
+ self.caption = caption
+
+ def show (self):
+ print "{0}".format(self.caption)
+ sys.stdout.write("[Y/y/N/n] : ")
+ ch = readch(choices = ['y', 'Y', 'n', 'N'])
+ if ch == None:
+ return None
+
+ print "\n"
+ if ch == 'y' or ch == 'Y':
+ return True
+ else:
+ return False
+
+# multi level cmd menu
+class CmdMenu(object):
+ def __init__ (self):
+ self.menus = []
+
+
+ def add_menu (self, caption, options):
+ menu = {}
+ menu['caption'] = caption
+ menu['options'] = options
+ self.menus.append(menu)
+
+ def show (self):
+ cur_level = 0
+ print "\n"
+
+ selected_path = []
+ for menu in self.menus:
+ # show all the options
+ print "{0}\n".format(menu['caption'])
+ for i, option in enumerate(menu['options']):
+ print "{0}. {1}".format(i + 1, option)
+
+ #print "\nPlease select an option: "
+ choices = range(0, len(menu['options']))
+ choices = [ chr(x + 48) for x in choices]
+
+ print ""
+ ch = readch(choices)
+ print ""
+
+ if ch == None:
+ return None
+
+ selected_path.append(int(ch) - 1)
+
+ return selected_path
+
+
+class AddStreamMenu(CmdMenu):
+ def __init__ (self):
+ super(AddStreamMenu, self).__init__()
+ self.add_menu('Please select type of stream', ['a', 'b', 'c'])
+ self.add_menu('Please select ISG', ['d', 'e', 'f'])
+
+# main console object
class TrexConsole(cmd.Cmd):
"""Trex Console"""
@@ -29,6 +135,8 @@ class TrexConsole(cmd.Cmd):
self.verbose = False
self.postcmd(False, "")
+
+ self.user_streams = {}
# a cool hack - i stole this function and added space
@@ -108,6 +216,13 @@ class TrexConsole(cmd.Cmd):
def do_acquire (self, line, force = False):
'''Acquire ports\n'''
+ # make sure that the user wants to acquire all
+ if line == "":
+ ask = YesNoMenu('Do you want to acquire all ports ? ')
+ rc = ask.show()
+ if rc == False:
+ return
+
port_list = self.parse_ports_from_line(line)
if not port_list:
return
@@ -312,25 +427,142 @@ class TrexConsole(cmd.Cmd):
print "{:<30} {:<30}".format(cmd + " - ", help)
+ def do_load_stream_list(self, line):
+ '''Loads a YAML stream list serialization into user console \n'''
+ args = line.split()
+ if args >= 2:
+ name = args[0]
+ yaml_path = args[1]
+ try:
+ multiplier = args[2]
+ except IndexError:
+ multiplier = 1
+ stream_list = CStreamList()
+ loaded_obj = stream_list.load_yaml(yaml_path, multiplier)
+ # print self.rpc_client.pretty_json(json.dumps(loaded_obj))
+ if name in self.user_streams:
+ print "Picked name already exist. Please pick another name."
+ else:
+ try:
+ compiled_streams = stream_list.compile_streams()
+ self.user_streams[name] = LoadedStreamList(loaded_obj,
+ [StreamPack(v.stream_id, v.stream.dump_compiled())
+ for k, v in compiled_streams.items()])
+
+ print "Stream '{0}' loaded successfully".format(name)
+ except Exception as e:
+ raise
+ return
+ else:
+ print "please provide load name and YAML path, separated by space.\n" \
+ "Optionally, you may provide a third argument to specify multiplier."
+
+ @staticmethod
+ def tree_autocomplete(text):
+ dir = os.path.dirname(text)
+ if dir:
+ path = dir
+ else:
+ path = "."
+ start_string = os.path.basename(text)
+ return [x
+ for x in os.listdir(path)
+ if x.startswith(start_string)]
+
+
+ def complete_load_stream_list(self, text, line, begidx, endidx):
+ arg_num = len(line.split()) - 1
+ if arg_num == 2:
+ return TrexConsole.tree_autocomplete(line.split()[-1])
+ else:
+ return [text]
+
+ def do_show_stream_list(self, line):
+ '''Shows the loaded stream list named [name] \n'''
+ args = line.split()
+ if args:
+ list_name = args[0]
+ try:
+ stream = self.user_streams[list_name]
+ if len(args) >= 2 and args[1] == "full":
+ print self.rpc_client.pretty_json(json.dumps(stream.compiled))
+ else:
+ print self.rpc_client.pretty_json(json.dumps(stream.loaded))
+ except KeyError as e:
+ print "Unknown stream list name provided"
+ else:
+ print "\nAvailable stream lists:\n{0}".format(', '.join([x
+ for x in self.user_streams.keys()]))
+
+ def complete_show_stream_list(self, text, line, begidx, endidx):
+ return [x
+ for x in self.user_streams.keys()
+ if x.startswith(text)]
+
+ def do_attach(self, line):
+ args = line.split()
+ if len(args) >= 1:
+ try:
+ stream_list = self.user_streams[args[0]]
+ port_list = self.parse_ports_from_line(' '.join(args[1:]))
+ owned = set(self.rpc_client.get_owned_ports())
+ if set(port_list).issubset(owned):
+ rc, resp_list = self.rpc_client.add_stream(port_list, stream_list.compiled)
+ if not rc:
+ print "\n*** " + resp_list + "\n"
+ return
+ else:
+ print "Not all desired ports are aquired.\n" \
+ "Acquired ports are: {acq}\n" \
+ "Requested ports: {req}\n" \
+ "Missing ports: {miss}".format(acq=list(owned),
+ req=port_list,
+ miss=list(set(port_list).difference(owned)))
+ except KeyError as e:
+ cause = e.args[0]
+ print "Provided stream list name '{0}' doesn't exists.".format(cause)
+ else:
+ print "Please provide list name and ports to attach to, or leave empty to attach to all ports."
+
- # do
- #def do_snapshot (self, line):
- #for key, value in self.rpc_client.snapshot()[1]['streams'].iteritems():
- #print str(key) + " " + str(value)
+
+
+
+
+
+
+ # adds a very simple stream
+ def do_add_simple_stream (self, line):
+ if line == "":
+ add_stream = AddStreamMenu()
+ add_stream.show()
+ return
+
+ params = line.split()
+ port_id = int(params[0])
+ stream_id = int(params[1])
+
+ packet = [0xFF,0xFF,0xFF]
+ rc, msg = self.rpc_client.add_stream(port_id = port_id, stream_id = stream_id, isg = 1.1, next_stream_id = -1, packet = packet)
+ if rc:
+ print "\nServer Response:\n\n" + self.rpc_client.pretty_json(json.dumps(msg)) + "\n"
+ else:
+ print "\n*** " + msg + "\n"
+
# aliasing
do_exit = do_EOF = do_q = do_quit
def setParserOptions ():
parser = argparse.ArgumentParser(prog="trex_console.py")
- parser.add_argument("-s", "--server", help = "T-Rex Server [default is localhost]",
+ parser.add_argument("-s", "--server", help = "TRex Server [default is localhost]",
default = "localhost",
type = str)
- parser.add_argument("-p", "--port", help = "T-Rex Server Port [default is 5050]\n",
+ parser.add_argument("-p", "--port", help = "TRex Server Port [default is 5050]\n",
default = 5050,
type = int)