Merge /home/greearb/btbits/x64_btbits/server/lf_scripts

This commit is contained in:
Ben Greear
2020-12-10 08:02:41 -08:00
29 changed files with 2210 additions and 664 deletions

View File

@@ -57,7 +57,11 @@ if (-f "$fname") {
open(FILE, ">$fname") or die "Couldn't open file: $fname for writing: $!\n\n";
my $foundit = 0;
my $i;
chomp(@lines);
# chomp is way to simplistic if we need to weed out \r\n characters as well
#chomp(@lines);
for( my $i=0; $i < @lines; $i++) {
($lines[$i]) = $lines[$i] =~ /^([^\r\n]+)\r?\n$/;
}
# we want to consolidate the $ip $hostname entry for MgrHostname
my @newlines = ();
my %more_hostnames = ();
@@ -65,7 +69,10 @@ if (-f "$fname") {
#my $blank = 0;
#my $was_blank = 0;
my $counter = 0;
my $debug = 1;
my $debug = 0;
if ((exists $ENV{"DEBUG"}) && ($ENV{"DEBUG"} eq "1")) {
$debug = 1;
}
my %host_map = (
"localhost.localdomain" => "127.0.0.1",
"localhost" => "127.0.0.1",
@@ -79,6 +86,8 @@ if (-f "$fname") {
"lanforge.localnet" => "192.168.1.101",
"lanforge.localdomain" => "192.168.1.101",
);
my %comment_map = ();
my %address_marker_map = ();
my %address_map = (
"127.0.0.1" => "localhost.localdomain localhost localhost4.localdomain4 localhost4",
"::1" => "localhost.localdomain localhost localhost6.loaldomain6 localhost6",
@@ -94,17 +103,27 @@ if (-f "$fname") {
my $previp = "";
for my $ln (@lines) {
next if (!(defined $ln));
print "\nLN[$ln]\n" if ($debug);
next if ($ln =~ /^\s*$/);
next if ($ln =~ /^\s*#/);
next if ($ln =~ /^###-LF-HOSTAME-NEXT-###/); # old typo
next if ($ln =~ /^###-LF-HOSTNAME-NEXT-###/);
my $comment = undef;
print "PARSING IPv4 ln[$ln]\n" if ($debug);
if ($ln =~ /#/) {
($comment) = $ln =~ /^[^#]+(#.*)$/;
($ln) = $ln =~ /^([^#]+)\s*#/;
print "line with comment becomes [$ln]\n" if ($debug);
}
@hunks = split(/\s+/, $ln);
my $middleip = 0;
my $counter2 = -1;
my $linehasip = 0;
my $lfhostname = 0;
if ((defined $comment) && ($comment ne "")) {
$comment_map{$hunks[0]} = $comment;
}
for my $hunk (@hunks) {
print "\n HUNK",$counter2,"-:$hunk:- " if ($debug);
$counter2++;
@@ -207,6 +226,7 @@ if (-f "$fname") {
print "NEWSTUFF $ip $address_map{$ip}\n" if ($debug);
}
# this might be premature
unshift(@newlines, "192.168.1.101 ".$address_map{"192.168.1.101"});
unshift(@newlines, "127.0.0.1 ".$address_map{"127.0.0.1"});
unshift(@newlines, "::1 ".$address_map{"::1"});
@@ -215,29 +235,74 @@ if (-f "$fname") {
delete($address_map{"127.0.0.1"});
delete($address_map{"::1"});
print Dumper(\%address_map) if ($debug);
print Dumper(\%host_map) if ($debug);
for my $key (sort keys %address_map){
next if ($key eq $ip);
if ($address_map{$key} =~ /\s*$MgrHostname\s*/) {
print("SKIPPING $key / $address_map{$key}\n")
if ($debug);
if ($debug) {
print "# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----\n";
print "\nAddress map\n";
print Dumper(\%address_map);
print "\nHost map\n";
print Dumper(\%host_map);
print "# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----\n";
sleep 2;
}
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
# we want to maintain the original line ordering as faithfully as possible
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
for my $ln (@lines) {
$ln = "" if (!(defined $ln));
print "OLD[$ln]\n" if ($debug);
# if we are comments or blank lines, preserve them
if (($ln =~ /^\s*$/) || ($ln =~ /^\s*#/)) {
push(@newlines, $ln);
next;
}
push(@newlines, $key." ".$address_map{$key});
@hunks = split(/\s+/, $ln);
if (exists $address_map{$hunks[0]}) {
if (exists $address_marker_map{$hunks[0]}) {
print "already printed $hunks[0]\n" if ($debug);
next;
}
my $comment = "";
if (exists $comment_map{$hunks[0]}) {
$comment = " $comment_map{$hunks[0]}";
}
push(@newlines, "$hunks[0] $address_map{$hunks[0]}$comment");
$address_marker_map{$hunks[0]} = 1;
next;
}
else {
die("unknown IP $hunks[0]");
}
}
if ($debug) {
print "# ----- NEW ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----\n";
for my $ln (@newlines) {
print "$ln\n";
}
}
#for my $key (sort keys %address_map){
# next if ($key eq $ip);
# if ($address_map{$key} =~ /\s*$MgrHostname\s*/) {
# print("SKIPPING $key / $address_map{$key}\n")
# if ($debug);
# next;
# }
# push(@newlines, $key." ".$address_map{$key});
#}
push(@newlines, "###-LF-HOSTNAME-NEXT-###");
push(@newlines, $ip." ".$address_map{$ip});
print Dumper(\@newlines) if ($debug);
sleep 5 if ($debug);
if ($debug) {
print Dumper(\@newlines);
sleep 5;
}
for my $ln (@newlines) {
print FILE "$ln\n";
}
print FILE "\n";
close FILE;
}
} # ~if found file
my $local_crt ="";
my $local_key ="";

61
check_large_files.sh Executable file
View File

@@ -0,0 +1,61 @@
#!/bin/bash
set -x
set -e
eyedee=`id -u`
if (( eyedee != 0 )); then
echo "Please become root to use this script"
exit 1
fi
# Find core files
core_files=()
cd /
while read F; do
core_files+=("$F")
done < <(ls /core* /home/lanforge/core* 2>/dev/null)
# Find ath10k crash residue
ath10_files=()
while read F; do
ath10_files+=("$F")
done < <(ls /home/lanforge/ath10* 2>/dev/null)
# Find size of /mnt/lf that is not mounted
cd /mnt
usage_mnt=`du -shxc .`
# Find size of /lib/modules
cd /lib/modules
usage_libmod=`du -sh *`
# Find how many kernels are installed
cd /boot
boot_kernels=(`ls init*`)
boot_usage=`du -sh .`
HR="---------------------------------------"
# #
# report sizes here #
# #
if (( ${#core_files[@]} > 0 )); then
echo "Core Files:"
echo "$HR"
printf '%s\n' "${core_files[@]}"
echo "$HR"
fi
echo "Usage of /mnt: $usage_mnt"
echo "Usage of /lib/modules: $usage_libmod"
echo "Boot usage: $boot_usage"
if (( ${#boot_kernels[@]} > 4 )); then
echo "Boot ramdisks:"
echo "$HR"
printf '%s\n' "${boot_kernels[@]}"
echo "$HR"
fi
# delete extra things now #
# remove

View File

@@ -36,13 +36,23 @@ class LFRequest:
else:
self.requested_url = url
if self.requested_url is None:
raise Exception("Bad LFRequest of url[%s] uri[%s] -> None" % url, uri)
if self.requested_url.find('//'):
protopos = self.requested_url.find("://")
self.requested_url = self.requested_url[:protopos + 2] + self.requested_url[protopos + 2:].replace("//", "/")
# finding '#' prolly indicates a macvlan (eth1#0)
# finding ' ' prolly indicates a field name that should imply %20
if (self.requested_url.find('#') >= 1):
self.requested_url = self.requested_url.replace('#', '%23')
if (self.requested_url.find(' ') >= 1):
self.requested_url = self.requested_url.replace(' ', '+')
if self.debug:
print("new LFRequest[%s]" % self.requested_url )
if self.requested_url is None:
raise Exception("Bad LFRequest of url[%s] uri[%s] -> None" % url, uri)
# request first url on stack
def formPost(self, show_error=True, debug=False, die_on_error_=False):
@@ -105,7 +115,7 @@ class LFRequest:
def jsonPost(self, show_error=True, debug=False, die_on_error_=False, response_json_list_=None):
return self.json_post(show_error=show_error, debug=debug, die_on_error_=die_on_error_, response_json_list_=response_json_list_)
def json_post(self, show_error=True, debug=False, die_on_error_=False, response_json_list_=None):
def json_post(self, show_error=True, debug=False, die_on_error_=False, response_json_list_=None, method_='POST'):
if (debug == False) and (self.debug == True):
debug = True
if self.die_on_error:
@@ -113,6 +123,7 @@ class LFRequest:
responses = []
if ((self.post_data != None) and (self.post_data is not self.No_Data)):
request = urllib.request.Request(url=self.requested_url,
method=method_,
data=json.dumps(self.post_data).encode("utf-8"),
headers=self.default_headers)
else:
@@ -124,7 +135,7 @@ class LFRequest:
resp = urllib.request.urlopen(request)
resp_data = resp.read().decode('utf-8')
if (debug):
print("----- LFRequest::jsonPost:118 debug: --------------------------------------------")
print("----- LFRequest::json_post:128 debug: --------------------------------------------")
print("URL: %s :%d "% (self.requested_url, resp.status))
LFUtils.debug_printer.pprint(resp.getheaders())
print("----- resp_data -------------------------------------------------")
@@ -136,15 +147,15 @@ class LFRequest:
raise ValueError("reponse_json_list_ needs to be type list")
j = json.loads(resp_data)
if debug:
print("----- LFRequest::jsonPost:129 debug: --------------------------------------------")
print("----- LFRequest::json_post:140 debug: --------------------------------------------")
LFUtils.debug_printer.pprint(j)
print("-------------------------------------------------")
response_json_list_.append(j)
return responses[0]
except urllib.error.HTTPError as error:
if show_error or die_on_error_ or (error.code != 404):
print("----- LFRequest::jsonPost:138 HTTPError: --------------------------------------------")
print("<%s> HTTP %s: %s"%(request.get_full_url(), error.code, error.reason, ))
print("----- LFRequest::json_post:147 HTTPError: --------------------------------------------")
print("<%s> HTTP %s: %s" % (request.get_full_url(), error.code, error.reason ))
print("Error: ", sys.exc_info()[0])
print("Request URL:", request.get_full_url())
@@ -167,21 +178,35 @@ class LFRequest:
exit(1)
except urllib.error.URLError as uerror:
if show_error:
print("----- LFRequest::jsonPost:162 URLError: ---------------------------------------------")
print("----- LFRequest::json_post:171 URLError: ---------------------------------------------")
print("Reason: %s; URL: %s"%(uerror.reason, request.get_full_url()))
print("------------------------------------------------------------------------")
if (die_on_error_ == True) or (self.die_on_error == True):
exit(1)
return None
def get(self, debug=False, die_on_error_=False):
def json_put(self, show_error=True, debug=False, die_on_error_=False, response_json_list_=None):
return self.json_post(show_error=show_error,
debug=debug,
die_on_error_=die_on_error_,
response_json_list_=response_json_list_,
method_='PUT')
def json_delete(self, show_error=True, debug=False, die_on_error_=False, response_json_list_=None):
return self.get_as_json(debug_=debug,
die_on_error_=die_on_error_,
method_='DELETE')
def get(self, debug=False, die_on_error_=False, method_='GET'):
if self.debug == True:
debug = True
if self.die_on_error == True:
die_on_error_ = True
if debug:
print("LFUtils.get: url: "+self.requested_url)
myrequest = urllib.request.Request(url=self.requested_url, headers=self.default_headers)
myrequest = urllib.request.Request(url=self.requested_url,
headers=self.default_headers,
method=method_)
myresponses = []
try:
myresponses.append(urllib.request.urlopen(myrequest))
@@ -223,9 +248,9 @@ class LFRequest:
def getAsJson(self, die_on_error_=False, debug_=False):
return self.get_as_json(die_on_error_=die_on_error_, debug_=debug_)
def get_as_json(self, die_on_error_=False, debug_=False):
def get_as_json(self, die_on_error_=False, debug_=False, method_='GET'):
responses = []
j = self.get(debug=debug_, die_on_error_=die_on_error_)
j = self.get(debug=debug_, die_on_error_=die_on_error_, method_=method_)
responses.append(j)
if len(responses) < 1:
return None

View File

@@ -281,16 +281,16 @@ def port_name_series(prefix="sta", start_id=0, end_id=1, padding_number=10000, r
"""
eid = None
if radio != None:
if radio is not None:
eid = name_to_eid(radio)
name_list = []
for i in range((padding_number + start_id), (padding_number + end_id + 1)):
sta_name = prefix + str(i)[1:]
if eid != None:
name_list.append("%i.%i.%s"%(eid[0], eid[1], sta_name))
else:
sta_name = "%s%s" % (prefix, str(i)[1:])
if eid is None:
name_list.append(sta_name)
else:
name_list.append("%i.%i.%s" % (eid[0], eid[1], sta_name))
return name_list
@@ -543,7 +543,7 @@ def wait_until_ports_appear(base_url="http://localhost:8080", port_list=(), debu
found_stations.append(port_name)
else:
lf_r = LFRequest.LFRequest(base_url, ncshow_url)
lf_r.addPostData({"shelf": shelf, "resource": resource_id, "port": port_name, "probe_flags": "1"})
lf_r.addPostData({"shelf": shelf, "resource": resource_id, "port": port_name, "probe_flags": 5})
lf_r.jsonPost()
if (len(found_stations) < len(port_list)):
sleep(2)

View File

@@ -1,16 +1,23 @@
#!env /usr/bin/python
import sys
import signal
import traceback
# Extend this class to use common set of debug and request features for your script
from pprint import pprint
import time
import LANforge.LFUtils
from LANforge.LFUtils import *
import argparse
from LANforge import LFRequest
import LANforge.LFRequest
class LFCliBase:
SHOULD_RUN = 0 # indicates normal operation
SHOULD_QUIT = 1 # indicates to quit loops, close files, send SIGQUIT to threads and return
SHOULD_HALT = 2 # indicates to quit loops, send SIGABRT to threads and exit
# do not use `super(LFCLiBase,self).__init__(self, host, port, _debug)
# that is py2 era syntax and will force self into the host variable, making you
# very confused.
@@ -19,7 +26,8 @@ class LFCliBase:
_halt_on_error=False,
_exit_on_error=False,
_exit_on_fail=False,
_local_realm=False):
_local_realm=False,
_capture_signal_list=[]):
self.fail_pref = "FAILED: "
self.pass_pref = "PASSED: "
self.lfclient_host = _lfjson_host
@@ -33,12 +41,110 @@ class LFCliBase:
self.halt_on_error = _halt_on_error
self.exit_on_error = _exit_on_error
self.exit_on_fail = _exit_on_fail
self.capture_signals = _capture_signal_list
# toggle using preexec_cli, preexec_method; the preexec_X parameters are useful
# when you desire the lfclient to check for existance of entities to run commands on,
# like when developing; you might toggle this with use_preexec = _debug
# Otherwise, preexec methods use more processing time because they add an extra CLI call
# into the queue, and inspect it -- typically nc_show_port
self.suppress_related_commands = None
self.finish = self.SHOULD_RUN
self.thread_map = {}
if len(_capture_signal_list) > 0:
for zignal in _capture_signal_list:
captured_signal(zignal, my_captured_signal)
#
def _finish(self):
"""
call this to indicate SIGQUIT
"""
self.finish = self.SHOULD_QUIT
def _halt(self):
"""
call this to indicate SIGABRT
"""
self.finish = self.SHOULD_HALT
def _should_finish(self):
"""
check this when in a run loop if SIGQUIT has been indicated
"""
if self.finish == self.SHOULD_RUN:
return False
if self.finish == self.SHOULD_QUIT:
return True
if self.finish == self.SHOULD_HALT:
return False
def _should_halt(self):
"""
check this when in a run loop if SIGABRT has been indicated
"""
if self.finish == self.SHOULD_RUN:
return False
if self.finish == self.SHOULD_QUIT:
return False
if self.finish == self.SHOULD_HALT:
return True
def track_thread(self, name, thread):
if self.thread_map is None:
self.thread_map = {}
self.thread_map[name] = thread
def get_thread(self, name):
if self.thread_map is None:
return None
if name in self.thread_map.keys():
return self.thread_map[name]
return None
def remove_thread(self, name):
if self.thread_map is None:
return None
if name not in self.thread_map.keys():
return None
thrud = self.thread_map[name]
del self.thread_map[name]
return thrud
def send_thread_signals(signum, fname):
if len(self.thread_map) < 1:
print("no threads to signal")
return
for (name, thread) in self.thread_map.items():
if self.debug:
print("sending signal %s to thread %s" % (signum, name))
# do a thing
def my_captured_signal(signum, frame):
"""
Override me to process signals, otherwise superclass signal handler is called.
You may use _finish() or _halt() to indicate finishing soon or halting immediately.
:return: True if we processed this signal
"""
print("my_captured_signal should be overridden")
return False
def caputured_signal(signum):
"""
Here is your opportunity to decide what to do on things like KeyboardInterrupt or other UNIX signals
Check that your subclass handled the signal or not. You may use _finish() or _halt() to indicate
finishing soon or halting immediately. Use signal.signal(signal.STOP) to enable this.
"""
if self.debug:
print("Captured signal %s" % signum)
if my_captured_signal(signum):
if self.debug:
print("subclass processed signal")
else:
if self.debug:
print("subclass ignored signal")
def clear_test_results(self):
self.test_results.clear()
@@ -87,22 +193,55 @@ class LFCliBase:
pprint.pprint(response_json_list_)
except Exception as x:
if self.debug or self.halt_on_error or self.exit_on_error:
print("jsonPost posted to %s" % _req_url)
print("json_post posted to %s" % _req_url)
pprint.pprint(_data)
print("Exception %s:" % x)
traceback.print_exception(Exception, x, x.__traceback__, chain=True)
if self.halt_on_error or self.exit_on_error:
exit(1)
return json_response
def json_put(self, _req_url, _data, debug_=False, response_json_list_=None):
"""
Send a PUT request. This is presently used for data sent to /status-msg for
creating a new messaging session. It is not presently used for CLI scripting
so lacks suppress_x features.
:param _req_url: url to put
:param _data: data to place at URL
:param debug_: enable debug output
:param response_json_list_: array for json results in the response object, (alternative return method)
:return: http response object
"""
json_response = None
try:
lf_r = LFRequest.LFRequest(self.lfclient_url, _req_url, debug_=self.debug, die_on_error_=self.exit_on_error)
lf_r.addPostData(_data)
if debug_ or self.debug:
LANforge.LFUtils.debug_printer.pprint(_data)
json_response = lf_r.json_put(show_error=self.debug,
debug=(self.debug or debug_),
response_json_list_=response_json_list_,
die_on_error_=self.exit_on_error)
if debug_ and (response_json_list_ is not None):
pprint.pprint(response_json_list_)
except Exception as x:
if self.debug or self.halt_on_error or self.exit_on_error:
print("json_put submitted to %s" % _req_url)
pprint.pprint(_data)
print("Exception %s:" % x)
traceback.print_exception(Exception, x, x.__traceback__, chain=True)
if self.halt_on_error or self.exit_on_error:
exit(1)
return json_response
def json_get(self, _req_url, debug_=False):
if self.debug or debug_:
print("URL: "+_req_url)
print("GET: "+_req_url)
json_response = None
# print("----- GET ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ")
try:
lf_r = LFRequest.LFRequest(self.lfclient_url, _req_url, debug_=(self.debug or debug_), die_on_error_=self.exit_on_error)
json_response = lf_r.getAsJson(debug_=self.debug, die_on_error_=self.halt_on_error)
json_response = lf_r.get_as_json(debug_=self.debug, die_on_error_=self.halt_on_error)
#debug_printer.pprint(json_response)
if (json_response is None) and (self.debug or debug_):
print("LFCliBase.json_get: no entity/response, probabily status 404")
@@ -117,6 +256,31 @@ class LFCliBase:
return json_response
def json_delete(self, _req_url, debug_=False):
if self.debug or debug_:
print("DELETE: "+_req_url)
json_response = None
try:
# print("----- DELETE ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ")
lf_r = LFRequest.LFRequest(self.lfclient_url, _req_url,
debug_=(self.debug or debug_),
die_on_error_=self.exit_on_error)
json_response = lf_r.json_delete(debug=self.debug,
die_on_error_=self.halt_on_error)
#debug_printer.pprint(json_response)
if (json_response is None) and (self.debug or debug_):
print("LFCliBase.json_delete: no entity/response, probabily status 404")
return None
except ValueError as ve:
if self.debug or self.halt_on_error or self.exit_on_error:
print("json_delete asked for " + _req_url)
print("Exception %s:" % ve)
traceback.print_exception(ValueError, ve, ve.__traceback__, chain=True)
if self.halt_on_error or self.exit_on_error:
sys.exit(1)
# print("----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ")
return json_response
@staticmethod
def response_list_to_map(json_list, key, debug_=False):
reverse_map = {}
@@ -172,10 +336,11 @@ class LFCliBase:
if duration >= 300:
print("Could not connect to LANforge GUI")
sys.exit(1)
#return ALL messages in list form
def get_result_list(self):
return self.test_results
#return ALL fail messages in list form
def get_failed_result_list(self):
fail_list = []
for result in self.test_results:
@@ -183,13 +348,29 @@ class LFCliBase:
fail_list.append(result)
return fail_list
#return ALL pass messages in list form
def get_passed_result_list(self):
pass_list = []
for result in self.test_results:
if result.startswith("PASS"):
pass_list.append(result)
return pass_list
def get_pass_message(self):
pass_messages = self.get_passed_result_list()
return "\n".join(pass_messages)
def get_fail_message(self):
fail_messages = self.get_failed_result_list()
return "\n".join(fail_messages)
def get_all_message(self):
return "\n".join(self.test_results)
#determines if overall test passes via comparing passes vs. fails
def passes(self):
pass_counter = 0
fail_counter = 0
@@ -202,7 +383,15 @@ class LFCliBase:
return True
return False
# use this inside the class to log a failure result
#EXIT script with a fail
def exit_fail(self,message="%d out of %d tests failed. Exiting script."):
total_len=len(self.get_result_list())
fail_len=len(self.get_failed_result_list())
print(message %(fail_len,total_len))
sys.exit(1)
# use this inside the class to log a failure result and print it if wished
def _fail(self, message, print_=False):
self.test_results.append(self.fail_pref + message)
if print_ or self.exit_on_fail:
@@ -210,7 +399,15 @@ class LFCliBase:
if self.exit_on_fail:
sys.exit(1)
# use this inside the class to log a pass result
#EXIT script with a success
def exit_success(self,message="%d out of %d tests passed successfully. Exiting script."):
num_total=len(self.get_result_list())
num_passing=len(self.get_passed_result_list())
print(message %(num_passing,num_total))
sys.exit(0)
# use this inside the class to log a pass result and print if wished.
def _pass(self, message, print_=False):
self.test_results.append(self.pass_pref + message)
if print_:
@@ -249,7 +446,7 @@ class LFCliBase:
parser.add_argument('--radio', help='radio EID, e.g: 1.wiphy2', default=None)
parser.add_argument('--security', help='WiFi Security protocol: <open | wep | wpa | wpa2 | wpa3 >', default=None)
parser.add_argument('--ssid', help='SSID for stations to associate to', default=None)
parser.add_argument('--passwd', '--passphrase', '--password', '--pwd', help='WiFi passphrase', default=None)
parser.add_argument('--passwd', help='WiFi passphrase', default=None)
parser.add_argument('--num_stations', help='Number of stations to create', default=0)
parser.add_argument('--test_id', help='Test ID (intended to use for ws events)', default="webconsole")
parser.add_argument('--debug', help='Enable debugging', default=False, action="store_true")

View File

@@ -370,7 +370,7 @@ class Realm(LFCliBase):
# Returns map of all stations with port+type == WIFI-STATION
def station_map(self):
response = super().json_get("/port/list?fields=_links,alias,device,port+type")
response = super().json_get("/port/list?fields=port,_links,alias,device,port+type")
if (response is None) or ("interfaces" not in response):
pprint(response)
print("station_list: incomplete response, halting")
@@ -554,6 +554,52 @@ class Realm(LFCliBase):
return not wait_more
def get_curr_num_ips(self,num_sta_with_ips=0,station_list=None, ipv4=True, ipv6=False, debug=False):
print("checking number of stations with ips...")
waiting_states = ["0.0.0.0", "NA", ""]
if (station_list is None) or (len(station_list) < 1):
raise ValueError("check for num curr ips expects non-empty list of ports")
for sta_eid in station_list:
if debug:
print("checking sta-eid: %s"%(sta_eid))
eid = self.name_to_eid(sta_eid)
response = super().json_get("/port/%s/%s/%s?fields=alias,ip,port+type,ipv6+address" %
(eid[0], eid[1], eid[2]))
if debug:
pprint(response)
if (response is None) or ("interface" not in response):
print("station_list: incomplete response:")
pprint(response)
#wait_more = True
break
if ipv4:
v = response['interface']
if (v['ip'] in waiting_states):
if debug:
print("Waiting for port %s to get IPv4 Address."%(sta_eid))
else:
if debug:
print("Found IP: %s on port: %s"%(v['ip'], sta_eid))
print("Incrementing stations with IP addresses found")
num_sta_with_ips+=1
else:
num_sta_with_ips+=1
if ipv6:
v = response['interface']
if (v['ip'] in waiting_states):
if debug:
print("Waiting for port %s to get IPv6 Address."%(sta_eid))
else:
if debug:
print("Found IP: %s on port: %s"%(v['ip'], sta_eid))
print("Incrementing stations with IP addresses found")
num_sta_with_ips+=1
else:
num_sta_with_ips+=1
return num_sta_with_ips
def duration_time_to_seconds(self, time_string):
if isinstance(time_string, str):
pattern = re.compile("^(\d+)([dhms]$)")
@@ -733,6 +779,9 @@ class Realm(LFCliBase):
def new_mvlan_profile(self):
return MACVLANProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug)
def new_test_group_profile(self):
return TestGroupProfile(self.lfclient_host, self.lfclient_port, local_realm=self, debug_=self.debug)
class MULTICASTProfile(LFCliBase):
def __init__(self, lfclient_host, lfclient_port, local_realm,
report_timer_=3000, name_prefix_="Unset", number_template_="00000", debug_=False):
@@ -2169,6 +2218,74 @@ class DUTProfile(LFCliBase):
"text-64": notebytes.decode('ascii')
}, self.debug)
class TestGroupProfile(LFCliBase):
def __init__(self, lfclient_host, lfclient_port, local_realm, test_group_name=None, debug_=False):
super().__init__(lfclient_host, lfclient_port, debug_, _halt_on_error=True)
self.local_realm = local_realm
self.group_name = test_group_name
self.cx_list = []
def start_group(self):
if self.group_name is not None:
self.local_realm.json_post("/cli-json/start_group", {"name": self.group_name})
else:
raise ValueError("test_group name must be set.")
def quiesce_group(self):
if self.group_name is not None:
self.local_realm.json_post("/cli-json/quiesce_group", {"name": self.group_name})
else:
raise ValueError("test_group name must be set.")
def stop_group(self):
if self.group_name is not None:
self.local_realm.json_post("/cli-json/stop_group", {"name": self.group_name})
else:
raise ValueError("test_group name must be set.")
def create_group(self):
if self.group_name is not None:
self.local_realm.json_post("/cli-json/add_group", {"name": self.group_name})
else:
raise ValueError("test_group name must be set.")
def remove_group(self):
if self.group_name is not None:
self.local_realm.json_post("/cli-json/rm_group", {"name": self.group_name})
else:
raise ValueError("test_group name must be set.")
def add_cx(self, cx_name):
self.local_realm.json_post("/cli-json/add_tgcx", {"tgname": self.test_group_name, "cxname": cx_name})
def rm_cx_from_list(self, cx_name):
self.local_realm.json_post("/cli-json/add_tgcx", {"tgname": self.test_group_name, "cxname": cx_name})
def check_group_exists(self):
test_groups = self.local_realm.json_get("/testgroups")
if test_groups is not None:
test_groups = test_groups["groups"]
for group in test_groups:
for k,v in group.items():
if v['name'] == self.group_name:
return True
else:
return False
def list_groups(self):
test_groups = self.local_realm.json_get("/testgroups")
tg_list = []
if test_groups is not None:
test_groups = test_groups["groups"]
for group in test_groups:
for k, v in group.items():
tg_list.append(v['name'])
return tg_list
def list_cxs(self):
# TODO: List cxs in profile, use cx_list or query?
pass
class FIOEndpProfile(LFCliBase):
"""
@@ -2212,7 +2329,6 @@ class FIOEndpProfile(LFCliBase):
self.created_cx = {}
self.created_endp = []
def start_cx(self):
print("Starting CXs...")
for cx_name in self.created_cx.keys():
@@ -2304,12 +2420,13 @@ class FIOEndpProfile(LFCliBase):
"payload_pattern": self.pattern,
}
# Read direction is copy of write only directory
if self.io_direction == "read":
endp_data["prefix"] = "wo_" + name + "_fio"
endp_data["directory"] = "/mnt/lf/wo_" + name + "_fio"
url = "cli-json/add_file_endp"
self.local_realm.json_post(url, endp_data, debug_=debug_, suppress_related_commands_=suppress_related_commands_)
self.local_realm.json_post(url, endp_data, debug_=True, suppress_related_commands_=suppress_related_commands_)
time.sleep(sleep_time)
data = {
@@ -2320,6 +2437,13 @@ class FIOEndpProfile(LFCliBase):
self.local_realm.json_post("cli-json/set_fe_info", data, debug_=debug_,
suppress_related_commands_=suppress_related_commands_)
self.local_realm.json_post("/cli-json/nc_show_endpoints", {"endpoint": "all"})
for port_name in ports:
if len(self.local_realm.name_to_eid(port_name)) == 3:
shelf = self.local_realm.name_to_eid(port_name)[0]
resource = self.local_realm.name_to_eid(port_name)[1]
name = self.local_realm.name_to_eid(port_name)[2]
endp_data = {
"alias": "CX_" + self.cx_prefix + name + "_fio",
"test_mgr": "default_tm",
@@ -2329,6 +2453,7 @@ class FIOEndpProfile(LFCliBase):
cx_post_data.append(endp_data)
self.created_cx[self.cx_prefix + name + "_fio"] = "CX_" + self.cx_prefix + name + "_fio"
# time.sleep(3)
for cx_data in cx_post_data:
url = "/cli-json/add_cx"
self.local_realm.json_post(url, cx_data, debug_=debug_, suppress_related_commands_=suppress_related_commands_)
@@ -2358,8 +2483,8 @@ class MACVLANProfile(LFCliBase):
self.ip_list = []
self.COMMANDS = ["set_port"]
self.desired_set_port_cmd_flags = []
self.desired_set_port_current_flags = ["if_down"]
self.desired_set_port_interest_flags = ["current_flags", "ifdown"]
self.desired_set_port_current_flags = [] # do not default down, "if_down"
self.desired_set_port_interest_flags = ["current_flags"] # do not default down, "ifdown"
self.set_port_data = {
"shelf": 1,
"resource": 1,
@@ -2481,7 +2606,7 @@ class MACVLANProfile(LFCliBase):
LFUtils.wait_until_ports_appear(base_url=self.lfclient_url, port_list=self.created_macvlans)
print(self.created_macvlans)
# time.sleep(sleep_time)
time.sleep(5)
for i in range(len(self.created_macvlans)):
eid = self.local_realm.name_to_eid(self.created_macvlans[i])
@@ -2503,7 +2628,7 @@ class MACVLANProfile(LFCliBase):
self.local_realm.rm_port(port_eid, check_exists=True)
time.sleep(.2)
# And now see if they are gone
LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=self.created_macvlans)
def admin_up(self):
for macvlan in self.created_macvlans:
@@ -2752,6 +2877,8 @@ class StationProfile:
number_template_="00000",
mode=0,
up=True,
resource=1,
shelf=1,
dhcp=True,
debug_=False,
use_ht160=False):
@@ -2761,6 +2888,8 @@ class StationProfile:
self.ssid_pass = ssid_pass
self.mode = mode
self.up = up
self.resource=resource
self.shelf=shelf
self.dhcp = dhcp
self.security = security
self.local_realm = local_realm
@@ -3020,8 +3149,6 @@ class StationProfile:
print("ERROR: StationProfile cleanup, list is empty")
return
del_count = len(desired_stations)
# First, request remove on the list.
for port_eid in desired_stations:
self.local_realm.rm_port(port_eid, check_exists=True)
@@ -3073,16 +3200,25 @@ class StationProfile:
self.add_sta_data["radio"] = radio_port
self.add_sta_data["resource"] = radio_resource
self.add_sta_data["shelf"] = radio_shelf
self.set_port_data["resource"] = radio_resource
self.set_port_data["shelf"] = radio_shelf
self.set_port_data["current_flags"] = self.add_named_flags(self.desired_set_port_current_flags,
set_port.set_port_current_flags)
self.set_port_data["interest"] = self.add_named_flags(self.desired_set_port_interest_flags,
set_port.set_port_interest_flags)
self.wifi_extra_data["resource"]=radio_resource
self.wifi_extra_data["shelf"]=radio_shelf
self.reset_port_extra_data["resource"]=radio_resource
self.reset_port_extra_data["shelf"]=radio_shelf
# these are unactivated LFRequest objects that we can modify and
# re-use inside a loop, reducing the number of object creations
add_sta_r = LFRequest.LFRequest(self.lfclient_url + "/cli-json/add_sta")
set_port_r = LFRequest.LFRequest(self.lfclient_url + "/cli-json/set_port")
wifi_extra_r = LFRequest.LFRequest(self.lfclient_url + "/cli-json/set_wifi_extra")
my_sta_names = []
#add radio here
if num_stations > 0:
my_sta_names = LFUtils.portNameSeries("sta", 0, num_stations - 1, int("1" + self.number_template))
else:
@@ -3106,6 +3242,8 @@ class StationProfile:
self.add_sta_data["radio"] = radio_port
self.add_sta_data["sta_name"] = name # for create station calls
self.set_port_data["port"] = name # for set_port calls.
self.set_port_data["shelf"] = radio_shelf
self.set_port_data["resource"] = radio_resource
self.station_names.append("%s.%s.%s" % (radio_shelf, radio_resource, name))
add_sta_r.addPostData(self.add_sta_data)

View File

@@ -50,8 +50,14 @@ class IPv4Test(LFCliBase):
self.station_profile.set_command_param("set_port", "report_timer", 1500)
self.station_profile.set_command_flag("set_port", "rpt_timer", 1)
self.station_profile.create(radio="wiphy0", sta_names_=self.sta_list, debug=self.debug)
self._pass("PASS: Station build finished")
self.station_profile.admin_up()
if self.local_realm.wait_for_ip(station_list=self.sta_list, debug=self.debug, timeout_sec=30):
self._pass("Station build finished")
self.passed()
else:
self._fail("Stations not able to acquire IP. Please check network input.")
self.failed()
def cleanup(self, sta_list):
self.station_profile.cleanup(sta_list)

View File

@@ -0,0 +1,117 @@
#!/usr/bin/env python3
import sys
import os
if sys.version_info[0] != 3:
print("This script requires Python 3")
exit(1)
if 'py-json' not in sys.path:
sys.path.append(os.path.join(os.path.abspath('..'), 'py-json'))
import LANforge
from LANforge.lfcli_base import LFCliBase
from LANforge import LFUtils
import realm
import argparse
import time
import pprint
class IPv4Test(LFCliBase):
def __init__(self, host, port, ssid, security, password, sta_list=None, number_template="00000", radio = "wiphy0",_debug_on=False,
_exit_on_error=False,
_exit_on_fail=False):
super().__init__(host, port, _debug=_debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail)
self.host = host
self.port = port
self.ssid = ssid
self.radio = radio
self.security = security
self.password = password
self.sta_list = sta_list
self.timeout = 120
self.number_template = number_template
self.debug = _debug_on
self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port)
self.station_profile = self.local_realm.new_station_profile()
self.station_profile.lfclient_url = self.lfclient_url
self.station_profile.ssid = self.ssid
self.station_profile.ssid_pass = self.password,
self.station_profile.security = self.security
self.station_profile.number_template_ = self.number_template
self.station_profile.mode = 0
def build(self):
# Build stations
#print("We've gotten into the build stations function")
self.station_profile.use_security(self.security, self.ssid, self.password)
self.station_profile.set_number_template(self.number_template)
print("Creating stations")
self.station_profile.set_command_flag("add_sta", "create_admin_down", 1)
self.station_profile.set_command_param("set_port", "report_timer", 1500)
self.station_profile.set_command_flag("set_port", "rpt_timer", 1)
self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug)
self.station_profile.admin_up()
if self.local_realm.wait_for_ip(station_list=self.sta_list, debug=self.debug, timeout_sec=30):
self._pass("Station build finished")
self.exit_success()
else:
self._fail("Stations not able to acquire IP. Please check network input.")
self.exit_fail()
def cleanup(self, sta_list):
self.station_profile.cleanup(sta_list)
LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=sta_list,
debug=self.debug)
def main():
lfjson_host = "localhost"
lfjson_port = 8080
parser = LFCliBase.create_basic_argparse(
prog='example_security_connection.py',
# formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=argparse.RawTextHelpFormatter,
epilog='''\
Example flags and command line input to run the script.
''',
description='''\
example_security_connection.py
--------------------
This python script creates an inputted number of stations using user-inputted security. This verifies that the most basic form of security works with the LANforge device.
--------------------
Generic command example:
python3 ./example_security_connection.py \\
--host localhost (optional) \\
--port 8080 (optional) \\
--num_stations 6 \\
--radio wiphy2
--security {open|wep|wpa|wpa2|wpa3} \\
--ssid netgear-wpa3 \\
--passwd admin123-wpa3 \\
--debug
''')
args = parser.parse_args()
num_sta = 2
if (args.num_stations is not None) and (int(args.num_stations) > 0):
num_stations_converted = int(args.num_stations)
num_sta = num_stations_converted
station_list = LFUtils.portNameSeries(prefix_="sta",
start_id_=0,
end_id_=num_sta-1,
padding_number_=10000,
radio=args.radio)
ip_test = IPv4Test(lfjson_host, lfjson_port, ssid=args.ssid, password=args.passwd, radio=args.radio,
security=args.security, sta_list=station_list)
ip_test.cleanup(station_list)
ip_test.timeout = 60
ip_test.build()
if __name__ == "__main__":
main()

View File

@@ -51,7 +51,13 @@ class IPv4Test(LFCliBase):
self.station_profile.set_command_param("set_port", "report_timer", 1500)
self.station_profile.set_command_flag("set_port", "rpt_timer", 1)
self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug)
self._pass("PASS: Station build finished")
self.station_profile.admin_up()
if self.local_realm.wait_for_ip(station_list=self.sta_list, debug=self.debug, timeout_sec=30):
self._pass("Station build finished")
self.passed()
else:
self._fail("Stations not able to acquire IP. Please check network input.")
self.failed()
def cleanup(self, sta_list):
self.station_profile.cleanup(sta_list)

View File

@@ -51,7 +51,13 @@ class IPv4Test(LFCliBase):
self.station_profile.set_command_param("set_port", "report_timer", 1500)
self.station_profile.set_command_flag("set_port", "rpt_timer", 1)
self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug)
self._pass("PASS: Station build finished")
self.station_profile.admin_up()
if self.local_realm.wait_for_ip(station_list=self.sta_list, debug=self.debug, timeout_sec=30):
self._pass("Station build finished")
self.passed()
else:
self._fail("Stations not able to acquire IP. Please check network input.")
self.failed()
def cleanup(self, sta_list):
self.station_profile.cleanup(sta_list)
@@ -71,7 +77,7 @@ def main():
''',
description='''\
example_wpa_connection.py
example_wpa2_connection.py
--------------------
Generic command example:

View File

@@ -51,7 +51,14 @@ class IPv4Test(LFCliBase):
self.station_profile.set_command_param("set_port", "report_timer", 1500)
self.station_profile.set_command_flag("set_port", "rpt_timer", 1)
self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug)
self._pass("PASS: Station build finished")
self.station_profile.admin_up()
if self.local_realm.wait_for_ip(station_list=self.sta_list, debug=self.debug, timeout_sec=30):
self._pass("Station build finished")
self.passed()
else:
self._fail("Stations not able to acquire IP. Please check network input.")
self.failed()
def cleanup(self, sta_list):
self.station_profile.cleanup(sta_list)

View File

@@ -52,8 +52,14 @@ class IPv4Test(LFCliBase):
self.station_profile.set_command_flag("set_port", "rpt_timer", 1)
self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug)
self.station_profile.admin_up()
if self.local_realm.wait_for_ip(station_list=self.sta_list, debug=self.debug, timeout_sec=30):
self._pass("Station build finished")
self.passed()
else:
self._fail("Stations not able to acquire IP. Please check network input.")
self.failed()
self._pass("PASS: Station build finished")
def cleanup(self, sta_list):
self.station_profile.cleanup(sta_list)

View File

@@ -37,7 +37,9 @@ class FileAdapter(object):
def flush(self):
pass # leave it to logging to flush properly
######################################
################################################################################
# cisco controller class :This class in the future will be moved to its own file
################################################################################
class cisco_():
def __init__(self, args):
@@ -614,19 +616,20 @@ class cisco_():
logg.info("configure ap {} channel {} chan_width {}".format(self.args.cisco_ap,self.args.cisco_channel,self.args.cisco_chan_width))
# Verify channel and channel width.
##########################################
# End of cisco controller class
##########################################
class L3VariableTime(LFCliBase):
def __init__(self, host, port, endp_types, args, tos, side_b, radio_name_list, number_of_stations_per_radio_list,
def __init__(self, host, port, endp_type, args, tos, side_b, radio_name_list, number_of_stations_per_radio_list,
ssid_list, ssid_password_list, ssid_security_list, wifimode_list,station_lists, name_prefix, debug_on, outfile,
test_keys,test_config,
reset_port_enable_list,
reset_port_time_min_list,
reset_port_time_max_list,
side_a_min_rate=560000, side_a_max_rate=0,
side_a_min_bps=560000, side_a_max_bps=0,
side_a_min_pdu=1518,side_a_max_pdu=0,
side_b_min_rate=560000, side_b_max_rate=0,
side_b_min_bps=560000, side_b_max_bps=0,
side_b_min_pdu=1518,side_b_max_pdu=0,
number_template="00", test_duration="256s",
polling_interval="60s",
@@ -636,7 +639,7 @@ class L3VariableTime(LFCliBase):
self.host = host
self.port = port
self.tos = tos.split()
self.endp_types = endp_types.split()
self.endp_type = endp_type
self.side_b = side_b
self.ssid_list = ssid_list
self.ssid_password_list = ssid_password_list
@@ -667,14 +670,6 @@ class L3VariableTime(LFCliBase):
self.test_config_dict = dict(map(lambda x: x.split('=='), str(self.test_config).replace('[','').replace(']','').replace("'","").split()))
# Some checking on the duration
#self.local_realm.parse_time(self.test_duration)
#if ( (radio_info_dict['reset_port_time_min'] >= args.test_duration)
# or (radio_info_dict['reset_port_time_max'] >= args.test_duration)):
# logg.info("port reset times min {} max {} mismatched with test duration {}"\
# .format(radio_info_dict['reset_port_time_min'],radio_info_dict['reset_port_time_max'],args.test_duration)))
# exit(1)
# Full spread-sheet data
if self.outfile is not None:
@@ -703,12 +698,12 @@ class L3VariableTime(LFCliBase):
self.cx_profile.host = self.host
self.cx_profile.port = self.port
self.cx_profile.name_prefix = self.name_prefix
self.cx_profile.side_a_min_bps = side_a_min_rate
self.cx_profile.side_a_max_bps = side_a_max_rate
self.cx_profile.side_a_min_bps = side_a_min_bps
self.cx_profile.side_a_max_bps = side_a_min_bps
self.cx_profile.side_a_min_pdu = side_a_min_pdu
self.cx_profile.side_a_max_pdu = side_a_max_pdu
self.cx_profile.side_b_min_bps = side_b_min_rate
self.cx_profile.side_b_max_bps = side_b_max_rate
self.cx_profile.side_b_min_bps = side_b_min_bps
self.cx_profile.side_b_max_bps = side_b_min_bps
self.cx_profile.side_b_min_pdu = side_b_min_pdu
self.cx_profile.side_b_max_pdu = side_b_max_pdu
@@ -745,8 +740,15 @@ class L3VariableTime(LFCliBase):
csv_rx_drop_percent_data.append(self.test_config_dict[key])
csv_rx_drop_percent_data.extend([self.epoch_time, self.time_stamp(),'rx_drop_percent'])
# remove multi cast since downstream only if selected
for key in [key for key in rx_drop_percent if "mtx" in key]: del rx_drop_percent[key]
if "upstream" in self.test_config_dict.values():
for key in [key for key in rx_drop_percent if "-A" in key]: del rx_drop_percent[key]
elif "downstream" in self.test_config_dict.values():
for key in [key for key in rx_drop_percent if "-B" in key]: del rx_drop_percent[key]
filtered_values = [v for _, v in rx_drop_percent.items() if v !=0]
average_rx_drop_percent = sum(filtered_values) / len(filtered_values) if len(filtered_values) != 0 else 0
@@ -774,13 +776,10 @@ class L3VariableTime(LFCliBase):
csv_rx_delta_row_data = []
csv_rx_delta_dict = {}
# this may need to be a list as more monitoring takes place.
for key in self.test_keys:
csv_rx_row_data.append(self.test_config_dict[key])
csv_rx_delta_row_data.append(self.test_config_dict[key])
csv_rx_row_data.extend([self.epoch_time, self.time_stamp(),'rx'])
csv_rx_delta_row_data.extend([self.epoch_time, self.time_stamp(),'rx_delta'])
for key in [key for key in old_list if "mtx" in key]: del old_list[key]
for key in [key for key in new_list if "mtx" in key]: del new_list[key]
@@ -788,27 +787,47 @@ class L3VariableTime(LFCliBase):
filtered_values = [v for _, v in new_list.items() if v !=0]
average_rx= sum(filtered_values) / len(filtered_values) if len(filtered_values) != 0 else 0
csv_performance_values=sorted(new_list.items(), key=lambda x: (x[1],x[0]), reverse=False)
# only evaluate upstream or downstream
new_evaluate_list = new_list.copy()
print("new_evaluate_list before",new_evaluate_list)
if "upstream" in self.test_config_dict.values():
for key in [key for key in new_evaluate_list if "-A" in key]: del new_evaluate_list[key]
print("upstream in dictionary values")
elif "downstream" in self.test_config_dict.values():
for key in [key for key in new_evaluate_list if "-B" in key]: del new_evaluate_list[key]
print("downstream in dictionary values")
'''print("new_evaluate_list after",new_evaluate_list)
csv_performance_values=sorted(new_evaluate_list.items(), key=lambda x: (x[1],x[0]), reverse=False)
csv_performance_values=self.csv_validate_list(csv_performance_values,5)
for i in range(5):
csv_rx_row_data.append(str(csv_performance_values[i]).replace(',',';'))
for i in range(-1,-6,-1):
csv_rx_row_data.append(str(csv_performance_values[i]).replace(',',';'))
csv_rx_row_data.append(average_rx)
csv_rx_row_data.append(average_rx)'''
if len(old_list) == len(new_list):
for item, value in old_list.items():
old_evaluate_list = old_list.copy()
if "upstream" in self.test_config_dict.values():
for key in [key for key in old_evaluate_list if "-A" in key]: del old_evaluate_list[key]
print("upstream in dictionary values")
elif "downstream" in self.test_config_dict.values():
for key in [key for key in old_evaluate_list if "-B" in key]: del old_evaluate_list[key]
print("downstream in dictionary values")
if len(old_evaluate_list) == len(new_evaluate_list):
for item, value in old_evaluate_list.items():
expected_passes +=1
if new_list[item] > old_list[item]:
if new_evaluate_list[item] > old_evaluate_list[item]:
passes += 1
#if self.debug: logg.info(item, new_list[item], old_list[item], " Difference: ", new_list[item] - old_list[item])
print(item, new_list[item], old_list[item], " Difference: ", new_list[item] - old_list[item])
#if self.debug: logg.info(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", new_evaluate_list[item] - old_evaluate_list[item])
print(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", new_evaluate_list[item] - old_evaluate_list[item])
else:
print("Failed to increase rx data: ", item, new_list[item], old_list[item])
print("Failed to increase rx data: ", item, new_evaluate_list[item], old_evaluate_list[item])
if not self.csv_started:
csv_rx_headers.append(item)
csv_rx_delta_dict.update({item:(new_list[item] - old_list[item])})
csv_rx_delta_dict.update({item:(new_evaluate_list[item] - old_evaluate_list[item])})
if not self.csv_started:
@@ -820,7 +839,25 @@ class L3VariableTime(LFCliBase):
# need to generate list first to determine worst and best
filtered_values = [v for _, v in csv_rx_delta_dict.items() if v !=0]
average_rx_delta= sum(filtered_values) / len(filtered_values) if len(filtered_values) != 0 else 0
#average_rx_delta= sum(filtered_values) / len(filtered_values) if len(filtered_values) != 0 else 0
max_tp_mbps = sum(filtered_values)
csv_rx_row_data.append(max_tp_mbps)
#To do needs to be read or passed in based on test type
expected_tp_mbps = max_tp_mbps
csv_rx_row_data.append(expected_tp_mbps)
# Todo pass or fail
if max_tp_mbps == expected_tp_mbps:
csv_rx_row_data.append("pass")
else:
csv_rx_row_data.append("fail")
csv_rx_row_data.extend([self.epoch_time, self.time_stamp(),'rx_delta'])
'''
csv_rx_row_data.extend([self.epoch_time, self.time_stamp(),'rx'])
csv_rx_delta_row_data.extend([self.epoch_time, self.time_stamp(),'rx_delta'])
csv_performance_delta_values=sorted(csv_rx_delta_dict.items(), key=lambda x: (x[1],x[0]), reverse=False)
csv_performance_delta_values=self.csv_validate_list(csv_performance_delta_values,5)
@@ -829,23 +866,24 @@ class L3VariableTime(LFCliBase):
for i in range(-1,-6,-1):
csv_rx_delta_row_data.append(str(csv_performance_delta_values[i]).replace(',',';'))
csv_rx_delta_row_data.append(average_rx_delta)
csv_rx_delta_row_data.append(average_rx_delta)'''
for item, value in old_list.items():
for item, value in old_evaluate_list.items():
expected_passes +=1
if new_list[item] > old_list[item]:
if new_evaluate_list[item] > old_evaluate_list[item]:
passes += 1
#if self.debug: logg.info(item, new_list[item], old_list[item], " Difference: ", new_list[item] - old_list[item])
print(item, new_list[item], old_list[item], " Difference: ", new_list[item] - old_list[item])
#if self.debug: logg.info(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", new_evaluate_list[item] - old_evaluate_list[item])
print(item, new_evaluate_list[item], old_evaluate_list[item], " Difference: ", new_evaluate_list[item] - old_evaluate_list[item])
else:
print("Failed to increase rx data: ", item, new_list[item], old_list[item])
print("Failed to increase rx data: ", item, new_evaluate_list[item], old_evaluate_list[item])
if not self.csv_started:
csv_rx_headers.append(item)
csv_rx_row_data.append(new_list[item])
csv_rx_delta_row_data.append(new_list[item] - old_list[item])
# note need to have all upstream and downstream in the csv table thus new_list and old_list
#csv_rx_row_data.append(new_list[item])
csv_rx_row_data.append(new_list[item] - old_list[item])
self.csv_add_row(csv_rx_row_data,self.csv_writer,self.csv_file)
self.csv_add_row(csv_rx_delta_row_data,self.csv_writer,self.csv_file)
#self.csv_add_row(csv_rx_delta_row_data,self.csv_writer,self.csv_file)
if passes == expected_passes:
return True
@@ -898,94 +936,6 @@ class L3VariableTime(LFCliBase):
if (int(sta_count) != int(self.total_stas)):
logg.info("WARNING: Cisco Controller reported %s stations, should be %s"%(sta_count, self.total_stas))
def verify_cac_on_ap(self):
pass
# Do this after you get the configuration Verify CAC
# use pySerial to check if the AP is configured:
# 1. You can grep for "DFS CAC timer enabled time 60"
# 2. and "changed to DFS channel 52, running CAC for 60 seconds
# Wait for 60 sec and check for this log "CAC_EXPIRY_EVT: CAC finished on DFS channel 52"
#"make a note of the time and check the CAC timer expired in 60-61 seconds."
# After CAC expires Verify Traffic. (the loop should start up may want some special detection)
def lf_hackrf_enable(self):
# hard coded for now
# need json and update to realm
#if os.path.isfile(self.args.hackrf):
# logg.info("hack rf file found {}".format(self.args.hackrf))
#else:
# logg.info("WARNING: hack rf file not found at {}".format(self.args.hackrf))
# look for lf_hackrf.py in local directory the look for in
pass
def verify_radar_detected_on_ap(self):
pass
#You will see logs as below in the AP:(show logging will help you getting this info)
#[*07/07/2020 23:44:27.7630] wcp/dfs :: RadarDetection: radar detected
#[*07/07/2020 23:44:27.7630] wcp/dfs :: RadarDetection: sending packet out to capwapd, slotId=1, msgLen=386, chanCnt=1 -100
#[*07/07/2020 23:44:27.7900] DOT11_DRV[1]: DFS CAC timer disabled time 0
#[*07/07/2020 23:44:27.7960] Enabling Channel and channel width Switch Announcement on current channel
#[*07/07/2020 23:44:27.8060] DOT11_DRV[1]: set_dfs Channel set to 36/20, CSA count 10
#[*07/07/2020 23:44:27.8620] DOT11_DRV[1]: DFS CAC timer enabled time 60
def verify_black_list_time_ap(self):
pass
def lf_hackrf_disable(self):
pass
#need to save the process id
# dfs dynamic frequency selection
def dfs(self):
if self.args == None:
return
if self.args.cisco_ctlr == None:
return
if self.args.cisco_dfs == False:
return
if self.args.cisco_channel == None:
return
if self.args.cisco_chan_width == None:
return
logg.info("testing dfs")
self.controller_show_ap_channel()
self.controller_disable_ap()
self.controller_set_channel_ap()
self.controller_set_chan_width_ap()
self.controller_enable_ap()
self.verify_cac_on_ap()
self.lf_hackrf_enable()
self.verify_radar_detected_on_ap()
self.verify_black_list_time_ap()
self.lf_hackrf_disable()
# For Testing only - since hackrf not causing channel changes
self.controller_disable_ap()
self.controller_set_channel_ap_36()
#self.dfs_set_chan_width_ap()
self.controller_enable_ap()
#check the AP for 52 is configured or not , check the CAC timer
# verify the clien can connect back to the AP once the CAC expires (check all connections)
def controller_channel_chan_width_config(self):
if self.args == None:
return
if self.args.cisco_ctlr == None:
return
if self.args.cisco_channel == None:
return
self.controller_disable_ap()
self.controller_set_channel_ap()
self.controller_set_chan_width_ap()
self.controller_enable_ap()
self.controller_show_ap_channel()
# need to actually check the CAC timer
time.sleep(60)
def reset_port_check(self):
for station_profile in self.station_profiles:
if station_profile.reset_port_extra_data['reset_port_enable']:
@@ -1039,15 +989,16 @@ class L3VariableTime(LFCliBase):
station_profile.create(radio=self.radio_name_list[index], sta_names_=self.station_lists[index], debug=self.debug, sleep_time=0)
index += 1
for etype in self.endp_types:
if etype == "mc_udp" or etype == "mc_udp6":
logg.info("Creating Multicast connections for endpoint type: %s"%(etype))
self.multicast_profile.create_mc_tx(etype, self.side_b, etype)
self.multicast_profile.create_mc_rx(etype, side_rx=station_profile.station_names)
else:
# 12/4/2020 put back in multi cast
#for etype in self.endp_types:
# if etype == "mc_udp" or etype == "mc_udp6":
# logg.info("Creating Multicast connections for endpoint type: %s"%(etype))
# self.multicast_profile.create_mc_tx(etype, self.side_b, etype)
# self.multicast_profile.create_mc_rx(etype, side_rx=station_profile.station_names)
for _tos in self.tos:
logg.info("Creating connections for endpoint type: %s TOS: %s"%(etype, _tos))
self.cx_profile.create(endp_type=etype, side_a=station_profile.station_names, side_b=self.side_b, sleep_time=0, tos=_tos)
logg.info("Creating connections for endpoint type: {} TOS: {} stations_names {}".format(self.endp_type, _tos, station_profile.station_names))
self.cx_profile.create(endp_type=self.endp_type, side_a=station_profile.station_names, side_b=self.side_b, sleep_time=0, tos=_tos)
self._pass("PASS: Stations build finished")
def start(self, print_pass=False, print_fail=False):
@@ -1070,6 +1021,7 @@ class L3VariableTime(LFCliBase):
exit(1) # why continue
time.sleep(30)
self.verify_controller()
# Multi cast may not be needed for scaling and performance
logg.info("Starting multicast traffic (if any configured)")
self.multicast_profile.start_mc(debug_=self.debug)
self.multicast_profile.refresh_mc(debug_=self.debug)
@@ -1087,10 +1039,10 @@ class L3VariableTime(LFCliBase):
passes = 0
expected_passes = 0
logg.info("polling_interval_seconds {}".format(self.polling_interval_seconds))
while cur_time < end_time:
#interval_time = cur_time + datetime.timedelta(seconds=5)
interval_time = cur_time + datetime.timedelta(seconds=self.polling_interval_seconds)
#logg.info("polling_interval_seconds {}".format(self.polling_interval_seconds))
while cur_time < interval_time:
cur_time = datetime.datetime.now()
self.reset_port_check()
@@ -1106,7 +1058,8 @@ class L3VariableTime(LFCliBase):
self._fail("FAIL: Not all stations increased traffic", print_fail)
old_rx_values = new_rx_values
self.__record_rx_dropped_percent(rx_drop_percent)
#percentage dropped not needed for scaling and performance , needed for longevity
#self.__record_rx_dropped_percent(rx_drop_percent)
cur_time = datetime.datetime.now()
@@ -1129,12 +1082,13 @@ class L3VariableTime(LFCliBase):
def csv_generate_column_headers(self):
csv_rx_headers = self.test_keys.copy()
csv_rx_headers.extend(['Time epoch','Time','Monitor'])
for i in range(1,6):
csv_rx_headers.extend
csv_rx_headers.extend(['Max TP Mbps','Expected TP','Pass Fail','Time epoch','Time','Monitor'])
'''for i in range(1,6):
csv_rx_headers.append("least_rx_data {}".format(i))
for i in range(1,6):
csv_rx_headers.append("most_rx_data_{}".format(i))
csv_rx_headers.append("average_rx_data")
csv_rx_headers.append("average_rx_data")'''
return csv_rx_headers
def csv_add_column_headers(self,headers):
@@ -1173,17 +1127,38 @@ def main():
#formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=argparse.RawTextHelpFormatter,
epilog='''\
Useful Information:
1. Polling interval for checking traffic is fixed at 1 minute
2. The test will generate csv file
3. The tx/rx rates are fixed at 256000 bits per second
4. Maximum stations per radio is 64
Scaling and Performance
''',
description='''\
lf_cisco_snp.py:
--------------------
##################################################################################
Task Description:
##################################################################################
-----------------
As we discussed, we need help in Candela SNP automation which involves cisco WLC controller and Candela automation. The framework we will build now will be used for years with all our new APs being added to this testbed.
Our ultimate aim is to achieve the following things:
1. 1 to 200 client SNP on 11ac (1, 50 and 200 client count tests)
1. 5 Ghz with different channel widths
2. Data encryption enabled/disabled
3. Local/central switching and authentication combinations
2. 1 to 37 client SNP on 11ax (1, 10 and 37 client count tests) eventually 200 clients
1. Different channel widths
2. Data encryption enabled/disabled
3. Local/central switching and authentication combinations
4. MU-MIMO and OFDMA enabled/disabled combination
3. CI/CD implementation
1. Download latest WLC images and upload them to the controller
2. Start the test suite
3. Generate a report per release
4. Display and graph all result data according to each release along with each testcase historical graph
5. Review overall AP performance across multiple AP platforms
Summary :
----------
create stations, create traffic between upstream port and stations, run traffic.
@@ -1197,7 +1172,7 @@ python .\\lf_cisco_snp.py --test_duration <duration> --endp_type <traffic types>
Multiple radios may be entered with individual --radio switches
generiic command with controller setting channel and channel width test duration 5 min
generiic command with controller setting channel and channel width test duration 30 sec
python3 lf_cisco_snp.py --cisco_ctlr <IP> --cisco_dfs True/False --mgr <Lanforge IP>
--cisco_channel <channel> --cisco_chan_width <20,40,80,120> --endp_type 'lf_udp lf_tcp mc_udp' --upstream_port <1.ethX>
--radio "radio==<radio 0 > stations==<number stations> ssid==<ssid> ssid_pw==<ssid password> security==<wpa2 , open> wifimode==<AUTO>"
@@ -1283,29 +1258,14 @@ python3 lf_cisco_snp.py --cisco_ctlr 192.168.100.112 --cisco_dfs True --mgr 192.
--radio "radio==1.wiphy1 stations==16 ssid==test_candela ssid_pw==[BLANK] security==open"
--test_duration 5m
TODO:
11a 5ghz
11b 24ghz
11g 24ghz
11bg 24ghz
11n 5ghz/24ghz
11ac 5ghz
TODO:
##############################################################################
Detailed test loop description 10/9/2020 - Karthik Recommendation
##############################################################################
Script logic loops:
AP {Axel, Vanc} Dynamic
frequency {24ghz, 5ghz} Common (band)
wifimode{11ax, 11ac, 11n, 11bg} Common (an anAX anAC abgn bg)
frequency {24ghz, 5ghz} Common (band) : 24ghz == b , 5ghz == a
wifimode{11ax (2.4 ghz or 5 ghz), 11ac (5 ghz only), 11n (2.4 ghz or 5ghz), 11bg(2.4 ghz)} Common (an anAX anAC abgn bg)
Bandwidth {20, 40, 80, 160}
data-encryption {enable/disable} Common
AP-mode {local/flexconnect} Common
@@ -1316,8 +1276,9 @@ AP {Axel, Vanc} Dynamic
Time (4 iterations of 30 sec and get the best average TP out of it)
Notes:
#############################################
CandelaTech Radios and what supports
#############################################
Radio descriptions:
ax200: so if AP is /n, then ax200 will connect at /n. But if AP is /AX, we have no way to force ax200 to act like /n
@@ -1329,31 +1290,31 @@ ath10K(9884) - wave-2 supports 4x4 802.11an-AC 5ghz (can act as ac , an)
Note: wave-2 radios can act as ac, an, (802.11an-AC) or legacy a/b/g (802.11bgn-AC)
wifimode:
11ax, 11ac, 11n, 11bg
#############################################
wifimodes needed to support
#############################################
11ax (2.4 ghz or 5 ghz), 11ac (5 ghz only), 11n (2.4ghz or 5 ghz), 11bg (2.4 ghz) (Cisco)
#############################################
5 Ghz
#############################################
Wifi mode: ax - 5ghz
Wifi mode: 11ax - 5ghz
Radios : ax200 : 802.11 /a/n/ac/AX
Wifi mode: 11ac - 5ghz
Radios : ath10K(9984) 802.11an-AC
Radios : ath10K(9984) 802.11an-AC (9984 are single band)
Wifi mode: 11n - 5ghz
Radios : ath10K(9984) 802.11an-AC
Radios : ath10K(9984) 802.11an-AC (9984 are single band)
#############################################
24 Ghz
#############################################
Wifi mode: 11ax - 24ghz
Radios : ax200 - 802.11 /b/g/n/AX
Wifi mode: 11ac - 24ghz
Radios : ax200 802.11 /b/g/n/AX (2.4Ghz doesn't officially support /AC, but often chips will do /AC there anyway)
Radios : ax200 802.11 /b/g/n/AX (2.4Ghz doesn't officially support /AC, but often chips will do /AC there anyway) (invalid)
Wifi mode: 11n - 24ghz
Radios : ax200 802.11 /b/g/n/AX
@@ -1361,13 +1322,19 @@ Radios : ax200 802.11 /b/g/n/AX
Wifi mode: 11bg - 24ghz
Radios : ax200 802.11 /b/g/n/AX
Wifi mode: 11bg
############################################
Radio support for specific Modes
############################################
cisco_wifimode == "anAX" or cisco_wifimode == "abgn" or cisco_wifimode == "bg":
radios = radio_AX200_abgn_ax_dict[cisco_client_density]
cisco_wifimode == "an" or cisco_wifimode == "anAC":
radios = radio_ath10K_9984_an_AC_dict[cisco_client_density]
TODO: Radio descriptions in realm , the 1. refers to the chassi hopefully corresponds to the shelf
############################################
Eventual Realm at Cisco
############################################
1.wiphy0 802.11abgn-ax iwlwifi(AX200) 523 - 1 stations - 5ghz/24ghz use only for 802.11ax - 24gz abgn
1.wiphy1 802.11abgn-ax iwlwifi(AX200) 523 - 1 stations - 5ghz/24ghz use only for 802.11ax - 24gz abgn
@@ -1458,10 +1425,10 @@ TODO: Radio descriptions in realm , the 1. refers to the chassi hopefully corres
parser.add_argument('-r','--radio', action='append', nargs=1, help='--radio \
\"radio==<number_of_wiphy stations=<=number of stations> ssid==<ssid> ssid_pw==<ssid password> security==<security> wifimode==<wifimode>\" '\
, required=False)
parser.add_argument('-amr','--side_a_min_rate', help='--side_a_min_rate, station min tx rate default 256000', default=256000)
#parser.add_argument('-bmr','--side_a_min_pdu', help='--side_a_min_pdu , station ipdu size default 1518', default=1518)
parser.add_argument('-bmr','--side_b_min_rate', help='--side_b_min_rate , upstream min tx rate default 256000', default=256000)
#parser.add_argument('-bmr','--side_b_min_pdu', help='--side_b_min_pdu , upstream pdu size default 1518', default=1518)
parser.add_argument('-amr','--side_a_min_bps', help='--side_a_min_bps, station min tx bits per second default 256000', default=256000)
parser.add_argument('-amp','--side_a_min_pdu', help='--side_a_min_pdu , station ipdu size default 1518', default=1518)
parser.add_argument('-bmr','--side_b_min_bps', help='--side_b_min_bps , upstream min tx rate default 256000', default=256000)
parser.add_argument('-bmp','--side_b_min_pdu', help='--side_b_min_pdu , upstream pdu size default 1518', default=1518)
# Parameters that allow for testing
parser.add_argument('-noc','--no_controller', help='--no_controller no configuration of the controller', action='store_true')
@@ -1544,7 +1511,6 @@ TODO: Radio descriptions in realm , the 1. refers to the chassi hopefully corres
['radio==1.wiphy7 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']]
radio_AX200_abgn_ax_dict_one = {'1' : radio_AX200_abgn_ax_list_001_one,
'8' : radio_AX200_abgn_ax_list_010_one}
@@ -1672,15 +1638,6 @@ TODO: Radio descriptions in realm , the 1. refers to the chassi hopefully corres
'50' : radio_ath10K_9984_an_AC_list_050,
'200' : radio_ath9K_9984_an_AC_list_200}
#radio_ath10K_9984_an_AC_dict = [['radio==6.wiphy8 stations==1 ssid==test-can ssid_pw==[BLANK] security==open wifimode==auto']]
radios1 = [['radio==1.wiphy1 stations==1 ssid==jedway-wpa2-x2048-4-1 ssid_pw==jedway-wpa2-x2048-4-1 security==wpa2 wifimode==abgn'],
['radio==1.wiphy2 stations==1 ssid==jedway-wpa2-x2048-5-1 ssid_pw==jedway-wpa2-x2048-5-1 security==wpa2 wifimode==an']]
MAX_NUMBER_OF_STATIONS = 200
radio_name_list = []
@@ -1726,15 +1683,20 @@ TODO: Radio descriptions in realm , the 1. refers to the chassi hopefully corres
# cisco_ap_modes = "local flex".split()
cisco_ap_modes = "local".split()
cisco_data_encryptions = "disable".split()
endp_types = "lf_udp lf_tcp"
cisco_packet_types = "lf_udp lf_tcp".split()
cisco_directions = "upstream downstream".split()
cisco_packet_sizes = "1518".split()
cisco_client_densities = "1".split()
cisco_data_encryptions = "disable".split()
cisco_side_a_min_bps = 500000000
cisco_side_b_min_bps = 500000000
radio_AX200_abgn_ax_dict = radio_AX200_abgn_ax_dict_one
radio_ath10K_9984_an_AC_dict = radio_ath10K_9984_an_AC_dict_one
elif args.cisco_test:
# Note the local system only supports 802.11-abgn , 802.11a
cisco_aps = "APA453.0E7B.CF9C".split()
cisco_bands = "a".split()
#cisco_wifimodes = "an anAX anAC abgn bg".split()
@@ -1745,11 +1707,18 @@ TODO: Radio descriptions in realm , the 1. refers to the chassi hopefully corres
cisco_chan_widths = "20".split()
cisco_ap_modes = "local".split()
cisco_data_encryptions = "disable".split()
endp_types = "lf_udp lf_tcp"
cisco_packet_types = "lf_udp lf_tcp".split()
#cisco_packet_types = "lf_udp".split()
#cisco_directions = "upstream downstream".split()
cisco_directions = "upstream downstream".split()
cisco_packet_sizes = "88 512 1370 1518".split()
#cisco_packet_sizes = "1518".split()
cisco_client_densities = "1".split()
cisco_data_encryptions = "disable".split()
cisco_side_a_min_bps = 500000000
cisco_side_b_min_bps = 500000000
radio_AX200_abgn_ax_dict = radio_AX200_abgn_ax_dict_test
radio_ath10K_9984_an_AC_dict = radio_ath10K_9984_an_AC_dict_test
@@ -1769,12 +1738,16 @@ TODO: Radio descriptions in realm , the 1. refers to the chassi hopefully corres
cisco_chan_widths = args.cisco_chan_width.split()
cisco_ap_modes = args.cisco_ap_mode.split()
cisco_client_densities = args.cisco_client_density.split()
endp_types = "lf_udp lf_tcp".split()
cisco_packet_types = args.endp_type.split()
cisco_directions = "upstream downstream".split()
cisco_packet_sizes = args.cisco_packet_size.split()
cisco_client_densities = args.cisco_client_density.split()
cisco_data_encryptions = args.cisco_data_encryption.split()
cisco_side_a_min_bps = args.side_a_min_bps
cisco_side_a_min_bps = args.side_b_min_bps
logg.info(cisco_aps)
logg.info(cisco_bands)
logg.info(cisco_wifimodes)
@@ -1782,38 +1755,62 @@ TODO: Radio descriptions in realm , the 1. refers to the chassi hopefully corres
logg.info(cisco_chan_widths)
logg.info(cisco_ap_modes)
logg.info(cisco_client_densities)
logg.info(endp_types)
logg.info(cisco_packet_types)
logg.info(cisco_packet_sizes)
logg.info(cisco_client_densities)
logg.info(cisco_data_encryptions)
ap_set = None
band_set = None
chan_width_set = None
ap_mode_set = None
tx_power_set = None
for cisco_ap in cisco_aps:
for cisco_band in cisco_bands: # frequency
for cisco_wifimode in cisco_wifimodes:
# check for valid frequency and wifi_mode combination put here to simplify logic since all radios do not support all modes
# "an anAX anAC abgn bg"
if((cisco_band == "a" and cisco_wifimode == "bg") or (cisco_band == "b" and cisco_wifimode == "anAC")):
pass # invalid combination continue
else:
for cisco_chan_width in cisco_chan_widths: #bandwidth
for cisco_data_encryption in cisco_data_encryptions:
for cisco_ap_mode in cisco_ap_modes:
for cisco_client_density in cisco_client_densities:
for cisco_packet_type in cisco_packet_types:
for cisco_direction in cisco_directions:
for cisco_packet_size in cisco_packet_sizes:
logg.info("###########################################################################################################################################")
logg.info("# TEST RUNNING , TEST RUNNING ############################################################################################################")
logg.info("###########################################################################################################################################")
test_config = "AP=={} Band=={} wifi_mode=={} BW=={} encryption=={} ap_mode=={} clients=={} packet_size=={}".format(cisco_ap,
cisco_band,cisco_wifimode,cisco_chan_width,cisco_data_encryption,cisco_ap_mode,cisco_client_density,cisco_packet_size)
print(test_config)
test_keys = ['AP','Band','wifi_mode','BW','encryption','ap_mode','clients','packet_size']
logg.info("# Cisco static settings: tx_power {} chan_5ghz {} chan_24ghz {} ".format(cisco_tx_power, cisco_chan_5ghz, cisco_chan_24ghz))
logg.info("# Cisco run Dynamic settings: {}".format(test_config))
logg.info("###########################################################################################################################################")
logg.info("###########################################################################################################################################")
# over write the configurations of args for controller
logg.info("#####################################################")
logg.info("# TEST RUNNING , TEST RUNNING ######################")
logg.info("#####################################################")
test_config = "AP=={} Band=={} wifi_mode=={} BW=={} encryption=={} ap_mode=={} clients=={} packet_type=={} direction=={} packet_size=={}".format(cisco_ap,
cisco_band,cisco_wifimode,cisco_chan_width,cisco_data_encryption,cisco_ap_mode,cisco_client_density,
cisco_packet_type,cisco_direction,cisco_packet_size)
test_keys = ['AP','Band','wifi_mode','BW','encryption','ap_mode','clients','packet_type','direction','packet_size']
logg.info("# Cisco run settings: {}".format(test_config))
if(args.no_controller):
logg.info("#########################################################################################################################################")
logg.info("# NO CONTROLLER SET")
logg.info("#########################################################################################################################################")
logg.info("################################################")
logg.info("# NO CONTROLLER SET , TEST MODE")
logg.info("################################################")
else:
if( cisco_ap != ap_set or
cisco_band != band_set or
cisco_chan_width != chan_width_set or
cisco_ap_mode != ap_mode_set or
cisco_tx_power != tx_power_set
):
logg.info("###############################################")
logg.info("# NEW CONTROLLER CONFIG")
logg.info("###############################################")
ap_set = cisco_ap
band_set = cisco_band
chan_width_set = cisco_chan_width
ap_mode_set = cisco_ap_mode
tx_power_set = cisco_tx_power
#############################################
# configure cisco controller
#############################################
cisco_args.cisco_ap = cisco_ap
cisco_args.cisco_band = cisco_band
if cisco_band == "a":
@@ -1842,20 +1839,48 @@ TODO: Radio descriptions in realm , the 1. refers to the chassi hopefully corres
cisco.controller_create_wlan()
cisco.controller_set_wireless_tag_policy()
cisco.controller_enable_wlan()
if cisco_band == "a":
cisco.controller_enable_network_5ghz()
else:
cisco.controller_enable_network_24ghz()
cisco.controller_enable_ap()
# need to actually check the CAC timer
time.sleep(30)
# TODO may need a static list of radios read for scaling and performance
####################################
# end of cisco controller code
####################################
else:
logg.info("###############################################")
logg.info("# NO CHANGE TO CONTROLLER CONFIG")
logg.info("###############################################")
logg.info("cisco_wifi_mode {}".format(cisco_wifimode))
if args.radio:
radios = args.radio
elif cisco_wifimode == "anAX" or cisco_wifimode == "abgn" or cisco_wifimode == "bg":
elif cisco_band == "a":
if cisco_wifimode == "anAX" or cisco_wifimode == "abgn":
#AX200 dual band
radios = radio_AX200_abgn_ax_dict[cisco_client_density]
elif cisco_wifimode == "an" or cisco_wifimode == "anAC":
elif cisco_wifimode == "an" or cisco_wifimode == "anAC" or cisco_wifimode =="auto":
#ath10K only supports 5Ghz
radios = radio_ath10K_9984_an_AC_dict[cisco_client_density]
else:
logg.info("##################################")
logg.info("# INVALID COMBINATION 5ghz")
logg.info("# Cisco run settings: {}".format(test_config))
logg.info("##################################")
exit(1)
else: # cisco_band == "b"
if cisco_wifimode == "an" or cisco_wifimode == "anAX" or cisco_wifimode == "abgn" or cisco_wifimode == "bg" or cisco_wifimode == "auto":
#AX200 dual band
radios = radio_AX200_abgn_ax_dict[cisco_client_density]
else:
logg.info("##################################")
logg.info("# INVALID COMBINATION 24 ghz")
logg.info("# Cisco run settings: {}".format(test_config))
logg.info("##################################")
exit(1)
logg.info("radios {}".format(radios))
for radio_ in radios:
radio_keys = ['radio','stations','ssid','ssid_pw','security','wifimode']
@@ -1875,7 +1900,6 @@ TODO: Radio descriptions in realm , the 1. refers to the chassi hopefully corres
else:
number_of_stations_per_radio_list.append(radio_info_dict['stations'])
wifimode_list.append(int(wifi_mode_dict[radio_info_dict['wifimode']]))
optional_radio_reset_keys = ['reset_port_enable']
radio_reset_found = True
for key in optional_radio_reset_keys:
@@ -1892,16 +1916,12 @@ TODO: Radio descriptions in realm , the 1. refers to the chassi hopefully corres
reset_port_enable_list.append(False)
reset_port_time_min_list.append('0s')
reset_port_time_max_list.append('0s')
# no stations for testing reconfiguration of the controller -
if(args.no_stations):
logg.info("###########################################################################################################################################")
logg.info("##################################")
logg.info("# NO STATIONS")
logg.info("###########################################################################################################################################")
logg.info("##################################")
else:
#####################
# temp removal of loop
######################
index = 0
station_lists = []
for (radio_name_, number_of_stations_per_radio_) in zip(radio_name_list,number_of_stations_per_radio_list):
@@ -1913,8 +1933,14 @@ TODO: Radio descriptions in realm , the 1. refers to the chassi hopefully corres
padding_number_=10000, radio=radio_name_)
station_lists.append(station_list)
index += 1
#logg.info("endp-types: %s"%(endp_types))
#enstanciate the
# Run Traffic Upstream (STA to AP)
if(cisco_direction == "upstream"):
side_a_min_bps = cisco_side_a_min_bps
side_b_min_bps = 0
# Run Traffic Downstream (AP to STA)
else:
side_a_min_bps = 0
side_b_min_bps = cisco_side_b_min_bps
# current default is to have a values
ip_var_test = L3VariableTime(
lfjson_host,
@@ -1923,7 +1949,7 @@ TODO: Radio descriptions in realm , the 1. refers to the chassi hopefully corres
number_template="00",
station_lists= station_lists,
name_prefix="LT-",
endp_types=endp_types,
endp_type=cisco_packet_type,
tos=args.tos,
side_b=side_b,
radio_name_list=radio_name_list,
@@ -1937,10 +1963,10 @@ TODO: Radio descriptions in realm , the 1. refers to the chassi hopefully corres
reset_port_enable_list=reset_port_enable_list,
reset_port_time_min_list=reset_port_time_min_list,
reset_port_time_max_list=reset_port_time_max_list,
side_a_min_rate=args.side_a_min_rate,
side_a_min_pdu =args.cisco_packet_size,
side_b_min_rate=args.side_b_min_rate,
side_b_min_pdu =args.cisco_packet_size,
side_a_min_bps=side_a_min_bps,
side_a_min_pdu =cisco_packet_size,
side_b_min_bps=side_b_min_bps,
side_b_min_pdu =cisco_packet_size,
debug_on=debug_on,
outfile=csv_outfile,
test_keys=test_keys,
@@ -1964,17 +1990,11 @@ TODO: Radio descriptions in realm , the 1. refers to the chassi hopefully corres
ssid_security_list = []
wifimode_list = []
ip_var_test.cleanup()
if ( args.no_stations):
pass
else:
ip_var_test.passes()
logg.info("Full test passed, all connections increased rx bytes")
################################
# end of commented out loop
################################
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,213 @@
#!/usr/bin/env python3
import sys
if sys.version_info[0] != 3:
print("This script requires Python 3")
exit(1)
import os
if 'py-json' not in sys.path:
sys.path.append(os.path.join(os.path.abspath('..'), 'py-json'))
from realm import Realm
from LANforge.lfcli_base import LFCliBase
from LANforge import LFUtils
import argparse
import time
import datetime
import pprint
class Test1KClients(LFCliBase):
def __init__(self,
host,
port,
upstream,
side_a_min_rate=0, side_a_max_rate=56000,
side_b_min_rate=0, side_b_max_rate=56000,
num_sta_=200,
_debug_on=True,
_exit_on_error=False,
_exit_on_fail=False):
super().__init__(host,
port,
_debug=_debug_on,
_local_realm=Realm(lfclient_host=host, lfclient_port=port),
_halt_on_error=_exit_on_error,
_exit_on_fail=_exit_on_fail)
self.ssid_radio_map = {
'1.1.wiphy0' : ("wpa2", "jedway-wpa2-x2048-4-4", "jedway-wpa2-x2048-4-4"),
'1.1.wiphy1' : ("wpa2", "jedway-wpa2-x2048-5-1", "jedway-wpa2-x2048-5-1"),
'1.1.wiphy2' : ("wpa2", "jedway-wpa2-x2048-4-1", "jedway-wpa2-x2048-4-1"),
'1.2.wiphy0' : ("wpa2", "jedway-wpa2-x2048-5-3", "jedway-wpa2-x2048-5-3"),
'1.2.wiphy1' : ("wpa2", "jedway-wpa2-x2048-4-4", "jedway-wpa2-x2048-4-4"),
'1.2.wiphy2' : ("wpa2", "jedway-wpa2-x2048-4-1", "jedway-wpa2-x2048-4-1"),
}
if num_sta_ is None:
raise ValueError("need a number of stations per radio")
self.num_sta = int(num_sta_)
self.station_radio_map = {
# port_name_series(prefix=prefix_, start_id=start_id_, end_id=end_id_, padding_number=padding_number_, radio=radio)
"1.1.wiphy0" : LFUtils.port_name_series(start_id=0, end_id=self.num_sta-1, padding_number=10000, radio="1.1.wiphy0"),
"1.1.wiphy1" : LFUtils.port_name_series(start_id=1000, end_id=1000+self.num_sta-1, padding_number=10000, radio="1.1.wiphy1"),
"1.1.wiphy2" : LFUtils.port_name_series(start_id=2000, end_id=2000+self.num_sta-1, padding_number=10000, radio="1.1.wiphy2"),
"1.2.wiphy0" : LFUtils.port_name_series(start_id=3000, end_id=3000+self.num_sta-1, padding_number=10000, radio="1.2.wiphy0"),
"1.2.wiphy1" : LFUtils.port_name_series(start_id=4000, end_id=4000+self.num_sta-1, padding_number=10000, radio="1.2.wiphy1"),
"1.2.wiphy2" : LFUtils.port_name_series(start_id=5000, end_id=5000+self.num_sta-1, padding_number=10000, radio="1.2.wiphy2")
}
self.upstream=upstream
self.name_prefix = "1k"
self.cx_profile = self.local_realm.new_l3_cx_profile()
self.cx_profile.name_prefix = self.name_prefix
self.cx_profile.side_a_min_bps = side_a_min_rate
self.cx_profile.side_a_max_bps = side_a_max_rate
self.cx_profile.side_b_min_bps = side_b_min_rate
self.cx_profile.side_b_max_bps = side_b_max_rate
self.station_profile_map = {}
def build(self):
for (radio, name_series) in self.station_radio_map.items():
print("building stations for %s"%radio)
if (name_series is None) or len(name_series) < 1:
print("No name series for %s"%radio)
continue
station_profile = self.local_realm.new_station_profile()
station_profile.use_security(self.ssid_radio_map[radio][0],
self.ssid_radio_map[radio][1],
self.ssid_radio_map[radio][2])
self.station_profile_map[radio] = station_profile
self._pass("defined %s station profiles" % len(self.station_radio_map))
for (radio, station_profile) in self.station_profile_map.items():
station_profile.create(radio=radio,
sta_names_=self.station_radio_map[radio],
dry_run=False,
up_=False,
debug=self.debug,
suppress_related_commands_=True,
use_radius=False,
hs20_enable=False,
sleep_time=.02)
station_profile.set_command_param("set_port", "report_timer", 1500)
station_profile.set_command_flag("set_port", "rpt_timer", 1)
self.cx_profile.create(endp_type="lf_udp", side_a=station_profile.station_names, side_b=self.upstream, sleep_time=0)
self._pass("built stations on %s radios" % len(self.station_radio_map))
def __get_rx_values(self):
cx_list = self.json_get("endp?fields=name,rx+bytes", debug_=self.debug)
# print(self.cx_profile.created_cx.values())
#print("==============\n", cx_list, "\n==============")
cx_rx_map = {}
for cx_name in cx_list['endpoint']:
if cx_name != 'uri' and cx_name != 'handler':
for item, value in cx_name.items():
for value_name, value_rx in value.items():
if value_name == 'rx bytes' and item in self.cx_profile.created_cx.values():
cx_rx_map[item] = value_rx
return cx_rx_map
def __compare_vals(self, old_list, new_list):
passes = 0
expected_passes = 0
if len(old_list) == len(new_list):
for item, value in old_list.items():
expected_passes += 1
if new_list[item] > old_list[item]:
passes += 1
# print(item, new_list[item], old_list[item], passes, expected_passes)
if passes == expected_passes:
return True
else:
return False
else:
return False
def start(self):
print("Bringing stations up...")
prev_ip_num=0
total_num_sta=6*self.num_sta
for (radio, station_profile) in self.station_profile_map.items():
station_profile.admin_up()
self.local_realm.wait_for_ip(station_list=self.station_radio_map[radio], debug=self.debug, timeout_sec=30)
curr_ip_num = self.local_realm.get_curr_num_ips(num_sta_with_ips=prev_ip_num,station_list=self.station_radio_map[radio], debug=self.debug)
while ((prev_ip_num < curr_ip_num) and (curr_ip_num < total_num_sta)):
self.local_realm.wait_for_ip(station_list=self.station_radio_map[radio], debug=self.debug, timeout_sec=60)
prev_ip_num = curr_ip_num
curr_ip_num = self.local_realm.get_curr_num_ips(num_sta_with_ips=prev_ip_num,station_list=self.station_radio_map[radio], debug=self.debug)
if curr_ip_num == total_num_sta:
self._pass("stations on radio %s up" % radio)
else:
self._fail("FAIL: Not all stations on radio %s up" % radio)
exit(1)
cur_time = datetime.datetime.now()
# old_cx_rx_values = self.__get_rx_values() #
end_time = self.local_realm.parse_time("3m") + cur_time
self.cx_profile.start_cx() #
passes = 0
expected_passes = 0
while cur_time < end_time:
interval_time = cur_time + datetime.timedelta(minutes=1)
while cur_time < interval_time:
cur_time = datetime.datetime.now()
time.sleep(1)
cur_time = datetime.datetime.now()
if passes == expected_passes:
self._pass("PASS: All tests passed", print_pass)
def stop(self):
pass
def cleanup(self):
#self.cx_profile.cleanup_prefix()
for (radio, name_series) in self.station_radio_map.items():
sta_list= self.station_radio_map[radio]
for sta in sta_list:
self.local_realm.rm_port(sta, check_exists=True)
def main():
num_sta=200
lfjson_host = "localhost"
lfjson_port = 8080
argparser = LFCliBase.create_basic_argparse(prog=__file__,
description="creates lots of stations across multiple radios",
formatter_class=argparse.RawTextHelpFormatter)
argparser.add_argument("--sta_per_radio",
type=int,
help="number of stations per radio")
argparser.add_argument("--test_duration",
type=int,
help="length of test duration")
args = argparser.parse_args()
kilo_test = Test1KClients(lfjson_host,
lfjson_port,
upstream=args.upstream_port,
num_sta_=args.sta_per_radio,
_debug_on=args.debug)
kilo_test.cleanup()
kilo_test.build()
if not kilo_test.passes():
print("test fails")
exit(1)
kilo_test.start()
if not kilo_test.passes():
print("test fails")
exit(1)
kilo_test.stop()
if not kilo_test.passes():
print("test fails")
exit(1)
kilo_test.cleanup()
if __name__ == "__main__":
main()

View File

@@ -1,79 +1,90 @@
#!/bin/bash
#Security connection examples#########################################
echo "Beginning example_wpa_connection.py test..."
chmod +x example_wpa2_connection.py
./example_wpa2_connection.py --num_stations 3 --ssid jedway-r8000-36 --passwd jedway-r8000-36 --radio wiphy0
chmod +x scenario.py
./scenario.py --load BLANK
chmod +x example_wep_connection.py
./example_wep_connection.py --ssid jedway-wep-48 --passwd jedway-wep-48 --radio wiphy1
./scenario.py --load BLANK
chmod +x example_wpa3_connection.py
./example_wpa3_connection.py
./scenario.py --load BLANK
chmod +x example_wpa_connection.py
./example_wpa_connection.py --radio wiphy1
./scenario.py --load BLANK
#test generic and test fileio######################################################
#chmod +x test_fileio.py
#./test_fileio.py
chmod +x test_generic.py
#lfping
./test_generic.py --num_stations 3 --ssid jedway-r8000-36 --passwd jedway-r8000-36 --radio wiphy0
#lfcurl
./test_generic.py --num_stations 3 --ssid jedway-r8000-36 --passwd jedway-r8000-36 --radio wiphy0
#generic
./test_generic.py --num_stations 3 --ssid jedway-r8000-36 --passwd jedway-r8000-36 --radio wiphy0
#speedtest
./test_generic.py --num_stations 3 --ssid jedway-r8000-36 --passwd jedway-r8000-36 --radio wiphy0
#iperf3
./test_generic.py --num_stations 3 --ssid jedway-r8000-36 --passwd jedway-r8000-36 --radio wiphy0
#Ipv4 connection tests##########################################
chmod +x test_ipv4_connection.py
./test_ipv4_connection.py
chmod +x test_ipv4_l4_ftp_upload.py
./test_ipv4_l4_ftp_upload.py
chmod +x test_ipv4_l4_ftp_urls_per_ten.py
./test_ipv4_l4_ftp_urls_per_ten.py
chmod +x test_ipv4_l4_ftp_wifi.py
./test_ipv4_l4_ftp_wifi.py
chmod +x test_ipv4_l4_urls_per_ten.py
./test_ipv4_l4_urls_per_ten.py
chmod +x test_ipv4_l4_wifi.py
./test_ipv4_l4_wifi.py
chmod +x test_ipv4_l4
./test_ipv4_l4.py
chmod +x test_ipv4_ps.py
./test_ipv4_l4_ps.py
chmod +x test_ipv4_ttls.py
./test_ipv4_l4_ttls.py
chmod +x test_ipv4_variable_time.py
./test_ipv4_variable_time.py
#Layer 3 tests################################################
chmod +x test_l3_longevity.py
./test_l3_longevity.py
chmod +x test_l3_powersave_traffic
./test_l3_powersave_traffic.py
chmod +x test_l3_scenario_traffic.py
./test_l3_scenario_traffic.py
chmod +x test_l3_unicast_traffic_gen.py
./test_l3_unicast_traffic_gen.py
chmod +x test_l3_WAN_LAN.py
./test_l3_WAN_LAN.py
#WANlink######################################################
chmod +x test_wanlink.py
./test_wanlink.py
#IPv6 connection tests########################################
chmod +x test_ipv6_connection.py
./test_ipv6_variable_connection.py
chmod +x test_ipv6_variable_time.py
./test_ipv6_variable_time.py
#STA Connect examples#########################################
chmod +x sta_connect_example.py
./sta_connect_example.py
chmod +x sta_connect_multi_example.py
./sta_connect_multi_example.py
chmod +x sta_connect.py
./sta_connect.py
chmod +x sta_connect2.py
./sta_connect2.py
#This bash script aims to automate the test process of all Candela Technologies's test_* scripts in the lanforge-scripts directory. The script can be run 2 ways and may include (via user input) the "start_num" and "stop_num" variables to select which tests should be run.
# OPTION ONE: ./test_all_scripts.sh : this command runs all the scripts in the array "testCommands"
# OPTION TWO: ./test_all_scripts.sh 4 5 : this command runs py-script commands (in testCommands array) that include the py-script options beginning with 4 and 5 (inclusive) in case function ret_case_num.
#Variables
NUM_STA=4
SSID_USED="jedway-wpa2-x2048-5-3"
PASSWD_USED="jedway-wpa2-x2048-5-3"
RADIO_USED="wiphy1"
SECURITY="wpa2"
CURR_TEST_NAME="BLANK"
CURR_TEST_NUM=0
STOP_NUM=9
START_NUM=0
#Test array
testCommands=("./example_wpa_connection.py --num_stations $NUM_STA --ssid jedway-r8000-36 --passwd jedway-r8000-36 --radio $RADIO_USED --security wpa"
"./example_wpa2_connection.py --num_stations $NUM_STA --ssid $SSID_USED --passwd $SSID_USED --radio $RADIO_USED --security wpa2"
"./example_wep_connection.py --num_stations $NUM_STA --ssid jedway-wep-48 --passwd jedway-wep-48 --radio $RADIO_USED --security wep"
"./example_wpa3_connection.py --num_stations $NUM_STA --ssid jedway-wpa3-1 --passwd jedway-wpa3-1 --radio $RADIO_USED --security wpa3"
"./test_ipv4_connection.py --radio wiphy2 --num_stations $NUM_STA --ssid $SSID_USED --passwd $PASSWD_USED --security $SECURITY --debug --upstream_port eth1"
"./test_generic.py --mgr localhost --mgr_port 4122 --radio $RADIO_USED --ssid SSID_USED --passwd $PASSWD_USED --num_stations $NUM_STA --type lfping --dest 10.40.0.1 --security $SECURITY"
"./test_generic.py --mgr localhost --mgr_port 4122 --radio $RADIO_USED --ssid $SSID_USED --passwd $PASSWD_USED --num_stations $NUM_STA --type speedtest --speedtest_min_up 20 --speedtest_min_dl 20 --speedtest_max_ping 150 --security $SECURITY"
"./test_ipv4_l4_urls_per_ten.py --upstream_port eth1 --radio $RADIO_USED --num_stations $NUM_STA --security $SECURITY --ssid $SSID_USED --passwd $PASSWD_USED --num_tests 1 --requests_per_ten 600 --target_per_ten 600"
"./test_ipv4_l4_wifi.py --upstream_port eth1 --radio wiphy0 --num_stations $NUM_STA --security $SECURITY --ssid jedway-wpa2-x2048-4-4 --passwd jedway-wpa2-x2048-4-4 --test_duration 3m"
"./test_ipv4_l4.py --radio wiphy3 --num_stations 4 --security wpa2 --ssid jedway-wpa2-x2048-4-1 --passwd jedway-wpa2-x2048-4-1 --url \"dl http://10.40.0.1 /dev/null\" --test_duration 2m --debug"
)
function ret_case_num(){
case $1 in
"example_wpa_connection")
echo 1 ;;
"example_wpa2_connection")
echo 2 ;;
"example_wpa3_connection")
echo 4 ;;
"example_wep_connection")
echo 3 ;;
"test_ipv4_connection")
echo 5 ;;
"test_generic")
echo 6 ;;
"test_ipv4_l4_urls_per_ten")
echo 7 ;;
"test_ipv4_l4_wifi")
echo 8 ;;
"test_ipv4_l4")
echo 9 ;;
esac
}
function blank_db() {
echo "Loading blank scenario..." >> ~/test_all_output_file.txt
./scenario.py --load BLANK >> ~/test_all_output_file.txt
#check_blank.py
}
function echo_print(){
echo "Beginning $CURR_TEST_NAME test..." >> ~/test_all_output_file.txt
}
function run_test(){
for i in "${testCommands[@]}"; do
CURR_TEST_NAME=${i%%.py*}
CURR_TEST_NAME=${CURR_TEST_NAME#./*}
CURR_TEST_NUM=$(ret_case_num $CURR_TEST_NAME)
if [[ $CURR_TEST_NUM -gt $STOP_NUM ]] || [[ $STOP_NUM -eq $CURR_NUM && $STOP_NUM -ne 0 ]]; then
exit 1
fi
if [[ $CURR_TEST_NUM -gt $START_NUM ]] || [[ $CURR_TEST_NUM -eq $START_NUM ]]; then
echo_print
eval $i >> ~/test_all_output_file.txt
if [ $? -ne 0 ]; then
echo $CURR_TEST_NAME failure
else
echo $CURR_TEST_NAME success
fi
if [[ "${CURR_TEST_NAME}" = @(example_wpa_connection|example_wpa2_connection|example_wpa3_connection|example_wep_connection) ]]; then
blank_db
fi
fi
done
}
function check_args(){
if [ ! -z $1 ]; then
START_NUM=$1
fi
if [ ! -z $2 ]; then
STOP_NUM=$2
fi
}
true > ~/test_all_output_file.txt
check_args $1 $2
run_test
#test generic and fileio are for macvlans

View File

@@ -18,6 +18,7 @@ import argparse
import realm
import time
import datetime
import pprint
class FileIOTest(LFCliBase):
@@ -44,7 +45,12 @@ class FileIOTest(LFCliBase):
gateway=None,
dhcp=True,
use_macvlans=False,
use_test_groups=False,
write_only_test_group=None,
read_only_test_group=None,
port_list=[],
ip_list=None,
mode=None,
_debug_on=False,
_exit_on_error=False,
_exit_on_fail=False):
@@ -58,14 +64,39 @@ class FileIOTest(LFCliBase):
self.password = password
self.number_template = number_template
self.test_duration = test_duration
self.sta_list = []
self.port_list = []
self.use_macvlans = use_macvlans
self.mode = mode
self.ip_list = ip_list
self.netmask = netmask
self.gateway = gateway
if self.use_macvlans:
if macvlan_parent != None:
if macvlan_parent is not None:
self.macvlan_parent = macvlan_parent
self.port_list = port_list
else:
self.sta_list = port_list
self.port_list = port_list
self.use_test_groups = use_test_groups
if self.use_test_groups:
if self.mode == "write":
if write_only_test_group is not None:
self.write_only_test_group = write_only_test_group
else:
raise ValueError("--write_only_test_group must be used to set test group name")
if self.mode == "read":
if read_only_test_group is not None:
self.read_only_test_group = read_only_test_group
else:
raise ValueError("--read_only_test_group must be used to set test group name")
if self.mode == "both":
if write_only_test_group is not None and read_only_test_group is not None:
self.write_only_test_group = write_only_test_group
self.read_only_test_group = read_only_test_group
else:
raise ValueError("--write_only_test_group and --read_only_test_group "
"must be used to set test group names")
#self.min_rw_size = self.parse_size(min_rw_size)
#self.max_rw_size = self.parse_size(max_rw_size)
#self.min_file_size = self.parse_size(min_file_size)
@@ -76,10 +107,10 @@ class FileIOTest(LFCliBase):
#self.max_write_rate_bps = self.parse_size_bps(max_write_rate_bps)
self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port)
self.endp_profile = self.local_realm.new_fio_endp_profile()
self.wo_profile = self.local_realm.new_fio_endp_profile()
self.mvlan_profile = self.local_realm.new_mvlan_profile()
if len(self.sta_list) > 0:
if not self.use_macvlans and len(self.port_list) > 0:
self.station_profile = self.local_realm.new_station_profile()
self.station_profile.lfclient_url = self.lfclient_url
self.station_profile.ssid = self.ssid
@@ -88,20 +119,21 @@ class FileIOTest(LFCliBase):
self.station_profile.number_template_ = self.number_template
self.station_profile.mode = 0
self.endp_profile.fs_type = fs_type
self.endp_profile.min_rw_size = LFUtils.parse_size(min_rw_size)
self.endp_profile.max_rw_size = LFUtils.parse_size(max_rw_size)
self.endp_profile.min_file_size = LFUtils.parse_size(min_file_size)
self.endp_profile.min_file_size = LFUtils.parse_size(min_file_size)
self.endp_profile.min_read_rate_bps = LFUtils.parse_size(min_read_rate_bps)
self.endp_profile.max_read_rate_bps = LFUtils.parse_size(max_read_rate_bps)
self.endp_profile.min_write_rate_bps = LFUtils.parse_size(min_write_rate_bps)
self.endp_profile.max_write_rate_bps = LFUtils.parse_size(max_write_rate_bps)
self.endp_profile.directory = directory
self.endp_profile.server_mount = server_mount
self.wo_profile.fs_type = fs_type
self.wo_profile.min_rw_size = LFUtils.parse_size(min_rw_size)
self.wo_profile.max_rw_size = LFUtils.parse_size(max_rw_size)
self.wo_profile.min_file_size = LFUtils.parse_size(min_file_size)
self.wo_profile.max_file_size = LFUtils.parse_size(max_file_size)
self.wo_profile.min_read_rate_bps = LFUtils.parse_size(min_read_rate_bps)
self.wo_profile.max_read_rate_bps = LFUtils.parse_size(max_read_rate_bps)
self.wo_profile.min_write_rate_bps = LFUtils.parse_size(min_write_rate_bps)
self.wo_profile.max_write_rate_bps = LFUtils.parse_size(max_write_rate_bps)
self.wo_profile.directory = directory
self.wo_profile.server_mount = server_mount
self.ro_profile = self.endp_profile.create_ro_profile()
self.ro_profile = self.wo_profile.create_ro_profile()
if self.use_macvlans:
self.mvlan_profile.num_macvlans = int(num_ports)
self.mvlan_profile.desired_macvlans = self.port_list
self.mvlan_profile.macvlan_parent = self.macvlan_parent
@@ -111,6 +143,20 @@ class FileIOTest(LFCliBase):
self.mvlan_profile.gateway = gateway
self.created_ports = []
if self.use_test_groups:
if self.mode is not None:
if self.mode.lower() == "write":
self.wo_tg_profile = self.local_realm.new_test_group_profile()
elif self.mode.lower() == "read":
self.ro_tg_profile = self.local_realm.new_test_group_profile()
elif self.mode.lower() == "both":
self.wo_tg_profile = self.local_realm.new_test_group_profile()
self.ro_tg_profile = self.local_realm.new_test_group_profile()
else:
raise ValueError("Unknown mode given ", self.mode)
else:
raise ValueError("Mode (read,write,both) must be specified")
def __compare_vals(self, val_list):
passes = 0
expected_passes = 0
@@ -121,18 +167,18 @@ class FileIOTest(LFCliBase):
if item[0] == 'r':
# print("TEST", item,
# val_list[item]['read-bps'],
# self.endp_profile.min_read_rate_bps,
# val_list[item]['read-bps'] > self.endp_profile.min_read_rate_bps)
# self.ro_profile.min_read_rate_bps,
# val_list[item]['read-bps'] > self.ro_profile.min_read_rate_bps)
if val_list[item]['read-bps'] > self.endp_profile.min_read_rate_bps:
if val_list[item]['read-bps'] > self.wo_profile.min_read_rate_bps:
passes += 1
else:
# print("TEST", item,
# val_list[item]['write-bps'],
# self.endp_profile.min_write_rate_bps,
# val_list[item]['write-bps'] > self.endp_profile.min_write_rate_bps)
# self.wo_profile.min_write_rate_bps,
# val_list[item]['write-bps'] > self.wo_profile.min_write_rate_bps)
if val_list[item]['write-bps'] > self.endp_profile.min_write_rate_bps:
if val_list[item]['write-bps'] > self.wo_profile.min_write_rate_bps:
passes += 1
if passes == expected_passes:
return True
@@ -143,11 +189,20 @@ class FileIOTest(LFCliBase):
def __get_values(self):
time.sleep(3)
cx_list = self.json_get("fileio/%s,%s?fields=write-bps,read-bps" % (','.join(self.endp_profile.created_cx.keys()), ','.join(self.ro_profile.created_cx.keys())),
debug_=self.debug)
if self.mode == "write":
cx_list = self.json_get("fileio/%s?fields=write-bps,read-bps" % (
','.join(self.wo_profile.created_cx.keys())), debug_=self.debug)
elif self.mode == "read":
cx_list = self.json_get("fileio/%s?fields=write-bps,read-bps" % (
','.join(self.ro_profile.created_cx.keys())), debug_=self.debug)
else:
cx_list = self.json_get("fileio/%s,%s?fields=write-bps,read-bps" % (
','.join(self.wo_profile.created_cx.keys()),
','.join(self.ro_profile.created_cx.keys())), debug_=self.debug)
# print(cx_list)
# print("==============\n", cx_list, "\n==============")
cx_map = {}
# pprint.pprint(cx_list)
if cx_list is not None:
cx_list = cx_list['endpoint']
for i in cx_list:
@@ -159,45 +214,114 @@ class FileIOTest(LFCliBase):
def build(self):
# Build stations
# print(self.min_tx_bps, self.min_rx_bps)
# TODO: Check for upstream port as child to bridge before macvlan create
if self.use_macvlans:
self.mvlan_profile.create(admin_down=True, sleep_time=.5, debug=self.debug)
print("Creating MACVLANs")
self.mvlan_profile.create(admin_down=False, sleep_time=.5, debug=self.debug)
self._pass("PASS: MACVLAN build finished")
self.created_ports += self.mvlan_profile.created_macvlans
if len(self.sta_list) > 0:
elif not self.use_macvlans and self.ip_list is None:
self.station_profile.use_security(self.security, self.ssid, self.password)
self.station_profile.set_number_template(self.number_template)
print("Creating stations")
self.station_profile.set_command_flag("add_sta", "create_admin_down", 1)
self.station_profile.set_command_param("set_port", "report_timer", 1500)
self.station_profile.set_command_flag("set_port", "rpt_timer", 1)
self.station_profile.create(radio=self.radio, sta_names_=self.sta_list, debug=self.debug)
self.station_profile.create(radio=self.radio, sta_names_=self.port_list, debug=self.debug)
self._pass("PASS: Station build finished")
self.created_ports += self.station_profile.station_names
if self.ip_list is not None:
if self.gateway is not None and self.netmask is not None:
for num_port in range(len(self.port_list)):
shelf = self.local_realm.name_to_eid(self.port_list[num_port])[0]
resource = self.local_realm.name_to_eid(self.port_list[num_port])[1]
port = self.local_realm.name_to_eid(self.port_list[num_port])[2]
req_url = "/cli-json/set_port"
data = {
"shelf": shelf,
"resource": resource,
"port": port,
"ip_addr": self.ip_list[num_port],
"netmask": self.netmask,
"gateway": self.gateway
}
self.local_realm.json_post(req_url, data)
self.created_ports.append("%s.%s.%s" % (shelf, resource, port))
else:
raise ValueError("Netmask and gateway must be specified")
self.endp_profile.create(ports=self.created_ports, sleep_time=.5, debug_=self.debug,
if self.mode is not None:
if self.mode.lower() == "write":
print("Creating Write Only CXs")
self.wo_profile.create(ports=self.created_ports, sleep_time=.5, debug_=self.debug,
suppress_related_commands_=None)
elif self.mode.lower() == "read":
print("Creating Read Only CXs")
self.ro_profile.create(ports=self.created_ports, sleep_time=.5, debug_=self.debug,
suppress_related_commands_=None)
elif self.mode.lower() == "both":
print("Creating Write Only CXs")
print("Creating Read Only CXs")
self.wo_profile.create(ports=self.created_ports, sleep_time=.5, debug_=self.debug,
suppress_related_commands_=None)
self.ro_profile.create(ports=self.created_ports, sleep_time=.5, debug_=self.debug,
suppress_related_commands_=None)
if self.use_test_groups:
print("Creating test groups...")
if self.mode is not None:
if self.mode.lower() == "write":
self.wo_tg_profile.cx_list = self.wo_profile.created_cx.values()
self.wo_tg_profile.create_group(group_name=self.write_only_test_group)
elif self.mode.lower() == "read":
self.ro_tg_profile.cx_list = self.ro_profile.created_cx.values()
self.ro_tg_profile.create_group(group_name=self.read_only_test_group)
elif self.mode.lower() == "both":
self.ro_tg_profile.cx_list = self.ro_profile.created_cx.values()
self.wo_tg_profile.cx_list = self.wo_profile.created_cx.values()
self.ro_tg_profile.create_group(group_name=self.read_only_test_group)
self.wo_tg_profile.create_group(group_name=self.write_only_test_group)
else:
raise ValueError("Unknown mode given ", self.mode)
else:
raise ValueError("Mode (read,write,both) must be specified")
def start(self, print_pass=False, print_fail=False):
temp_ports = self.port_list.copy()
temp_ports = self.created_ports.copy()
#temp_stas.append(self.local_realm.name_to_eid(self.upstream_port)[2])
if not self.use_macvlans:
self.station_profile.admin_up()
else:
self.mvlan_profile.admin_up()
exit(1)
if self.local_realm.wait_for_ip(temp_ports):
if self.local_realm.wait_for_ip(temp_ports, debug=self.debug):
self._pass("All ports got IPs", print_pass)
else:
self._fail("Ports failed to get IPs", print_fail)
cur_time = datetime.datetime.now()
# print("Got Values")
end_time = self.local_realm.parse_time(self.test_duration) + cur_time
self.endp_profile.start_cx()
if self.use_test_groups:
if self.mode == "write":
self.wo_tg_profile.start_group(group_name=self.write_only_test_group)
elif self.mode == "read":
self.ro_tg_profile.start_group(group_name=self.read_only_test_group)
else:
self.wo_tg_profile.start_group(group_name=self.write_only_test_group)
time.sleep(2)
self.ro_tg_profile.start_group(group_name=self.read_only_test_group)
else:
if self.mode == "write":
self.wo_profile.start_cx()
elif self.mode == "read":
self.ro_profile.start_cx()
else:
self.wo_profile.start_cx()
time.sleep(2)
self.ro_profile.start_cx()
passes = 0
expected_passes = 0
print("Starting Test...")
@@ -225,19 +349,52 @@ class FileIOTest(LFCliBase):
self._pass("PASS: All tests passes", print_pass)
def stop(self):
self.endp_profile.stop_cx()
if self.use_test_groups:
if self.mode == "write":
self.wo_tg_profile.stop_group(group_name=self.write_only_test_group)
elif self.mode == "read":
self.ro_tg_profile.stop_group(group_name=self.read_only_test_group)
else:
self.wo_tg_profile.stop_group(group_name=self.write_only_test_group)
time.sleep(2)
self.ro_tg_profile.stop_group(group_name=self.read_only_test_group)
else:
if self.mode == "write":
self.wo_profile.stop_cx()
elif self.mode == "read":
self.ro_profile.stop_cx()
else:
self.wo_profile.stop_cx()
time.sleep(2)
self.ro_profile.stop_cx()
if not self.use_macvlans:
self.station_profile.admin_down()
else:
self.mvlan_profile.admin_down()
def cleanup(self, sta_list=None):
self.endp_profile.cleanup()
def cleanup(self, port_list=None):
if self.use_test_groups:
if self.mode == "read":
self.ro_tg_profile.remove_group(group_name=self.read_only_test_group)
elif self.mode == "write":
self.wo_tg_profile.remove_group(group_name=self.write_only_test_group)
else:
self.ro_tg_profile.remove_group(group_name=self.read_only_test_group)
self.wo_tg_profile.remove_group(group_name=self.write_only_test_group)
time.sleep(1)
self.wo_profile.cleanup()
self.ro_profile.cleanup()
if len(self.sta_list) > 0:
self.station_profile.cleanup(sta_list)
LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=sta_list, debug=self.debug)
if not self.use_macvlans and self.ip_list is None:
self.station_profile.cleanup(port_list)
elif self.use_macvlans:
self.mvlan_profile.cleanup()
# LFUtils.wait_until_ports_disappear(base_url=self.lfclient_url, port_list=port_list, debug=self.debug)
def main():
lfjson_host = "localhost"
@@ -253,9 +410,11 @@ def main():
test_fileio.py:
--------------------
Generic command layout:
python ./test_fileio.py --upstream_port <port> --radio <radio 0> <stations> <ssid> <ssid password> <security type: wpa2, open, wpa3> --debug
./test_fileio.py --macvlan_parent <port> --num_ports <num ports> --use_macvlans
--first_mvlan_ip <first ip in series> --netmask <netmask to use> --gateway <gateway ip addr>
python3 ./test_fileio.py --upstream_port eth1 --fio_type fe_nfs4 --min_read 1Mbps --min_write 1Gbps --server_mount 192.168.93.195:/tmp/test
./test_fileio.py --macvlan_parent eth2 --num_ports 3 --use_macvlans --first_mvlan_ip 192.168.92.13
--netmask 255.255.255.0 --gateway 192.168.92.1
''')
parser.add_argument('--test_duration', help='sets the duration of the test', default="5m")
@@ -268,7 +427,8 @@ python3 ./test_fileio.py --upstream_port eth1 --fio_type fe_nfs4 --min_read 1Mbp
parser.add_argument('--max_read_rate_bps', help='maximum bps read rate', default=10e9)
parser.add_argument('--min_write_rate_bps', help='minimum bps write rate', default=10e9)
parser.add_argument('--max_write_rate_bps', help='maximum bps write rate', default="1G")
parser.add_argument('--directory', help='--directory directory to read/write in. Absolute path suggested', default="AUTO")
parser.add_argument('--directory', help='--directory directory to read/write in. Absolute path suggested',
default="AUTO")
parser.add_argument('--server_mount', help='--server_mount The server to mount, ex: 192.168.100.5/exports/test1',
default="10.40.0.1:/var/tmp/test")
parser.add_argument('--macvlan_parent', help='specifies parent port for macvlan creation', default=None)
@@ -278,13 +438,21 @@ python3 ./test_fileio.py --upstream_port eth1 --fio_type fe_nfs4 --min_read 1Mbp
parser.add_argument('--first_mvlan_ip', help='specifies first static ip address to be used or dhcp', default=None)
parser.add_argument('--netmask', help='specifies netmask to be used with static ip addresses', default=None)
parser.add_argument('--gateway', help='specifies default gateway to be used with static addressing', default=None)
parser.add_argument('--use_test_groups', help='will use test groups to start/stop instead of single endps/cxs',
action='store_true', default=False)
parser.add_argument('--read_only_test_group', help='specifies name to use for read only test group', default=None)
parser.add_argument('--write_only_test_group', help='specifies name to use for write only test group', default=None)
parser.add_argument('--mode', help='write,read,both', default='both', type=str)
parser.add_argument('--use_ports', help='list of comma separated ports to use with ips, \'=\' separates name and ip'
'{ port_name1=ip_addr1,port_name1=ip_addr2 }', default=None)
args = parser.parse_args()
port_list = []
if args.first_port is not None:
ip_list = []
if args.first_port is not None and args.use_ports is not None:
if args.first_port.startswith("sta"):
if (args.num_ports is not None) and (int(args.num_ports) > 0):
start_num = int(args.first_port[4:])
start_num = int(args.first_port[3:])
num_ports = int(args.num_ports)
port_list = LFUtils.port_name_series(prefix="sta", start_id=start_num, end_id=start_num+num_ports-1,
padding_number=10000,
@@ -302,6 +470,7 @@ python3 ./test_fileio.py --upstream_port eth1 --fio_type fe_nfs4 --min_read 1Mbp
"first_port must contain parent port and num_ports must be greater than 0"
% (args.num_ports, args.macvlan_parent, args.first_port))
else:
if args.use_ports is None:
num_ports = int(args.num_ports)
if not args.use_macvlans:
port_list = LFUtils.port_name_series(prefix="sta", start_id=0, end_id=num_ports - 1,
@@ -311,18 +480,35 @@ python3 ./test_fileio.py --upstream_port eth1 --fio_type fe_nfs4 --min_read 1Mbp
port_list = LFUtils.port_name_series(prefix=args.macvlan_parent + "#", start_id=0,
end_id=num_ports - 1, padding_number=100000,
radio=args.radio)
else:
temp_list = args.use_ports.split(',')
for port in temp_list:
port_list.append(port.split('=')[0])
ip_list.append(port.split('=')[1])
if len(port_list) != len(ip_list):
raise ValueError(temp_list, " ports must have matching ip addresses!")
print(port_list)
print(ip_list)
if args.first_mvlan_ip is not None:
if args.first_mvlan_ip.lower() == "dhcp":
dhcp = True
else:
dhcp = False
print(port_list)
else:
dhcp = True
# print(port_list)
# exit(1)
ip_test = FileIOTest(args.mgr,
args.mgr_port,
ssid=args.ssid,
password=args.passwd,
security=args.security,
port_list=port_list,
ip_list=ip_list,
test_duration=args.test_duration,
upstream_port=args.upstream_port,
_debug_on=args.debug,
@@ -344,7 +530,11 @@ python3 ./test_fileio.py --upstream_port eth1 --fio_type fe_nfs4 --min_read 1Mbp
max_write_rate_bps=args.max_write_rate_bps,
directory=args.directory,
server_mount=args.server_mount,
num_ports=args.num_ports
num_ports=args.num_ports,
use_test_groups=args.use_test_groups,
write_only_test_group=args.write_only_test_group,
read_only_test_group=args.read_only_test_group,
mode=args.mode
# want a mount options param
)
@@ -352,7 +542,6 @@ python3 ./test_fileio.py --upstream_port eth1 --fio_type fe_nfs4 --min_read 1Mbp
ip_test.build()
if not ip_test.passes():
print(ip_test.get_fail_message())
exit(1)
ip_test.start(False, False)
ip_test.stop()
if not ip_test.passes():

View File

@@ -19,7 +19,7 @@ import datetime
import json
class GenTest(LFCliBase):
def __init__(self, host, port, ssid, security, password, sta_list, name_prefix, upstream,
def __init__(self, host, port, ssid, security, passwd, sta_list, name_prefix, upstream,
number_template="000", test_duration="5m", type="lfping", dest=None, cmd =None,
interval=1, radio=None, speedtest_min_up=None, speedtest_min_dl=None, speedtest_max_ping=None,
_debug_on=False,
@@ -31,7 +31,7 @@ class GenTest(LFCliBase):
self.upstream = upstream
self.sta_list = sta_list
self.security = security
self.password = password
self.passwd = passwd
self.number_template = number_template
self.name_prefix = name_prefix
self.test_duration = test_duration
@@ -48,7 +48,7 @@ class GenTest(LFCliBase):
self.station_profile.lfclient_url = self.lfclient_url
self.station_profile.ssid = self.ssid
self.station_profile.ssid_pass = self.password,
self.station_profile.ssid_pass = self.passwd,
self.station_profile.security = self.security
self.station_profile.number_template_ = self.number_template
self.station_profile.mode = 0
@@ -155,7 +155,7 @@ class GenTest(LFCliBase):
self.station_profile.admin_down()
def build(self):
self.station_profile.use_security(self.security, self.ssid, self.password)
self.station_profile.use_security(self.security, self.ssid, self.passwd)
self.station_profile.set_number_template(self.number_template)
print("Creating stations")
self.station_profile.set_command_flag("add_sta", "create_admin_down", 1)
@@ -194,6 +194,20 @@ python3 ./test_generic.py --upstream_port eth1
--test_duration 2m
--interval 1s
--debug
Example commands:
LFPING:
./test_generic.py --mgr localhost --mgr_port 4122 --radio wiphy0 --num_stations 3 --ssid jedway-wpa2-x2048-4-1 --passwd jedway-wpa2-x2048-4-1 --type lfping --dest 10.40.0.1 --security wpa2
LFCURL (under construction):
./test_generic.py --mgr localhost --mgr_port 4122 --radio wiphy1 --num_stations 3 --ssid jedway-wpa2-x2048-4-1 --passwd jedway-wpa2-x2048-4-1 --security wpa2 --type lfcurl --dest 10.40.0.1
GENERIC:
./test_generic.py --mgr localhost--mgr_port 4122 --radio wiphy1 --num_stations 3 --ssid jedway-wpa2-x2048-4-1 --passwd jedway-wpa2-x2048-4-1 --security wpa2 --type generic
SPEEDTEST:
./test_generic.py --mgr localhost --mgr_port 4122 --radio wiphy2 --num_stations 3 --ssid jedway-wpa2-x2048-4-1 --passwd jedway-wpa2-x2048-4-1 --type speedtest --speedtest_min_up 20
--speedtest_min_dl 20 --speedtest_max_ping 150 --security wpa2
IPERF3 (under construction):
./test_generic.py --mgr localhost --mgr_port 4122 --radio wiphy1 --num_stations 3 --ssid jedway-wpa2-x2048-4-1 --passwd jedway-wpa2-x2048-4-1 --security wpa2 --type iperf3
''')
parser.add_argument('--type', help='type of command to run: generic, lfping, iperf3-client, iperf3-server, lfcurl', default="lfping")
@@ -228,7 +242,7 @@ python3 ./test_generic.py --upstream_port eth1
interval=1,
ssid=args.ssid,
upstream=args.upstream_port,
password=args.passwd,
passwd=args.passwd,
security=args.security,
test_duration=args.test_duration,
speedtest_min_up=args.speedtest_min_up,

View File

@@ -126,12 +126,9 @@ Generic command example:
./test_ipv4_connection.py --upstream_port eth1 \\
--radio wiphy0 \\
--num_stations 3 \\
--security {open|wep|wpa|wpa2|wpa3} \\
--security open {open|wep|wpa|wpa2|wpa3} \\
--ssid netgear \\
--passwd admin123 \\
--dest 10.40.0.1 \\
--test_duration 2m \\
--interval 1s \\
--passwd BLANK \\
--debug
''')
@@ -142,7 +139,6 @@ Generic command example:
num_stations_converted = int(args.num_stations)
num_sta = num_stations_converted
ws_event = LFCliBase("192.168.200.15", 8080)
station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=num_sta-1, padding_number_=10000)
ip_test = IPv4Test(lfjson_host, lfjson_port, ssid=args.ssid, password=args.passwd,
@@ -152,19 +148,20 @@ Generic command example:
ip_test.build()
if not ip_test.passes():
print(ip_test.get_fail_message())
ws_event.add_event(name="test_ipv4_connection.py", message=ip_test.get_fail_message())
ip_test.add_event(name="test_ipv4_connection.py", message=ip_test.get_fail_message())
exit(1)
ip_test.start(station_list, False, False)
ip_test.stop()
if not ip_test.passes():
print(ip_test.get_fail_message())
ws_event.add_event(name="test_ipv4_connection.py", message=ip_test.get_fail_message())
ip_test.add_event(name="test_ipv4_connection.py", message=ip_test.get_fail_message())
exit(1)
time.sleep(30)
ip_test.cleanup(station_list)
if ip_test.passes():
print("Full test passed, all stations associated and got IP")
ws_event.add_event(name="test_ipv4_connection.py", message="Full test passed, all stations associated and got IP")
ip_test.add_event(name="test_ipv4_connection.py", message="Full test passed, all stations associated and got IP")
#exit(1)
if __name__ == "__main__":
main()

View File

@@ -173,7 +173,7 @@ def main():
--num_stations 3 \\
--security {open|wep|wpa|wpa2|wpa3} \\
--ssid netgear \\
--url dl http://10.40.0.1 /dev/null \\
--url "dl http://10.40.0.1 /dev/null" \\
--password admin123 \\
--test_duration 2m \\
--debug

View File

@@ -165,15 +165,13 @@ def main():
test_ipv4_l4_ftp_upload.py
--------------------
Generic command example:
python3 ./test_ipv4_l4_ftp_wifi.py --upstream_port eth1 \\
./test_ipv4_l4_ftp_upload.py --upstream_port eth1 \\
--radio wiphy0 \\
--num_stations 3 \\
--security {open|wep|wpa|wpa2|wpa3} \\
--ssid netgear \\
--passwd admin123 \\
--dest 10.40.0.1 \\
--test_duration 2m \\
--interval 1s \\
--url "ul ftp://10.40.0.1 /dev/null" \\
--requests_per_ten 600 \\
--debug

View File

@@ -33,11 +33,11 @@ class IPV4L4(LFCliBase):
self.security = security
self.password = password
self.url = url
self.requests_per_ten = requests_per_ten
self.requests_per_ten = int(requests_per_ten)
self.number_template = number_template
self.sta_list = station_list
self.num_tests = num_tests
self.target_requests_per_ten = target_requests_per_ten
self.num_tests = int(num_tests)
self.target_requests_per_ten = int(target_requests_per_ten)
self.local_realm = realm.Realm(lfclient_host=self.host, lfclient_port=self.port)
self.station_profile = self.local_realm.new_station_profile()
@@ -63,7 +63,7 @@ class IPV4L4(LFCliBase):
if name in self.cx_profile.created_cx.keys():
expected_passes += 1
if info['urls/s'] * self.requests_per_ten >= self.target_requests_per_ten * .9:
# print(name, info['urls/s'], info['urls/s'] * self.requests_per_ten, self.target_requests_per_ten * .9)
print(name, info['urls/s'], info['urls/s'] * self.requests_per_ten, self.target_requests_per_ten * .9)
passes += 1
return passes == expected_passes
@@ -84,7 +84,7 @@ class IPV4L4(LFCliBase):
temp_stas = self.sta_list.copy()
# temp_stas.append(self.local_realm.name_to_eid(self.upstream_port)[2])
cur_time = datetime.datetime.now()
interval_time = cur_time + datetime.timedelta(minutes=10)
interval_time = cur_time + datetime.timedelta(minutes=2)
passes = 0
expected_passes = 0
self.station_profile.admin_up()
@@ -99,6 +99,7 @@ class IPV4L4(LFCliBase):
expected_passes += 1
while cur_time < interval_time:
time.sleep(1)
print(".",end="")
cur_time = datetime.datetime.now()
if self.cx_profile.check_errors(self.debug):
@@ -110,7 +111,7 @@ class IPV4L4(LFCliBase):
else:
self._fail("FAIL: Errors found getting to %s " % self.url, print_fail)
break
interval_time = cur_time + datetime.timedelta(minutes=10)
interval_time = cur_time + datetime.timedelta(minutes=2)
if passes == expected_passes:
self._pass("PASS: All tests passes", print_pass)
@@ -146,9 +147,6 @@ python3 ./test_ipv4_l4_urls_per_ten.py --upstream_port eth1 \\
--security {open|wep|wpa|wpa2|wpa3} \\
--ssid netgear \\
--passwd admin123 \\
--dest 10.40.0.1 \\
--test_duration 2m \\
--interval 1s \\
--requests_per_ten 600 \\
--num_tests 1 \\
--url "dl http://10.40.0.1 /dev/null" \\
@@ -173,7 +171,7 @@ python3 ./test_ipv4_l4_urls_per_ten.py --upstream_port eth1 \\
station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=num_sta-1, padding_number_=10000,
radio=args.radio)
ip_test = IPV4L4(args.mgr, lfjson_port, ssid=args.ssid, password=args.passwd, upstream_port=args.upstream_port,
ip_test = IPV4L4(args.mgr, lfjson_port, ssid=args.ssid, password=args.passwd, radio=args.radio, upstream_port=args.upstream_port,
security=args.security, station_list=station_list, url=args.url, num_tests=args.num_tests,
target_requests_per_ten=args.target_per_ten,
requests_per_ten=args.requests_per_ten)

View File

@@ -173,12 +173,10 @@ python3 ./test_ipv4_l4_wifi.py --upstream_port eth1 \\
--security {open|wep|wpa|wpa2|wpa3} \\
--ssid netgear \\
--passwd admin123 \\
--dest 10.40.0.1 \\
--test_duration 2m \\
--interval 1s \\
--requests_per_ten 600 \\
--direction {ul | dl} \\
--dest /dev/null \\
--dest /dev/null (or 10.40.0.1)\\
--debug
''')
@@ -197,7 +195,7 @@ python3 ./test_ipv4_l4_wifi.py --upstream_port eth1 \\
station_list = LFUtils.portNameSeries(prefix_="sta", start_id_=0, end_id_=num_sta-1, padding_number_=10000,
radio=args.radio)
ip_test = IPV4L4(args.mgr, lfjson_port, ssid=args.ssid, password=args.passwd,
ip_test = IPV4L4(args.mgr, lfjson_port, ssid=args.ssid, password=args.passwd, radio=args.radio,
security=args.security, station_list=station_list, direction=args.direction,dest=args.dest,
test_duration=args.test_duration, upstream_port=args.upstream_port,
requests_per_ten=args.requests_per_ten, _debug_on=args.debug)

View File

@@ -66,8 +66,6 @@ class IPV4VariableTime(LFCliBase):
def __get_rx_values(self):
cx_list = self.json_get("endp?fields=name,rx+bytes", debug_=self.debug)
# print(self.cx_profile.created_cx.values())
# print("==============\n", cx_list, "\n==============")
cx_rx_map = {}
for cx_name in cx_list['endpoint']:
if cx_name != 'uri' and cx_name != 'handler':
@@ -85,8 +83,6 @@ class IPV4VariableTime(LFCliBase):
expected_passes += 1
if new_list[item] > old_list[item]:
passes += 1
# print(item, new_list[item], old_list[item], passes, expected_passes)
if passes == expected_passes:
return True
else:
@@ -142,10 +138,6 @@ class IPV4VariableTime(LFCliBase):
time.sleep(1)
new_cx_rx_values = self.__get_rx_values()
# print(old_cx_rx_values, new_cx_rx_values)
# print("\n-----------------------------------")
# print(cur_time, end_time, cur_time + datetime.timedelta(minutes=1))
# print("-----------------------------------\n")
expected_passes += 1
if self.__compare_vals(old_cx_rx_values, new_cx_rx_values):
passes += 1
@@ -183,24 +175,22 @@ def main():
prog='test_ipv4_variable_time.py',
# formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=argparse.RawTextHelpFormatter,
epilog='''\
Useful Information:
1. TBD
''',
description='''\
test_ipv4_variable_time.py:
--------------------
TBD
---------------------
Generic command layout:
python ./test_ipv4_variable_time.py --upstream_port <port> --radio <radio 0> <stations> <ssid> <ssid password> <security type: wpa2, open, wpa3> --debug
Note: multiple --radio switches may be entered up to the number of radios available:
--radio <radio 0> <stations> <ssid> <ssid password> --radio <radio 01> <number of last station> <ssid> <ssid password>
python3 ./test_ipv4_variable_time.py --upstream_port eth1 --radio wiphy0 32 candelaTech-wpa2-x2048-4-1 candelaTech-wpa2-x2048-4-1 wpa2 --radio wiphy1 64 candelaTech-wpa2-x2048-5-3 candelaTech-wpa2-x2048-5-3 wpa2
./test_ipv4_variable_time.py
--upstream_port eth1
--radio wiphy3
--num_stations 4
-ssid jedway-wpa2-x2048-4-1
-passwd jedway-wpa2-x2048-4-1
--security {wpa2|open|wpa|wpa3}
--a_min 250000
--b_min 260000
--test_duration 2m
--debug
''')
parser.add_argument('--a_min', help='--a_min bps rate minimum for side_a', default=256000)

View File

@@ -288,7 +288,6 @@ test_ipv4_ttls.py:
enable_pkc=args.enable_pkc,
)
ttls_test.cleanup(station_list)
#ttls_test.timeout = 60
ttls_test.build()
if not ttls_test.passes():
print(ttls_test.get_fail_message())

0
py-scripts/test_l3_scenario_throughput.py Normal file → Executable file
View File

345
py-scripts/test_status_msg.py Executable file
View File

@@ -0,0 +1,345 @@
#!/usr/bin/env python3
import os
import sys
if sys.version_info[0] != 3:
print("This script requires Python 3")
exit(1)
if 'py-json' not in sys.path:
sys.path.append(os.path.join(os.path.abspath('..'), 'py-json'))
import argparse
from LANforge.lfcli_base import LFCliBase
import time
from uuid import uuid1
import pprint
from pprint import pprint
class TestStatusMessage(LFCliBase):
def __init__(self, host, port,
_deep_clean=False,
_debug_on=False,
_exit_on_error=False,
_exit_on_fail=False):
super().__init__(host, port, _debug=_debug_on, _halt_on_error=_exit_on_error, _exit_on_fail=_exit_on_fail)
self.deep_clean = _deep_clean
self.check_connect()
def build(self):
"""create a new session"""
new_session = uuid1()
self.status_msg_url = "/status-msg"
self.session_url = "/status-msg/"+str(new_session)
# print("----- ----- ----- ----- ----- PUT ----- ----- ----- ----- ----- ----- ")
self.json_put(self.session_url, _data={})
# we should see list of sessions
try:
#print("----- ----- ----- ----- ----- GET ----- ----- ----- ----- ----- ----- ")
session_response = self.json_get(self.status_msg_url)
if self.debug:
pprint(session_response)
if "sessions" not in session_response:
print("----- ----- ----- ----- ----- BAD ----- ----- ----- ----- ----- ----- ")
self._fail("response lacks sessions element")
if len(session_response["sessions"]) < 2:
self._fail("why do we have less than two sessions?")
for session in session_response["sessions"]:
#print("----- ----- ----- ----- ----- SESSION ----- ----- ----- ----- ----- ----- ")
pprint(session)
self._pass("session created")
except ValueError as ve:
print("----- ----- ----- ----- ----- what??? ----- ----- ----- ----- ----- ----- ")
self._fail(ve)
return
def start(self, print_pass=False, print_fail=False):
"""
create a series of messages
:return: None
"""
#print("----- ----- ----- ----- ----- START ----- %s ----- ----- ----- ----- ----- " % self.session_url)
message_response = self.json_get(self.session_url)
if self.debug:
pprint(message_response)
if "empty" in message_response:
self._pass("empty response, zero messages")
elif "messages" in message_response:
messages_a = message_response["messages"]
if len(messages_a) > 0:
self._fail("we should have zero messages")
for msg_num in ( 1, 2, 3, 4, 5 ):
#print("----- ----- ----- ----- ----- ----- %s ----- ----- ----- ----- ----- " % msg_num)
#print("session url: "+self.session_url)
self.msg_count = msg_num
self.json_post(self.session_url, {
"key": "test_status_message.py",
"content-type":"application/json",
"message":"message %s"%msg_num
})
message_response = self.json_get(self.session_url)
if len(message_response["messages"]) != msg_num:
pprint(message_response)
self._fail("we should have %s messages"%msg_num)
self._pass("created and listed %s messages counted"%msg_num)
def stop(self):
"""
make sure we read those messages
:return: None
"""
message_list_response = self.json_get(self.session_url)
if "empty" in message_list_response:
self._fail("empty response, we expect 1 or more messages")
msg_num = 0
for message_o in message_list_response["messages"]:
msg_url = message_o["_links"]
print("Message url: "+msg_url)
message_response = self.json_get(msg_url)
if self.debug:
pprint(message_response)
for message_o in message_response["messages"]:
msg_num += 1
content_o = message_o
print("id %s" % content_o["message_id"])
print("key %s" % content_o["message"]["key"])
print("content-type %s" % content_o["message"]["content-type"])
print("message %s" % content_o["message"]["message"])
if msg_num != self.msg_count:
self._fail("(stop) expected %s messages, saw %s" % (self.msg_count, msg_num))
else:
self._pass("saw correct number of messages")
def cleanup(self):
"""delete messages and delete the session"""
message_list_response = self.json_get(self.session_url)
if "empty" in message_list_response:
self._fail("empty response, we expect 1 or more messages")
last_link = ""
msg_num = 0
for message_o in message_list_response["messages"]:
msg_url = message_o["_links"]
# print("Delete Message url: "+msg_url)
last_link = message_o["_links"]
msg_num += 1
if msg_num != self.msg_count:
self._fail("(cleanup) expected %s messages, saw %s" % (self.msg_count, msg_num))
message_response = self.json_delete(last_link)
if self.debug:
pprint(message_response)
# check message removal
message_list_response = self.json_get(self.session_url)
msg_num = len(message_list_response["messages"])
if msg_num != (self.msg_count - 1):
self._fail("(cleanup) expected %s messages, saw %s" % ((self.msg_count - 1), msg_num))
else:
self._pass("(cleanup) messages decreased by one")
all_url = self.session_url + "/all"
message_response = self.json_delete(all_url)
if self.debug:
pprint(message_response)
message_list_response = self.json_get(self.session_url)
if self.debug:
pprint(message_list_response)
if "messages" in message_list_response:
msg_num = len(message_list_response["messages"])
elif "empty" in message_list_response:
msg_num = 0
if (msg_num == 0):
self._pass("deleted all messages in session")
else:
self._fail("failed to delete all messages in session")
# make sure we fail on removing session incorrectly
try:
if self.debug:
print("--- del -------------------- -------------------- --------------------")
self.exit_on_error=False
self.halt_on_error=False
message_response = self.json_delete(self.session_url, debug_=False)
if self.debug:
print("--- ~del -------------------- -------------------- --------------------")
except ValueError as ve:
print("- - - - - - - - - - - - - - - - - - - - - - -")
print(ve)
print("- - - - - - - - - - - - - - - - - - - - - - -")
sessions_list_response = self.json_get("/status-msg")
if self.debug:
pprint(sessions_list_response)
session_list = sessions_list_response["sessions"]
counter = 0
for session_o in session_list:
if self.debug:
print("session %s link %s " % (self.session_url, session_o["_links"]))
if session_o["_links"] == self.session_url:
counter += 1
self._pass("session not deleted")
break
if counter == 0:
self._fail("session incorrectly deleted")
try:
if self.debug:
print("--- del -------------------- -------------------- --------------------")
self.exit_on_error=False
self.halt_on_error=False
message_response = self.json_delete(self.session_url+"/this", debug_=False)
if self.debug:
print("--- ~del -------------------- -------------------- --------------------")
except ValueError as ve:
print(ve)
sessions_list_response = self.json_get("/status-msg")
if self.debug:
pprint(sessions_list_response)
session_list = sessions_list_response["sessions"]
counter = 0
for session_o in session_list:
if session_o["_links"] == self.session_url:
counter += 1
self._fail("session not deleted: "+session_o["_links"])
break
if counter == 0:
self._pass("session correctly deleted")
# make sure we fail on removing session zero
if not self.deep_clean:
return True
print("Deleting all sessions...")
counter = 0
for session_o in session_list:
counter += 1
self.json_delete(session_o["_links"]+"/all")
print("cleaned %s sessions" % counter)
counter = 0
for session_o in session_list:
if session_o["session-id"] == "0":
continue
counter += 1
self.json_delete(session_o["_links"]+"/this")
print("deleted %s sessions" % counter)
def main():
lfjson_port = 8080
parser = LFCliBase.create_bare_argparse(
prog=__file__,
# formatter_class=argparse.RawDescriptionHelpFormatter,
formatter_class=argparse.RawTextHelpFormatter,
description="""
Test the status message passing functions of /status-msg:
- create a session: PUT /status-msg/<new-session-id>
- post message: POST /status-msg/<new-session-id>
- list sessions: GET /status-msg/
- list messages for session: GET /status-msg/<new-session-id>
- delete message: DELETE /status-msg/<new-session-id>/message-id
- delete session: DELETE /status-msg/<new-session-id>/this
- delete all messages in session: DELETE /status-msg/<new-session-id>/all
""")
parser.add_argument('--action', default="run_test", help="""
Actions can be:
run_test : run a messaging test
new : create new session
update : add message to session, requires --session, --key, --message
read : read message(s) from session, requires --session
list : list messages from session
delete : delete message, all messages using session/all or session using session/this
""")
parser.add_argument('--session', type=str, help='explicit session or session/message-id')
parser.add_argument('--deep_clean', type=bool, help='remove all messages and all sessions')
parser.add_argument('--key', type=str, help='how to key the message')
parser.add_argument('--message', type=str, help='message to include')
args = parser.parse_args()
status_messages = TestStatusMessage(args.mgr,
lfjson_port,
_debug_on=False,
_exit_on_error=False,
_exit_on_fail=False)
if args.action == "new":
if args.session is not None:
status_messages.json_put("/status-msg/"+args.session, {})
else:
u = uuid1()
status_messages.json_put("/status-msg/"+u, {})
print("created session /status-msg/"+u)
return
if args.action == "update":
if args.session is None:
print("requires --session")
return
if args.key is None:
print("requires --key")
return
if args.message is None:
print("requires --message")
return
status_messages.json_post("/status-msg/"+args.session, {
"key": args.key,
"content-type": "text/plain",
"message": args.message
})
return
if args.action == "list":
if args.session is None:
response_o = status_messages.json_get("/status-msg/")
pprint(response_o["sessions"])
else:
response_o = status_messages.json_get("/status-msg/"+args.session)
pprint(response_o["messages"])
return
if args.action == "read":
if args.session is None:
print("requires --session")
return
response_o = status_messages.json_get("/status-msg/"+args.session)
pprint(response_o)
return
if args.action == "delete":
if args.session is None:
print("requires --session")
return
response_o = status_messages.json_delete("/status-msg/"+args.session)
pprint(response_o)
return
if args.action == "run_test":
if args.deep_clean:
status_messages.deep_clean = True
status_messages.build()
if not status_messages.passes():
print(status_messages.get_fail_message())
exit(1)
status_messages.start(False, False)
status_messages.stop()
if not status_messages.passes():
print(status_messages.get_fail_message())
exit(1)
status_messages.cleanup()
if status_messages.passes():
print("Full test passed, all messages read and cleaned up")
exit(0)
if __name__ == "__main__":
main()

140
py-scripts/testgroup.py Executable file
View File

@@ -0,0 +1,140 @@
#!/usr/bin/env python3
import sys
if sys.version_info[0] != 3:
print("This script requires Python 3")
exit(1)
if 'py-json' not in sys.path:
sys.path.append('../py-json')
from LANforge.lfcli_base import LFCliBase
from LANforge.LFUtils import *
from LANforge import LFUtils
import argparse
import realm
class TestGroup(LFCliBase):
def __init__(self, host, port,
group_name=None,
add_cx_list=[],
rm_cx_list=[],
tg_action=None,
cx_action=None,
list_groups=None,
show_group=None):
self.local_realm = realm.Realm(lfclient_host=host, lfclient_port=port)
self.tg_profile = self.local_realm.new_test_group_profile()
if group_name is None and list_groups is None and (tg_action is not None or cx_action is not None or
add_cx_list is not None or rm_cx_list is not None or show_group is not None):
raise ValueError("Group name must be set if manipulating test groups")
else:
self.tg_profile.group_name = group_name
self.tg_action = tg_action
self.cx_action = cx_action
self.list_groups = list_groups
self.show_group = show_group
self.add_cx_list = add_cx_list
self.rm_cx_list = rm_cx_list
def do_cx_action(self):
if self.cx_action == 'start':
print("Starting %s" % self.tg_profile.group_name)
self.tg_profile.start_group()
elif self.cx_action == 'stop':
print("Stopping %s" % self.tg_profile.group_name)
self.tg_profile.stop_group()
elif self.cx_action == 'quiesce':
print("Quiescing %s" % self.tg_profile.group_name)
self.tg_profile.quiesce_group()
def do_tg_action(self):
if self.tg_action == 'add':
print("Creating %s" % self.tg_profile.group_name)
self.tg_profile.create_group()
if self.tg_action == 'del':
print("Removing %s" % self.tg_profile.group_name)
if self.tg_profile.check_group_exists():
self.tg_profile.remove_group()
else:
print("%s not found, no action taken" % self.tg_profile.group_name)
def show_info(self):
if self.list_groups:
print("Current Test Groups: ")
for group in self.tg_profile.list_groups():
print(group)
if self.show_group:
print("show_group not yet implemented")
def update_cxs(self):
if len(self.add_cx_list) > 0:
for cx in self.add_cx_list:
self.tg_profile.add_cx(cx)
self.tg_profile.cx_list.append(cx)
if len(self.rm_cx_list) > 0:
for cx in self.rm_cx_list:
self.tg_profile.rm_cx(cx)
if cx in self.tg_profile.cx_list:
self.tg_profile.cx_list.remove(cx)
def main():
parser = LFCliBase.create_bare_argparse(
prog='testgroup.py',
formatter_class=argparse.RawTextHelpFormatter,
epilog='''Control and query test groups\n''',
description='''testgroup.py
--------------------
Generic command example:
''')
parser.add_argument('--group_name', help='specify the name of the test group to use', default=None)
parser.add_argument('--list_groups', help='list all existing test groups', action='store_true', default=False)
tg_group = parser.add_mutually_exclusive_group()
tg_group.add_argument('--add_group', help='add new test group', action='store_true', default=False)
tg_group.add_argument('--del_group', help='delete test group', action='store_true', default=False)
parser.add_argument('--show_group', help='show connections in current test group', action='store_true', default=False)
cx_group = parser.add_mutually_exclusive_group()
cx_group.add_argument('--start_group', help='start all cxs in chosen test group', default=None)
cx_group.add_argument('--stop_group', help='stop all cxs in chosen test group', default=None)
cx_group.add_argument('--quiesce_group', help='quiesce all cxs in chosen test groups', default=None)
parser.add_argument('--add_cx', help='add cx to chosen test group', nargs='*', default=[])
parser.add_argument('--remove_cx', help='remove cx from chosen test group', nargs='*', default=[])
args = parser.parse_args()
tg_action = None
cx_action = None
if args.add_group:
tg_action = 'add'
elif args.del_group:
tg_action = 'del'
if args.start_group:
cx_action = 'start'
elif args.stop_group:
cx_action = 'stop'
elif args.quiesce_group:
cx_action = 'quiesce'
tg = TestGroup(host=args.mgr, port=args.mgr_port,
group_name=args.group_name,
add_cx_list=args.add_cx, rm_cx_list=args.remove_cx, cx_action=cx_action,
tg_action=tg_action, list_groups=args.list_groups, show_group=args.show_group)
tg.do_tg_action()
tg.update_cxs()
tg.do_cx_action()
tg.show_info()
if __name__ == "__main__":
main()

0
py-scripts/wlan_capacity_calculator.py Normal file → Executable file
View File

0
py-scripts/ws_generic_monitor_test.py Normal file → Executable file
View File