.gitignore update
This commit is contained in:
@ -1,5 +0,0 @@
|
||||
"""Services package for system operations"""
|
||||
from .system_service import SystemService
|
||||
|
||||
__all__ = ['SystemService']
|
||||
|
||||
@ -1,225 +0,0 @@
|
||||
"""
|
||||
System Service Module
|
||||
|
||||
Provides system monitoring and health check functionality for the Remote Access API.
|
||||
Includes checks for database connectivity, daemon status, and system resources.
|
||||
"""
|
||||
|
||||
import socket
|
||||
import psutil
|
||||
from datetime import datetime
|
||||
from typing import Dict, Any, Optional
|
||||
import structlog
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
|
||||
class SystemService:
|
||||
"""Service for system health checks and monitoring"""
|
||||
|
||||
def __init__(self, service_start_time: Optional[datetime] = None):
|
||||
"""
|
||||
Initialize SystemService
|
||||
|
||||
Args:
|
||||
service_start_time: Service startup time for uptime calculation
|
||||
"""
|
||||
self.service_start_time = service_start_time or datetime.now()
|
||||
|
||||
@staticmethod
|
||||
def check_database_connection(guacamole_client: Any, guacamole_url: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Check Guacamole database connectivity
|
||||
|
||||
Args:
|
||||
guacamole_client: Guacamole client instance
|
||||
guacamole_url: Guacamole base URL
|
||||
|
||||
Returns:
|
||||
Status dictionary with connection state
|
||||
"""
|
||||
try:
|
||||
# Try to get system token (requires database access)
|
||||
token = guacamole_client.get_system_token()
|
||||
|
||||
if token:
|
||||
return {
|
||||
"status": "ok",
|
||||
"message": "Database connection healthy"
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"status": "error",
|
||||
"message": "Failed to obtain system token"
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Database connection check failed", error=str(e))
|
||||
return {
|
||||
"status": "error",
|
||||
"error": str(e),
|
||||
"message": "Database connection failed"
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def check_guacd_daemon() -> Dict[str, Any]:
|
||||
"""
|
||||
Check if guacd daemon is running
|
||||
|
||||
Returns:
|
||||
Status dictionary with daemon state
|
||||
"""
|
||||
try:
|
||||
# Check if guacd is listening on default port 4822
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.settimeout(2)
|
||||
result = sock.connect_ex(('localhost', 4822))
|
||||
sock.close()
|
||||
|
||||
if result == 0:
|
||||
return {
|
||||
"status": "ok",
|
||||
"message": "guacd daemon is running",
|
||||
"port": 4822
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"status": "error",
|
||||
"message": "guacd daemon is not accessible",
|
||||
"port": 4822
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error("guacd daemon check failed", error=str(e))
|
||||
return {
|
||||
"status": "error",
|
||||
"error": str(e),
|
||||
"message": "Failed to check guacd daemon"
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def check_system_resources() -> Dict[str, Any]:
|
||||
"""
|
||||
Check system resources (CPU, RAM, Disk)
|
||||
|
||||
Returns:
|
||||
Status dictionary with resource usage
|
||||
"""
|
||||
try:
|
||||
# CPU usage
|
||||
cpu_percent = psutil.cpu_percent(interval=1)
|
||||
|
||||
# Memory usage
|
||||
memory = psutil.virtual_memory()
|
||||
memory_percent = memory.percent
|
||||
|
||||
# Disk usage
|
||||
disk = psutil.disk_usage('/')
|
||||
disk_percent = disk.percent
|
||||
|
||||
# Determine overall status based on thresholds
|
||||
status = "ok"
|
||||
warnings = []
|
||||
|
||||
if cpu_percent > 90:
|
||||
status = "critical"
|
||||
warnings.append(f"CPU usage critical: {cpu_percent}%")
|
||||
elif cpu_percent > 80:
|
||||
status = "warning"
|
||||
warnings.append(f"CPU usage high: {cpu_percent}%")
|
||||
|
||||
if memory_percent > 90:
|
||||
status = "critical"
|
||||
warnings.append(f"Memory usage critical: {memory_percent}%")
|
||||
elif memory_percent > 80:
|
||||
if status == "ok":
|
||||
status = "warning"
|
||||
warnings.append(f"Memory usage high: {memory_percent}%")
|
||||
|
||||
if disk_percent > 90:
|
||||
status = "critical"
|
||||
warnings.append(f"Disk usage critical: {disk_percent}%")
|
||||
elif disk_percent > 80:
|
||||
if status == "ok":
|
||||
status = "warning"
|
||||
warnings.append(f"Disk usage high: {disk_percent}%")
|
||||
|
||||
result = {
|
||||
"status": status,
|
||||
"cpu_percent": round(cpu_percent, 2),
|
||||
"memory_percent": round(memory_percent, 2),
|
||||
"disk_percent": round(disk_percent, 2),
|
||||
"memory_available_gb": round(memory.available / (1024**3), 2),
|
||||
"disk_free_gb": round(disk.free / (1024**3), 2)
|
||||
}
|
||||
|
||||
if warnings:
|
||||
result["warnings"] = warnings
|
||||
|
||||
if status == "ok":
|
||||
result["message"] = "System resources healthy"
|
||||
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logger.error("System resources check failed", error=str(e))
|
||||
return {
|
||||
"status": "error",
|
||||
"error": str(e),
|
||||
"message": "Failed to check system resources"
|
||||
}
|
||||
|
||||
def get_system_info(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Get system information (uptime, version, etc.)
|
||||
|
||||
Returns:
|
||||
Dictionary with system information
|
||||
"""
|
||||
try:
|
||||
uptime_seconds = int((datetime.now() - self.service_start_time).total_seconds())
|
||||
|
||||
return {
|
||||
"uptime_seconds": uptime_seconds,
|
||||
"uptime_formatted": self._format_uptime(uptime_seconds),
|
||||
"python_version": f"{psutil.PROCFS_PATH if hasattr(psutil, 'PROCFS_PATH') else 'N/A'}",
|
||||
"cpu_count": psutil.cpu_count(),
|
||||
"boot_time": datetime.fromtimestamp(psutil.boot_time()).isoformat()
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to get system info", error=str(e))
|
||||
return {
|
||||
"error": str(e),
|
||||
"message": "Failed to retrieve system information"
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _format_uptime(seconds: int) -> str:
|
||||
"""
|
||||
Format uptime seconds to human-readable string
|
||||
|
||||
Args:
|
||||
seconds: Uptime in seconds
|
||||
|
||||
Returns:
|
||||
Formatted uptime string
|
||||
"""
|
||||
days = seconds // 86400
|
||||
hours = (seconds % 86400) // 3600
|
||||
minutes = (seconds % 3600) // 60
|
||||
secs = seconds % 60
|
||||
|
||||
parts = []
|
||||
if days > 0:
|
||||
parts.append(f"{days}d")
|
||||
if hours > 0:
|
||||
parts.append(f"{hours}h")
|
||||
if minutes > 0:
|
||||
parts.append(f"{minutes}m")
|
||||
if secs > 0 or not parts:
|
||||
parts.append(f"{secs}s")
|
||||
|
||||
return " ".join(parts)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user