-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
30 changed files
with
14,877 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[submodule "RestApi/Python/RestApi_v2/modules"] | ||
path = RestApi/Python/RestApi_v2/modules | ||
url = https://github.com/OpenIxia/bps_restpy.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
# Title: suite_data_to_csv | ||
# Note:This Python script using the bps_restpy and pytz package (pip install bps_restpy pytz) | ||
# Actions: Exports the suite data to a csv | ||
# 1. Login to BPSQT box | ||
# 2. Based on the QT_SUITE_RUNID get each test result | ||
# 3. Extract aditional data from the bps legacy report for the specific test (REPORT_SECTIONS) | ||
# 4. write all to csv: OUT_RESULTS_CSV | ||
# ================ | ||
|
||
import re | ||
from pytz import timezone | ||
from datetime import datetime, timedelta | ||
from bps_restpy.bps import BPS | ||
|
||
|
||
######################################## | ||
# Demo script global variables | ||
# bps system info | ||
bps_system = '10.36.83.240' # bpsqt system ip | ||
bpsuser = 'admin' # system username | ||
bpspass = 'admin' # system password | ||
|
||
# go to BPSQT suite result that you are interested in | ||
# set QT_SUITE_RUNID to the number found at the end of the link | ||
QT_SUITE_RUNID = '692' # https://<chassisip>/bpse/ui/suites/netsecOpen/runSummary/692 | ||
#sections that should be extracted from BPS legacy report | ||
REPORT_SECTIONS = [ 'Application Response Time', | ||
'Application First Byte Time', | ||
'Connection First Byte Time' | ||
] | ||
#results file output | ||
OUT_RESULTS_CSV = 'QT_NSO_RESULT_ID' + QT_SUITE_RUNID + '.csv' | ||
######################################## | ||
# Login to BPS box | ||
bps = BPS(bps_system, bpsuser, bpspass) | ||
bps.login() | ||
|
||
|
||
def testStart2Date(datestr): | ||
# 'Tue Sep 24 05:27:13 2019' | ||
tmp = datestr.split() | ||
tmp[-2] = '' | ||
tmp = ' '.join(tmp) | ||
date = datetime.strptime(tmp, '%a %b %d %H:%M:%S %Y') | ||
date = timezone('US/Pacific').localize(date) | ||
date = date.astimezone(timezone('UTC')) | ||
return date | ||
|
||
|
||
def suiteStart2Date(datestr): | ||
# "2020-03-12T22:36:26.651-07:00" | ||
tmp = datestr.split('.') | ||
needsAdjustment = re.search(r'\d\d\d[+-](\d\d\:\d\d)',tmp[-1]) | ||
if needsAdjustment: | ||
adjustemntTZ = datetime.strptime(needsAdjustment.group(1), '%H:%M') | ||
# exclude ms and timezone adjutment and set date | ||
tmp = ' '.join(tmp[:-1]) | ||
date = datetime.strptime(tmp, '%Y-%m-%dT%H:%M:%S') | ||
date = date + timedelta(hours=adjustemntTZ.hour, minutes=adjustemntTZ.minute, seconds=0) | ||
date = timezone('UTC').localize(date) | ||
return date | ||
|
||
|
||
def get_reports_data(bps, run_id): | ||
# getReportContents 1st 'IP Summary' section | ||
#'exceptions' | ||
contents = bps.reports.getReportContents(runid=run_id) | ||
report_results = {} | ||
for section_to_get in REPORT_SECTIONS: | ||
for section in contents: | ||
if section['Section Name'] == section_to_get: | ||
print("Report result: %s for runid: %s" % (section, run_id)) | ||
report_results[section_to_get] = bps.reports.getReportTable( | ||
runid=run_id, | ||
sectionId=section['Section ID']) | ||
break | ||
report_results_aggregated = {} | ||
for section in REPORT_SECTIONS: | ||
report_results_aggregated[section] = get_aggregated_value(report_results[section]) | ||
|
||
return report_results_aggregated | ||
|
||
#compute min/max and avg for given report table() and last sustain in minutes | ||
def get_aggregated_value(report_stat_data, sustain_duration=9, rampdown_duration=5): | ||
# ex : report_results['Application Response Time'] is: | ||
# [{u'Timestamp': [...]}, {u'Average Response Time': [...]}, {u'Instantaneous Response Time': [...]}] | ||
#get sustain index | ||
time_samples = report_stat_data[0]['Timestamp'] | ||
sustain_start_time = float(time_samples[-1]) - (60 * sustain_duration) - (60 * rampdown_duration) | ||
sustain_last_time = float(time_samples[-1]) - (60 * rampdown_duration) | ||
for sustain__start_index, val in enumerate(time_samples): | ||
if float(val) > sustain_start_time: | ||
break | ||
for sustain_end_index, val in enumerate(time_samples): | ||
if float(val) > sustain_last_time: | ||
break | ||
table_collumn_name = list(report_stat_data[2].keys())[0] | ||
measurements = report_stat_data[2][table_collumn_name][sustain__start_index:sustain_end_index] | ||
measurements = [float(y.strip('~')) for y in measurements] | ||
try: | ||
return_val = [min(measurements), average(measurements), max(measurements)] | ||
except ValueError as e: | ||
print('Problems when calculating average : %s' % str(e)) | ||
return_val = ['Err', 'Err', 'Err'] | ||
return return_val | ||
|
||
|
||
def average(lst): | ||
return sum(y for y in lst)/len(lst) | ||
|
||
|
||
def get_app_times(testname, suiteStartTime, suiteDuration): | ||
suite_start_date = suiteStart2Date(suiteStartTime) | ||
suite_duration_date = datetime.strptime(suiteDuration, '%H:%M:%S') | ||
suite_end_date = suite_start_date + \ | ||
timedelta(hours=suite_duration_date.hour, minutes=suite_duration_date.minute) | ||
# query the last 200 bps results matching the test name | ||
results = bps.reports.search( | ||
searchString=testname, limit=200, sort='startTime', sortorder='descending') | ||
for result in results: | ||
if not result['startTime']: | ||
continue | ||
test_start_date = testStart2Date(result['startTime']) | ||
print ("Test Date : %s Suite : %s <-> %s" % (test_start_date.strftime('%Y-%m-%dT%H:%M:%S'), | ||
suite_start_date.strftime('%Y-%m-%dT%H:%M:%S'), | ||
suite_end_date.strftime('%Y-%m-%dT%H:%M:%S') | ||
) | ||
) | ||
if test_start_date >= suite_start_date and test_start_date <= suite_end_date: | ||
avg_timings = get_reports_data(bps, result['runid']) | ||
break | ||
return avg_timings | ||
################################# | ||
|
||
|
||
|
||
#Using a GET request to obtain the status of the suite | ||
|
||
params = {'responseDepth': '4'} | ||
url = 'https://' + bps_system +'/bpse/api/v2/results/' + QT_SUITE_RUNID | ||
r = bps.session.get(url, params=params) | ||
if not r.status_code == 200: | ||
raise Exception('Failed to get results for suite id: %s returned %s' % (QT_SUITE_RUNID, r.contents)) | ||
suite = r.json() | ||
csv_handle = open(OUT_RESULTS_CSV, 'w+') | ||
head_line_csv = ",".join([suite['suite'], | ||
'startDate:' + suite['startDate'] +' duration:' + suite['duration'], | ||
suite['state'], | ||
suite['id'] | ||
]) | ||
head_line_csv = head_line_csv + ',' + ' min,avg,max,'.join(REPORT_SECTIONS) | ||
print(head_line_csv) | ||
csv_handle.write(head_line_csv + '\n') | ||
suiteStartTime = suite['startDate'] | ||
suiteDuration = suite['duration'] | ||
for category in suite['categories']: | ||
print(category['category']) | ||
csv_handle.write(category['category'] + '\n') | ||
for test in category['tests']: | ||
if test['state'] == 'Skipped': | ||
continue | ||
match = re.search(r'achieved\s(\d*)', test['goals'][0]['result']) | ||
val = 'x' | ||
if match: | ||
val = match.group(1) | ||
durations = get_app_times(test['name'], suiteStartTime, suiteDuration) | ||
test_csv_line = ", ".join([test['test'], test['grading']['description'], val, test['goals'][0]['units']]) | ||
for section in REPORT_SECTIONS: | ||
if section in REPORT_SECTIONS: | ||
try: | ||
durations_to_strings = ['%.2f' % d for d in durations[section]] | ||
except TypeError: | ||
durations_to_strings = durations[section] | ||
test_csv_line = test_csv_line + ',' + ','.join(durations_to_strings) | ||
else: | ||
test_csv_line = test_csv_line + ',' + ','.join(['0', '0', '0']) | ||
print(test_csv_line) | ||
csv_handle.write(test_csv_line + '\n') | ||
csv_handle.close() | ||
|
||
# logout bps session | ||
print("Session logout") | ||
bps.logout() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# MIT LICENSE | ||
# | ||
# Copyright 1997 - 2019 by IXIA Keysight | ||
# | ||
# Permission is hereby granted, free of charge, to any person obtaining a copy | ||
# of this software and associated documentation files (the "Software"), | ||
# to deal in the Software without restriction, including without limitation | ||
# the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
# and/or sell copies of the Software, and to permit persons to whom the | ||
# Software is furnished to do so, subject to the following conditions: | ||
# | ||
# The above copyright notice and this permission notice shall be included in | ||
# all copies or substantial portions of the Software. | ||
# | ||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
# THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
include LICENSE | ||
include README.md | ||
include RELEASENOTES.md | ||
include setup.py | ||
include version.txt | ||
recursive-include bps_restpy *.py | ||
recursive-include bps_restpy *.bpt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
## The BreakingPoint RESTv2 API Python Wrapper | ||
[![pypi](https://img.shields.io/pypi/v/bps-restpy.svg)](https://pypi.org/project/bps-restpy) | ||
[![python](https://img.shields.io/pypi/pyversions/bps-restpy.svg)](https://pypi.python.org/pypi/bps-restpy) | ||
[![license](https://img.shields.io/badge/license-MIT-green.svg)](https://en.wikipedia.org/wiki/MIT_License) | ||
[![downloads](https://pepy.tech/badge/bps-restpy)](https://pepy.tech/project/bps-restpy) | ||
|
||
## BreakingPoint detail | ||
Network testing with [BreakingPoint®](https://www.ixiacom.com/products/network-security-testing-breakingpoint). By simulating real-world legitimate traffic, distributed denial of service (DDoS), exploits, malware, and fuzzing, BreakingPoint validates an organization’s security infrastructure, reduces the risk of network degradation by almost 80%, and increases attack readiness by nearly 70%. And with our new TrafficREWIND solution, you'll get even more realistic and high-fidelity validation by adding production network insight into BreakingPoint test traffic configuration | ||
More details: | ||
|
||
## Install the package | ||
``` | ||
pip install --upgrade bps-restpy | ||
``` | ||
|
||
## Start scripting | ||
```python | ||
"""This script demonstrates how to get started with bps_restpy scripting. | ||
# Title: Python Script Sample To Run a Canned Test. | ||
# Actions: | ||
# 1. Login to BPS box | ||
# 2. Reserve ports | ||
# 3. Load a test from the box and start the run | ||
# 4. Wait for the test to finish | ||
# 5. Get test result | ||
# 6. Get and print the Synopsis page from report | ||
# 7. Unreserve ports | ||
# 8. Logout | ||
#================ | ||
######################################## | ||
import time, sys, os | ||
# Import corresponding BPS RESTv2 python2.7/ 3 library from outside the folder with samples. | ||
sys.path.insert(1, os.path.dirname(os.getcwd())) | ||
from bps_restpy.bps import BPS, pp | ||
######################################## | ||
######################################## | ||
# Demo script global variables | ||
######################################## | ||
# Demo script global variables | ||
canned_test_name = 'AppSim' | ||
#bps system info | ||
bps_system = '<BPS_BOX_IP/HOSTNAME>' | ||
bpsuser = 'bps user' | ||
bpspass = 'bps pass' | ||
slot_number = 2 | ||
port_list = [0, 1] | ||
######################################## | ||
######################################## | ||
# Login to BPS box | ||
bps = BPS(bps_system, bpsuser, bpspass) | ||
bps.login() | ||
######################################## | ||
print("Load a canned test: ") | ||
bps.testmodel.load(canned_test_name) | ||
######################################## | ||
print("Reserve Ports") | ||
for p in port_list: | ||
bps.topology.reserve([{'slot': slot_number, 'port': p, 'group': 2}]) | ||
######################################## | ||
print("Run test and Get Stats:") | ||
test_id_json = bps.testmodel.run(modelname=canned_test_name, group=2) | ||
testid = str( test_id_json["runid"] ) | ||
run_id = 'TEST-' + testid | ||
print("Test Run Id: %s"%run_id) | ||
#get the ids for all tests running on the chassis | ||
runningTests_Ids = [test['id'] for test in bps.topology.runningTest.get()] | ||
#wait while the test is still running | ||
while run_id in runningTests_Ids: | ||
run_state = bps.topology.runningTest[run_id].get() | ||
#print progress if test started | ||
try: print ('progress: %s%% , runtime %ss' % (run_state['progress'], run_state['runtime'] )) | ||
except: print ("Starting...") | ||
time.sleep(2) | ||
#update the current running tests | ||
runningTests_Ids = [test['id'] for test in bps.topology.runningTest.get()] | ||
print("~The test finished the execution.") | ||
results = bps.reports.search(searchString=canned_test_name, limit=10, sort="endTime", sortorder="descending") | ||
result = results[0] | ||
print ("%s execution duration %s ended with status: %s " % (result['name'], result['duration'], result['result']) ) | ||
#getting 3.4 Section: Synopsys Summary of Results from the Report | ||
tabledata = bps.reports.getReportTable(runid=testid, sectionId="3.4") | ||
pp(tabledata) | ||
print ("Unreserving the ports") | ||
for p in port_list: | ||
bps.topology.unreserve([{'slot': slot_number, 'port': p, 'group': 2}]) | ||
bps.logout() | ||
``` | ||
wew | ||
## Documentation | ||
Documentation is available using the following methods: | ||
* [Online web based documentation and samples](https://github.com/OpenIxia/BreakingPoint) | ||
* On your BreakingPoint System RestApi found near the BreakingPoint App | ||
* Documentation available in the online doc browser is also inlined in each class, property and method and can be viewed using the python help command | ||
```python | ||
from bps_restpy.bps import BPS, pp | ||
#login to your Breaking Point System | ||
help(BPS) | ||
bps = BPS('your_bps_IP_or_FQDN', 'admin', 'admin') | ||
help(bps.testmodel.importModel) | ||
``` | ||
## Additional Samples | ||
Visit the [OpenIxia breakingpoint-restpy sample site maintained by solution architects](https://github.com/OpenIxia/BreakingPoint) for in depth end-to-end samples that demonstrate the following: | ||
* building a configuration | ||
* from scratch | ||
* from an existing BreakingPoint configuration | ||
* running the configuration | ||
* connecting ports to hardware | ||
* starting protocols | ||
* starting traffic | ||
* getting statistics | ||
* port stats | ||
* traffic stats | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Release Notes | ||
|
||
### Nov 2019 | ||
* 1.0.1 | ||
* Add BreakingPoint RESTv2 Python Wraper library and samples. (supported from BreakingPoint Release 9.0 Update2 +) | ||
* Support for older versions and BreakingPoint RESTv1 API library files can be foudn in the build |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
""" | ||
# MIT LICENSE | ||
# | ||
# Copyright 1997 - 2019 by IXIA Keysight | ||
# | ||
# Permission is hereby granted, free of charge, to any person obtaining a copy | ||
# of this software and associated documentation files (the "Software"), | ||
# to deal in the Software without restriction, including without limitation | ||
# the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
# and/or sell copies of the Software, and to permit persons to whom the | ||
# Software is furnished to do so, subject to the following conditions: | ||
# | ||
# The above copyright notice and this permission notice shall be included in | ||
# all copies or substantial portions of the Software. | ||
# | ||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
# THE SOFTWARE. | ||
*Created with Breaking Point build : 9.00v9.00.108.12""" | ||
import sys,os | ||
#sys.path.insert(0,os.path.abspath(__file__+"/../..")) | ||
if sys.version_info[0] >= 3: | ||
from .restPyWrapper3 import BPS, pp | ||
else: | ||
from .restPyWrapper import BPS, pp |
Empty file.
Oops, something went wrong.