cowmesh-network-test/cowmesh_router_iperf_test.py

154 lines
5.0 KiB
Python
Raw Normal View History

2023-04-20 11:00:28 +00:00
"""
script to do a basic holistic test of the cowmesh network,
testing internet connection speed using iperf,
between all nodes in the mesh
"""
2023-04-27 08:46:42 +00:00
import datetime
2023-04-20 11:00:28 +00:00
import os
import re
import time
import asyncio, asyncssh, sys
import paramiko
import subprocess
import json
2023-05-01 16:26:45 +00:00
from cowmesh_constants import NODES, HOST_TO_IP
2023-04-20 11:00:28 +00:00
2023-04-28 14:55:31 +00:00
from cowmesh_helpers import cleanup_iperf_server
2023-04-20 11:00:28 +00:00
PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
SECRETS_PATH = os.path.join(PROJECT_PATH, "secrets.json")
with open(SECRETS_PATH, 'r') as f:
SECRETS = json.loads(f.read())
2023-04-28 12:04:41 +00:00
class CowmeshRouterIperfTester:
2023-04-20 11:00:28 +00:00
2023-05-01 16:26:45 +00:00
def __init__(self, log=None, debug=False, time=10):
2023-04-27 08:46:42 +00:00
if log:
self.log = log
self.debug = debug
2023-05-01 16:26:45 +00:00
self.time = time
2023-04-28 14:55:31 +00:00
self.results = {}
2023-04-20 11:00:28 +00:00
2023-04-27 08:46:42 +00:00
async def log(self, msg):
print(msg)
2023-04-20 11:00:28 +00:00
2023-04-27 08:46:42 +00:00
async def debug_log(self, msg):
if self.debug:
await self.log(msg)
2023-04-20 11:00:28 +00:00
2023-04-27 08:46:42 +00:00
async def test_between_two_nodes(self, node_a, node_b):
await self.log("++ running test from {} to {}".format(node_a, node_b))
2023-04-20 11:00:28 +00:00
u_name = 'root'
pswd = SECRETS["ROUTER_PASSWORD"]
myconn = paramiko.SSHClient()
myconn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
2023-04-27 08:46:42 +00:00
myconn.connect(node_a, username =u_name, password=pswd)
2023-05-01 16:26:45 +00:00
ip = HOST_TO_IP[node_b]
2023-04-20 11:00:28 +00:00
2023-04-28 12:04:41 +00:00
remote_cmd = 'iperf -c {ip} -p 5001 -t {seconds}'.format(ip=ip, seconds=self.time)
2023-04-20 11:00:28 +00:00
(stdin, stdout, stderr) = myconn.exec_command(remote_cmd)
2023-04-27 08:46:42 +00:00
output = str(stdout.read())
await self.debug_log("output: {}".format(output))
await self.debug_log("errors: {}".format(stderr.read()))
2023-04-20 11:00:28 +00:00
myconn.close()
2023-04-27 08:46:42 +00:00
match = re.search("(\S+) Mbits", output)
if match:
to_return = match.group(1)
else:
2023-05-01 16:26:45 +00:00
match = re.search("(\S+) Kbits", output)
if match:
to_return = match.group(1)
to_return = float(to_return) / 1000.0
else:
to_return = None
2023-04-27 08:46:42 +00:00
return to_return
async def start_iperf_servers(self):
2023-05-01 16:26:45 +00:00
for node in NODES:
try:
print("++ starting iperf server on {}".format(node))
u_name = 'root'
pswd = SECRETS["ROUTER_PASSWORD"]
myconn = paramiko.SSHClient()
myconn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
myconn.connect(node, username=u_name, password=pswd)
remote_cmd = 'iperf -s &'
(stdin, stdout, stderr) = myconn.exec_command(remote_cmd)
await self.debug_log("{}".format(stdout.read()))
await self.debug_log("{}".format(type(myconn)))
await self.debug_log("Options available to deal with the connections are many like\n{}".format(dir(myconn)))
myconn.close()
except:
try:
await self.log("++ error starting iperf server on {}".format(node))
except:
continue
2023-04-27 08:46:42 +00:00
2023-04-28 14:55:31 +00:00
async def cleanup_iperf_servers(self):
await self.log("shutting down iperf servers")
2023-05-01 16:26:45 +00:00
for node in NODES:
2023-04-28 14:55:31 +00:00
user = "root"
password = SECRETS["ROUTER_PASSWORD"]
2023-05-01 16:26:45 +00:00
ip = HOST_TO_IP[node]
2023-04-28 14:55:31 +00:00
await cleanup_iperf_server(node=node, ip=ip, username=user, password=password, log=self.log)
2023-04-27 08:46:42 +00:00
async def run_test(self):
2023-05-01 16:26:45 +00:00
try:
await self.start_iperf_servers()
except:
pass
2023-04-27 08:46:42 +00:00
2023-05-01 16:26:45 +00:00
for node_a in NODES:
for node_b in NODES:
2023-04-27 08:46:42 +00:00
if node_a == node_b:
await self.debug_log("skip self")
continue
2023-05-01 16:26:45 +00:00
try:
r = await self.test_between_two_nodes(node_a, node_b)
result_key = "{} -> {}".format(node_a, node_b)
self.results[result_key] = r
except Exception as e:
try:
await self.log("++ error running test between {} and {}: {}".format(node_a, node_b, e))
except:
continue
2023-04-28 14:55:31 +00:00
# try:
# await self.cleanup_iperf_servers()
# except:
# await self.log("error shutting down iperf servers")
2023-04-20 11:00:28 +00:00
2023-04-27 08:46:42 +00:00
async def output_results(self):
results_str = ""
now = datetime.datetime.now()
date = now.date()
time = now.time()
results_str += "**** iperf results on {date:%m-%d-%Y} at {time:%H:%M}:\n\n".format(date=date, time=time)
2023-04-28 14:55:31 +00:00
for test_name, result in self.results.items():
2023-04-27 08:46:42 +00:00
results_str += "{}: {} mbps\n".format(test_name, result)
await self.log(results_str)
2023-04-20 11:00:28 +00:00
2023-04-27 08:46:42 +00:00
if __name__ == "__main__":
try:
2023-04-28 12:04:41 +00:00
tester = CowmeshRouterIperfTester()
2023-04-20 11:00:28 +00:00
2023-04-27 08:46:42 +00:00
async def main_fun():
await tester.run_test()
await tester.output_results()
2023-04-20 11:00:28 +00:00
2023-04-27 08:46:42 +00:00
asyncio.get_event_loop().run_until_complete(main_fun())
2023-04-20 11:00:28 +00:00
2023-04-27 08:46:42 +00:00
except (OSError, asyncssh.Error) as exc:
sys.exit('SSH connection failed: ' + str(exc))