summaryrefslogtreecommitdiffstats
path: root/scripts/automation/regression
diff options
context:
space:
mode:
authorYaroslav Brustinov <ybrustin@cisco.com>2017-01-30 11:31:57 +0200
committerYaroslav Brustinov <ybrustin@cisco.com>2017-01-30 11:31:57 +0200
commitce9cf27303d53a579bfa1084f3694646dd62b089 (patch)
tree399d7882e552b26f433bc836876b3b03b7df3211 /scripts/automation/regression
parentefbe56332fdf6a5c386152e4a2af3a2b56f723b5 (diff)
regression: add global config file (currently ELK and GA info)
Change-Id: I3b3158668059255b85e9da0af6dfc8e319894556 Signed-off-by: Yaroslav Brustinov <ybrustin@cisco.com>
Diffstat (limited to 'scripts/automation/regression')
-rwxr-xr-xscripts/automation/regression/cfg/global_regression_cfg.yaml19
-rw-r--r--scripts/automation/regression/trex.py421
-rwxr-xr-xscripts/automation/regression/trex_unit_test.py23
3 files changed, 40 insertions, 423 deletions
diff --git a/scripts/automation/regression/cfg/global_regression_cfg.yaml b/scripts/automation/regression/cfg/global_regression_cfg.yaml
new file mode 100755
index 00000000..4bb9fb54
--- /dev/null
+++ b/scripts/automation/regression/cfg/global_regression_cfg.yaml
@@ -0,0 +1,19 @@
+#-------------------------------------------
+# Various global parameters of regression
+#-------------------------------------------
+
+
+########## Reporting results #########
+
+elk:
+ server: sceasr-b20
+ port: 9200
+
+google:
+ id: UA-75220362-3
+ queue_size: 100
+ timeout: 5
+ blocking: 0
+
+
+
diff --git a/scripts/automation/regression/trex.py b/scripts/automation/regression/trex.py
index 4f5eba60..36e204af 100644
--- a/scripts/automation/regression/trex.py
+++ b/scripts/automation/regression/trex.py
@@ -11,6 +11,8 @@ from CProgressDisp import TimedProgressBar
from stateful_tests.tests_exceptions import TRexInUseError
import datetime
import copy
+import outer_packages
+import yaml
class CTRexScenario:
modes = set() # list of modes of this setup: loopback, virtual etc.
@@ -44,6 +46,7 @@ class CTRexScenario:
json_verbose = False
elk = None
elk_info = None
+ global_cfg = None
def copy_elk_info ():
assert(CTRexScenario.elk_info)
@@ -53,420 +56,12 @@ def copy_elk_info ():
d['timestamp']=timestamp.strftime("%Y-%m-%d %H:%M:%S")
return(d)
-
+global_cfg = 'cfg/global_regression_cfg.yaml'
+if not os.path.exists(global_cfg):
+ raise Exception('Global configuration file %s is missing' % global_cfg)
+with open(global_cfg) as f:
+ CTRexScenario.global_cfg = yaml.safe_load(f.read())
-class CTRexRunner:
- """This is an instance for generating a CTRexRunner"""
- def __init__ (self, config_dict, yaml):
- self.trex_config = config_dict#misc_methods.load_config_file(config_file)
- self.yaml = yaml
-
-
- def get_config (self):
- """ get_config() -> dict
-
- Returns the stored configuration of the TRex server of the CTRexRunner instance as a dictionary
- """
- return self.trex_config
-
- def set_yaml_file (self, yaml_path):
- """ update_yaml_file (self, yaml_path) -> None
-
- Defines the yaml file to be used by the TRex.
- """
- self.yaml = yaml_path
-
-
- def generate_run_cmd (self, multiplier, cores, duration, nc = True, export_path="/tmp/trex.txt", **kwargs):
- """ generate_run_cmd(self, multiplier, duration, export_path) -> str
-
- Generates a custom running command for the kick-off of the TRex traffic generator.
- Returns a command (string) to be issued on the trex server
-
- Parameters
- ----------
- multiplier : float
- Defines the TRex multiplier factor (platform dependant)
- duration : int
- Defines the duration of the test
- export_path : str
- a full system path to which the results of the trex-run will be logged.
-
- """
- fileName, fileExtension = os.path.splitext(self.yaml)
- if self.yaml == None:
- raise ValueError('TRex yaml file is not defined')
- elif fileExtension != '.yaml':
- raise TypeError('yaml path is not referencing a .yaml file')
-
- if 'results_file_path' in kwargs:
- export_path = kwargs['results_file_path']
-
- trex_cmd_str = './t-rex-64 -c %d -m %f -d %d -f %s '
-
- if nc:
- trex_cmd_str = trex_cmd_str + ' --nc '
-
- trex_cmd = trex_cmd_str % (cores,
- multiplier,
- duration,
- self.yaml)
- # self.trex_config['trex_latency'])
-
- for key, value in kwargs.items():
- tmp_key = key.replace('_','-')
- dash = ' -' if (len(key)==1) else ' --'
- if value == True:
- trex_cmd += (dash + tmp_key)
- else:
- trex_cmd += (dash + '{k} {val}'.format( k = tmp_key, val = value ))
-
- print("\nTRex COMMAND: ", trex_cmd)
-
- cmd = 'sshpass.exp %s %s root "cd %s; %s > %s"' % (self.trex_config['trex_password'],
- self.trex_config['trex_name'],
- self.trex_config['trex_version_path'],
- trex_cmd,
- export_path)
-
- return cmd;
-
- def generate_fetch_cmd (self, result_file_full_path="/tmp/trex.txt"):
- """ generate_fetch_cmd(self, result_file_full_path) -> str
-
- Generates a custom command for which will enable to fetch the resutls of the TRex run.
- Returns a command (string) to be issued on the trex server.
-
- Example use: fetch_trex_results() - command that will fetch the content from the default log file- /tmp/trex.txt
- fetch_trex_results("/tmp/trex_secondary_file.txt") - command that will fetch the content from a custom log file- /tmp/trex_secondary_file.txt
- """
- #dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
- script_running_dir = os.path.dirname(os.path.realpath(__file__)) # get the current script working directory so that the sshpass could be accessed.
- cmd = script_running_dir + '/sshpass.exp %s %s root "cat %s"' % (self.trex_config['trex_password'],
- self.trex_config['trex_name'],
- result_file_full_path);
- return cmd;
-
-
-
- def run (self, multiplier, cores, duration, **kwargs):
- """ run(self, multiplier, duration, results_file_path) -> CTRexResults
-
- Running the TRex server based on the config file.
- Returns a CTRexResults object containing the results of the run.
-
- Parameters
- ----------
- multiplier : float
- Defines the TRex multiplier factor (platform dependant)
- duration : int
- Defines the duration of the test
- results_file_path : str
- a full system path to which the results of the trex-run will be logged and fetched from.
-
- """
- tmp_path = None
- # print kwargs
- if 'export_path' in kwargs:
- tmp_path = kwargs['export_path']
- del kwargs['export_path']
- cmd = self.generate_run_cmd(multiplier, cores, duration, tmp_path, **kwargs)
- else:
- cmd = self.generate_run_cmd(multiplier, cores, duration, **kwargs)
-
-# print 'TRex complete command to be used:'
-# print cmd
- # print kwargs
-
- progress_thread = TimedProgressBar(duration)
- progress_thread.start()
- interrupted = False
- try:
- start_time = time.time()
- start = datetime.datetime.now()
- results = subprocess.call(cmd, shell = True, stdout = open(os.devnull, 'wb'))
- end_time = time.time()
- fin = datetime.datetime.now()
- # print "Time difference : ", fin-start
- runtime_deviation = abs(( (end_time - start_time)/ (duration+15) ) - 1)
- print("runtime_deviation: %2.0f %%" % ( runtime_deviation*100.0))
- if ( runtime_deviation > 0.6 ) :
- # If the run stopped immediately - classify as Trex in use or reachability issue
- interrupted = True
- if ((end_time - start_time) < 2):
- raise TRexInUseError ('TRex run failed since TRex is used by another process, or due to reachability issues')
- else:
- CTRexScenario.trex_crashed = True
- # results = subprocess.Popen(cmd, stdout = open(os.devnull, 'wb'),
- # shell=True, preexec_fn=os.setsid)
- except KeyboardInterrupt:
- print("\nTRex test interrupted by user during traffic generation!!")
- results.killpg(results.pid, signal.SIGTERM) # Send the kill signal to all the process groups
- interrupted = True
- raise RuntimeError
- finally:
- progress_thread.join(isPlannedStop = (not interrupted) )
-
- if results!=0:
- sys.stderr.write("TRex run failed. Please Contact trex-dev mailer for further details")
- sys.stderr.flush()
- return None
- elif interrupted:
- sys.stderr.write("TRex run failed due user-interruption.")
- sys.stderr.flush()
- return None
- else:
-
- if tmp_path:
- cmd = self.generate_fetch_cmd( tmp_path )#**kwargs)#results_file_path)
- else:
- cmd = self.generate_fetch_cmd()
-
- try:
- run_log = subprocess.check_output(cmd, shell = True)
- trex_result = CTRexResult(None, run_log)
- trex_result.load_file_lines()
- trex_result.parse()
-
- return trex_result
-
- except subprocess.CalledProcessError:
- sys.stderr.write("TRex result fetching failed. Please Contact trex-dev mailer for further details")
- sys.stderr.flush()
- return None
-
-class CTRexResult():
- """This is an instance for generating a CTRexResult"""
- def __init__ (self, file, buffer = None):
- self.file = file
- self.buffer = buffer
- self.result = {}
-
-
- def load_file_lines (self):
- """ load_file_lines(self) -> None
-
- Loads into the self.lines the content of self.file
- """
- if self.buffer:
- self.lines = self.buffer.split("\n")
- else:
- f = open(self.file,'r')
- self.lines = f.readlines()
- f.close()
-
-
- def dump (self):
- """ dump(self) -> None
-
- Prints nicely the content of self.result dictionary into the screen
- """
- for key, value in self.result.items():
- print("{0:20} : \t{1}".format(key, float(value)))
-
- def update (self, key, val, _str):
- """ update (self, key, val, _str) -> None
-
- Updates the self.result[key] with a possibly new value representation of val
- Example: 15K might be updated into 15000.0
-
- Parameters
- ----------
- key :
- Key of the self.result dictionary of the TRexResult instance
- val : float
- Key of the self.result dictionary of the TRexResult instance
- _str : str
- a represntation of the BW (.
-
- """
-
- s = _str.strip()
-
- if s[0]=="G":
- val = val*1E9
- elif s[0]=="M":
- val = val*1E6
- elif s[0]=="K":
- val = val*1E3
-
- if key in self.result:
- if self.result[key] > 0:
- if (val/self.result[key] > 0.97 ):
- self.result[key]= val
- else:
- self.result[key] = val
- else:
- self.result[key] = val
-
-
-
- def parse (self):
- """ parse(self) -> None
-
- Parse the content of the result file from the TRex test and upload the data into
- """
- stop_read = False
- d = {
- 'total-tx' : 0,
- 'total-rx' : 0,
- 'total-pps' : 0,
- 'total-cps' : 0,
-
- 'expected-pps' : 0,
- 'expected-cps' : 0,
- 'expected-bps' : 0,
- 'active-flows' : 0,
- 'open-flows' : 0
- }
-
- self.error = ""
-
- # Parse the output of the test, line by line (each line matches another RegEx and as such
- # different rules apply
- for line in self.lines:
- match = re.match(".*/var/run/.rte_config.*", line)
- if match:
- stop_read = True
- continue
-
- #Total-Tx : 462.42 Mbps Nat_time_out : 0 ==> we try to parse the next decimal in this case Nat_time_out
-# match = re.match("\W*(\w(\w|[-])+)\W*([:]|[=])\W*(\d+[.]\d+)\W*\w+\W+(\w+)\W*([:]|[=])\W*(\d+)(.*)", line);
-# if match:
-# key = misc_methods.mix_string(match.group(5))
-# val = float(match.group(7))
-# # continue to parse !! we try the second
-# self.result[key] = val #update latest
-
- # check if we need to stop reading
- match = re.match(".*latency daemon has stopped.*", line)
- if match:
- stop_read = True
- continue
-
- match = re.match("\W*(\w(\w|[-])+)\W*([:]|[=])\W*(\d+[.]\d+)(.*ps)\s+(\w+)\W*([:]|[=])\W*(\d+)", line)
- if match:
- key = misc_methods.mix_string(match.group(1))
- val = float(match.group(4))
- if key in d:
- if stop_read == False:
- self.update (key, val, match.group(5))
- else:
- self.result[key] = val # update latest
- key2 = misc_methods.mix_string(match.group(6))
- val2 = int(match.group(8))
- self.result[key2] = val2 # always take latest
-
-
- match = re.match("\W*(\w(\w|[-])+)\W*([:]|[=])\W*(\d+[.]\d+)(.*)", line)
- if match:
- key = misc_methods.mix_string(match.group(1))
- val = float(match.group(4))
- if key in d:
- if stop_read == False:
- self.update (key, val, match.group(5))
- else:
- self.result[key] = val # update latest
- continue
-
- match = re.match("\W*(\w(\w|[-])+)\W*([:]|[=])\W*(\d+)(.*)", line)
- if match:
- key = misc_methods.mix_string(match.group(1))
- val = float(match.group(4))
- self.result[key] = val #update latest
- continue
-
- match = re.match("\W*(\w(\w|[-])+)\W*([:]|[=])\W*(OK)(.*)", line)
- if match:
- key = misc_methods.mix_string(match.group(1))
- val = 0 # valid
- self.result[key] = val #update latest
- continue
-
- match = re.match("\W*(Cpu Utilization)\W*([:]|[=])\W*(\d+[.]\d+) %(.*)", line)
- if match:
- key = misc_methods.mix_string(match.group(1))
- val = float(match.group(3))
- if key in self.result:
- if (self.result[key] < val): # update only if larger than previous value
- self.result[key] = val
- else:
- self.result[key] = val
- continue
-
- match = re.match(".*(rx_check\s.*)\s+:\s+(\w+)", line)
- if match:
- key = misc_methods.mix_string(match.group(1))
- try:
- val = int(match.group(2))
- except ValueError: # corresponds with rx_check validation case
- val = match.group(2)
- finally:
- self.result[key] = val
- continue
-
-
- def get_status (self, drop_expected = False):
- if (self.error != ""):
- print(self.error)
- return (self.STATUS_ERR_FATAL)
-
- d = self.result
-
- # test for latency
- latency_limit = 5000
- if ( d['maximum-latency'] > latency_limit ):
- self.reason="Abnormal latency measured (higher than %s" % latency_limit
- return self.STATUS_ERR_LATENCY
-
- # test for drops
- if drop_expected == False:
- if ( d['total-pkt-drop'] > 0 ):
- self.reason=" At least one packet dropped "
- return self.STATUS_ERR_DROP
-
- # test for rx/tx distance
- rcv_vs_tx = d['total-tx']/d['total-rx']
- if ( (rcv_vs_tx >1.2) or (rcv_vs_tx <0.9) ):
- self.reason="rx and tx should be close"
- return self.STATUS_ERR_RX_TX_DISTANCE
-
- # expected measurement
- expect_vs_measued=d['total-tx']/d['expected-bps']
- if ( (expect_vs_measued >1.1) or (expect_vs_measued < 0.9) ) :
- print(expect_vs_measued)
- print(d['total-tx'])
- print(d['expected-bps'])
- self.reason="measure is not as expected"
- return self.STATUS_ERR_BAD_EXPECTED_MEASUREMENT
-
- if ( d['latency-any-error'] !=0 ):
- self.reason=" latency-any-error has error"
- return self.STATUS_ERR_LATENCY_ANY_ERROR
-
- return self.STATUS_OK
-
- # return types
- STATUS_OK = 0
- STATUS_ERR_FATAL = 1
- STATUS_ERR_LATENCY = 2
- STATUS_ERR_DROP = 3
- STATUS_ERR_RX_TX_DISTANCE = 4
- STATUS_ERR_BAD_EXPECTED_MEASUREMENT = 5,
- STATUS_ERR_LATENCY_ANY_ERROR = 6
-
-def test_TRex_result_parser():
- t=CTRexResult('trex.txt');
- t.load_file_lines()
- t.parse()
- print(t.result)
-
-
-
-
-if __name__ == "__main__":
- #test_TRex_result_parser();
- pass
diff --git a/scripts/automation/regression/trex_unit_test.py b/scripts/automation/regression/trex_unit_test.py
index 39984c7d..2a544711 100755
--- a/scripts/automation/regression/trex_unit_test.py
+++ b/scripts/automation/regression/trex_unit_test.py
@@ -399,16 +399,19 @@ class CTRexTestConfiguringPlugin(Plugin):
if not CTRexScenario.trex.check_master_connectivity():
fatal('Could not connect to master daemon')
if options.ga and CTRexScenario.setup_name:
- CTRexScenario.GAManager = GAmanager_Regression(GoogleID = 'UA-75220362-3',
- AnalyticsUserID = CTRexScenario.setup_name,
- QueueSize = 100,
- Timeout = 3, # seconds
- UserPermission = 1,
- BlockingMode = 0,
- appName = 'TRex',
- appVer = CTRexScenario.trex_version)
-
- CTRexScenario.elk = trex_elk.TRexEs('sceasr-b20',9200);
+ CTRexScenario.GAManager = GAmanager_Regression(
+ GoogleID = CTRexScenario.global_cfg['google']['id'],
+ AnalyticsUserID = CTRexScenario.setup_name,
+ QueueSize = CTRexScenario.global_cfg['google']['queue_size'],
+ Timeout = CTRexScenario.global_cfg['google']['timeout'], # seconds
+ UserPermission = 1,
+ BlockingMode = CTRexScenario.global_cfg['google']['blocking'],
+ appName = 'TRex',
+ appVer = CTRexScenario.trex_version)
+
+ CTRexScenario.elk = trex_elk.TRexEs(
+ CTRexScenario.global_cfg['elk']['server'],
+ CTRexScenario.global_cfg['elk']['port']);
self.set_cont_elk_info ()
def set_cont_elk_info (self):