Feature: Snapshot-Tab in Datasets mit Kontextmenü (Clone/Rename/Rollback/Destroy)

- Snapshots direkt im Datasets-Tab ladbar (lazy, per Pool)
- Tabelle: Name, Created, Used, Referenced, Clones
- Kontextmenü (⋮) mit Clone, Rename, Roll Back, Destroy Snapshot
- Backend: /api/snapshots/clone + /api/snapshots/rename Endpoints

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-04 22:51:08 +02:00
parent 3938083f31
commit 8d27745984
3 changed files with 243 additions and 7 deletions
+46
View File
@@ -35,6 +35,14 @@ class CreateSnapshotRequest(BaseModel):
class RollbackSnapshotRequest(BaseModel):
snapshot: str
class CloneSnapshotRequest(BaseModel):
snapshot: str
target: str # full target dataset name
class RenameSnapshotRequest(BaseModel):
snapshot: str
new_name: str # new snapshot tag (after @)
@router.get("/", response_model=List[Snapshot])
async def list_snapshots(
@@ -96,6 +104,44 @@ async def delete_snapshot(
raise HTTPException(status_code=500, detail=str(e))
@router.post("/clone")
async def clone_snapshot(
request: CloneSnapshotRequest,
current_user: str = Depends(get_current_user)
):
"""Clone snapshot to a new dataset"""
try:
result = zfs_runner.run_command(["zfs", "clone", request.snapshot, request.target])
if result[2] != 0:
raise HTTPException(status_code=400, detail=result[1])
zfs_runner.clear_cache()
return {"status": "success", "message": f"Cloned to {request.target}"}
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/rename")
async def rename_snapshot(
request: RenameSnapshotRequest,
current_user: str = Depends(get_current_user)
):
"""Rename snapshot"""
try:
dataset = request.snapshot.split("@")[0]
new_full = f"{dataset}@{request.new_name}"
result = zfs_runner.run_command(["zfs", "rename", request.snapshot, new_full])
if result[2] != 0:
raise HTTPException(status_code=400, detail=result[1])
zfs_runner.clear_cache()
return {"status": "success", "message": f"Renamed to {new_full}"}
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/rollback")
async def rollback_snapshot(
request: RollbackSnapshotRequest,