Merge branch '3.1' into code-review-fixes

This commit is contained in:
Guobin Yue 2026-08-15 22:39:42 +08:00 committed by GitHub
commit 74a51a1f9f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 73 additions and 2 deletions

View File

@ -21,7 +21,9 @@ API routes for compute.
import os
import psutil
import cpuinfo
from functools import lru_cache
from gns3server.config import Config
from gns3server.utils.cpu_percent import CpuPercent
from gns3server.version import __version__
@ -42,6 +44,11 @@ from typing import Optional, List
router = APIRouter()
@lru_cache(maxsize=1)
def get_cpu_model() -> str:
return cpuinfo.get_cpu_info().get("brand_raw", "")
@router.post("/projects/{project_id}/ports/udp", status_code=status.HTTP_201_CREATED)
def allocate_udp_port(project_id: UUID) -> dict:
"""
@ -119,10 +126,15 @@ def compute_statistics() -> dict:
swap_free = psutil.swap_memory().free
swap_used = psutil.swap_memory().used
cpu_percent = int(CpuPercent.get())
load_average_percent = [int(x / psutil.cpu_count() * 100) for x in psutil.getloadavg()]
cpu_count = psutil.cpu_count(logical=True) or 1
cpu_count_physical = psutil.cpu_count(logical=False)
raw_load_average = psutil.getloadavg()
load_average = [round(x, 2) for x in raw_load_average]
load_average_percent = [round(x / cpu_count * 100, 2) for x in raw_load_average]
memory_percent = int(psutil.virtual_memory().percent)
swap_percent = int(psutil.swap_memory().percent)
disk_usage_percent = int(psutil.disk_usage(get_default_project_directory()).percent)
disk_usage = psutil.disk_usage(get_default_project_directory())
disk_usage_percent = int(disk_usage.percent)
except psutil.Error as e:
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR)
# raise HTTPConflict(text="Psutil error detected: {}".format(e))
@ -135,9 +147,16 @@ def compute_statistics() -> dict:
"swap_free": swap_free,
"swap_used": swap_used,
"cpu_usage_percent": cpu_percent,
"cpu_count": cpu_count,
"cpu_count_physical": cpu_count_physical,
"cpu_model": get_cpu_model(),
"memory_usage_percent": memory_percent,
"swap_usage_percent": swap_percent,
"disk_usage_percent": disk_usage_percent,
"disk_total": disk_usage.total,
"disk_used": disk_usage.used,
"disk_free": disk_usage.free,
"load_average": load_average,
"load_average_percent": load_average_percent,
}

View File

@ -17,6 +17,8 @@
import asyncio
import signal
import os
import time
import psutil
from fastapi import APIRouter, Request, Depends, WebSocket, WebSocketDisconnect, status
from fastapi.responses import StreamingResponse
@ -42,6 +44,13 @@ log = logging.getLogger(__name__)
router = APIRouter()
def get_server_uptime_seconds() -> int:
try:
return max(0, int(time.time() - psutil.Process().create_time()))
except psutil.Error:
return 0
@router.get(
"/version",
response_model=schemas.Version,
@ -246,6 +255,7 @@ async def statistics() -> dict:
webwireshark_stats = await collect_webwireshark_stats(projects)
return {
"uptime_seconds": get_server_uptime_seconds(),
"computes": compute_statistics,
"projects": project_stats,
"nodes": node_stats,

View File

@ -0,0 +1,28 @@
from types import SimpleNamespace
from unittest.mock import patch
from gns3server.api.routes.compute.compute import compute_statistics
def test_compute_statistics_preserves_load_average_precision() -> None:
memory = SimpleNamespace(total=8192, available=4096, percent=50)
swap = SimpleNamespace(total=1024, free=512, used=512, percent=50)
disk = SimpleNamespace(total=16384, used=4096, free=12288, percent=25)
with patch("gns3server.api.routes.compute.compute.CpuPercent.get", return_value=10), \
patch("gns3server.api.routes.compute.compute.get_cpu_model", return_value="Test CPU"), \
patch("gns3server.api.routes.compute.compute.psutil.virtual_memory", return_value=memory), \
patch("gns3server.api.routes.compute.compute.psutil.swap_memory", return_value=swap), \
patch("gns3server.api.routes.compute.compute.psutil.disk_usage", return_value=disk), \
patch("gns3server.api.routes.compute.compute.psutil.cpu_count", return_value=4), \
patch("gns3server.api.routes.compute.compute.psutil.getloadavg", return_value=(1.25, 2.5, 3.75)):
statistics = compute_statistics()
assert statistics["load_average"] == [1.25, 2.5, 3.75]
assert statistics["load_average_percent"] == [31.25, 62.5, 93.75]
assert statistics["cpu_count"] == 4
assert statistics["cpu_count_physical"] == 4
assert statistics["cpu_model"] == "Test CPU"
assert statistics["disk_total"] == 16384
assert statistics["disk_used"] == 4096
assert statistics["disk_free"] == 12288

View File

@ -0,0 +1,14 @@
from unittest.mock import MagicMock, patch
from gns3server.api.routes.controller.controller import get_server_uptime_seconds
def test_server_uptime_uses_process_creation_time() -> None:
process = MagicMock()
process.create_time.return_value = 50.25
with patch("gns3server.api.routes.controller.controller.time.time", return_value=200.75), \
patch("gns3server.api.routes.controller.controller.psutil.Process", return_value=process):
uptime = get_server_uptime_seconds()
assert uptime == 150