scrub operation + ZFS Pool CRUD
Some checks failed
CI / test-build (push) Failing after 2m14s

This commit is contained in:
2025-12-15 01:19:44 +07:00
parent 9779b30a65
commit abd8cef10a
9 changed files with 1124 additions and 63 deletions

View File

@@ -100,35 +100,112 @@ func (a *App) handleGetPool(w http.ResponseWriter, r *http.Request) {
func (a *App) handleDeletePool(w http.ResponseWriter, r *http.Request) {
name := pathParam(r, "/api/v1/pools/")
if name == "" {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "pool name required"})
writeError(w, errors.ErrBadRequest("pool name required"))
return
}
if err := a.zfs.DestroyPool(name); err != nil {
log.Printf("destroy pool error: %v", err)
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
writeError(w, errors.ErrInternal("failed to destroy pool").WithDetails(err.Error()))
return
}
writeJSON(w, http.StatusOK, map[string]string{"message": "pool destroyed", "name": name})
}
func (a *App) handleImportPool(w http.ResponseWriter, r *http.Request) {
var req struct {
Name string `json:"name"`
Options map[string]string `json:"options,omitempty"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, errors.ErrBadRequest("invalid request body").WithDetails(err.Error()))
return
}
if req.Name == "" {
writeError(w, errors.ErrBadRequest("pool name required"))
return
}
if err := a.zfs.ImportPool(req.Name, req.Options); err != nil {
log.Printf("import pool error: %v", err)
writeError(w, errors.ErrInternal("failed to import pool").WithDetails(err.Error()))
return
}
writeJSON(w, http.StatusOK, map[string]string{"message": "pool imported", "name": req.Name})
}
func (a *App) handleExportPool(w http.ResponseWriter, r *http.Request) {
name := pathParam(r, "/api/v1/pools/")
if name == "" {
writeError(w, errors.ErrBadRequest("pool name required"))
return
}
var req struct {
Force bool `json:"force,omitempty"`
}
// Force is optional, decode if body exists
_ = json.NewDecoder(r.Body).Decode(&req)
if err := a.zfs.ExportPool(name, req.Force); err != nil {
log.Printf("export pool error: %v", err)
writeError(w, errors.ErrInternal("failed to export pool").WithDetails(err.Error()))
return
}
writeJSON(w, http.StatusOK, map[string]string{"message": "pool exported", "name": name})
}
func (a *App) handleListAvailablePools(w http.ResponseWriter, r *http.Request) {
pools, err := a.zfs.ListAvailablePools()
if err != nil {
log.Printf("list available pools error: %v", err)
writeError(w, errors.ErrInternal("failed to list available pools").WithDetails(err.Error()))
return
}
writeJSON(w, http.StatusOK, map[string]interface{}{
"pools": pools,
})
}
func (a *App) handleScrubPool(w http.ResponseWriter, r *http.Request) {
name := pathParam(r, "/api/v1/pools/")
if name == "" {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "pool name required"})
writeError(w, errors.ErrBadRequest("pool name required"))
return
}
if err := a.zfs.ScrubPool(name); err != nil {
log.Printf("scrub pool error: %v", err)
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
writeError(w, errors.ErrInternal("failed to start scrub").WithDetails(err.Error()))
return
}
writeJSON(w, http.StatusOK, map[string]string{"message": "scrub started", "pool": name})
}
func (a *App) handleGetScrubStatus(w http.ResponseWriter, r *http.Request) {
name := pathParam(r, "/api/v1/pools/")
if name == "" {
writeError(w, errors.ErrBadRequest("pool name required"))
return
}
status, err := a.zfs.GetScrubStatus(name)
if err != nil {
log.Printf("get scrub status error: %v", err)
writeError(w, errors.ErrInternal("failed to get scrub status").WithDetails(err.Error()))
return
}
writeJSON(w, http.StatusOK, status)
}
// Dataset Handlers
func (a *App) handleListDatasets(w http.ResponseWriter, r *http.Request) {
pool := r.URL.Query().Get("pool")