JNC Linux

This commit is contained in:
joaquin.navajas
2026-05-11 08:09:47 +02:00
parent 373493ca2f
commit 0d10ab8110
31 changed files with 3165 additions and 90 deletions
+228
View File
@@ -0,0 +1,228 @@
import socket
import subprocess
import time
from datetime import datetime
from typing import Dict, List, Tuple, Optional
from PyQt6.QtCore import QThread, pyqtSignal
class ConnectivityTestThread(QThread):
"""Thread para ejecutar tests de conectividad en paralelo."""
test_result = pyqtSignal(dict) # Emite resultado de cada test
all_finished = pyqtSignal() # Emite cuando todos terminan
def __init__(self, tests: List[Dict]):
super().__init__()
self.tests = tests
self.results = []
def run(self):
for test in self.tests:
result = self._run_test(test)
self.results.append(result)
self.test_result.emit(result)
self.all_finished.emit()
def _run_test(self, test: Dict) -> Dict:
"""Ejecuta un test individual y retorna resultado."""
host = test["host"]
port = test["port"]
protocol = test.get("protocol", "TCP")
test_type = test.get("type", "connectivity")
result = {
"host": host,
"port": port,
"protocol": protocol,
"type": test_type,
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"success": False,
"status": "Unknown",
"latency_ms": None,
"error": None,
"details": "",
}
try:
if protocol == "TCP":
result.update(self._test_tcp(host, port))
elif protocol == "UDP":
if test_type == "ntp":
result.update(self._test_ntp(host))
else:
result.update(self._test_udp(host, port))
else:
result["error"] = f"Protocolo desconocido: {protocol}"
except Exception as e:
result["error"] = str(e)
result["status"] = "Error"
return result
def _test_tcp(self, host: str, port: int) -> Dict:
"""Test de conectividad TCP."""
start_time = time.time()
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
result = sock.connect_ex((host, port))
latency = (time.time() - start_time) * 1000
sock.close()
if result == 0:
return {
"success": True,
"status": "Open",
"latency_ms": round(latency, 2),
"details": f"Conexión TCP exitosa en {latency:.2f}ms",
}
else:
return {
"success": False,
"status": "Closed/Filtered",
"latency_ms": None,
"details": f"No se pudo conectar (código: {result})",
}
except socket.timeout:
return {
"success": False,
"status": "Timeout",
"latency_ms": None,
"details": "Timeout esperando respuesta",
}
except Exception as e:
return {
"success": False,
"status": "Error",
"latency_ms": None,
"error": str(e),
"details": f"Error: {str(e)}",
}
def _test_udp(self, host: str, port: int) -> Dict:
"""Test básico UDP (envía paquete y espera respuesta)."""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(3)
start_time = time.time()
# Enviar paquete vacío
sock.sendto(b"", (host, port))
try:
data, addr = sock.recvfrom(1024)
latency = (time.time() - start_time) * 1000
sock.close()
return {
"success": True,
"status": "Open",
"latency_ms": round(latency, 2),
"details": f"Respuesta UDP recibida en {latency:.2f}ms",
}
except socket.timeout:
sock.close()
return {
"success": False,
"status": "Open|Filtered",
"latency_ms": None,
"details": "No respuesta (puerto puede estar abierto pero filtrado)",
}
except Exception as e:
return {
"success": False,
"status": "Error",
"latency_ms": None,
"error": str(e),
"details": f"Error: {str(e)}",
}
def _test_ntp(self, host: str) -> Dict:
"""Test NTP específico (puerto UDP 123)."""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(5)
start_time = time.time()
# Paquete NTP básico (modo 3: cliente)
ntp_packet = bytearray(48)
ntp_packet[0] = 0x1B # LI=0, VN=3, Mode=3
sock.sendto(ntp_packet, (host, 123))
try:
data, addr = sock.recvfrom(1024)
latency = (time.time() - start_time) * 1000
if len(data) >= 48:
# Extraer timestamp NTP
try:
seconds = (
(data[40] << 24)
| (data[41] << 16)
| (data[42] << 8)
| data[43]
)
# NTP epoch: 1900-01-01
ntp_epoch = datetime(1900, 1, 1)
ntp_time = ntp_epoch.timestamp() + seconds
ntp_dt = datetime.fromtimestamp(ntp_time)
time_str = ntp_dt.strftime('%Y-%m-%d %H:%M:%S')
except (ValueError, OverflowError, OSError):
time_str = "Timestamp no válido"
sock.close()
return {
"success": True,
"status": "Open",
"latency_ms": round(latency, 2),
"details": f"NTP hora local: {time_str}",
}
else:
sock.close()
return {
"success": False,
"status": "Error",
"latency_ms": None,
"details": "Respuesta NTP incompleta",
}
except socket.timeout:
sock.close()
return {
"success": False,
"status": "Timeout",
"latency_ms": None,
"details": "Timeout esperando respuesta NTP",
}
except Exception as e:
return {
"success": False,
"status": "Error",
"latency_ms": None,
"error": str(e),
"details": f"Error NTP: {str(e)}",
}
class VLAN35Checker:
"""Gestor de tests de conectividad para VLAN 35."""
def __init__(self):
# Configuración por defecto basada en el script .bat
self.default_tests = [
{"host": "10.47.8.133", "port": 515, "protocol": "TCP", "type": "connectivity"},
{"host": "10.47.8.133", "port": 9195, "protocol": "TCP", "type": "connectivity"},
{"host": "10.47.8.135", "port": 9191, "protocol": "TCP", "type": "connectivity"},
{"host": "10.47.8.135", "port": 9192, "protocol": "TCP", "type": "connectivity"},
{"host": "10.240.225.171", "port": 465, "protocol": "TCP", "type": "connectivity"},
{"host": "10.244.255.250", "port": 123, "protocol": "UDP", "type": "ntp"},
]
def get_default_tests(self) -> List[Dict]:
"""Retorna la lista de tests por defecto."""
return self.default_tests.copy()
def run_tests(self, tests: List[Dict]) -> ConnectivityTestThread:
"""Inicia los tests en un thread."""
thread = ConnectivityTestThread(tests)
thread.start()
return thread