Files
zebra-power/backend/app/services/wol_service.py

89 lines
2.9 KiB
Python

import asyncio
import subprocess
from typing import List
from sqlalchemy.orm import Session
from app.database import Server, WolLog
from app.models.schemas import WolLogCreate
from app.services.logging_service import LoggingService
import logging
logger = logging.getLogger(__name__)
class WolService:
@staticmethod
async def send_wol_packet(mac_address: str) -> bool:
try:
result = subprocess.run(
["wakeonlan", mac_address],
capture_output=True,
text=True,
timeout=10
)
return result.returncode == 0
except subprocess.TimeoutExpired:
logger.error(f"WOL timeout for MAC: {mac_address}")
return False
except Exception as e:
logger.error(f"WOL error for MAC {mac_address}: {str(e)}")
return False
@staticmethod
async def ping_server(ip_address: str) -> bool:
try:
result = subprocess.run(
["ping", "-c", "1", "-W", "3", ip_address],
capture_output=True,
text=True,
timeout=5
)
return result.returncode == 0
except subprocess.TimeoutExpired:
return False
except Exception as e:
logger.error(f"Ping error for IP {ip_address}: {str(e)}")
return False
@staticmethod
async def wake_server(db: Session, server_id: int) -> bool:
server = db.query(Server).filter(Server.id == server_id).first()
if not server:
return False
success = await WolService.send_wol_packet(server.mac_address)
# Log to both WolLog (backward compatibility) and ActionLog (new unified system)
log_entry = WolLog(
server_id=server_id,
action="wake",
success=success,
message=f"WOL packet sent to {server.mac_address}" if success else "Failed to send WOL packet"
)
db.add(log_entry)
# Log to unified action log
LoggingService.log_wol_action(
db=db,
server_id=server_id,
server_name=server.name,
success=success,
message=f"WOL packet {'sent successfully' if success else 'failed'} to {server.name} ({server.mac_address})"
)
return success
@staticmethod
async def check_all_servers_status(db: Session) -> None:
servers = db.query(Server).all()
tasks = []
for server in servers:
tasks.append(WolService.ping_server(server.ip_address))
results = await asyncio.gather(*tasks)
from datetime import datetime
for server, is_online in zip(servers, results):
server.is_online = is_online
server.last_ping = datetime.utcnow()
db.commit()