JNC Linux
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user