import threading import time import subprocess import logging from datetime import datetime from zerotier_client import ZeroTierClient from config import PING_INTERVAL logger = logging.getLogger(__name__) class PingService: def __init__(self): self.zt_client = ZeroTierClient() self.nodes_status = {} self.running = False self.thread = None self.network_id = None def set_network_id(self, network_id): """Imposta l'ID della rete da monitorare""" self.network_id = network_id def ping_node(self, ip_address): """Fa il ping a un nodo e ritorna True se online""" try: result = subprocess.run( ['ping', '-c', '1', '-W', '3', ip_address], capture_output=True, timeout=5 ) return result.returncode == 0 except Exception as e: logger.error(f'Ping error for {ip_address}: {e}') return False def update_node_status(self): """Aggiorna lo stato di tutti i nodi""" if not self.network_id: logger.warning('Network ID not set') return peers = self.zt_client.get_peers(self.network_id) current_time = datetime.now().isoformat() for peer in peers: peer_id = peer.get('id') hostname = peer.get('name', 'Unknown') config = peer.get('config', {}) # Estrai IP ZeroTier dal config ip_addresses = config.get('ipAssignments', []) if not ip_addresses: continue zt_ip = ip_addresses[0] # Fa il ping is_online = self.ping_node(zt_ip) self.nodes_status[peer_id] = { 'id': peer_id, 'hostname': hostname, 'ip': zt_ip, 'online': is_online, 'status': 'online' if is_online else 'offline', 'last_check': current_time } logger.info(f'Updated status for {len(self.nodes_status)} nodes') def get_nodes_status(self): """Ritorna lo stato di tutti i nodi""" return list(self.nodes_status.values()) def start(self, network_id): """Avvia il servizio di ping in background""" if self.running: logger.warning('Service already running') return self.network_id = network_id self.running = True self.thread = threading.Thread(target=self._run, daemon=True) self.thread.start() logger.info('Ping service started') def _run(self): """Loop principale del servizio""" while self.running: try: self.update_node_status() except Exception as e: logger.error(f'Error in ping service: {e}') time.sleep(PING_INTERVAL) def stop(self): """Arresta il servizio""" self.running = False if self.thread: self.thread.join(timeout=5) logger.info('Ping service stopped')