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}) }