diff options
author | 2016-01-27 13:03:51 +0200 | |
---|---|---|
committer | 2016-01-27 13:03:51 +0200 | |
commit | c581c5bb6314b5f80d315c23354f8866ed2a71ff (patch) | |
tree | 8e1e4e041e027f3c14a542730ffd688882c69522 /scripts/automation/trex_control_plane/client | |
parent | 52f599e870f0a3d98cebdf4d49607a6f50cf3380 (diff) | |
parent | 1e69b27f272fef2e3124693b865521a4927418f5 (diff) |
Merge to latest
Diffstat (limited to 'scripts/automation/trex_control_plane/client')
3 files changed, 450 insertions, 337 deletions
diff --git a/scripts/automation/trex_control_plane/client/trex_port.py b/scripts/automation/trex_control_plane/client/trex_port.py index dcb03da3..c8147faf 100644 --- a/scripts/automation/trex_control_plane/client/trex_port.py +++ b/scripts/automation/trex_control_plane/client/trex_port.py @@ -3,6 +3,7 @@ from collections import namedtuple, OrderedDict from common.trex_types import * from common import trex_stats from client_utils import packet_builder + StreamOnPort = namedtuple('StreamOnPort', ['compiled_stream', 'metadata']) ########## utlity ############ @@ -48,7 +49,6 @@ class Port(object): self.streams = {} self.profile = None self.session_id = session_id - self.loaded_stream_pack = None self.port_stats = trex_stats.CPortStats(self) @@ -138,63 +138,44 @@ class Port(object): # 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_writable(): - return self.err("Please stop port before attempting to add streams") + # add streams + def add_streams (self, streams_list): - params = {"handler": self.handler, - "port_id": self.port_id, - "stream_id": stream_id, - "stream": stream_obj} - - rc = self.transmit("add_stream", params) - if rc.bad(): - return self.err(rc.err()) - - # add the stream - self.streams[stream_id] = StreamOnPort(stream_obj, Port._generate_stream_metadata(stream_id, stream_obj)) - - # the only valid state now - self.state = self.STATE_STREAMS + if not self.is_acquired(): + return self.err("port is not owned") - return self.ok() + if not self.is_port_writable(): + return self.err("Please stop port before attempting to add streams") - # add multiple streams - def add_streams (self, LoadedStreamList_obj): batch = [] + for stream in (streams_list if isinstance(streams_list, list) else [streams_list]): - self.loaded_stream_pack = LoadedStreamList_obj - compiled_stream_list = LoadedStreamList_obj.compiled - - for stream_pack in compiled_stream_list: params = {"handler": self.handler, "port_id": self.port_id, - "stream_id": stream_pack.stream_id, - "stream": stream_pack.stream} + "stream_id": stream.get_id(), + "stream": stream.to_json()} cmd = RpcCmdData('add_stream', params) batch.append(cmd) + # meta data for show streams + self.streams[stream.get_id()] = StreamOnPort(stream.to_json(), + Port._generate_stream_metadata(stream.get_id(), stream.to_json())) + rc = self.transmit_batch(batch) - if rc.bad(): + if not rc: return self.err(rc.err()) - # validate that every action succeeded - - # add the stream - for stream_pack in compiled_stream_list: - self.streams[stream_pack.stream_id] = StreamOnPort(stream_pack.stream, - Port._generate_stream_metadata(stream_pack.stream_id, - stream_pack.stream)) + # the only valid state now self.state = self.STATE_STREAMS return self.ok() + + # remove stream from port def remove_stream (self, stream_id): @@ -460,10 +441,6 @@ class Port(object): def generate_loaded_streams_sum(self, stream_id_list): if self.state == self.STATE_DOWN or self.state == self.STATE_STREAMS: return {} - elif self.loaded_stream_pack is None: - # avoid crashing when sync with remote server isn't operational - # TODO: MAKE SURE TO HANDLE THIS CASE FOR BETTER UX - return {} streams_data = {} if not stream_id_list: @@ -476,7 +453,7 @@ class Port(object): if stream_id in self.streams} - return {"referring_file" : self.loaded_stream_pack.name, + return {"referring_file" : "", "streams" : streams_data} @staticmethod 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 32618a05..65e69938 100755 --- a/scripts/automation/trex_control_plane/client/trex_stateless_client.py +++ b/scripts/automation/trex_control_plane/client/trex_stateless_client.py @@ -23,56 +23,9 @@ import re import random from trex_port import Port from common.trex_types import * +from common.trex_stl_exceptions import * from trex_async_client import CTRexAsyncClient -# basic error for API -class STLError(Exception): - def __init__ (self, msg): - self.msg = str(msg) - - def __str__ (self): - exc_type, exc_obj, exc_tb = sys.exc_info() - fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] - - - s = "\n******\n" - s += "Error at {0}:{1}\n\n".format(format_text(fname, 'bold'), format_text(exc_tb.tb_lineno), 'bold') - s += "specific error:\n\n{0}\n".format(format_text(self.msg, 'bold')) - - return s - - def brief (self): - return self.msg - - -# raised when the client state is invalid for operation -class STLStateError(STLError): - def __init__ (self, op, state): - self.msg = "Operation '{0}' is not valid while '{1}'".format(op, state) - - -# port state error -class STLPortStateError(STLError): - def __init__ (self, port, op, state): - self.msg = "Operation '{0}' on port(s) '{1}' is not valid while port(s) '{2}'".format(op, port, state) - - -# raised when argument is not valid for operation -class STLArgumentError(STLError): - def __init__ (self, name, got, valid_values = None, extended = None): - self.msg = "Argument: '{0}' invalid value: '{1}'".format(name, got) - if valid_values: - self.msg += " - valid values are '{0}'".format(valid_values) - - if extended: - self.msg += "\n{0}".format(extended) - -# raised when timeout occurs -class STLTimeoutError(STLError): - def __init__ (self, timeout): - self.msg = "Timeout: operation took more than '{0}' seconds".format(timeout) - - ############################ logger ############################# ############################ ############################# @@ -541,14 +494,14 @@ class STLClient(object): return rc - def __add_stream(self, stream_id, stream_obj, port_id_list = None): + def __add_streams(self, stream_list, port_id_list = None): port_id_list = self.__ports(port_id_list) rc = RC() for port_id in port_id_list: - rc.add(self.ports[port_id].add_stream(stream_id, stream_obj)) + rc.add(self.ports[port_id].add_streams(stream_list)) return rc @@ -605,7 +558,7 @@ class STLClient(object): return self.ports[port_id].get_stream_id_list() - def __start_traffic (self, multiplier, duration, port_id_list = None, force = False): + def __start (self, multiplier, duration, port_id_list = None, force = False): port_id_list = self.__ports(port_id_list) @@ -617,7 +570,7 @@ class STLClient(object): return rc - def __resume_traffic (self, port_id_list = None, force = False): + def __resume (self, port_id_list = None, force = False): port_id_list = self.__ports(port_id_list) rc = RC() @@ -627,7 +580,7 @@ class STLClient(object): return rc - def __pause_traffic (self, port_id_list = None, force = False): + def __pause (self, port_id_list = None, force = False): port_id_list = self.__ports(port_id_list) rc = RC() @@ -638,7 +591,7 @@ class STLClient(object): return rc - def __stop_traffic (self, port_id_list = None, force = False): + def __stop (self, port_id_list = None, force = False): port_id_list = self.__ports(port_id_list) rc = RC() @@ -649,7 +602,7 @@ class STLClient(object): return rc - def __update_traffic (self, mult, port_id_list = None, force = False): + def __update (self, mult, port_id_list = None, force = False): port_id_list = self.__ports(port_id_list) rc = RC() @@ -660,7 +613,7 @@ class STLClient(object): return rc - def __validate_traffic (self, port_id_list = None): + def __validate (self, port_id_list = None): port_id_list = self.__ports(port_id_list) rc = RC() @@ -672,7 +625,6 @@ class STLClient(object): - # connect to server def __connect(self): @@ -684,26 +636,19 @@ class STLClient(object): self.connected = False # connect sync channel - self.logger.pre_cmd("connecting to RPC server on {0}:{1}".format(self.connection_info['server'], self.connection_info['sync_port'])) + self.logger.pre_cmd("Connecting to RPC server on {0}:{1}".format(self.connection_info['server'], self.connection_info['sync_port'])) rc = self.comm_link.connect() self.logger.post_cmd(rc) if not rc: return rc - # connect async channel - self.logger.pre_cmd("connecting to publisher server on {0}:{1}".format(self.connection_info['server'], self.connection_info['async_port'])) - rc = self.async_client.connect() - self.logger.post_cmd(rc) - - if not rc: - return rc - # version rc = self._transmit("get_version") if not rc: return rc + self.server_version = rc.data() self.global_stats.server_version = rc.data() @@ -740,7 +685,16 @@ class STLClient(object): return rc + # connect async channel + self.logger.pre_cmd("connecting to publisher server on {0}:{1}".format(self.connection_info['server'], self.connection_info['async_port'])) + rc = self.async_client.connect() + self.logger.post_cmd(rc) + + if not rc: + return rc + self.connected = True + return RC_OK() @@ -758,101 +712,6 @@ class STLClient(object): return RC_OK() - # ping server - def __ping (self): - return self._transmit("ping") - - - # start command - def __start (self, port_id_list, stream_list, mult, force, duration, dry): - - - self.logger.pre_cmd("Removing all streams from port(s) {0}:".format(port_id_list)) - rc = self.__remove_all_streams(port_id_list) - self.logger.post_cmd(rc) - - if not rc: - return rc - - - self.logger.pre_cmd("Attaching {0} streams to port(s) {1}:".format(len(stream_list.compiled), port_id_list)) - rc = self.__add_stream_pack(stream_list, port_id_list) - self.logger.post_cmd(rc) - - if not rc: - return rc - - # when not on dry - start the traffic , otherwise validate only - if not dry: - - self.logger.pre_cmd("Starting traffic on port(s) {0}:".format(port_id_list)) - rc = self.__start_traffic(mult, duration, port_id_list, force) - self.logger.post_cmd(rc) - - return rc - else: - - rc = self.__validate(port_id_list) - if rc.bad(): - return rc - - # show a profile on one port for illustration - self.ports[port_id_list[0]].print_profile(mult, duration) - - return rc - - - # stop cmd - def __stop (self, port_id_list): - - self.logger.pre_cmd("Stopping traffic on port(s) {0}:".format(port_id_list)) - rc = self.__stop_traffic(port_id_list) - self.logger.post_cmd(rc) - - if not rc: - return rc - - return RC_OK() - - #update cmd - def __update (self, port_id_list, mult, force): - - self.logger.pre_cmd("Updating traffic on port(s) {0}:".format(port_id_list)) - rc = self.__update_traffic(mult, port_id_list, force) - self.logger.post_cmd(rc) - - return rc - - - # pause cmd - def __pause (self, port_id_list): - - self.logger.pre_cmd("Pausing traffic on port(s) {0}:".format(port_id_list)) - rc = self.__pause_traffic(port_id_list) - self.logger.post_cmd(rc) - - return rc - - - # resume cmd - def __resume (self, port_id_list): - - self.logger.pre_cmd("Resume traffic on port(s) {0}:".format(port_id_list)) - rc = self.__resume_traffic(port_id_list) - self.logger.post_cmd(rc) - - return rc - - - # validate port(s) profile - def __validate (self, port_id_list): - self.logger.pre_cmd("Validating streams on port(s) {0}:".format(port_id_list)) - rc = self.__validate_traffic(port_id_list) - self.logger.post_cmd(rc) - - return rc - - # clear stats def __clear_stats(self, port_id_list, clear_global): @@ -862,9 +721,7 @@ class STLClient(object): if clear_global: self.global_stats.clear_stats() - self.logger.pre_cmd("clearing stats on port(s) {0}:".format(port_id_list)) - rc = RC_OK() - self.logger.post_cmd(rc) + self.logger.log_cmd("clearing stats on port(s) {0}:".format(port_id_list)) return RC @@ -891,30 +748,6 @@ class STLClient(object): return stats - def __process_profiles (self, profiles, out): - - for profile in (profiles if isinstance(profiles, list) else [profiles]): - # filename - if isinstance(profile, str): - - if not os.path.isfile(profile): - return RC_ERR("file '{0}' does not exists".format(profile)) - - try: - stream_list = self.streams_db.load_yaml_file(profile) - except Exception as e: - rc = RC_ERR(str(e)) - return rc - - out.append(stream_list) - - else: - return RC_ERR("unknown profile '{0}'".format(profile)) - - - return RC_OK() - - ############ functions used by other classes but not users ############## def _verify_port_id_list (self, port_id_list): @@ -1014,7 +847,8 @@ class STLClient(object): ############################ ############################# ############################ ############################# def __enter__ (self): - self.connect(mode = "RWF") + self.connect() + self.acquire(force = True) self.reset() return self @@ -1134,36 +968,79 @@ class STLClient(object): ############################ ############################# - # set the log on verbose level + """ + Sets verbose level + + :parameters: + level : enum + LoggerApi.VERBOSE_QUIET + LoggerApi.VERBOSE_NORMAL + LoggerApi.VERBOSE_HIGH + + :raises: + None + + """ def set_verbose (self, level): self.logger.set_verbose(level) - # connects to the server - # mode can be: - # 'RO' - read only - # 'RW' - read/write - # 'RWF' - read write forced (take ownership) + """ + Connects to the TRex server + + :parameters: + None + + :raises: + + :exc:`STLError` + + """ @__api_check(False) - def connect (self, mode = "RW"): - modes = ['RO', 'RW', 'RWF'] - if not mode in modes: - raise STLArgumentError('mode', mode, modes) - + def connect (self): rc = self.__connect() if not rc: raise STLError(rc) - # acquire all ports for 'RW' or 'RWF' - if (mode == "RW") or (mode == "RWF"): - self.acquire(ports = self.get_all_ports(), force = True if mode == "RWF" else False) + """ + Disconnects from the server + + :parameters: + stop_traffic : bool + tries to stop traffic before disconnecting + + + """ + @__api_check(False) + def disconnect (self, stop_traffic = True): + + # try to stop ports but do nothing if not possible + if stop_traffic: + try: + self.stop() + except STLError: + pass + + self.logger.pre_cmd("Disconnecting from server at '{0}':'{1}'".format(self.connection_info['server'], + self.connection_info['sync_port'])) + rc = self.__disconnect() + self.logger.post_cmd(rc) + + + + """ + Acquires ports for executing commands + :parameters: + ports : list + ports to execute the command + force : bool + force acquire the ports + :raises: + + :exc:`STLError` - # acquire ports - # this is not needed if connect was called with "RW" or "RWF" - # but for "RO" this might be needed + """ @__api_check(True) def acquire (self, ports = None, force = False): # by default use all ports @@ -1186,102 +1063,218 @@ class STLClient(object): self.logger.post_cmd(rc) if not rc: + # cleanup self.__release(ports) raise STLError(rc) - # force connect syntatic sugar - @__api_check(False) - def fconnect (self): - self.connect(mode = "RWF") + """ + Pings the server + :parameters: + None + + + :raises: + + :exc:`STLError` + + """ + @__api_check(True) + def ping(self): + self.logger.pre_cmd( "Pinging the server on '{0}' port '{1}': ".format(self.connection_info['server'], + self.connection_info['sync_port'])) + rc = self._transmit("ping") + + self.logger.post_cmd(rc) - # disconnects from the server - @__api_check(False) - def disconnect (self, log = True): - rc = self.__disconnect() - if log: - self.logger.log_cmd("Disconnecting from server at '{0}':'{1}'".format(self.connection_info['server'], - self.connection_info['sync_port'])) if not rc: raise STLError(rc) - # teardown - call after test is done - # NEVER throws an exception - @__api_check(False) - def teardown (self, stop_traffic = True): - - # try to stop traffic - if stop_traffic and self.get_active_ports(): - try: - self.stop() - except STLError: - pass - - # disconnect - self.__disconnect() + """ + force acquire ports, stop the traffic, remove all streams and clear stats + :parameters: + ports : list + ports to execute the command + + :raises: + + :exc:`STLError` - # pings the server on the RPC channel + """ @__api_check(True) - def ping(self): - self.logger.pre_cmd( "Pinging the server on '{0}' port '{1}': ".format(self.connection_info['server'], - self.connection_info['sync_port'])) - rc = self.__ping() - - self.logger.post_cmd(rc) + def reset(self, ports = None): + + # by default use all ports + if ports == None: + ports = self.get_all_ports() + # verify ports + rc = self._validate_port_list(ports) if not rc: - raise STLError(rc) + raise STLArgumentError('ports', ports, valid_values = self.get_all_ports()) + + self.acquire(ports, force = True) + self.stop(ports) + self.remove_all_streams(ports) + self.clear_stats(ports) + + + """ + remove all streams from port(s) + :parameters: + ports : list + ports to execute the command + + :raises: + + :exc:`STLError` - # reset the server by performing - # force acquire, stop, and remove all streams + """ @__api_check(True) - def reset(self): + def remove_all_streams (self, ports = None): - self.logger.pre_cmd("Force acquiring all ports:") - rc = self.__acquire(force = True) + # by default use all ports + if ports == None: + ports = self.get_acquired_ports() + + # verify valid port id list + rc = self._validate_port_list(ports) + if not rc: + raise STLArgumentError('ports', ports, valid_values = self.get_all_ports()) + + self.logger.pre_cmd("Removing all streams from port(s) {0}:".format(ports)) + rc = self.__remove_all_streams(ports) self.logger.post_cmd(rc) if not rc: raise STLError(rc) + + """ + add a list of streams to port(s) - # force stop all ports - self.logger.pre_cmd("Stop traffic on all ports:") - rc = self.__stop_traffic(self.get_all_ports(), True) - self.logger.post_cmd(rc) + :parameters: + ports : list + ports to execute the command + streams: list + streams to attach + + :raises: + + :exc:`STLError` + + """ + @__api_check(True) + def add_streams (self, streams, ports = None): + # by default use all ports + if ports == None: + ports = self.get_acquired_ports() + # verify valid port id list + rc = self._validate_port_list(ports) if not rc: - raise STLError(rc) + raise STLArgumentError('ports', ports, valid_values = self.get_all_ports()) + # transform single stream + if not isinstance(streams, list): + streams = [streams] - # remove all streams - self.logger.pre_cmd("Removing all streams from all ports:") - rc = self.__remove_all_streams(self.get_all_ports()) + # check streams + if not all([isinstance(stream, STLStream) for stream in streams]): + raise STLArgumentError('streams', streams) + + self.logger.pre_cmd("Attaching {0} streams to port(s) {1}:".format(len(streams), ports)) + rc = self.__add_streams(streams, ports) self.logger.post_cmd(rc) if not rc: raise STLError(rc) - self.clear_stats() + """ + load a profile file to port(s) + + :parameters: + filename : str + filename to load + ports : list + ports to execute the command + - # start cmd + :raises: + + :exc:`STLError` + + """ + @__api_check(True) + def load_profile (self, filename, ports = None): + + # check filename + if not os.path.isfile(filename): + raise STLError("file '{0}' does not exists".format(filename)) + + # by default use all ports + if ports == None: + ports = self.get_acquired_ports() + + # verify valid port id list + rc = self._validate_port_list(ports) + if not rc: + raise STLArgumentError('ports', ports, valid_values = self.get_all_ports()) + + # load the YAML + try: + streams_pack = self.streams_db.load_yaml_file(filename) + except Exception as e: + raise STLError(str(e)) + + # HACK - convert the stream pack to simple streams + streams = [] + for stream in streams_pack.compiled: + s = HACKSTLStream(stream) + streams.append(s) + + self.add_streams(streams, ports) + + + + """ + start traffic on port(s) + + :parameters: + ports : list + ports to execute command + + mult : str + multiplier in a form of pps, bps, or line util in % + examples: "5kpps", "10gbps", "85%", "32mbps" + + force : bool + imply stopping the port of active and also + forces a profile that exceeds the L1 BW + + duration : int + limit the run for time in seconds + -1 means unlimited + + total : bool + should the B/W be divided by the ports + or duplicated for each + + + :raises: + + :exc:`STLError` + + """ @__api_check(True) def start (self, - profiles, ports = None, mult = "1", force = False, duration = -1, - dry = False, total = False): @@ -1313,57 +1306,87 @@ class STLClient(object): raise STLArgumentError('total', total) - # process profiles - stream_list = [] - rc = self.__process_profiles(profiles, stream_list) - if not rc: - raise STLError(rc) - - # verify ports are stopped or force stop them active_ports = list(set(self.get_active_ports()).intersection(ports)) if active_ports: if not force: - msg = "Port(s) {0} are active - please stop them or specify 'force'".format(active_ports) - raise STLError(msg) + raise STLError("Port(s) {0} are active - please stop them or specify 'force'".format(active_ports)) else: - rc = self.__stop(active_ports) + rc = self.stop(active_ports) if not rc: raise STLError(rc) - # dry run - if dry: - self.logger.log(format_text("\n*** DRY RUN ***", 'bold')) - - # call private method to start + # start traffic + self.logger.pre_cmd("Starting traffic on port(s) {0}:".format(ports)) + rc = self.__start(mult_obj, duration, ports, force) + self.logger.post_cmd(rc) - rc = self.__start(ports, stream_list[0], mult_obj, force, duration, dry) if not rc: raise STLError(rc) - # stop traffic on ports + + """ + stop port(s) + + :parameters: + ports : list + ports to execute the command + + + :raises: + + :exc:`STLError` + + """ @__api_check(True) def stop (self, ports = None): # by default the user means all the active ports if ports == None: ports = self.get_active_ports() + if not ports: + return # verify valid port id list rc = self._validate_port_list(ports) if not rc: raise STLArgumentError('ports', ports, valid_values = self.get_all_ports()) + self.logger.pre_cmd("Stopping traffic on port(s) {0}:".format(ports)) rc = self.__stop(ports) + self.logger.post_cmd(rc) + if not rc: raise STLError(rc) - # update traffic + """ + update traffic on port(s) + + :parameters: + ports : list + ports to execute command + + mult : str + multiplier in a form of pps, bps, or line util in % + and also with +/- + examples: "5kpps+", "10gbps-", "85%", "32mbps", "20%+" + + force : bool + forces a profile that exceeds the L1 BW + + total : bool + should the B/W be divided by the ports + or duplicated for each + + + :raises: + + :exc:`STLError` + + """ @__api_check(True) def update (self, ports = None, mult = "1", total = False, force = False): @@ -1389,13 +1412,26 @@ class STLClient(object): # call low level functions - rc = self.__update(ports, mult_obj, force) + self.logger.pre_cmd("Updating traffic on port(s) {0}:".format(ports)) + rc = self.__update(mult, ports, force) + self.logger.post_cmd(rc) + if not rc: raise STLError(rc) - # pause traffic on ports + """ + pause traffic on port(s) + + :parameters: + ports : list + ports to execute command + + :raises: + + :exc:`STLError` + + """ @__api_check(True) def pause (self, ports = None): @@ -1408,13 +1444,26 @@ class STLClient(object): if not rc: raise STLArgumentError('ports', ports, valid_values = self.get_all_ports()) + self.logger.pre_cmd("Pausing traffic on port(s) {0}:".format(ports)) rc = self.__pause(ports) + self.logger.post_cmd(rc) + if not rc: raise STLError(rc) - # resume traffic on ports + """ + resume traffic on port(s) + + :parameters: + ports : list + ports to execute command + + :raises: + + :exc:`STLError` + + """ @__api_check(True) def resume (self, ports = None): @@ -1427,13 +1476,39 @@ class STLClient(object): if not rc: raise STLArgumentError('ports', ports, valid_values = self.get_all_ports()) + self.logger.pre_cmd("Resume traffic on port(s) {0}:".format(ports)) rc = self.__resume(ports) + self.logger.post_cmd(rc) + if not rc: raise STLError(rc) + """ + validate port(s) configuration + + :parameters: + ports : list + ports to execute command + + mult : str + multiplier in a form of pps, bps, or line util in % + examples: "5kpps", "10gbps", "85%", "32mbps" + + duration : int + limit the run for time in seconds + -1 means unlimited + + total : bool + should the B/W be divided by the ports + or duplicated for each + + :raises: + + :exc:`STLError` + + """ @__api_check(True) - def validate (self, ports = None): + def validate (self, ports = None, mult = "1", duration = "-1", total = False): if ports == None: ports = self.get_acquired_ports() @@ -1442,18 +1517,47 @@ class STLClient(object): if not rc: raise STLArgumentError('ports', ports, valid_values = self.get_all_ports()) + # verify multiplier + mult_obj = parsing_opts.decode_multiplier(mult, + allow_update = True, + divide_count = len(ports) if total else 1) + if not mult_obj: + raise STLArgumentError('mult', mult) + + + if not isinstance(duration, (int, float)): + raise STLArgumentError('duration', duration) + + + self.logger.pre_cmd("Validating streams on port(s) {0}:".format(ports)) rc = self.__validate(ports) - if not rc: - raise STLError(rc) + self.logger.post_cmd(rc) - # clear stats + for port in ports: + self.ports[port].print_profile(mult_obj, duration) + + + """ + clear stats on port(s) + + :parameters: + ports : list + ports to execute command + + clear_global : bool + clear the global stats + + :raises: + + :exc:`STLError` + + """ @__api_check(False) def clear_stats (self, ports = None, clear_global = True): # by default use all ports if ports == None: - ports = self.get_acquired_ports() + ports = self.get_all_ports() # verify valid port id list rc = self._validate_port_list(ports) @@ -1473,7 +1577,21 @@ class STLClient(object): - # wait while traffic is on, on timeout throw STLTimeoutError + """ + block until specify port(s) traffic has ended + + :parameters: + ports : list + ports to execute command + + timeout : int + timeout in seconds + + :raises: + + :exc:`STLTimeoutError` - in case timeout has expired + + :exe:'STLError' + + """ @__api_check(True) def wait_on_traffic (self, ports = None, timeout = 60): @@ -1495,13 +1613,24 @@ class STLClient(object): raise STLTimeoutError(timeout) - # clear all async events + """ + clear all events + + :parameters: + None + + :raises: + None + + """ def clear_events (self): self.event_handler.clear_events() + ############################ Line ############################# ############################ Commands ############################# ############################ ############################# + # console decorator def __console(f): def wrap(*args): @@ -1539,7 +1668,8 @@ class STLClient(object): return # call the API - self.connect("RWF" if opts.force else "RW") + self.connect() + self.acquire(force = opts.force) # true means print time return True @@ -1587,18 +1717,24 @@ class STLClient(object): msg = "Port(s) {0} are active - please stop them or add '--force'\n".format(active_ports) self.logger.log(format_text(msg, 'bold')) return + else: + self.stop(active_ports) + # remove all streams + self.remove_all_streams(opts.ports) + # pack the profile - profiles = [opts.file[0]] - - self.start(profiles, - opts.ports, - opts.mult, - opts.force, - opts.duration, - opts.dry, - opts.total) + self.load_profile(opts.file[0], opts.ports) + + if opts.dry: + self.validate(opts.ports, opts.mult, opts.duration, opts.total) + else: + self.start(opts.ports, + opts.mult, + opts.force, + opts.duration, + opts.total) # true means print time return True diff --git a/scripts/automation/trex_control_plane/client/trex_stateless_sim.py b/scripts/automation/trex_control_plane/client/trex_stateless_sim.py index 3196c666..a8f24d65 100644 --- a/scripts/automation/trex_control_plane/client/trex_stateless_sim.py +++ b/scripts/automation/trex_control_plane/client/trex_stateless_sim.py @@ -247,7 +247,7 @@ def setParserOptions(): parser.add_argument('-m', '--multiplier', help = parsing_opts.match_multiplier_help, dest = 'mult', - default = {'type':'raw', 'value':1, 'op': 'abs'}, + default = "1", type = parsing_opts.match_multiplier_strict) group = parser.add_mutually_exclusive_group() |