From 7d157e513678d053dcb93a7cc6c280979a7bbd61 Mon Sep 17 00:00:00 2001 From: HornetMaidan Date: Sat, 5 Oct 2024 00:31:47 +0500 Subject: [PATCH] added tailscale subnet availability check --- lainmonitor.py | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/lainmonitor.py b/lainmonitor.py index 5386e5a..178272b 100644 --- a/lainmonitor.py +++ b/lainmonitor.py @@ -3,9 +3,11 @@ #usage: python3 lainmonitor.py | or run it as a service #author: hornetmaidan import subprocess +import threading import telebot #define the variables status, hostname, uptime, zerotier, prosody, postgres, tailscale, disk, ping = 'unknown', 'unknown', 'unknown', 'unknown', 'unknown', 'unknown', 'unknown', 'unknown', 'unknown' +nodes, hostnames, reach, threads = [], [], [], [] #telegram bot token TOKEN = 'PLACE_YOUR_TOKEN_HERE' @@ -29,15 +31,30 @@ def getinfo(): status = 'online' return hostname, uptime, zerotier, prosody, postgres, tailscale, disk -#ping tailscale (change the IP address to the one you want or add more) +#function to ping tailscale nodes +def ping_node(node, hostname): + ping = subprocess.Popen(f"ping {node} -c 1 | grep '1 packets'", shell=True, stdout=subprocess.PIPE).stdout.read().decode().strip() + if '1 received' in ping: + reach.append(f'{node}/{hostname} is reachable') + else: + reach.append(f'{node}/{hostname} is unreachable') + +#ping tailscale nodes def check_tailscale(): - global ping - ping = subprocess.Popen("ping TAILSCALE_IP -c 1 | grep '1 packets'", shell=True, stdout=subprocess.PIPE).stdout.read().decode().strip() - if '1 received' in ping: - ping = 'connected' - else: - ping = 'unreachable' - return ping + global nodes, hostnames, reach, threads, ping + nodes_output = subprocess.Popen("tailscale status | grep '100'", shell=True, stdout=subprocess.PIPE).stdout.read().decode().strip() + nodes = [line.split()[0] for line in nodes_output.split('\n') if line] + hostnames = [line.split()[1] for line in nodes_output.split('\n') if line] + + for node, hostname in zip(nodes, hostnames): + thread = threading.Thread(target=ping_node, args=(node, hostname)) + threads.append(thread) + thread.start() + + for thread in threads: + thread.join() + + return reach #debug handler def check(): @@ -69,7 +86,7 @@ def handle(message): bot.reply_to(message, 'work in progress...') elif message.text == '/ping': check_tailscale() - bot.reply_to(message, f'ping status: {ping}') + bot.reply_to(message, f'ping status: \n\n{reach}') #polling bot.polling() \ No newline at end of file