1
This commit is contained in:
@@ -9,11 +9,24 @@ from datetime import datetime
|
||||
|
||||
from app.db.session import get_db
|
||||
from app.core.security import verify_token
|
||||
from app.schemas.benchmark import BenchmarkPayload, BenchmarkResponse, BenchmarkDetail, BenchmarkSummary
|
||||
from app.schemas.benchmark import (
|
||||
BenchmarkPayload,
|
||||
BenchmarkResponse,
|
||||
BenchmarkDetail,
|
||||
BenchmarkSummary,
|
||||
BenchmarkUpdate,
|
||||
)
|
||||
from app.models.device import Device
|
||||
from app.models.hardware_snapshot import HardwareSnapshot
|
||||
from app.models.benchmark import Benchmark
|
||||
from app.utils.scoring import calculate_global_score
|
||||
from app.utils.scoring import (
|
||||
calculate_global_score,
|
||||
calculate_cpu_score,
|
||||
calculate_memory_score,
|
||||
calculate_disk_score,
|
||||
calculate_network_score,
|
||||
calculate_gpu_score
|
||||
)
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -91,7 +104,7 @@ async def submit_benchmark(
|
||||
snapshot.ram_slots_total = hw.ram.slots_total if hw.ram else None
|
||||
snapshot.ram_slots_used = hw.ram.slots_used if hw.ram else None
|
||||
snapshot.ram_ecc = hw.ram.ecc if hw.ram else None
|
||||
snapshot.ram_layout_json = json.dumps([slot.dict() for slot in hw.ram.layout]) if hw.ram and hw.ram.layout else None
|
||||
snapshot.ram_layout_json = json.dumps([slot.model_dump() for slot in hw.ram.layout]) if hw.ram and hw.ram.layout else None
|
||||
|
||||
# GPU
|
||||
snapshot.gpu_summary = f"{hw.gpu.vendor} {hw.gpu.model}" if hw.gpu and hw.gpu.model else None
|
||||
@@ -104,11 +117,12 @@ async def submit_benchmark(
|
||||
|
||||
# Storage
|
||||
snapshot.storage_summary = f"{len(hw.storage.devices)} device(s)" if hw.storage and hw.storage.devices else None
|
||||
snapshot.storage_devices_json = json.dumps([d.dict() for d in hw.storage.devices]) if hw.storage and hw.storage.devices else None
|
||||
snapshot.partitions_json = json.dumps([p.dict() for p in hw.storage.partitions]) if hw.storage and hw.storage.partitions else None
|
||||
snapshot.storage_devices_json = json.dumps([d.model_dump() for d in hw.storage.devices]) if hw.storage and hw.storage.devices else None
|
||||
snapshot.partitions_json = json.dumps([p.model_dump() for p in hw.storage.partitions]) if hw.storage and hw.storage.partitions else None
|
||||
|
||||
# Network
|
||||
snapshot.network_interfaces_json = json.dumps([i.dict() for i in hw.network.interfaces]) if hw.network and hw.network.interfaces else None
|
||||
snapshot.network_interfaces_json = json.dumps([i.model_dump() for i in hw.network.interfaces]) if hw.network and hw.network.interfaces else None
|
||||
snapshot.network_shares_json = json.dumps([share.model_dump() for share in hw.network_shares]) if hw.network_shares else None
|
||||
|
||||
# OS / Motherboard
|
||||
snapshot.os_name = hw.os.name if hw.os else None
|
||||
@@ -116,15 +130,29 @@ async def submit_benchmark(
|
||||
snapshot.kernel_version = hw.os.kernel_version if hw.os else None
|
||||
snapshot.architecture = hw.os.architecture if hw.os else None
|
||||
snapshot.virtualization_type = hw.os.virtualization_type if hw.os else None
|
||||
snapshot.screen_resolution = hw.os.screen_resolution if hw.os else None
|
||||
snapshot.display_server = hw.os.display_server if hw.os else None
|
||||
snapshot.session_type = hw.os.session_type if hw.os else None
|
||||
snapshot.last_boot_time = hw.os.last_boot_time if hw.os else None
|
||||
snapshot.uptime_seconds = hw.os.uptime_seconds if hw.os else None
|
||||
snapshot.battery_percentage = hw.os.battery_percentage if hw.os else None
|
||||
snapshot.battery_status = hw.os.battery_status if hw.os else None
|
||||
snapshot.battery_health = hw.os.battery_health if hw.os else None
|
||||
snapshot.hostname = hw.os.hostname if hw.os else None
|
||||
snapshot.desktop_environment = hw.os.desktop_environment if hw.os else None
|
||||
snapshot.motherboard_vendor = hw.motherboard.vendor if hw.motherboard else None
|
||||
snapshot.motherboard_model = hw.motherboard.model if hw.motherboard else None
|
||||
snapshot.bios_vendor = hw.motherboard.bios_vendor if hw.motherboard and hasattr(hw.motherboard, 'bios_vendor') else None
|
||||
snapshot.bios_version = hw.motherboard.bios_version if hw.motherboard else None
|
||||
snapshot.bios_date = hw.motherboard.bios_date if hw.motherboard else None
|
||||
|
||||
# PCI and USB Devices
|
||||
snapshot.pci_devices_json = json.dumps([d.model_dump(by_alias=True) for d in hw.pci_devices]) if hw.pci_devices else None
|
||||
snapshot.usb_devices_json = json.dumps([d.model_dump() for d in hw.usb_devices]) if hw.usb_devices else None
|
||||
|
||||
# Misc
|
||||
snapshot.sensors_json = json.dumps(hw.sensors.dict()) if hw.sensors else None
|
||||
snapshot.raw_info_json = json.dumps(hw.raw_info.dict()) if hw.raw_info else None
|
||||
snapshot.sensors_json = json.dumps(hw.sensors.model_dump()) if hw.sensors else None
|
||||
snapshot.raw_info_json = json.dumps(hw.raw_info.model_dump()) if hw.raw_info else None
|
||||
|
||||
# Add to session only if it's a new snapshot
|
||||
if not existing_snapshot:
|
||||
@@ -135,18 +163,61 @@ async def submit_benchmark(
|
||||
# 3. Create benchmark
|
||||
results = payload.results
|
||||
|
||||
# Calculate global score if not provided or recalculate
|
||||
global_score = calculate_global_score(
|
||||
cpu_score=results.cpu.score if results.cpu else None,
|
||||
memory_score=results.memory.score if results.memory else None,
|
||||
disk_score=results.disk.score if results.disk else None,
|
||||
network_score=results.network.score if results.network else None,
|
||||
gpu_score=results.gpu.score if results.gpu else None
|
||||
)
|
||||
# Recalculate scores from raw metrics using new formulas
|
||||
cpu_score = None
|
||||
cpu_score_single = None
|
||||
cpu_score_multi = None
|
||||
|
||||
# Use provided global_score if available and valid
|
||||
if results.global_score is not None:
|
||||
global_score = results.global_score
|
||||
if results.cpu:
|
||||
# Use scores from script if available (preferred), otherwise calculate
|
||||
if results.cpu.score_single is not None:
|
||||
cpu_score_single = results.cpu.score_single
|
||||
elif results.cpu.events_per_sec_single:
|
||||
cpu_score_single = calculate_cpu_score(results.cpu.events_per_sec_single)
|
||||
|
||||
if results.cpu.score_multi is not None:
|
||||
cpu_score_multi = results.cpu.score_multi
|
||||
elif results.cpu.events_per_sec_multi:
|
||||
cpu_score_multi = calculate_cpu_score(results.cpu.events_per_sec_multi)
|
||||
|
||||
# Use score from script if available, otherwise calculate
|
||||
if results.cpu.score is not None:
|
||||
cpu_score = results.cpu.score
|
||||
elif results.cpu.events_per_sec_multi:
|
||||
cpu_score = cpu_score_multi
|
||||
elif results.cpu.events_per_sec:
|
||||
cpu_score = calculate_cpu_score(results.cpu.events_per_sec)
|
||||
|
||||
memory_score = None
|
||||
if results.memory and results.memory.throughput_mib_s:
|
||||
memory_score = calculate_memory_score(results.memory.throughput_mib_s)
|
||||
|
||||
disk_score = None
|
||||
if results.disk:
|
||||
disk_score = calculate_disk_score(
|
||||
read_mb_s=results.disk.read_mb_s,
|
||||
write_mb_s=results.disk.write_mb_s
|
||||
)
|
||||
|
||||
network_score = None
|
||||
if results.network:
|
||||
network_score = calculate_network_score(
|
||||
upload_mbps=results.network.upload_mbps,
|
||||
download_mbps=results.network.download_mbps
|
||||
)
|
||||
|
||||
gpu_score = None
|
||||
if results.gpu and results.gpu.glmark2_score:
|
||||
gpu_score = calculate_gpu_score(results.gpu.glmark2_score)
|
||||
|
||||
# Calculate global score from recalculated component scores
|
||||
global_score = calculate_global_score(
|
||||
cpu_score=cpu_score,
|
||||
memory_score=memory_score,
|
||||
disk_score=disk_score,
|
||||
network_score=network_score,
|
||||
gpu_score=gpu_score
|
||||
)
|
||||
|
||||
# Extract network results for easier frontend access
|
||||
network_results = None
|
||||
@@ -155,7 +226,7 @@ async def submit_benchmark(
|
||||
"upload_mbps": results.network.upload_mbps if hasattr(results.network, 'upload_mbps') else None,
|
||||
"download_mbps": results.network.download_mbps if hasattr(results.network, 'download_mbps') else None,
|
||||
"ping_ms": results.network.ping_ms if hasattr(results.network, 'ping_ms') else None,
|
||||
"score": results.network.score
|
||||
"score": network_score
|
||||
}
|
||||
|
||||
benchmark = Benchmark(
|
||||
@@ -165,11 +236,13 @@ async def submit_benchmark(
|
||||
bench_script_version=payload.bench_script_version,
|
||||
|
||||
global_score=global_score,
|
||||
cpu_score=results.cpu.score if results.cpu else None,
|
||||
memory_score=results.memory.score if results.memory else None,
|
||||
disk_score=results.disk.score if results.disk else None,
|
||||
network_score=results.network.score if results.network else None,
|
||||
gpu_score=results.gpu.score if results.gpu else None,
|
||||
cpu_score=cpu_score,
|
||||
cpu_score_single=cpu_score_single,
|
||||
cpu_score_multi=cpu_score_multi,
|
||||
memory_score=memory_score,
|
||||
disk_score=disk_score,
|
||||
network_score=network_score,
|
||||
gpu_score=gpu_score,
|
||||
|
||||
details_json=json.dumps(results.dict()),
|
||||
network_results_json=json.dumps(network_results) if network_results else None
|
||||
@@ -210,9 +283,54 @@ async def get_benchmark(
|
||||
bench_script_version=benchmark.bench_script_version,
|
||||
global_score=benchmark.global_score,
|
||||
cpu_score=benchmark.cpu_score,
|
||||
cpu_score_single=benchmark.cpu_score_single,
|
||||
cpu_score_multi=benchmark.cpu_score_multi,
|
||||
memory_score=benchmark.memory_score,
|
||||
disk_score=benchmark.disk_score,
|
||||
network_score=benchmark.network_score,
|
||||
gpu_score=benchmark.gpu_score,
|
||||
details=json.loads(benchmark.details_json)
|
||||
details=json.loads(benchmark.details_json),
|
||||
notes=benchmark.notes
|
||||
)
|
||||
|
||||
|
||||
@router.patch("/benchmarks/{benchmark_id}", response_model=BenchmarkSummary)
|
||||
async def update_benchmark_entry(
|
||||
benchmark_id: int,
|
||||
payload: BenchmarkUpdate,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""
|
||||
Update editable benchmark fields (currently only notes).
|
||||
"""
|
||||
benchmark = db.query(Benchmark).filter(Benchmark.id == benchmark_id).first()
|
||||
|
||||
if not benchmark:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Benchmark {benchmark_id} not found"
|
||||
)
|
||||
|
||||
update_data = payload.model_dump(exclude_unset=True)
|
||||
|
||||
if "notes" in update_data:
|
||||
benchmark.notes = update_data["notes"]
|
||||
|
||||
db.add(benchmark)
|
||||
db.commit()
|
||||
db.refresh(benchmark)
|
||||
|
||||
return BenchmarkSummary(
|
||||
id=benchmark.id,
|
||||
run_at=benchmark.run_at.isoformat(),
|
||||
global_score=benchmark.global_score,
|
||||
cpu_score=benchmark.cpu_score,
|
||||
cpu_score_single=benchmark.cpu_score_single,
|
||||
cpu_score_multi=benchmark.cpu_score_multi,
|
||||
memory_score=benchmark.memory_score,
|
||||
disk_score=benchmark.disk_score,
|
||||
network_score=benchmark.network_score,
|
||||
gpu_score=benchmark.gpu_score,
|
||||
bench_script_version=benchmark.bench_script_version,
|
||||
notes=benchmark.notes
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@ Linux BenchTools - Devices API
|
||||
"""
|
||||
|
||||
import json
|
||||
from fastapi import APIRouter, Depends, HTTPException, status, Query
|
||||
from fastapi import APIRouter, Depends, HTTPException, status, Query, Response
|
||||
from sqlalchemy.orm import Session
|
||||
from typing import List
|
||||
|
||||
@@ -68,7 +68,8 @@ async def get_devices(
|
||||
disk_score=last_bench.disk_score,
|
||||
network_score=last_bench.network_score,
|
||||
gpu_score=last_bench.gpu_score,
|
||||
bench_script_version=last_bench.bench_script_version
|
||||
bench_script_version=last_bench.bench_script_version,
|
||||
notes=last_bench.notes
|
||||
)
|
||||
|
||||
items.append(DeviceSummary(
|
||||
@@ -80,6 +81,9 @@ async def get_devices(
|
||||
location=device.location,
|
||||
owner=device.owner,
|
||||
tags=device.tags,
|
||||
purchase_store=device.purchase_store,
|
||||
purchase_date=device.purchase_date,
|
||||
purchase_price=device.purchase_price,
|
||||
created_at=device.created_at.isoformat(),
|
||||
updated_at=device.updated_at.isoformat(),
|
||||
last_benchmark=last_bench_summary
|
||||
@@ -125,7 +129,8 @@ async def get_device(
|
||||
disk_score=last_bench.disk_score,
|
||||
network_score=last_bench.network_score,
|
||||
gpu_score=last_bench.gpu_score,
|
||||
bench_script_version=last_bench.bench_script_version
|
||||
bench_script_version=last_bench.bench_script_version,
|
||||
notes=last_bench.notes
|
||||
)
|
||||
|
||||
# Get last hardware snapshot
|
||||
@@ -146,20 +151,40 @@ async def get_device(
|
||||
cpu_base_freq_ghz=last_snapshot.cpu_base_freq_ghz,
|
||||
cpu_max_freq_ghz=last_snapshot.cpu_max_freq_ghz,
|
||||
ram_total_mb=last_snapshot.ram_total_mb,
|
||||
ram_used_mb=last_snapshot.ram_used_mb,
|
||||
ram_free_mb=last_snapshot.ram_free_mb,
|
||||
ram_shared_mb=last_snapshot.ram_shared_mb,
|
||||
ram_slots_total=last_snapshot.ram_slots_total,
|
||||
ram_slots_used=last_snapshot.ram_slots_used,
|
||||
gpu_summary=last_snapshot.gpu_summary,
|
||||
gpu_model=last_snapshot.gpu_model,
|
||||
storage_summary=last_snapshot.storage_summary,
|
||||
storage_devices_json=last_snapshot.storage_devices_json,
|
||||
partitions_json=last_snapshot.partitions_json,
|
||||
network_interfaces_json=last_snapshot.network_interfaces_json,
|
||||
network_shares_json=last_snapshot.network_shares_json,
|
||||
os_name=last_snapshot.os_name,
|
||||
os_version=last_snapshot.os_version,
|
||||
kernel_version=last_snapshot.kernel_version,
|
||||
architecture=last_snapshot.architecture,
|
||||
virtualization_type=last_snapshot.virtualization_type,
|
||||
screen_resolution=last_snapshot.screen_resolution,
|
||||
display_server=last_snapshot.display_server,
|
||||
session_type=last_snapshot.session_type,
|
||||
last_boot_time=last_snapshot.last_boot_time,
|
||||
uptime_seconds=last_snapshot.uptime_seconds,
|
||||
battery_percentage=last_snapshot.battery_percentage,
|
||||
battery_status=last_snapshot.battery_status,
|
||||
battery_health=last_snapshot.battery_health,
|
||||
hostname=last_snapshot.hostname,
|
||||
desktop_environment=last_snapshot.desktop_environment,
|
||||
motherboard_vendor=last_snapshot.motherboard_vendor,
|
||||
motherboard_model=last_snapshot.motherboard_model
|
||||
motherboard_model=last_snapshot.motherboard_model,
|
||||
bios_vendor=last_snapshot.bios_vendor,
|
||||
bios_version=last_snapshot.bios_version,
|
||||
bios_date=last_snapshot.bios_date,
|
||||
pci_devices_json=last_snapshot.pci_devices_json,
|
||||
usb_devices_json=last_snapshot.usb_devices_json
|
||||
)
|
||||
|
||||
# Get documents for this device
|
||||
@@ -189,6 +214,9 @@ async def get_device(
|
||||
location=device.location,
|
||||
owner=device.owner,
|
||||
tags=device.tags,
|
||||
purchase_store=device.purchase_store,
|
||||
purchase_date=device.purchase_date,
|
||||
purchase_price=device.purchase_price,
|
||||
created_at=device.created_at.isoformat(),
|
||||
updated_at=device.updated_at.isoformat(),
|
||||
last_benchmark=last_bench_summary,
|
||||
@@ -232,7 +260,8 @@ async def get_device_benchmarks(
|
||||
disk_score=b.disk_score,
|
||||
network_score=b.network_score,
|
||||
gpu_score=b.gpu_score,
|
||||
bench_script_version=b.bench_script_version
|
||||
bench_script_version=b.bench_script_version,
|
||||
notes=b.notes
|
||||
)
|
||||
for b in benchmarks
|
||||
]
|
||||
@@ -276,3 +305,25 @@ async def update_device(
|
||||
|
||||
# Return updated device (reuse get_device logic)
|
||||
return await get_device(device_id, db)
|
||||
|
||||
|
||||
@router.delete("/devices/{device_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
async def delete_device(
|
||||
device_id: int,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""
|
||||
Delete a device and all related data
|
||||
"""
|
||||
device = db.query(Device).filter(Device.id == device_id).first()
|
||||
|
||||
if not device:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND,
|
||||
detail=f"Device {device_id} not found"
|
||||
)
|
||||
|
||||
db.delete(device)
|
||||
db.commit()
|
||||
|
||||
return Response(status_code=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
Reference in New Issue
Block a user