package storage import ( "net/http" "github.com/atlasos/calypso/internal/common/database" "github.com/atlasos/calypso/internal/common/logger" "github.com/atlasos/calypso/internal/tasks" "github.com/gin-gonic/gin" ) // Handler handles storage-related API requests type Handler struct { diskService *DiskService lvmService *LVMService taskEngine *tasks.Engine db *database.DB logger *logger.Logger } // NewHandler creates a new storage handler func NewHandler(db *database.DB, log *logger.Logger) *Handler { return &Handler{ diskService: NewDiskService(db, log), lvmService: NewLVMService(db, log), taskEngine: tasks.NewEngine(db, log), db: db, logger: log, } } // ListDisks lists all physical disks func (h *Handler) ListDisks(c *gin.Context) { disks, err := h.diskService.DiscoverDisks(c.Request.Context()) if err != nil { h.logger.Error("Failed to list disks", "error", err) c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list disks"}) return } c.JSON(http.StatusOK, gin.H{"disks": disks}) } // SyncDisks syncs discovered disks to database func (h *Handler) SyncDisks(c *gin.Context) { userID, _ := c.Get("user_id") // Create async task taskID, err := h.taskEngine.CreateTask(c.Request.Context(), tasks.TaskTypeRescan, userID.(string), map[string]interface{}{ "operation": "sync_disks", }) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create task"}) return } // Run sync in background go func() { ctx := c.Request.Context() h.taskEngine.StartTask(ctx, taskID) h.taskEngine.UpdateProgress(ctx, taskID, 50, "Discovering disks...") if err := h.diskService.SyncDisksToDatabase(ctx); err != nil { h.taskEngine.FailTask(ctx, taskID, err.Error()) return } h.taskEngine.UpdateProgress(ctx, taskID, 100, "Disk sync completed") h.taskEngine.CompleteTask(ctx, taskID, "Disks synchronized successfully") }() c.JSON(http.StatusAccepted, gin.H{"task_id": taskID}) } // ListVolumeGroups lists all volume groups func (h *Handler) ListVolumeGroups(c *gin.Context) { vgs, err := h.lvmService.ListVolumeGroups(c.Request.Context()) if err != nil { h.logger.Error("Failed to list volume groups", "error", err) c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list volume groups"}) return } c.JSON(http.StatusOK, gin.H{"volume_groups": vgs}) } // ListRepositories lists all repositories func (h *Handler) ListRepositories(c *gin.Context) { repos, err := h.lvmService.ListRepositories(c.Request.Context()) if err != nil { h.logger.Error("Failed to list repositories", "error", err) c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list repositories"}) return } c.JSON(http.StatusOK, gin.H{"repositories": repos}) } // GetRepository retrieves a repository by ID func (h *Handler) GetRepository(c *gin.Context) { repoID := c.Param("id") repo, err := h.lvmService.GetRepository(c.Request.Context(), repoID) if err != nil { if err.Error() == "repository not found" { c.JSON(http.StatusNotFound, gin.H{"error": "repository not found"}) return } h.logger.Error("Failed to get repository", "error", err) c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get repository"}) return } c.JSON(http.StatusOK, repo) } // CreateRepositoryRequest represents a repository creation request type CreateRepositoryRequest struct { Name string `json:"name" binding:"required"` Description string `json:"description"` VolumeGroup string `json:"volume_group" binding:"required"` SizeGB int64 `json:"size_gb" binding:"required"` } // CreateRepository creates a new repository func (h *Handler) CreateRepository(c *gin.Context) { var req CreateRepositoryRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"}) return } userID, _ := c.Get("user_id") sizeBytes := req.SizeGB * 1024 * 1024 * 1024 repo, err := h.lvmService.CreateRepository( c.Request.Context(), req.Name, req.VolumeGroup, sizeBytes, userID.(string), ) if err != nil { h.logger.Error("Failed to create repository", "error", err) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, repo) } // DeleteRepository deletes a repository func (h *Handler) DeleteRepository(c *gin.Context) { repoID := c.Param("id") if err := h.lvmService.DeleteRepository(c.Request.Context(), repoID); err != nil { if err.Error() == "repository not found" { c.JSON(http.StatusNotFound, gin.H{"error": "repository not found"}) return } h.logger.Error("Failed to delete repository", "error", err) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "repository deleted successfully"}) }