BAMS initial project structure
This commit is contained in:
422
backend/internal/api/handlers.go
Normal file
422
backend/internal/api/handlers.go
Normal file
@@ -0,0 +1,422 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/bams/backend/internal/services"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func handleHealth() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
jsonResponse(w, http.StatusOK, map[string]interface{}{
|
||||
"status": "ok",
|
||||
"timestamp": time.Now().Unix(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func handleDashboard(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// Get dashboard data from all services
|
||||
dashboard := map[string]interface{}{
|
||||
"disk": map[string]interface{}{
|
||||
"total_capacity": 0,
|
||||
"used_capacity": 0,
|
||||
"repositories": 0,
|
||||
},
|
||||
"tape": map[string]interface{}{
|
||||
"library_status": "unknown",
|
||||
"drives_active": 0,
|
||||
"total_slots": 0,
|
||||
"loaded_tapes": 0,
|
||||
},
|
||||
"iscsi": map[string]interface{}{
|
||||
"targets": 0,
|
||||
"sessions": 0,
|
||||
},
|
||||
"bacula": map[string]interface{}{
|
||||
"status": "unknown",
|
||||
},
|
||||
"alerts": []map[string]interface{}{},
|
||||
}
|
||||
|
||||
// Populate from services
|
||||
repos, _ := sm.Disk.ListRepositories()
|
||||
if repos != nil {
|
||||
dashboard["disk"].(map[string]interface{})["repositories"] = len(repos)
|
||||
}
|
||||
|
||||
library, _ := sm.Tape.GetLibrary()
|
||||
if library != nil {
|
||||
dashboard["tape"].(map[string]interface{})["library_status"] = library.Status
|
||||
dashboard["tape"].(map[string]interface{})["drives_active"] = library.ActiveDrives
|
||||
dashboard["tape"].(map[string]interface{})["total_slots"] = library.TotalSlots
|
||||
}
|
||||
|
||||
targets, _ := sm.ISCSI.ListTargets()
|
||||
if targets != nil {
|
||||
dashboard["iscsi"].(map[string]interface{})["targets"] = len(targets)
|
||||
}
|
||||
|
||||
sessions, _ := sm.ISCSI.ListSessions()
|
||||
if sessions != nil {
|
||||
dashboard["iscsi"].(map[string]interface{})["sessions"] = len(sessions)
|
||||
}
|
||||
|
||||
baculaStatus, _ := sm.Bacula.GetStatus()
|
||||
if baculaStatus != nil {
|
||||
dashboard["bacula"].(map[string]interface{})["status"] = baculaStatus.Status
|
||||
}
|
||||
|
||||
jsonResponse(w, http.StatusOK, dashboard)
|
||||
}
|
||||
}
|
||||
|
||||
// Disk repository handlers
|
||||
func handleListRepositories(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
repos, err := sm.Disk.ListRepositories()
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, repos)
|
||||
}
|
||||
}
|
||||
|
||||
func handleCreateRepository(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
Name string `json:"name"`
|
||||
Size string `json:"size"`
|
||||
Type string `json:"type"` // "lvm" or "zfs"
|
||||
VGName string `json:"vg_name,omitempty"`
|
||||
PoolName string `json:"pool_name,omitempty"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
jsonError(w, http.StatusBadRequest, "Invalid request body")
|
||||
return
|
||||
}
|
||||
|
||||
repo, err := sm.Disk.CreateRepository(req.Name, req.Size, req.Type, req.VGName, req.PoolName)
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusCreated, repo)
|
||||
}
|
||||
}
|
||||
|
||||
func handleGetRepository(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
repo, err := sm.Disk.GetRepository(vars["id"])
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusNotFound, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, repo)
|
||||
}
|
||||
}
|
||||
|
||||
func handleDeleteRepository(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
if err := sm.Disk.DeleteRepository(vars["id"]); err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusNoContent, nil)
|
||||
}
|
||||
}
|
||||
|
||||
// Tape library handlers
|
||||
func handleGetLibrary(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
library, err := sm.Tape.GetLibrary()
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, library)
|
||||
}
|
||||
}
|
||||
|
||||
func handleInventory(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if err := sm.Tape.RunInventory(); err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, map[string]string{"status": "inventory_started"})
|
||||
}
|
||||
}
|
||||
|
||||
func handleListDrives(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
drives, err := sm.Tape.ListDrives()
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, drives)
|
||||
}
|
||||
}
|
||||
|
||||
func handleLoadTape(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
var req struct {
|
||||
Slot int `json:"slot"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
jsonError(w, http.StatusBadRequest, "Invalid request body")
|
||||
return
|
||||
}
|
||||
|
||||
if err := sm.Tape.LoadTape(vars["id"], req.Slot); err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, map[string]string{"status": "load_started"})
|
||||
}
|
||||
}
|
||||
|
||||
func handleUnloadTape(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
var req struct {
|
||||
Slot int `json:"slot"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
jsonError(w, http.StatusBadRequest, "Invalid request body")
|
||||
return
|
||||
}
|
||||
|
||||
if err := sm.Tape.UnloadTape(vars["id"], req.Slot); err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, map[string]string{"status": "unload_started"})
|
||||
}
|
||||
}
|
||||
|
||||
func handleListSlots(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
slots, err := sm.Tape.ListSlots()
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, slots)
|
||||
}
|
||||
}
|
||||
|
||||
// iSCSI target handlers
|
||||
func handleListTargets(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
targets, err := sm.ISCSI.ListTargets()
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, targets)
|
||||
}
|
||||
}
|
||||
|
||||
func handleCreateTarget(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
IQN string `json:"iqn"`
|
||||
Portals []string `json:"portals"`
|
||||
Initiators []string `json:"initiators"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
jsonError(w, http.StatusBadRequest, "Invalid request body")
|
||||
return
|
||||
}
|
||||
|
||||
target, err := sm.ISCSI.CreateTarget(req.IQN, req.Portals, req.Initiators)
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusCreated, target)
|
||||
}
|
||||
}
|
||||
|
||||
func handleGetTarget(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
target, err := sm.ISCSI.GetTarget(vars["id"])
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusNotFound, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, target)
|
||||
}
|
||||
}
|
||||
|
||||
func handleUpdateTarget(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
var req struct {
|
||||
Portals []string `json:"portals"`
|
||||
Initiators []string `json:"initiators"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
jsonError(w, http.StatusBadRequest, "Invalid request body")
|
||||
return
|
||||
}
|
||||
|
||||
target, err := sm.ISCSI.UpdateTarget(vars["id"], req.Portals, req.Initiators)
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, target)
|
||||
}
|
||||
}
|
||||
|
||||
func handleDeleteTarget(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
if err := sm.ISCSI.DeleteTarget(vars["id"]); err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusNoContent, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func handleApplyTarget(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
if err := sm.ISCSI.ApplyTarget(vars["id"]); err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, map[string]string{"status": "applied"})
|
||||
}
|
||||
}
|
||||
|
||||
func handleListSessions(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
sessions, err := sm.ISCSI.ListSessions()
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, sessions)
|
||||
}
|
||||
}
|
||||
|
||||
// Bacula handlers
|
||||
func handleBaculaStatus(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
status, err := sm.Bacula.GetStatus()
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, status)
|
||||
}
|
||||
}
|
||||
|
||||
func handleGetBaculaConfig(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
config, err := sm.Bacula.GetConfig()
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, config)
|
||||
}
|
||||
}
|
||||
|
||||
func handleGenerateBaculaConfig(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
config, err := sm.Bacula.GenerateConfig()
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, config)
|
||||
}
|
||||
}
|
||||
|
||||
func handleBaculaInventory(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if err := sm.Bacula.RunInventory(); err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, map[string]string{"status": "inventory_started"})
|
||||
}
|
||||
}
|
||||
|
||||
func handleBaculaRestart(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if err := sm.Bacula.Restart(); err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, map[string]string{"status": "restart_started"})
|
||||
}
|
||||
}
|
||||
|
||||
// Logs and diagnostics handlers
|
||||
func handleGetLogs(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
lines := 100
|
||||
if linesStr := r.URL.Query().Get("lines"); linesStr != "" {
|
||||
if n, err := strconv.Atoi(linesStr); err == nil {
|
||||
lines = n
|
||||
}
|
||||
}
|
||||
logs, err := sm.Logs.GetLogs(vars["service"], lines)
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
jsonResponse(w, http.StatusOK, logs)
|
||||
}
|
||||
}
|
||||
|
||||
func handleStreamLogs(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// WebSocket streaming would be implemented here
|
||||
jsonError(w, http.StatusNotImplemented, "WebSocket streaming not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
func handleDownloadBundle(sm *services.ServiceManager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
bundle, err := sm.Logs.GenerateSupportBundle()
|
||||
if err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/zip")
|
||||
w.Header().Set("Content-Disposition", "attachment; filename=bams-support-bundle.zip")
|
||||
w.Write(bundle)
|
||||
}
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
func jsonResponse(w http.ResponseWriter, status int, data interface{}) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(status)
|
||||
if data != nil {
|
||||
json.NewEncoder(w).Encode(data)
|
||||
}
|
||||
}
|
||||
|
||||
func jsonError(w http.ResponseWriter, status int, message string) {
|
||||
jsonResponse(w, status, map[string]string{"error": message})
|
||||
}
|
||||
Reference in New Issue
Block a user