new features

This commit is contained in:
Mateusz Gruszczyński
2026-04-14 15:43:25 +02:00
parent 1a2ae0d607
commit 92a0f99fb3
17 changed files with 580 additions and 154 deletions

View File

@@ -191,6 +191,8 @@ class BackupService:
router = self._router_for_user(db, user, router_id)
if router.device_type != 'routeros':
raise HTTPException(status_code=400, detail='Text export is available only for RouterOS devices')
if router.disable_all_backups or router.disable_export_backups:
raise HTTPException(status_code=400, detail='Exports are disabled for this device')
settings = settings_service.get_or_create(db)
stamp = datetime.now().strftime('%Y%m%d_%H%M%S')
name = f'{router.name}_{router.id}_{stamp}.rsc'
@@ -214,6 +216,8 @@ class BackupService:
def binary_backup(self, db: Session, user: User, router_id: int) -> Backup:
router = self._router_for_user(db, user, router_id)
if router.disable_all_backups or router.disable_binary_backups:
raise HTTPException(status_code=400, detail='Binary backups are disabled for this device')
settings = settings_service.get_or_create(db)
stamp = datetime.now().strftime('%Y%m%d_%H%M%S')
base_name = f'{router.name}_{router.id}_{stamp}'
@@ -306,6 +310,13 @@ class BackupService:
routers = db.query(Router).filter(Router.owner_id == user.id).all()
result = []
for router in routers:
if router.disable_all_backups or router.disable_export_backups:
result.append({
'router': router.name,
'status': 'skipped',
'message': 'Exports are disabled for this device',
})
continue
if (router.device_type or 'routeros').lower() != 'routeros':
result.append({
'router': router.name,
@@ -324,6 +335,13 @@ class BackupService:
routers = db.query(Router).filter(Router.owner_id == user.id).all()
result = []
for router in routers:
if router.disable_all_backups or router.disable_binary_backups:
result.append({
'router': router.name,
'status': 'skipped',
'message': 'Binary backups are disabled for this device',
})
continue
try:
backup = self.binary_backup(db, user, router.id)
result.append({'router': router.name, 'status': 'ok', 'backup_id': backup.id})

View File

@@ -1,6 +1,10 @@
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime
import io
from pathlib import Path
import platform
import re
import subprocess
import paramiko
from sqlalchemy.orm import Session
@@ -11,6 +15,30 @@ from app.services.swos_beta_service import swos_beta_service
class RouterService:
def ping(self, router: Router):
if getattr(router, 'disable_ping', False):
return {'router_id': router.id, 'reachable': False, 'latency_ms': None, 'disabled': True}
count_flag = '-n' if platform.system().lower().startswith('win') else '-c'
timeout_flag = '-w' if platform.system().lower().startswith('win') else '-W'
command = ['ping', count_flag, '1', timeout_flag, '1', router.host]
try:
completed = subprocess.run(command, capture_output=True, text=True, timeout=3, check=False)
output = completed.stdout + "\n" + completed.stderr
if completed.returncode != 0:
return {'router_id': router.id, 'reachable': False, 'latency_ms': None, 'disabled': False}
match = re.search(r'time[=<]\s*([0-9]+(?:[.,][0-9]+)?)\s*ms', output, re.IGNORECASE)
latency = float(match.group(1).replace(',', '.')) if match else None
return {'router_id': router.id, 'reachable': True, 'latency_ms': latency, 'disabled': False}
except Exception:
return {'router_id': router.id, 'reachable': False, 'latency_ms': None, 'disabled': False}
def ping_many(self, routers: list[Router]):
if not routers:
return []
max_workers = min(8, max(1, len(routers)))
with ThreadPoolExecutor(max_workers=max_workers) as executor:
return list(executor.map(self.ping, routers))
def _load_pkey(self, ssh_key_str: str):
key_str = (ssh_key_str or "").strip()
key_buffer = io.StringIO(key_str)

View File

@@ -212,6 +212,8 @@ class SchedulerService:
with SessionLocal() as db:
routers = db.query(Router).all()
for router in routers:
if router.disable_all_backups or router.disable_export_backups:
continue
try:
backup_service.export_router(db, type('U', (), {'id': router.owner_id})(), router.id)
except Exception as exc:
@@ -221,6 +223,8 @@ class SchedulerService:
with SessionLocal() as db:
routers = db.query(Router).all()
for router in routers:
if router.disable_all_backups or router.disable_binary_backups:
continue
try:
backup_service.binary_backup(db, type('U', (), {'id': router.owner_id})(), router.id)
except Exception as exc: