From bb6dec2ed238069b6a0c079d2031246704b717c4 Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Mon, 16 Nov 2015 21:59:31 +0200 Subject: created general trex console class added dynamic server async support fixed bugs --- .../trex_control_plane/client/trex_async_client.py | 5 +++-- .../trex_control_plane/client/trex_stateless_client.py | 2 +- .../trex_control_plane/console/trex_console.py | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+), 3 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 d13513bf..31bec93f 100644 --- a/scripts/automation/trex_control_plane/client/trex_async_client.py +++ b/scripts/automation/trex_control_plane/client/trex_async_client.py @@ -151,16 +151,17 @@ class TrexAsyncStatsManager(): class CTRexAsyncClient(): - def __init__ (self, port): + def __init__ (self, server, port): self.port = port + self.server = server self.raw_snapshot = {} self.stats = TrexAsyncStatsManager() - self.tr = "tcp://localhost:{0}".format(self.port) + self.tr = "tcp://{0}:{1}".format(self.server, self.port) print "\nConnecting To ZMQ Publisher At {0}".format(self.tr) self.active = True 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 4478ed3f..21f62ece 100755 --- a/scripts/automation/trex_control_plane/client/trex_stateless_client.py +++ b/scripts/automation/trex_control_plane/client/trex_stateless_client.py @@ -338,7 +338,7 @@ class CTRexStatelessClient(object): self._server_version = None self.__err_log = None - self._async_client = CTRexAsyncClient(async_port) + self._async_client = CTRexAsyncClient(server, async_port) self.streams_db = CStreamsDB() diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 7cb65fa6..8e8b25ec 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -39,6 +39,24 @@ import parsing_opts __version__ = "1.0" +class TRexGeneralCmd(cmd.Cmd): + def __init__(self): + cmd.Cmd.__init__(self) + + def emptyline(self): + """Called when an empty line is entered in response to the prompt. + + This overriding is such that when empty line is passed, **nothing happens**. + """ + return + + def completenames(self, text, *ignored): + """ + This overriding is such that a space is added to name completion. + """ + dotext = 'do_'+text + return [a[3:]+' ' for a in self.get_names() if a.startswith(dotext)] + # # main console object class TRexConsole(cmd.Cmd): -- cgit 1.2.3-korg From 84e9d7a4a8bbb3afb4861652e2d56bc27097f794 Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Thu, 19 Nov 2015 02:30:48 +0200 Subject: History feature is DONE Fixed bugs Cleaned code, more like PEP8 --- .../client/trex_stateless_client.py | 55 ++++++++++------------ .../trex_control_plane/console/trex_console.py | 52 ++++++++++++++++---- 2 files changed, 68 insertions(+), 39 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 21f62ece..3dcfae28 100755 --- a/scripts/automation/trex_control_plane/client/trex_stateless_client.py +++ b/scripts/automation/trex_control_plane/client/trex_stateless_client.py @@ -139,8 +139,7 @@ class CStreamsDB(object): # describes a single port -class Port: - +class Port(object): STATE_DOWN = 0 STATE_IDLE = 1 STATE_STREAMS = 2 @@ -156,14 +155,14 @@ class Port: self.streams = {} - def err (self, msg): + def err(self, msg): return RC_ERR("port {0} : {1}".format(self.port_id, msg)) - def ok (self): + def ok(self): return RC_OK() # take the port - def acquire (self, force = False): + def acquire(self, force = False): params = {"port_id": self.port_id, "user": self.user, "force": force} @@ -178,7 +177,7 @@ class Port: # release the port - def release (self): + def release(self): params = {"port_id": self.port_id, "handler": self.handler} @@ -190,25 +189,24 @@ class Port: else: return self.err(rc.data) - def is_acquired (self): + def is_acquired(self): return (self.handler != None) - def is_active (self): - return (self.state == self.STATE_TX ) or (self.state == self.STATE_PAUSE) - - def sync (self, sync_data): + def is_active(self): + return(self.state == self.STATE_TX ) or (self.state == self.STATE_PAUSE) + def sync(self, sync_data): self.handler = sync_data['handler'] - - if sync_data['state'] == "DOWN": + port_state = sync_data['state'].upper() + if port_state == "DOWN": self.state = self.STATE_DOWN - elif sync_data['state'] == "IDLE": + elif port_state == "IDLE": self.state = self.STATE_IDLE - elif sync_data['state'] == "STREAMS": + elif port_state == "STREAMS": self.state = self.STATE_STREAMS - elif sync_data['state'] == "TX": + elif port_state == "TX": self.state = self.STATE_TX - elif sync_data['state'] == "PAUSE": + elif port_state == "PAUSE": self.state = self.STATE_PAUSE else: raise Exception("port {0}: bad state received from server '{1}'".format(self.port_id, sync_data['state'])) @@ -217,14 +215,14 @@ class Port: # return TRUE if write commands - def is_port_writeable (self): - # operations on port can be done on state idle or state sreams + def is_port_writable (self): + # operations on port can be done on state idle or state streams return ((self.state == self.STATE_IDLE) or (self.state == self.STATE_STREAMS)) # add stream to the port def add_stream (self, stream_id, stream_obj): - if not self.is_port_writeable(): + if not self.is_port_writable(): return self.err("Please stop port before attempting to add streams") @@ -332,6 +330,7 @@ class CTRexStatelessClient(object): self.user = username self.comm_link = CTRexStatelessClient.CCommLink(server, sync_port, virtual) self.verbose = False + self.ports = [] self._conn_handler = {} self._active_ports = set() self._system_info = None @@ -378,7 +377,7 @@ class CTRexStatelessClient(object): ############ boot up section ################ # connection sequence - def connect (self): + def connect(self): self.connected = False @@ -394,7 +393,7 @@ class CTRexStatelessClient(object): self.system_info = data - # cache supported cmds + # cache supported commands rc, data = self.transmit("get_supported_cmds") if not rc: return RC_ERR(data) @@ -402,8 +401,7 @@ class CTRexStatelessClient(object): self.supported_cmds = data # create ports - self.ports = [] - for port_id in xrange(0, self.get_port_count()): + for port_id in xrange(self.get_port_count()): self.ports.append(Port(port_id, self.user, self.transmit)) # acquire all ports @@ -485,7 +483,6 @@ class CTRexStatelessClient(object): return RC_ERR(data) for port_info in data: - rc = self.ports[port_info['port_id']].sync(port_info) if rc.bad(): return rc @@ -619,23 +616,23 @@ class CTRexStatelessClient(object): ######################### Console (high level) API ######################### - def cmd_ping (self): + def cmd_ping(self): rc = self.ping() rc.annotate("Pinging the server on '{0}' port '{1}': ".format(self.get_connection_ip(), self.get_connection_port())) return rc - def cmd_connect (self): + def cmd_connect(self): rc = self.connect() rc.annotate() return rc - def cmd_disconnect (self): + def cmd_disconnect(self): rc = self.disconnect() rc.annotate() return rc # reset - def cmd_reset (self): + def cmd_reset(self): # sync with the server diff --git a/scripts/automation/trex_control_plane/console/trex_console.py b/scripts/automation/trex_control_plane/console/trex_console.py index 8e8b25ec..ea2f5f12 100755 --- a/scripts/automation/trex_control_plane/console/trex_console.py +++ b/scripts/automation/trex_control_plane/console/trex_console.py @@ -23,6 +23,7 @@ import json import ast import argparse import random +import readline import string import os import sys @@ -36,12 +37,38 @@ import trex_status import parsing_opts -__version__ = "1.0" +__version__ = "1.1" class TRexGeneralCmd(cmd.Cmd): def __init__(self): cmd.Cmd.__init__(self) + # configure history behaviour + self._history_file_dir = "/tmp/trex/console/" + self._history_file = self.get_history_file_full_path() + readline.set_history_length(100) + # load history, if any + self.load_console_history() + + + def get_console_identifier(self): + return self.__class__.__name__ + + def get_history_file_full_path(self): + return "{dir}{filename}.hist".format(dir=self._history_file_dir, + filename=self.get_console_identifier()) + + def load_console_history(self): + if os.path.exists(self._history_file): + readline.read_history_file(self._history_file) + return + + def save_console_history(self): + if not os.path.exists(self._history_file_dir): + os.makedirs(self._history_file_dir) + # os.mknod(self._history_file) + readline.write_history_file(self._history_file) + return def emptyline(self): """Called when an empty line is entered in response to the prompt. @@ -57,15 +84,22 @@ class TRexGeneralCmd(cmd.Cmd): dotext = 'do_'+text return [a[3:]+' ' for a in self.get_names() if a.startswith(dotext)] + def precmd(self, line): + # before doing anything, save history snapshot of the console + # this is done before executing the command in case of ungraceful application exit + self.save_console_history() + return line + + # # main console object -class TRexConsole(cmd.Cmd): +class TRexConsole(TRexGeneralCmd): """Trex Console""" - def __init__(self, stateless_client, acquire_all_ports = True, verbose = False): - cmd.Cmd.__init__(self) - + def __init__(self, stateless_client, acquire_all_ports=True, verbose=False): self.stateless_client = stateless_client + TRexGeneralCmd.__init__(self) + self.verbose = verbose self.acquire_all_ports = acquire_all_ports @@ -78,11 +112,9 @@ class TRexConsole(cmd.Cmd): ################### internal section ######################## - # a cool hack - i stole this function and added space - def completenames(self, text, *ignored): - dotext = 'do_'+text - return [a[3:]+' ' for a in self.get_names() if a.startswith(dotext)] - + def get_console_identifier(self): + return "{context}_{server}".format(context=self.__class__.__name__, + server=self.stateless_client.get_system_info()['hostname']) def register_main_console_methods(self): main_names = set(self.trex_console.get_names()).difference(set(dir(self.__class__))) -- cgit 1.2.3-korg