# Dataset Mountpoint Validation ## Issue User meminta validasi bahwa mount point untuk dataset dan volume harus berada di dalam directory pool yang terkait. ## Solution Menambahkan validasi untuk memastikan mount point dataset berada di dalam pool mount point directory (`/opt/calypso/data/pool//`). ## Changes Made ### Updated `backend/internal/storage/zfs.go` **File**: `backend/internal/storage/zfs.go` (line 728-814) **Key Changes:** 1. **Mount Point Validation** - Validasi bahwa mount point yang user berikan harus berada di dalam pool directory - Menggunakan `filepath.Rel()` untuk memastikan mount point tidak keluar dari pool directory 2. **Default Mount Point** - Jika mount point tidak disediakan, set default ke `/opt/calypso/data/pool///` - Memastikan semua dataset mount point berada di dalam pool directory 3. **Mount Point Always Set** - Untuk filesystem datasets, mount point selalu di-set (baik user-provided atau default) - Tidak lagi conditional pada `req.MountPoint != ""` **Before:** ```go if req.Type == "filesystem" && req.MountPoint != "" { mountPath := filepath.Clean(req.MountPoint) // ... create directory ... } // Later: if req.Type == "filesystem" && req.MountPoint != "" { args = append(args, "-o", fmt.Sprintf("mountpoint=%s", req.MountPoint)) } ``` **After:** ```go poolMountPoint := fmt.Sprintf("/opt/calypso/data/pool/%s", poolName) var mountPath string if req.Type == "filesystem" { if req.MountPoint != "" { // Validate mount point is within pool directory mountPath = filepath.Clean(req.MountPoint) // ... validation logic ... } else { // Use default mount point mountPath = filepath.Join(poolMountPoint, req.Name) } // ... create directory ... } // Later: if req.Type == "filesystem" { args = append(args, "-o", fmt.Sprintf("mountpoint=%s", mountPath)) } ``` ## Mount Point Structure ### Pool Mount Point ``` /opt/calypso/data/pool// ``` ### Dataset Mount Point (Default) ``` /opt/calypso/data/pool/// ``` ### Dataset Mount Point (Custom - must be within pool) ``` /opt/calypso/data/pool/// ``` ## Validation Rules 1. **User-provided mount point**: - Must be within `/opt/calypso/data/pool//` - Cannot use `..` to escape pool directory - Must be a valid directory path 2. **Default mount point**: - Automatically set to `/opt/calypso/data/pool///` - Always within pool directory 3. **Volumes**: - Volumes cannot have mount points (already validated in handler) ## Error Messages - `mount point must be within pool directory: (pool mount: )` - Jika mount point di luar pool directory - `mount point path exists but is not a directory: ` - Jika path sudah ada tapi bukan directory - `failed to create mount directory ` - Jika gagal membuat directory ## Testing 1. **Create dataset without mount point**: - Should use default: `/opt/calypso/data/pool///` 2. **Create dataset with valid mount point**: - Mount point: `/opt/calypso/data/pool//custom-path/` - Should succeed 3. **Create dataset with invalid mount point**: - Mount point: `/opt/calypso/data/other-path/` - Should fail with validation error 4. **Create volume**: - Should not set mount point (volumes don't have mount points) ## Status ✅ **COMPLETED** - Mount point validation untuk dataset sudah diterapkan ## Date 2026-01-09