adding snapshot function
Some checks failed
CI / test-build (push) Failing after 1m0s

This commit is contained in:
2025-12-14 23:17:26 +07:00
parent 461edbc970
commit ed96137bad
8 changed files with 1075 additions and 20 deletions

View File

@@ -2,6 +2,7 @@ package httpapp
import (
"encoding/json"
"fmt"
"log"
"net/http"
@@ -287,47 +288,167 @@ func (a *App) handleDeleteZVOL(w http.ResponseWriter, r *http.Request) {
// Snapshot Handlers
func (a *App) handleListSnapshots(w http.ResponseWriter, r *http.Request) {
snapshots := []models.Snapshot{} // Stub
dataset := r.URL.Query().Get("dataset")
snapshots, err := a.zfs.ListSnapshots(dataset)
if err != nil {
log.Printf("list snapshots error: %v", err)
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
}
writeJSON(w, http.StatusOK, snapshots)
}
func (a *App) handleCreateSnapshot(w http.ResponseWriter, r *http.Request) {
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented"})
var req struct {
Dataset string `json:"dataset"`
Name string `json:"name"`
Recursive bool `json:"recursive,omitempty"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid request body"})
return
}
if req.Dataset == "" || req.Name == "" {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "dataset and name are required"})
return
}
if err := a.zfs.CreateSnapshot(req.Dataset, req.Name, req.Recursive); err != nil {
log.Printf("create snapshot error: %v", err)
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
}
snapshotName := fmt.Sprintf("%s@%s", req.Dataset, req.Name)
snap, err := a.zfs.GetSnapshot(snapshotName)
if err != nil {
writeJSON(w, http.StatusCreated, map[string]string{"message": "snapshot created", "name": snapshotName})
return
}
writeJSON(w, http.StatusCreated, snap)
}
func (a *App) handleGetSnapshot(w http.ResponseWriter, r *http.Request) {
name := pathParam(r, "/api/v1/snapshots/")
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "name": name})
if name == "" {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "snapshot name required"})
return
}
snap, err := a.zfs.GetSnapshot(name)
if err != nil {
writeJSON(w, http.StatusNotFound, map[string]string{"error": err.Error()})
return
}
writeJSON(w, http.StatusOK, snap)
}
func (a *App) handleDeleteSnapshot(w http.ResponseWriter, r *http.Request) {
name := pathParam(r, "/api/v1/snapshots/")
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "name": name})
if name == "" {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "snapshot name required"})
return
}
recursive := r.URL.Query().Get("recursive") == "true"
if err := a.zfs.DestroySnapshot(name, recursive); err != nil {
log.Printf("destroy snapshot error: %v", err)
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
}
writeJSON(w, http.StatusOK, map[string]string{"message": "snapshot destroyed", "name": name})
}
// Snapshot Policy Handlers
func (a *App) handleListSnapshotPolicies(w http.ResponseWriter, r *http.Request) {
policies := []models.SnapshotPolicy{} // Stub
dataset := r.URL.Query().Get("dataset")
var policies []models.SnapshotPolicy
if dataset != "" {
policies = a.snapshotPolicy.ListForDataset(dataset)
} else {
policies = a.snapshotPolicy.List()
}
writeJSON(w, http.StatusOK, policies)
}
func (a *App) handleCreateSnapshotPolicy(w http.ResponseWriter, r *http.Request) {
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented"})
var policy models.SnapshotPolicy
if err := json.NewDecoder(r.Body).Decode(&policy); err != nil {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid request body"})
return
}
if policy.Dataset == "" {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "dataset is required"})
return
}
a.snapshotPolicy.Set(&policy)
writeJSON(w, http.StatusCreated, policy)
}
func (a *App) handleGetSnapshotPolicy(w http.ResponseWriter, r *http.Request) {
dataset := pathParam(r, "/api/v1/snapshot-policies/")
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "dataset": dataset})
if dataset == "" {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "dataset name required"})
return
}
policy, err := a.snapshotPolicy.Get(dataset)
if err != nil {
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
}
if policy == nil {
writeJSON(w, http.StatusNotFound, map[string]string{"error": "policy not found"})
return
}
writeJSON(w, http.StatusOK, policy)
}
func (a *App) handleUpdateSnapshotPolicy(w http.ResponseWriter, r *http.Request) {
dataset := pathParam(r, "/api/v1/snapshot-policies/")
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "dataset": dataset})
if dataset == "" {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "dataset name required"})
return
}
var policy models.SnapshotPolicy
if err := json.NewDecoder(r.Body).Decode(&policy); err != nil {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid request body"})
return
}
// Ensure dataset matches URL parameter
policy.Dataset = dataset
a.snapshotPolicy.Set(&policy)
writeJSON(w, http.StatusOK, policy)
}
func (a *App) handleDeleteSnapshotPolicy(w http.ResponseWriter, r *http.Request) {
dataset := pathParam(r, "/api/v1/snapshot-policies/")
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "dataset": dataset})
if dataset == "" {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "dataset name required"})
return
}
if err := a.snapshotPolicy.Delete(dataset); err != nil {
log.Printf("delete snapshot policy error: %v", err)
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
return
}
writeJSON(w, http.StatusOK, map[string]string{"message": "policy deleted", "dataset": dataset})
}
// SMB Share Handlers
@@ -417,18 +538,41 @@ func (a *App) handleRemoveLUN(w http.ResponseWriter, r *http.Request) {
// Job Handlers
func (a *App) handleListJobs(w http.ResponseWriter, r *http.Request) {
jobs := []models.Job{} // Stub
status := models.JobStatus(r.URL.Query().Get("status"))
jobs := a.jobManager.List(status)
writeJSON(w, http.StatusOK, jobs)
}
func (a *App) handleGetJob(w http.ResponseWriter, r *http.Request) {
id := pathParam(r, "/api/v1/jobs/")
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "id": id})
if id == "" {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "job id required"})
return
}
job, err := a.jobManager.Get(id)
if err != nil {
writeJSON(w, http.StatusNotFound, map[string]string{"error": err.Error()})
return
}
writeJSON(w, http.StatusOK, job)
}
func (a *App) handleCancelJob(w http.ResponseWriter, r *http.Request) {
id := pathParam(r, "/api/v1/jobs/")
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "id": id})
if id == "" {
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "job id required"})
return
}
if err := a.jobManager.Cancel(id); err != nil {
log.Printf("cancel job error: %v", err)
writeJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()})
return
}
writeJSON(w, http.StatusOK, map[string]string{"message": "job cancelled", "id": id})
}
// Auth Handlers (stubs)