Files
calypso/backend/internal/system/handler.go
2025-12-26 17:47:20 +00:00

134 lines
3.8 KiB
Go

package system
import (
"net/http"
"strconv"
"github.com/atlasos/calypso/internal/common/logger"
"github.com/atlasos/calypso/internal/tasks"
"github.com/gin-gonic/gin"
)
// Handler handles system management API requests
type Handler struct {
service *Service
taskEngine *tasks.Engine
logger *logger.Logger
}
// NewHandler creates a new system handler
func NewHandler(log *logger.Logger, taskEngine *tasks.Engine) *Handler {
return &Handler{
service: NewService(log),
taskEngine: taskEngine,
logger: log,
}
}
// ListServices lists all system services
func (h *Handler) ListServices(c *gin.Context) {
services, err := h.service.ListServices(c.Request.Context())
if err != nil {
h.logger.Error("Failed to list services", "error", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list services"})
return
}
c.JSON(http.StatusOK, gin.H{"services": services})
}
// GetServiceStatus retrieves status of a specific service
func (h *Handler) GetServiceStatus(c *gin.Context) {
serviceName := c.Param("name")
status, err := h.service.GetServiceStatus(c.Request.Context(), serviceName)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "service not found"})
return
}
c.JSON(http.StatusOK, status)
}
// RestartService restarts a system service
func (h *Handler) RestartService(c *gin.Context) {
serviceName := c.Param("name")
if err := h.service.RestartService(c.Request.Context(), serviceName); err != nil {
h.logger.Error("Failed to restart service", "error", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "service restarted successfully"})
}
// GetServiceLogs retrieves journald logs for a service
func (h *Handler) GetServiceLogs(c *gin.Context) {
serviceName := c.Param("name")
linesStr := c.DefaultQuery("lines", "100")
lines, err := strconv.Atoi(linesStr)
if err != nil {
lines = 100
}
logs, err := h.service.GetJournalLogs(c.Request.Context(), serviceName, lines)
if err != nil {
h.logger.Error("Failed to get logs", "error", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get logs"})
return
}
c.JSON(http.StatusOK, gin.H{"logs": logs})
}
// GenerateSupportBundle generates a diagnostic support bundle
func (h *Handler) GenerateSupportBundle(c *gin.Context) {
userID, _ := c.Get("user_id")
// Create async task
taskID, err := h.taskEngine.CreateTask(c.Request.Context(),
tasks.TaskTypeSupportBundle, userID.(string), map[string]interface{}{
"operation": "generate_support_bundle",
})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create task"})
return
}
// Run bundle generation in background
go func() {
ctx := c.Request.Context()
h.taskEngine.StartTask(ctx, taskID)
h.taskEngine.UpdateProgress(ctx, taskID, 50, "Collecting system information...")
outputPath := "/tmp/calypso-support-bundle-" + taskID
if err := h.service.GenerateSupportBundle(ctx, outputPath); err != nil {
h.taskEngine.FailTask(ctx, taskID, err.Error())
return
}
h.taskEngine.UpdateProgress(ctx, taskID, 100, "Support bundle generated")
h.taskEngine.CompleteTask(ctx, taskID, "Support bundle generated successfully")
}()
c.JSON(http.StatusAccepted, gin.H{"task_id": taskID})
}
// ListNetworkInterfaces lists all network interfaces
func (h *Handler) ListNetworkInterfaces(c *gin.Context) {
interfaces, err := h.service.ListNetworkInterfaces(c.Request.Context())
if err != nil {
h.logger.Error("Failed to list network interfaces", "error", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list network interfaces"})
return
}
// Ensure we return an empty array instead of null
if interfaces == nil {
interfaces = []NetworkInterface{}
}
c.JSON(http.StatusOK, gin.H{"interfaces": interfaces})
}