refactor func_process_wireguard_status to improve data handling and parsing

This commit is contained in:
Eduardo Silva
2026-01-12 19:10:14 -03:00
parent 61b35601f3
commit e430ff6b0e
3 changed files with 78 additions and 85 deletions

View File

@@ -4,6 +4,7 @@ import os
import subprocess import subprocess
import time import time
import uuid import uuid
from typing import Dict, Any
import pytz import pytz
import requests import requests
@@ -211,56 +212,50 @@ def api_instance_info(request):
return JsonResponse(data) return JsonResponse(data)
def func_process_wireguard_status(): def func_process_wireguard_status() -> Dict[str, Any]:
# Query WireGuard status from the system and construct the data dictionary command = "wg show all dump"
commands = {
'latest-handshakes': "wg show all latest-handshakes | expand | tr -s ' '",
'allowed-ips': "wg show all allowed-ips | expand | tr -s ' '",
'transfer': "wg show all transfer | expand | tr -s ' '",
'endpoints': "wg show all endpoints | expand | tr -s ' '",
}
data = {}
for key, command in commands.items():
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
stdout, stderr = process.communicate() stdout, stderr = process.communicate()
if process.returncode != 0: if process.returncode != 0:
return JsonResponse({'error': stderr}, status=400) return {"message": stderr, "status": "error"}
current_interface = None data: Dict[str, Dict[str, Dict[str, Any]]] = {}
for line in stdout.strip().split('\n'):
parts = line.split() # wg dump format is tab-separated.
if len(parts) >= 3: # There are two kinds of lines:
interface, peer, value = parts[0], parts[1], " ".join(parts[2:]) # - Interface line: interface \t private_key \t public_key \t listen_port \t fwmark
current_interface = interface # - Peer line: interface \t peer_public_key \t preshared_key \t endpoint \t allowed_ips \t latest_handshake \t transfer_rx \t transfer_tx \t persistent_keepalive
elif len(parts) == 2 and current_interface: for line in stdout.strip().split("\n"):
peer, value = parts parts = line.split("\t")
else: if len(parts) < 5:
continue continue
interface = parts[0]
# Peer lines are expected to have at least 9 fields
if len(parts) < 9:
# interface line, ignore
continue
peer_public_key = parts[1]
endpoint = parts[3]
allowed_ips_raw = parts[4]
latest_handshake = parts[5]
transfer_rx = parts[6]
transfer_tx = parts[7]
if interface not in data: if interface not in data:
data[interface] = {} data[interface] = {}
if peer not in data[interface]: data[interface][peer_public_key] = {
data[interface][peer] = { "allowed-ips": [ip for ip in allowed_ips_raw.split(",") if ip] if allowed_ips_raw else [],
'allowed-ips': [], "latest-handshakes": latest_handshake or "",
'latest-handshakes': '', "transfer": {"tx": int(transfer_tx or 0), "rx": int(transfer_rx or 0)},
'transfer': {'tx': 0, 'rx': 0}, "endpoints": endpoint or "",
'endpoints': '',
} }
if key == 'allowed-ips':
data[interface][peer]['allowed-ips'].append(value)
elif key == 'transfer':
rx, tx = value.split()[-2:]
data[interface][peer]['transfer'] = {'tx': int(tx), 'rx': int(rx)}
elif key == 'endpoints':
data[interface][peer]['endpoints'] = value
else:
data[interface][peer][key] = value
return data return data

View File

@@ -3,6 +3,7 @@ import logging
import os import os
import subprocess import subprocess
import time import time
from typing import Dict, Any
import requests import requests
@@ -40,55 +41,50 @@ class ClusterWorker:
self.base_url = f"{MASTER_SERVER_ADDRESS}/api/cluster" self.base_url = f"{MASTER_SERVER_ADDRESS}/api/cluster"
def func_process_wireguard_status(self): def func_process_wireguard_status(self) -> Dict[str, Any]:
# Query WireGuard status from the system and construct the data dictionary command = "wg show all dump"
commands = {
'latest-handshakes': "wg show all latest-handshakes | expand | tr -s ' '",
'allowed-ips': "wg show all allowed-ips | expand | tr -s ' '",
'transfer': "wg show all transfer | expand | tr -s ' '",
'endpoints': "wg show all endpoints | expand | tr -s ' '",
}
data = {}
for key, command in commands.items():
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
stdout, stderr = process.communicate() stdout, stderr = process.communicate()
if process.returncode != 0: if process.returncode != 0:
return {'error': stderr} return {"message": stderr, "status": "error"}
current_interface = None data: Dict[str, Dict[str, Dict[str, Any]]] = {}
for line in stdout.strip().split('\n'):
parts = line.split() # wg dump format is tab-separated.
if len(parts) >= 3: # There are two kinds of lines:
interface, peer, value = parts[0], parts[1], " ".join(parts[2:]) # - Interface line: interface \t private_key \t public_key \t listen_port \t fwmark
current_interface = interface # - Peer line: interface \t peer_public_key \t preshared_key \t endpoint \t allowed_ips \t latest_handshake \t transfer_rx \t transfer_tx \t persistent_keepalive
elif len(parts) == 2 and current_interface: for line in stdout.strip().split("\n"):
peer, value = parts parts = line.split("\t")
else: if len(parts) < 5:
continue continue
interface = parts[0]
# Peer lines are expected to have at least 9 fields
if len(parts) < 9:
# interface line, ignore
continue
peer_public_key = parts[1]
endpoint = parts[3]
allowed_ips_raw = parts[4]
latest_handshake = parts[5]
transfer_rx = parts[6]
transfer_tx = parts[7]
if interface not in data: if interface not in data:
data[interface] = {} data[interface] = {}
if peer not in data[interface]: data[interface][peer_public_key] = {
data[interface][peer] = { "allowed-ips": [ip for ip in allowed_ips_raw.split(",") if ip] if allowed_ips_raw else [],
'allowed-ips': [], "latest-handshakes": latest_handshake or "",
'latest-handshakes': '', "transfer": {"tx": int(transfer_tx or 0), "rx": int(transfer_rx or 0)},
'transfer': {'tx': 0, 'rx': 0}, "endpoints": endpoint or "",
'endpoints': '',
} }
if key == 'allowed-ips':
data[interface][peer]['allowed-ips'].append(value)
elif key == 'transfer':
rx, tx = value.split()[-2:]
data[interface][peer]['transfer'] = {'tx': int(tx), 'rx': int(rx)}
elif key == 'endpoints':
data[interface][peer]['endpoints'] = value
else:
data[interface][peer][key] = value
return data return data

View File

@@ -593,7 +593,9 @@
}; };
const checkAllowedIps = (allowedIpsElement, allowedIpsApiResponse) => { const checkAllowedIps = (allowedIpsElement, allowedIpsApiResponse) => {
const apiIps = allowedIpsApiResponse[0].split(' '); const apiIps = Array.isArray(allowedIpsApiResponse)
? allowedIpsApiResponse.filter(Boolean)
: (allowedIpsApiResponse || '').split(/\s+/).filter(Boolean);
const htmlIpsText = allowedIpsElement.textContent.trim(); const htmlIpsText = allowedIpsElement.textContent.trim();
const htmlIpsArray = htmlIpsText.match(/\b(?:\d{1,3}\.){3}\d{1,3}\/\d{1,2}\b/g) || []; const htmlIpsArray = htmlIpsText.match(/\b(?:\d{1,3}\.){3}\d{1,3}\/\d{1,2}\b/g) || [];