Compare commits
2 Commits
098948c98f
...
a138b92f3a
Author | SHA1 | Date | |
---|---|---|---|
|
a138b92f3a | ||
|
1fb2a1d1c7 |
22
cowmesh_constants.py
Normal file
22
cowmesh_constants.py
Normal file
@ -0,0 +1,22 @@
|
||||
NODES = [
|
||||
"jaaga",
|
||||
"redcottage",
|
||||
"new-gazebo2",
|
||||
"kotemanetp",
|
||||
"guard",
|
||||
"ddhills",
|
||||
"bambino",
|
||||
"thimmanayaka"
|
||||
]
|
||||
|
||||
HOST_TO_IP = {
|
||||
"jaaga": "10.56.121.19",
|
||||
"redcottage": "10.56.58.194",
|
||||
"redcottage2": "10.56.114.42",
|
||||
"new-gazebo2": "10.56.114.42",
|
||||
"new-gazebo": "10.56.113.2",
|
||||
"guard": "10.56.121.73",
|
||||
"kotemanetp": "10.56.40.113",
|
||||
"thimmanayaka": "10.56.39.34",
|
||||
"bambino": "10.56.0.102"
|
||||
}
|
17
cowmesh_helpers.py
Normal file
17
cowmesh_helpers.py
Normal file
@ -0,0 +1,17 @@
|
||||
import paramiko
|
||||
|
||||
|
||||
async def cleanup_iperf_server(node, ip, username, password, log):
|
||||
await log("++ stopping iperf server on {}".format(node))
|
||||
|
||||
myconn = paramiko.SSHClient()
|
||||
myconn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
myconn.connect(ip, username=username, password=password)
|
||||
|
||||
remote_cmd = 'pgrep iperf | xargs kill'
|
||||
(stdin, stdout, stderr) = myconn.exec_command(remote_cmd)
|
||||
await log("{}".format(stdout.read()))
|
||||
await log("{}".format(type(myconn)))
|
||||
await log("Options available to deal with the connections are many like\n{}".format(dir(myconn)))
|
||||
myconn.close()
|
@ -11,6 +11,7 @@ import asyncio, asyncssh, sys
|
||||
import paramiko
|
||||
import subprocess
|
||||
import json
|
||||
from cowmesh_helpers import cleanup_iperf_server
|
||||
|
||||
PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
|
||||
SECRETS_PATH = os.path.join(PROJECT_PATH, "secrets.json")
|
||||
@ -25,8 +26,6 @@ nodes = [
|
||||
"writer", # pi in new-gazebo
|
||||
]
|
||||
|
||||
results = {}
|
||||
|
||||
|
||||
class CowmeshPiIperfTester:
|
||||
|
||||
@ -35,6 +34,7 @@ class CowmeshPiIperfTester:
|
||||
self.log = log
|
||||
self.debug = debug
|
||||
self.time = time
|
||||
self.results = {}
|
||||
|
||||
async def log(self, msg):
|
||||
print(msg)
|
||||
@ -73,21 +73,35 @@ class CowmeshPiIperfTester:
|
||||
|
||||
async def start_iperf_servers(self):
|
||||
for node in nodes:
|
||||
print("++ starting iperf server on {}".format(node))
|
||||
try:
|
||||
print("++ starting iperf server on {}".format(node))
|
||||
user = SECRETS["HOST_INFO"][node]["user"]
|
||||
password = SECRETS["HOST_INFO"][node]["password"]
|
||||
|
||||
myconn = paramiko.SSHClient()
|
||||
myconn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
myconn.connect(node, username=user, password=password)
|
||||
|
||||
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:
|
||||
self.log("++ error starting iperf server on {}".format(node))
|
||||
except:
|
||||
continue
|
||||
|
||||
async def cleanup_iperf_servers(self):
|
||||
await self.log("++ shutting down iperf servers")
|
||||
for node in nodes:
|
||||
user = SECRETS["HOST_INFO"][node]["user"]
|
||||
password = SECRETS["HOST_INFO"][node]["password"]
|
||||
|
||||
myconn = paramiko.SSHClient()
|
||||
myconn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
myconn.connect(node, username=user, password=password)
|
||||
|
||||
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()
|
||||
ip = SECRETS["HOST_INFO"][node]["ip"]
|
||||
await cleanup_iperf_server(node=node, ip=ip, username=user, password=password, log=self.log)
|
||||
|
||||
async def run_test(self):
|
||||
|
||||
@ -99,9 +113,17 @@ class CowmeshPiIperfTester:
|
||||
await self.debug_log("skip self")
|
||||
continue
|
||||
|
||||
r = await self.test_between_two_nodes(node_a, node_b)
|
||||
result_key = "{} -> {}".format(node_a, node_b)
|
||||
results[result_key] = r
|
||||
try:
|
||||
r = await self.test_between_two_nodes(node_a, node_b)
|
||||
self.results[result_key] = r
|
||||
except Exception as e:
|
||||
self.results[result_key] = "error: {}".format(e)
|
||||
|
||||
# try:
|
||||
# await self.cleanup_iperf_servers()
|
||||
# except:
|
||||
# await self.log("error shutting down iperf servers")
|
||||
|
||||
async def output_results(self):
|
||||
results_str = ""
|
||||
@ -109,7 +131,7 @@ class CowmeshPiIperfTester:
|
||||
date = now.date()
|
||||
time = now.time()
|
||||
results_str += "**** computer-to-computer iperf results on {date:%m-%d-%Y} at {time:%H:%M}:\n\n".format(date=date, time=time)
|
||||
for test_name, result in results.items():
|
||||
for test_name, result in self.results.items():
|
||||
results_str += "{}: {} mbps\n".format(test_name, result)
|
||||
await self.log(results_str)
|
||||
|
||||
|
97
cowmesh_pi_speedtest.py
Normal file
97
cowmesh_pi_speedtest.py
Normal file
@ -0,0 +1,97 @@
|
||||
"""
|
||||
run speedtest-cli on every computer in mesh
|
||||
"""
|
||||
import datetime
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import asyncio, asyncssh, sys
|
||||
import paramiko
|
||||
import subprocess
|
||||
import json
|
||||
from cowmesh_helpers import cleanup_iperf_server
|
||||
|
||||
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())
|
||||
|
||||
base_node = "janastunuc" # nuc in jaaga
|
||||
|
||||
nodes = [
|
||||
"janastunuc", # nuc in jaaga
|
||||
"solipi", # pi in guard
|
||||
"writer", # pi in new-gazebo
|
||||
]
|
||||
|
||||
|
||||
class CowmeshPiSpeedtestTester:
|
||||
|
||||
def __init__(self, log=None, debug=False):
|
||||
if log:
|
||||
self.log = log
|
||||
self.debug = debug
|
||||
self.results = {}
|
||||
|
||||
async def log(self, msg):
|
||||
print(msg)
|
||||
|
||||
async def debug_log(self, msg):
|
||||
if self.debug:
|
||||
await self.log(msg)
|
||||
|
||||
async def speedtest_node(self, node):
|
||||
await self.log("++ running speedtest on {}".format(node))
|
||||
user = SECRETS["HOST_INFO"][node]["user"]
|
||||
password = SECRETS["HOST_INFO"][node]["password"]
|
||||
|
||||
myconn = paramiko.SSHClient()
|
||||
myconn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
ip = SECRETS["HOST_INFO"][node]["ip"]
|
||||
myconn.connect(ip, username=user, password=password)
|
||||
|
||||
remote_cmd = 'speedtest-cli --simple'
|
||||
(stdin, stdout, stderr) = myconn.exec_command(remote_cmd)
|
||||
output = str(stdout.read())
|
||||
await self.debug_log("output: {}".format(output))
|
||||
await self.debug_log("errors: {}".format(stderr.read()))
|
||||
myconn.close()
|
||||
|
||||
return output
|
||||
|
||||
async def run_test(self):
|
||||
|
||||
for node in nodes:
|
||||
r = await self.speedtest_node(node)
|
||||
result_key = "{}".format(node)
|
||||
self.results[result_key] = r
|
||||
|
||||
async def output_results(self):
|
||||
results_str = ""
|
||||
now = datetime.datetime.now()
|
||||
date = now.date()
|
||||
time = now.time()
|
||||
results_str += "**** computer speedtests on {date:%m-%d-%Y} at {time:%H:%M}:\n\n".format(date=date, time=time)
|
||||
for test_name, result in self.results.items():
|
||||
result = str(result)
|
||||
result = result.replace("b'", "")
|
||||
result = result.replace("'", "")
|
||||
result = result.replace("\\n", " | ")
|
||||
results_str += "{}: {}\n".format(test_name, result)
|
||||
await self.log(results_str)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
tester = CowmeshPiSpeedtestTester()
|
||||
|
||||
async def main_fun():
|
||||
await tester.run_test()
|
||||
await tester.output_results()
|
||||
|
||||
asyncio.get_event_loop().run_until_complete(main_fun())
|
||||
|
||||
|
||||
except (OSError, asyncssh.Error) as exc:
|
||||
sys.exit('SSH connection failed: ' + str(exc))
|
@ -11,40 +11,24 @@ import asyncio, asyncssh, sys
|
||||
import paramiko
|
||||
import subprocess
|
||||
import json
|
||||
from cowmesh_constants import NODES, HOST_TO_IP
|
||||
|
||||
from cowmesh_helpers import cleanup_iperf_server
|
||||
|
||||
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())
|
||||
|
||||
nodes = [
|
||||
"jaaga",
|
||||
"redcottage",
|
||||
"new-gazebo2",
|
||||
"kotemanetp",
|
||||
"guard"
|
||||
]
|
||||
|
||||
host_to_ip = {
|
||||
"jaaga": "10.56.121.19",
|
||||
"redcottage": "10.56.58.194",
|
||||
"redcottage2": "10.56.114.42",
|
||||
"new-gazebo2": "10.56.114.42",
|
||||
"new-gazebo": "10.56.113.2",
|
||||
"guard": "10.56.121.73",
|
||||
"kotemanetp": "10.56.40.113"
|
||||
}
|
||||
|
||||
results = {}
|
||||
|
||||
|
||||
class CowmeshRouterIperfTester:
|
||||
|
||||
def __init__(self, log=None, debug=False, seconds=10):
|
||||
def __init__(self, log=None, debug=False, time=10):
|
||||
if log:
|
||||
self.log = log
|
||||
self.debug = debug
|
||||
self.time = seconds
|
||||
self.time = time
|
||||
self.results = {}
|
||||
|
||||
async def log(self, msg):
|
||||
print(msg)
|
||||
@ -63,7 +47,7 @@ class CowmeshRouterIperfTester:
|
||||
|
||||
myconn.connect(node_a, username =u_name, password=pswd)
|
||||
|
||||
ip = host_to_ip[node_b]
|
||||
ip = HOST_TO_IP[node_b]
|
||||
|
||||
remote_cmd = 'iperf -c {ip} -p 5001 -t {seconds}'.format(ip=ip, seconds=self.time)
|
||||
(stdin, stdout, stderr) = myconn.exec_command(remote_cmd)
|
||||
@ -76,41 +60,73 @@ class CowmeshRouterIperfTester:
|
||||
if match:
|
||||
to_return = match.group(1)
|
||||
else:
|
||||
to_return = None
|
||||
match = re.search("(\S+) Kbits", output)
|
||||
if match:
|
||||
to_return = match.group(1)
|
||||
to_return = float(to_return) / 1000.0
|
||||
else:
|
||||
to_return = None
|
||||
|
||||
return to_return
|
||||
|
||||
async def start_iperf_servers(self):
|
||||
for node in nodes:
|
||||
print("++ starting iperf server on {}".format(node))
|
||||
u_name = 'root'
|
||||
pswd = SECRETS["ROUTER_PASSWORD"]
|
||||
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 = paramiko.SSHClient()
|
||||
myconn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
myconn.connect(node, username=u_name, password=pswd)
|
||||
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()
|
||||
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
|
||||
|
||||
async def cleanup_iperf_servers(self):
|
||||
await self.log("shutting down iperf servers")
|
||||
for node in NODES:
|
||||
user = "root"
|
||||
password = SECRETS["ROUTER_PASSWORD"]
|
||||
ip = HOST_TO_IP[node]
|
||||
await cleanup_iperf_server(node=node, ip=ip, username=user, password=password, log=self.log)
|
||||
|
||||
async def run_test(self):
|
||||
|
||||
await self.start_iperf_servers()
|
||||
try:
|
||||
await self.start_iperf_servers()
|
||||
except:
|
||||
pass
|
||||
|
||||
for node_a in nodes:
|
||||
for node_b in nodes:
|
||||
for node_a in NODES:
|
||||
for node_b in NODES:
|
||||
if node_a == node_b:
|
||||
await self.debug_log("skip self")
|
||||
continue
|
||||
|
||||
r = await self.test_between_two_nodes(node_a, node_b)
|
||||
result_key = "{} -> {}".format(node_a, node_b)
|
||||
results[result_key] = r
|
||||
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
|
||||
# try:
|
||||
# await self.cleanup_iperf_servers()
|
||||
# except:
|
||||
# await self.log("error shutting down iperf servers")
|
||||
|
||||
async def output_results(self):
|
||||
results_str = ""
|
||||
@ -118,7 +134,7 @@ class CowmeshRouterIperfTester:
|
||||
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)
|
||||
for test_name, result in results.items():
|
||||
for test_name, result in self.results.items():
|
||||
results_str += "{}: {} mbps\n".format(test_name, result)
|
||||
await self.log(results_str)
|
||||
|
||||
|
@ -7,29 +7,24 @@ import os
|
||||
import time
|
||||
import asyncio, asyncssh, sys
|
||||
import subprocess
|
||||
|
||||
import json
|
||||
import paramiko
|
||||
|
||||
PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
|
||||
test_img_path = os.path.join(PROJECT_PATH, "test.png")
|
||||
|
||||
SECRETS_PATH = os.path.join(PROJECT_PATH, "secrets.json")
|
||||
with open(SECRETS_PATH, 'r') as f:
|
||||
SECRETS = json.loads(f.read())
|
||||
|
||||
base_node = "janastunuc" # nuc in jaaga
|
||||
|
||||
nodes = [
|
||||
"janastunuc", # nuc in jaaga
|
||||
"solipi", # pi in guard
|
||||
"writer", # pi in new-gazebo
|
||||
]
|
||||
|
||||
node_dict = {
|
||||
"jagga-nuc": {
|
||||
"ip": "10.56.10.247",
|
||||
"user": "cow",
|
||||
"node_path": "/datadrive/data/cowmesh-network-test"
|
||||
},
|
||||
"redcottage-pi": {
|
||||
"ip": "10.56.148.122",
|
||||
"user": "admin",
|
||||
"node_path": "/home/admin/cowmesh-network-test"
|
||||
},
|
||||
"newgazebo-pi": {
|
||||
"ip": "10.56.11.111",
|
||||
"user": "pi",
|
||||
"node_path": "/home/pi/cowmesh-network-test"
|
||||
},
|
||||
}
|
||||
|
||||
# url for downloading test.png from the internet
|
||||
internet_url = "https://canalswans.commoninternet.net/test.png"
|
||||
@ -44,12 +39,13 @@ if PREPARE_TEST:
|
||||
os.system(internet_scp_cmd)
|
||||
|
||||
# first put the image on every node without testing the time (so that the test is prepared to run)
|
||||
for name, from_node_vals in node_dict.items():
|
||||
for name, from_node_vals in SECRETS["HOST_INFO"].items():
|
||||
print("PREPARING NODE {}".format(name))
|
||||
ip = from_node_vals["ip"]
|
||||
dir_path = from_node_vals["node_path"]
|
||||
file_path = os.path.join(dir_path, "test.png")
|
||||
user = from_node_vals["user"]
|
||||
password = from_node_vals["password"]
|
||||
mkdir_cmd = "ssh {user}@{ip} 'mkdir -p {dir_path}'".format(user=user, ip=ip, dir_path=dir_path)
|
||||
os.system(mkdir_cmd)
|
||||
scp_cmd = "scp {test_img_path} {user}@{ip}:{file_path}".format(
|
||||
@ -60,16 +56,43 @@ if PREPARE_TEST:
|
||||
)
|
||||
os.system(scp_cmd)
|
||||
|
||||
myconn = paramiko.SSHClient()
|
||||
myconn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
myconn.connect(ip, username=user, password=password)
|
||||
remote_cmd = 'mkdir -p {dir_path}'.format(dir_path=dir_path)
|
||||
(stdin, stdout, stderr) = myconn.exec_command(remote_cmd)
|
||||
output = str(stdout.read())
|
||||
print("output: {}".format(output))
|
||||
print(("errors: {}".format(stderr.read())))
|
||||
|
||||
scp_cmd = "scp {test_img_path} {user}@{ip}:{file_path}".format(
|
||||
test_img_path=test_img_path,
|
||||
ip=ip,
|
||||
user=user,
|
||||
file_path=file_path
|
||||
)
|
||||
(stdin, stdout, stderr) = myconn.exec_command(scp_cmd)
|
||||
output = str(stdout.read())
|
||||
print("output: {}".format(output))
|
||||
print(("errors: {}".format(stderr.read())))
|
||||
|
||||
myconn.close()
|
||||
|
||||
results = {}
|
||||
|
||||
async def run_test():
|
||||
# run the test on each node
|
||||
for from_name, from_node_vals in node_dict.items():
|
||||
node_dict = SECRETS["HOST_INFO"]
|
||||
for node in nodes:
|
||||
from_name = node
|
||||
from_node_vals = node_dict[node]
|
||||
from_ip = from_node_vals["ip"]
|
||||
from_dir_path = from_node_vals["node_path"]
|
||||
from_file_path = os.path.join(from_dir_path, "test.png")
|
||||
from_user = from_node_vals["user"]
|
||||
for to_name, to_node_vals in node_dict.items():
|
||||
from_password = from_node_vals["password"]
|
||||
for to_name in nodes:
|
||||
to_node_vals = node_dict[to_name]
|
||||
if from_name == to_name:
|
||||
print("skip self")
|
||||
continue
|
||||
@ -80,35 +103,40 @@ async def run_test():
|
||||
to_ip = to_node_vals["ip"]
|
||||
to_dir_path = to_node_vals["node_path"]
|
||||
to_file_path = os.path.join(to_dir_path, "download.png")
|
||||
to_password = to_node_vals["password"]
|
||||
|
||||
async with asyncssh.connect(from_ip, username=from_user) as conn:
|
||||
scp_cmd = "scp -i {key_path} {from_file_path} {to_user}@{to_ip}:{to_file_path}".format(
|
||||
key_path="$HOME/.ssh/janastu",
|
||||
to_user=to_user,
|
||||
to_ip=to_ip,
|
||||
to_file_path=to_file_path,
|
||||
from_file_path=from_file_path
|
||||
)
|
||||
|
||||
scp_cmd = "scp -i {key_path} {from_file_path} {to_user}@{to_ip}:{to_file_path}".format(
|
||||
key_path="$HOME/.ssh/janastu",
|
||||
to_user=to_user,
|
||||
to_ip=to_ip,
|
||||
to_file_path=to_file_path,
|
||||
from_file_path=from_file_path
|
||||
)
|
||||
start = time.time()
|
||||
|
||||
print(scp_cmd)
|
||||
myconn = paramiko.SSHClient()
|
||||
myconn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
myconn.connect(from_ip, username=from_user, password=from_password)
|
||||
print(scp_cmd)
|
||||
(stdin, stdout, stderr) = myconn.exec_command(scp_cmd)
|
||||
exit_status = stdout.channel.recv_exit_status()
|
||||
output = str(stdout.read())
|
||||
error = str(stderr.read())
|
||||
print("output: {}".format(output))
|
||||
print(("errors: {}".format(stderr.read())))
|
||||
|
||||
start = time.time()
|
||||
result = await conn.run(scp_cmd)
|
||||
|
||||
if result.exit_status == 0:
|
||||
print(result.stdout, end='')
|
||||
end = time.time()
|
||||
elapsed = (end - start)
|
||||
result_key = "{}->{}".format(from_name, to_name)
|
||||
print("{}: {} seconds".format(result_key, elapsed))
|
||||
results[result_key] = elapsed
|
||||
else:
|
||||
print(result.stderr, end='', file=sys.stderr)
|
||||
print('Program exited with status %d' % result.exit_status,
|
||||
file=sys.stderr)
|
||||
results[result_key] = "error: {}".format(result.stderr)
|
||||
return
|
||||
result_key = "{} -> {}".format(from_name, to_name)
|
||||
if exit_status == 0:
|
||||
print("success: {}".format(output))
|
||||
end = time.time()
|
||||
elapsed = (end - start)
|
||||
print("{}: {} seconds".format(result_key, elapsed))
|
||||
results[result_key] = elapsed
|
||||
else:
|
||||
print("error: {}".format(error))
|
||||
results[result_key] = "error: {}".format(error)
|
||||
return
|
||||
|
||||
# scp_with_time_cmd = "set -e; /usr/bin/time -f '%e' {}".format(scp_cmd)
|
||||
# print("running: {}".format(scp_with_time_cmd))
|
||||
@ -117,6 +145,7 @@ async def run_test():
|
||||
def run_laptop_test():
|
||||
from_name = "laptop"
|
||||
# also measure transfers from laptop
|
||||
node_dict = SECRETS["HOST_INFO"]
|
||||
for to_name, to_node_vals in node_dict.items():
|
||||
print("** running test.png transfer test from laptop to {}".format(to_name))
|
||||
|
||||
@ -154,8 +183,8 @@ def run_laptop_test():
|
||||
|
||||
|
||||
try:
|
||||
asyncio.get_event_loop().run_until_complete(run_test())
|
||||
# run_laptop_test()
|
||||
# asyncio.get_event_loop().run_until_complete(run_test())
|
||||
run_laptop_test()
|
||||
|
||||
print("** final results **")
|
||||
file_size = 13476
|
||||
|
0
get_device_info.y.py
Normal file
0
get_device_info.y.py
Normal file
@ -1,16 +1,19 @@
|
||||
import asyncio
|
||||
import logging
|
||||
from datetime import date, datetime
|
||||
|
||||
from telegram import Update
|
||||
from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, MessageHandler, filters
|
||||
import os
|
||||
import json
|
||||
|
||||
from cowmesh_pi_speedtest import CowmeshPiSpeedtestTester
|
||||
from cowmesh_router_iperf_test import CowmeshRouterIperfTester
|
||||
from cowmesh_pi_iperf_test import CowmeshPiIperfTester
|
||||
|
||||
PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
|
||||
SECRETS_PATH = os.path.join(PROJECT_PATH, "secrets.json")
|
||||
LOG_DIR_PATH = "/datadrive/apps/moonlight_analytics/results"
|
||||
with open(SECRETS_PATH, 'r') as f:
|
||||
SECRETS = json.loads(f.read())
|
||||
|
||||
@ -19,151 +22,270 @@ logging.basicConfig(
|
||||
level=logging.INFO
|
||||
)
|
||||
|
||||
class MoonlightTester:
|
||||
|
||||
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text="This is the moonlight analytics bot for mesh network diagnostics.\n\nType /help to see available commands.", message_thread_id=update.message.message_thread_id)
|
||||
async def start(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text="This is the moonlight analytics bot for mesh network diagnostics.\n\nType /help to see available commands.", message_thread_id=update.message.message_thread_id)
|
||||
|
||||
|
||||
async def caps(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""
|
||||
this is just a function to test that the bot is working as expected
|
||||
"""
|
||||
text_caps = ' '.join(context.args).upper()
|
||||
print("chat_id: {}".format(update.effective_chat.id))
|
||||
print("message_thread_id: {}".format(update.message.message_thread_id))
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=text_caps, message_thread_id=update.message.message_thread_id)
|
||||
async def caps(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""
|
||||
this is just a function to test that the bot is working as expected
|
||||
"""
|
||||
text_caps = ' '.join(context.args).upper()
|
||||
print("chat_id: {}".format(update.effective_chat.id))
|
||||
print("message_thread_id: {}".format(update.message.message_thread_id))
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=text_caps, message_thread_id=update.message.message_thread_id)
|
||||
|
||||
|
||||
async def router_iperf(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
async def router_iperf(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
|
||||
time = context.args[0] if context.args else None
|
||||
if not time:
|
||||
time = 10
|
||||
async def log(msg):
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=msg, message_thread_id=update.message.message_thread_id)
|
||||
time = context.args[0] if context.args else None
|
||||
if not time:
|
||||
time = 10
|
||||
|
||||
if update.effective_chat.id != int(SECRETS["TELEGRAM_LOG_CHAT_ID"]):
|
||||
await log("++ can only start iperf test from Moonlight Bot group")
|
||||
return
|
||||
log_name = "moonlight-{:%m-%d-%Y}-{:%H-%M}-router-iperf.txt".format(date.today(), datetime.now())
|
||||
log_location = os.path.join(LOG_DIR_PATH, log_name)
|
||||
|
||||
await log("++ starting router iperf test with {} seconds per test".format(time))
|
||||
tester = CowmeshRouterIperfTester(log=log, seconds=time)
|
||||
await tester.run_test()
|
||||
await tester.output_results()
|
||||
async def offline_log(msg):
|
||||
with open(log_location, 'a') as log_file:
|
||||
log_file.write(msg + "\n")
|
||||
|
||||
async def log(msg):
|
||||
await offline_log(msg)
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=msg,
|
||||
message_thread_id=update.message.message_thread_id)
|
||||
|
||||
if update.effective_chat.id != int(SECRETS["TELEGRAM_LOG_CHAT_ID"]):
|
||||
await log("++ can only start iperf test from Moonlight Bot group")
|
||||
return
|
||||
|
||||
await log("++ starting router iperf test with {} seconds per test".format(time))
|
||||
tester = CowmeshRouterIperfTester(log=log, time=time)
|
||||
await tester.run_test()
|
||||
await tester.output_results()
|
||||
|
||||
# send log file
|
||||
document = open(log_location, 'rb')
|
||||
await context.bot.send_document(update.effective_chat.id, document,
|
||||
message_thread_id=update.message.message_thread_id)
|
||||
|
||||
async def pi_iperf(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
|
||||
time = context.args[0] if context.args else None
|
||||
if not time:
|
||||
time = 10
|
||||
|
||||
log_name = "moonlight-{:%m-%d-%Y}-{:%H-%M}-pi-iperf.txt".format(date.today(), datetime.now())
|
||||
log_location = os.path.join(LOG_DIR_PATH, log_name)
|
||||
|
||||
async def offline_log(msg):
|
||||
with open(log_location, 'a') as log_file:
|
||||
log_file.write(msg + "\n")
|
||||
async def log(msg):
|
||||
await offline_log(msg)
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=msg, message_thread_id=update.message.message_thread_id)
|
||||
|
||||
if update.effective_chat.id != int(SECRETS["TELEGRAM_LOG_CHAT_ID"]):
|
||||
await log("++ can only start iperf test from Moonlight Bot group")
|
||||
return
|
||||
|
||||
await log("++ starting pi iperf test with {} seconds per test".format(time))
|
||||
tester = CowmeshPiIperfTester(log=log, time=time)
|
||||
await tester.run_test()
|
||||
await tester.output_results()
|
||||
|
||||
# send log file
|
||||
document = open(log_location, 'rb')
|
||||
await context.bot.send_document(update.effective_chat.id, document, message_thread_id=update.message.message_thread_id)
|
||||
|
||||
|
||||
async def pi_iperf(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
async def speedtest(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
|
||||
time = context.args[0] if context.args else None
|
||||
if not time:
|
||||
time = 10
|
||||
async def log(msg):
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=msg, message_thread_id=update.message.message_thread_id)
|
||||
log_name = "moonlight-{:%m-%d-%Y}-{:%H-%M}-pi-speedtest.txt".format(date.today(), datetime.now())
|
||||
log_location = os.path.join(LOG_DIR_PATH, log_name)
|
||||
|
||||
if update.effective_chat.id != int(SECRETS["TELEGRAM_LOG_CHAT_ID"]):
|
||||
await log("++ can only start iperf test from Moonlight Bot group")
|
||||
return
|
||||
async def offline_log(msg):
|
||||
with open(log_location, 'a') as log_file:
|
||||
log_file.write(msg + "\n")
|
||||
|
||||
await log("++ starting pi iperf test with {} seconds per test".format(time))
|
||||
tester = CowmeshPiIperfTester(log=log, time=time)
|
||||
await tester.run_test()
|
||||
await tester.output_results()
|
||||
async def log(msg):
|
||||
await offline_log(msg)
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=msg,
|
||||
message_thread_id=update.message.message_thread_id)
|
||||
|
||||
if update.effective_chat.id != int(SECRETS["TELEGRAM_LOG_CHAT_ID"]):
|
||||
await log("++ can only start test from Moonlight Bot group")
|
||||
return
|
||||
|
||||
await log("++ starting pi speedtest-cli speedtest")
|
||||
tester = CowmeshPiSpeedtestTester(log=log)
|
||||
await tester.run_test()
|
||||
await tester.output_results()
|
||||
|
||||
# send log file
|
||||
document = open(log_location, 'rb')
|
||||
await context.bot.send_document(update.effective_chat.id, document,
|
||||
message_thread_id=update.message.message_thread_id)
|
||||
|
||||
async def unknown(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text="Sorry, I didn't understand that, please run /help for a list of available commands.", message_thread_id=update.message.message_thread_id)
|
||||
|
||||
|
||||
async def unknown(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text="Sorry, I didn't understand that, please run /help for a list of available commands.", message_thread_id=update.message.message_thread_id)
|
||||
def about_message(self):
|
||||
msg = "This is a bot designed to help measure the performance of a mesh network through active testing. " \
|
||||
"Every night the bot runs a network test using iperf to measure the connectivity between all the nodes in the mesh, " \
|
||||
"and logs the result to this channel. " \
|
||||
"Members of this channel can also initiate a new network iperf test at any time by sending a message to this channel, " \
|
||||
"with the command /iperf . " \
|
||||
"Telegram users outside of this channel cannot initiate a test, to help keep the network secure from being " \
|
||||
"overrun by malicious users. " \
|
||||
"The network test runs at night because that is when the fewest people are using the network, and so is more likely to " \
|
||||
"give consistent results with less random variability. " \
|
||||
"Please be mindful of initiating too many iperf tests during the day, as it uses a lot of network resources " \
|
||||
"to run the test and could interfere with the internet connections of people using the network. "
|
||||
return msg
|
||||
|
||||
|
||||
def about_message():
|
||||
msg = "This is a bot designed to help measure the performance of a mesh network through active testing. " \
|
||||
"Every night the bot runs a network test using iperf to measure the connectivity between all the nodes in the mesh, " \
|
||||
"and logs the result to this channel. " \
|
||||
"Members of this channel can also initiate a new network iperf test at any time by sending a message to this channel, " \
|
||||
"with the command /iperf . " \
|
||||
"Telegram users outside of this channel cannot initiate a test, to help keep the network secure from being " \
|
||||
"overrun by malicious users. " \
|
||||
"The network test runs at night because that is when the fewest people are using the network, and so is more likely to " \
|
||||
"give consistent results with less random variability. " \
|
||||
"Please be mindful of initiating too many iperf tests during the day, as it uses a lot of network resources " \
|
||||
"to run the test and could interfere with the internet connections of people using the network. "
|
||||
return msg
|
||||
def help_message(self):
|
||||
msg = "This bot runs an iperf test every night and logs the results here. You can also initiate a new test using the command /iperf " \
|
||||
"or read a longer message explaining how this bot works by typing the command /readme."
|
||||
return msg
|
||||
|
||||
|
||||
def help_message():
|
||||
msg = "This bot runs an iperf test every night and logs the results here. You can also initiate a new test using the command /iperf " \
|
||||
"or read a longer message explaining how this bot works by typing the command /readme."
|
||||
return msg
|
||||
async def about(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
text = self.about_message()
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=text, message_thread_id=update.message.message_thread_id)
|
||||
|
||||
|
||||
async def about(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
text = about_message()
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=text, message_thread_id=update.message.message_thread_id)
|
||||
async def help_fun(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
text = self.help_message()
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=text, message_thread_id=update.message.message_thread_id)
|
||||
|
||||
async def send_log(self, bot, chat_id, message_thread_id, log_location):
|
||||
# send log file
|
||||
document = open(log_location, 'rb')
|
||||
bot.send_document(chat_id, document, message_thread_id=message_thread_id)
|
||||
|
||||
async def nightly_router_iperf(self, time=10):
|
||||
token = SECRETS["TELEGRAM_TOKEN"]
|
||||
application = ApplicationBuilder().token(token).build()
|
||||
chat_id = SECRETS["TELEGRAM_LOG_CHAT_ID"]
|
||||
message_thread_id = SECRETS.get("TELEGRAM_LOG_MESSAGE_THREAD_ID")
|
||||
bot = application.bot
|
||||
|
||||
log_name = "moonlight-{:%M-%d-%Y}-{:%H:%m}-router-iperf.txt".format(datetime.today(), datetime.now())
|
||||
log_location = os.path.join(LOG_DIR_PATH, log_name)
|
||||
|
||||
async def offline_log(msg):
|
||||
with open(log_location, 'a') as log_file:
|
||||
log_file.write(msg)
|
||||
|
||||
async def log(msg):
|
||||
await offline_log(msg)
|
||||
try:
|
||||
await bot.send_message(chat_id=chat_id, text=msg, message_thread_id=message_thread_id)
|
||||
except:
|
||||
pass
|
||||
|
||||
await log("☾☾ starting nightly router-to-router iperf test with {time} seconds per test".format(time=time))
|
||||
tester = CowmeshRouterIperfTester(log=log, time=time)
|
||||
await tester.run_test()
|
||||
await tester.output_results()
|
||||
await self.send_log(bot=bot, log_location=log_location, chat_id=chat_id, message_thread_id=message_thread_id)
|
||||
|
||||
|
||||
async def help_fun(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
text = help_message()
|
||||
await context.bot.send_message(chat_id=update.effective_chat.id, text=text, message_thread_id=update.message.message_thread_id)
|
||||
|
||||
async def nightly_pi_iperf(self, time=10):
|
||||
token = SECRETS["TELEGRAM_TOKEN"]
|
||||
application = ApplicationBuilder().token(token).build()
|
||||
chat_id = SECRETS["TELEGRAM_LOG_CHAT_ID"]
|
||||
message_thread_id = SECRETS.get("TELEGRAM_LOG_MESSAGE_THREAD_ID")
|
||||
bot = application.bot
|
||||
|
||||
|
||||
async def nightly_router_iperf(time=10):
|
||||
token = SECRETS["TELEGRAM_TOKEN"]
|
||||
application = ApplicationBuilder().token(token).build()
|
||||
chat_id = SECRETS["TELEGRAM_LOG_CHAT_ID"]
|
||||
message_thread_id = SECRETS.get("TELEGRAM_LOG_MESSAGE_THREAD_ID")
|
||||
bot = application.bot
|
||||
log_name = "moonlight-{:%M-%d-%Y}-{:%H:%m}-pi-iperf.txt".format(datetime.today(), datetime.now())
|
||||
log_location = os.path.join(LOG_DIR_PATH, log_name)
|
||||
|
||||
async def log(msg):
|
||||
await bot.send_message(chat_id=chat_id, text=msg, message_thread_id=message_thread_id)
|
||||
async def offline_log(msg):
|
||||
with open(log_location, 'a') as log_file:
|
||||
log_file.write(msg)
|
||||
|
||||
await log("☾☾ starting nightly router-to-router iperf test with {} seconds per test")
|
||||
tester = CowmeshRouterIperfTester(log=log, time=time)
|
||||
await tester.run_test()
|
||||
await tester.output_results()
|
||||
async def log(msg):
|
||||
await offline_log(msg)
|
||||
try:
|
||||
await bot.send_message(chat_id=chat_id, text=msg, message_thread_id=message_thread_id)
|
||||
except:
|
||||
pass
|
||||
|
||||
await log("☾☾ starting nightly computer-to-computer iperf test with {} seconds per test".format(time))
|
||||
tester = CowmeshPiIperfTester(log=log, time=time)
|
||||
await tester.run_test()
|
||||
await tester.output_results()
|
||||
await self.send_log(bot=bot, log_location=log_location, chat_id=chat_id, message_thread_id=message_thread_id)
|
||||
|
||||
|
||||
async def nightly_pi_iperf(time=10):
|
||||
token = SECRETS["TELEGRAM_TOKEN"]
|
||||
application = ApplicationBuilder().token(token).build()
|
||||
chat_id = SECRETS["TELEGRAM_LOG_CHAT_ID"]
|
||||
message_thread_id = SECRETS.get("TELEGRAM_LOG_MESSAGE_THREAD_ID")
|
||||
bot = application.bot
|
||||
|
||||
async def log(msg):
|
||||
await bot.send_message(chat_id=chat_id, text=msg, message_thread_id=message_thread_id)
|
||||
async def nightly_pi_speedtest(self):
|
||||
token = SECRETS["TELEGRAM_TOKEN"]
|
||||
application = ApplicationBuilder().token(token).build()
|
||||
chat_id = SECRETS["TELEGRAM_LOG_CHAT_ID"]
|
||||
message_thread_id = SECRETS.get("TELEGRAM_LOG_MESSAGE_THREAD_ID")
|
||||
bot = application.bot
|
||||
|
||||
await log("☾☾ starting nightly computer-to-computer iperf test with {} seconds per test".format(time))
|
||||
tester = CowmeshPiIperfTester(log=log, time=time)
|
||||
await tester.run_test()
|
||||
await tester.output_results()
|
||||
log_name = "moonlight-{:%M-%d-%Y}-{:%H:%m}-pi-iperf.txt".format(datetime.today(), datetime.now())
|
||||
log_location = os.path.join(LOG_DIR_PATH, log_name)
|
||||
|
||||
async def offline_log(msg):
|
||||
with open(log_location, 'a') as log_file:
|
||||
log_file.write(msg)
|
||||
|
||||
async def log(msg):
|
||||
await offline_log(msg)
|
||||
try:
|
||||
await bot.send_message(chat_id=chat_id, text=msg, message_thread_id=message_thread_id)
|
||||
except:
|
||||
pass
|
||||
|
||||
await log("☾☾ starting nightly speedtest-cli speedtest")
|
||||
tester = CowmeshPiSpeedtestTester(log=log)
|
||||
await tester.run_test()
|
||||
await tester.output_results()
|
||||
await self.send_log(bot=bot, log_location=log_location, chat_id=chat_id, message_thread_id=message_thread_id)
|
||||
|
||||
|
||||
def init_bot_listener():
|
||||
token = SECRETS["TELEGRAM_TOKEN"]
|
||||
application = ApplicationBuilder().token(token).build()
|
||||
|
||||
start_handler = CommandHandler('start', start)
|
||||
application.add_handler(start_handler)
|
||||
def init_bot_listener(self):
|
||||
token = SECRETS["TELEGRAM_TOKEN"]
|
||||
application = ApplicationBuilder().token(token).build()
|
||||
|
||||
caps_handler = CommandHandler('caps', caps)
|
||||
application.add_handler(caps_handler)
|
||||
start_handler = CommandHandler('start', self.start)
|
||||
application.add_handler(start_handler)
|
||||
|
||||
about_handler = CommandHandler('readme', about)
|
||||
application.add_handler(about_handler)
|
||||
caps_handler = CommandHandler('caps', self.caps)
|
||||
application.add_handler(caps_handler)
|
||||
|
||||
help_handler = CommandHandler('help', help_fun)
|
||||
application.add_handler(help_handler)
|
||||
about_handler = CommandHandler('readme', self.about)
|
||||
application.add_handler(about_handler)
|
||||
|
||||
iperf_handler = CommandHandler('iperf', router_iperf)
|
||||
application.add_handler(iperf_handler)
|
||||
help_handler = CommandHandler('help', self.help_fun)
|
||||
application.add_handler(help_handler)
|
||||
|
||||
pi_iperf_handler = CommandHandler('pi_iperf', pi_iperf)
|
||||
application.add_handler(pi_iperf_handler)
|
||||
iperf_handler = CommandHandler('iperf', self.router_iperf)
|
||||
application.add_handler(iperf_handler)
|
||||
|
||||
unknown_handler = MessageHandler(filters.COMMAND, unknown)
|
||||
application.add_handler(unknown_handler)
|
||||
pi_iperf_handler = CommandHandler('pi_iperf', self.pi_iperf)
|
||||
application.add_handler(pi_iperf_handler)
|
||||
|
||||
application.run_polling()
|
||||
speedtest_handler = CommandHandler('speedtest', self.speedtest)
|
||||
application.add_handler(speedtest_handler)
|
||||
|
||||
unknown_handler = MessageHandler(filters.COMMAND, self.unknown)
|
||||
application.add_handler(unknown_handler)
|
||||
|
||||
application.run_polling()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
init_bot_listener()
|
||||
tester = MoonlightTester()
|
||||
tester.init_bot_listener()
|
@ -1,12 +1,15 @@
|
||||
import argparse
|
||||
from moonlight_analytics import nightly_router_iperf, nightly_pi_iperf
|
||||
from moonlight_analytics import MoonlightTester
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tester = MoonlightTester()
|
||||
time = sys.argv[2] if len(sys.argv) > 2 else 10
|
||||
if sys.argv[1] == "router":
|
||||
asyncio.get_event_loop().run_until_complete(nightly_router_iperf(time=time))
|
||||
asyncio.get_event_loop().run_until_complete(tester.nightly_router_iperf(time=time))
|
||||
elif sys.argv[1] == "pi":
|
||||
asyncio.get_event_loop().run_until_complete(nightly_pi_iperf(time=time))
|
||||
asyncio.get_event_loop().run_until_complete(tester.nightly_pi_iperf(time=time))
|
||||
elif sys.argv[1] == "speedtest":
|
||||
asyncio.get_event_loop().run_until_complete(tester.nightly_pi_speedtest())
|
Loading…
x
Reference in New Issue
Block a user