Files
wlan-lanforge-scripts/stationStressTest.py

430 lines
11 KiB
Python
Executable File

#!/usr/bin/env python3
import os
import sys
import time
sys.path.append('py-json')
import json
import pprint
import datetime
from LANforge import LFRequest
from LANforge import LFUtils
import argparse
import re
import math
import string
import emailHelper
debugOn = False
sender = "lanforge@candelatech.com"
def jsonReq(mgrURL, reqURL, data, debug=False):
lf_r = LFRequest.LFRequest(mgrURL + reqURL)
lf_r.addPostData(data)
if debug:
json_response = lf_r.jsonPost(debug)
LFUtils.debug_printer.pprint(json_response)
sys.exit(1)
else:
lf_r.jsonPost(debug)
def execWrap(cmd):
if os.system(cmd) != 0:
print("\nError with " + cmd + ",bye\n")
exit(1)
def getJsonInfo(mgrURL, reqURL):
lf_r = LFRequest.LFRequest(mgrURL + reqURL)
json_response = lf_r.getAsJson(debugOn)
return json_response
parser = argparse.ArgumentParser(description="Create max stations for each radio")
parser.add_argument("--test_duration", type=str, help="Full duration for the test to run. Should be specified by a number followed by a character. d for days, h for hours, m for minutes, s for seconds")
parser.add_argument("--test_end_time", type=str, help="Specify a time and date to end the test. Should be formatted as year-month-date_hour:minute. Date should be specified in numbers and time should be 24 hour format. Ex: 2020-5-14_14:30")
parser.add_argument("--report_interval", type=str, help="How often a report is made. Should be specified by a number followed by a character. d for days, h for hours, m for minutes, s for seconds")
parser.add_argument("--output_dir", type=str, help="Directory to ouptut to")
parser.add_argument("--output_prefix", type=str, help="Name of the file. Timestamp and .html will be appended to the end")
parser.add_argument("--email", type=str, help="Email address of recipient")
args = None
try:
args = parser.parse_args()
if (args.test_duration is not None):
pattern = re.compile("^(\d+)([dhms]$)")
td = pattern.match(args.test_duration)
if td != None:
durTime = int(td.group(1))
durMeasure = str(td.group(2))
now = datetime.datetime.now()
if durMeasure == "d":
durationTime = datetime.timedelta(days = durTime)
elif durMeasure == "h":
durationTime = datetime.timedelta(hours = durTime)
elif durMeasure == "m":
durationTime = datetime.timedelta(minutes = durTime)
else:
durationTime = datetime.timedelta(seconds = durTime)
else:
parser.print_help()
parser.exit()
elif (args.test_end_time is not None):
now = datetime.datetime.now()
try:
endTime = datetime.datetime.strptime(args.test_end_time,"%Y-%m-%d_%H:%M")
if endTime < now:
raise ValueError
parser.print_help()
parser.exit()
else:
curTime = datetime.datetime.now()
durationTime = endTime - curTime
except ValueError as exception:
print(exception)
parser.print_help()
parser.exit()
else:
parser.print_help()
parser.exit()
if (args.report_interval is not None):
pattern = re.compile("^(\d+)([dhms])$")
ri = pattern.match(args.report_interval)
if ri != None:
intTime = int(ri.group(1))
intMeasure = str(ri.group(2))
if intMeasure == "d":
intervalTime = datetime.timedelta(days = intTime)
elif intMeasure == "h":
intervalTime = datetime.timedelta(hours = intTime)
elif intMeasure == "m":
intervalTime = datetime.timedelta(minutes = intTime)
else:
intervalTime = datetime.timedelta(seconds = intTime)
else:
parser.print_help()
parser.exit()
else:
parser.print_help()
parser.exit()
if (args.output_dir != None):
outputDir = args.output_dir
else:
parser.print_help()
parser.exit()
if (args.output_prefix != None):
outputPrefix = args.output_prefix
else:
parser.print_help()
parser.exit()
if (args.email != None):
recipient = args.email
else:
parser.print_help()
parser.exit()
except Exception as e:
logging.exception(e)
usage()
exit(2)
stations = []
radios = {"wiphy0":200, #max 200
"wiphy1":200, #max 200
"wiphy2":64, #max 64
"wiphy3":200} #max 200
#radioName:numStations
radio_ssid_map = {"wiphy0":"jedway-wpa2-x2048-4-1",
"wiphy1":"jedway-wpa2-x2048-5-3",
"wiphy2":"jedway-wpa2-x2048-5-1",
"wiphy3":"jedway-wpa2-x2048-4-4"}
ssid_passphrase_map = {"jedway-wpa2-x2048-4-1":"jedway-wpa2-x2048-4-1",
"jedway-wpa2-x2048-5-3":"jedway-wpa2-x2048-5-3",
"jedway-wpa2-x2048-5-1":"jedway-wpa2-x2048-5-1",
"jedway-wpa2-x2048-4-4":"jedway-wpa2-x2048-4-4"}
paddingNum = 1000 #uses all but the first number to create names for stations
mgrURL = "http://localhost:8080/"
#clean up old stations
print("Cleaning up old Stations")
for radio, numStations in radios.items():
for i in range(0,numStations):
staName = "sta" + radio[-1:] + str(paddingNum + i)[1:]
if getJsonInfo(mgrURL, "port/1/1/"+staName) != None:
reqURL = "cli-json/rm_vlan"
data = {
"shelf":1,
"resource":1,
"port":staName
}
jsonReq(mgrURL, reqURL, data)
reqURL = "cli-json/rm_cx"
data = {
"test_mgr":"default_tm",
"cx_name":staName
}
jsonReq(mgrURL, reqURL, data)
reqURL = "cli-json/rm_endp"
data = {
"endp_name":staName + "-A"
}
jsonReq(mgrURL, reqURL, data)
reqURL = "cli-json/rm_endp"
data = {
"endp_name":staName + "-B"
}
#create new stations
print("Creating Stations")
reqURL = "cli-json/add_sta"
for radio, numStations in radios.items():
for i in range(0,numStations):
staName = "sta" + radio[-1:] + str(paddingNum + i)[1:]
stations.append(staName)
data = {
"shelf":1,
"resource":1,
"radio":radio,
"sta_name":staName,
"ssid":radio_ssid_map[radio],
"key":ssid_passphrase_map[radio_ssid_map[radio]],
"mode":1,
"mac":"xx:xx:xx:xx:*:xx",
"flags":0x400
}
#print("Creating station {}".format(staName))
jsonReq(mgrURL, reqURL, data)
time.sleep(0.5)
#LFUtils.portDhcpUpRequest(1, staName)
time.sleep(10)
#check eth1 for ip
eth1IP = getJsonInfo(mgrURL, "port/1/1/eth1")
if eth1IP['interface']['ip'] == "0.0.0.0":
print("Switching eth1 to dhcp")
LFUtils.portDownRequest(1,"eth1")
time.sleep(1)
reqURL = "cli-json/set_port"
data = {
"shelf":1,
"resource":1,
"port":"eth1",
"current_flags":0x80000000,
"interest":0x4002
}
jsonReq(mgrURL,reqURL,data)
#LFUtils.portDhcpUpRequest(1,"eth1")
time.sleep(5)
LFUtils.portUpRequest(1,"eth1")
time.sleep(10)
#create cross connects
print("Creating cross connects")
for staName in stations:
cmd = ("./lf_firemod.pl --action create_cx --cx_name " + staName + " --use_ports eth1," + staName + " --use_speeds 2600,2600 --endp_type udp > sst.log")
execWrap(cmd)
#set stations to dchp up
print("Turning on DHCP for stations")
for staName in stations:
#print("Setting {} flags".format(staName))
reqURL = "cli-json/set_port"
data = {
"shelf":1,
"resource":1,
"port":staName,
"current_flags":0x80000000,
"interest":0x4002
}
jsonReq(mgrURL,reqURL,data)
#LFUtils.portDhcpUpRequest(1,staName)
time.sleep(15)
#start traffic through cxs
print("Starting CX Traffic")
for name in stations:
cmd = ("./lf_firemod.pl --mgr localhost --quiet 0 --action do_cmd --cmd \"set_cx_state default_tm " + name + " RUNNING\" >> sst.log")
execWrap(cmd)
#create weblog for monitoring stations
curTime = datetime.datetime.now().strftime("%Y-%m-%d_%H%M")
webLog = outputDir + outputPrefix + "{}.html".format(curTime)
try:
f = open(webLog,"w")
except IOError as err:
print(err)
print("Please ensure correct permissions have been assigned in target directory")
sys.exit()
top = """<html>
<head>
<title>Test report</title>
<style>
body, td, p, div, span { font-size: 8pt; }
h1, h2, h3 { text-align: center; font-family: "Century Gothic",Arial,Helvetica,sans;}
</style>
</head>
<body>
<h1>Long test on %s</h1>
<p2>Key</p2>
<p1 style="background-color:rgb(0,255,0);">All stations associated and with ip</p1>
<p1 style="background-color:rgb(255,200,0);">All stations associated and at least one without ip</p1>
<p1 style="background-color:rgb(255,150,150);">No stations associated and without ip</p1>
<table>
""" % datetime.date.today()
f.write(top)
f.close()
f = open(webLog, "a")
f.write("<tr>\n")
for name in radios:
f.write("<th>{}</th>\n".format(name))
f.write("</tr>\n")
curTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
subject = "Station Test Begin Report Notification"
body = "Report begun at {}\n See {}".format(curTime, webLog)
email = emailHelper.writeEmail(body)
emailHelper.sendEmail(email, sender, recipient, subject)
print("Logging Info to {}".format(webLog))
curTime = datetime.datetime.now()
endTime = curTime + durationTime
while curTime <= (endTime):
f.write("<tr>\n")
for radio, numStations in radios.items():
withoutIP = 0
dissociated = 0
good = 0
for i in range(0,numStations):
staName = "sta" + radio[-1:] + str(paddingNum + i)[1:]
staStatus = getJsonInfo(mgrURL, "port/1/1/" + staName)
#print(staName)
if staStatus['interface']['ip'] == "0.0.0.0":
withoutIP += 1
if staStatus['interface']['ap'] == None:
dissociated += 1
else:
good += 1
if withoutIP and not dissociated:
f.write("<td style=\"background-color:rgb(255,200,0);\">{}/{}</td>\n".format(good,numStations)) #without IP assigned
elif dissociated:
f.write("<td style=\"background-color:rgb(255,150,150);\">{}/{}</td>\n".format(good,numStations)) #dissociated from AP
else:
f.write("<td style=\"background-color:rgb(0,255,0);\">{}/{}</td>\n".format(good,numStations)) #with IP and associated
f.write("<td>{}</td>\n".format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M")))
f.write("</tr>\n")
curTime = datetime.datetime.now()
intTime = curTime + intervalTime
while curTime <= intTime:
#print(curTime, intTime)
time.sleep(1)
curTime = datetime.datetime.now()
#sleep(1)
curTime = datetime.datetime.now()
f.write("</table></body></html>\n")
f.close()
curTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
subject = "Station Test End Report Notification"
body = "Report finished at {} see {}".format(curTime, webLog)
email = emailHelper.writeEmail(body)
emailHelper.sendEmail(email, sender, recipient, subject)
print("Stopping CX Traffic")
for name in stations:
cmd = ("./lf_firemod.pl --mgr localhost --quiet 0 --action do_cmd --cmd \"set_cx_state default_tm " + name + " STOPPED\" >> sst.log")
execWrap(cmd)
time.sleep(10)
#remove all created stations and cross connects
print("Cleaning Up...")
for staName in stations:
reqURL = "cli-json/rm_vlan"
data = {
"shelf":1,
"resource":1,
"port":staName
}
jsonReq(mgrURL, reqURL, data)
reqURL = "cli-json/rm_cx"
data = {
"test_mgr":"default_tm",
"cx_name":staName
}
jsonReq(mgrURL, reqURL, data)
reqURL = "cli-json/rm_endp"
data = {
"endp_name":staName + "-A"
}
jsonReq(mgrURL, reqURL, data)
reqURL = "cli-json/rm_endp"
data = {
"endp_name":staName + "-B"
}
jsonReq(mgrURL, reqURL, data)