Files
zfs/internal/client/snapshot.go
2026-02-15 12:58:05 +01:00

78 lines
2.4 KiB
Go

// Package client provides ZFS snapshot backup client functionality.
// This file contains snapshot management functions for creating and sending snapshots.
package client
import (
"fmt"
"os/exec"
"strings"
"github.com/mistifyio/go-zfs"
)
// CreateBookmark creates a ZFS bookmark from a snapshot.
// Bookmarks allow incremental sends even after the source snapshot is deleted.
func (c *Client) CreateBookmark(snapshot *zfs.Dataset) error {
// Extract snapshot name from full path (dataset@snapshot -> snapshot)
parts := strings.Split(snapshot.Name, "@")
if len(parts) != 2 {
return fmt.Errorf("invalid snapshot name format: %s", snapshot.Name)
}
snapshotName := parts[1]
bookmarkName := fmt.Sprintf("%s#%s", c.config.LocalDataset, snapshotName)
// Create bookmark using zfs command
cmd := exec.Command("zfs", "bookmark", snapshot.Name, bookmarkName)
output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("failed to create bookmark: %v: %s", err, string(output))
}
fmt.Printf("✓ Created bookmark: %s\n", bookmarkName)
return nil
}
// GetLastBookmark returns the most recent bookmark for the dataset.
// Bookmarks are used as the base for incremental sends.
func (c *Client) GetLastBookmark() (string, error) {
// List all bookmarks for the dataset
cmd := exec.Command("zfs", "list", "-t", "bookmark", "-o", "name", "-H", "-r", c.config.LocalDataset)
output, err := cmd.Output()
if err != nil {
return "", nil // No bookmarks yet
}
bookmarks := strings.Split(strings.TrimSpace(string(output)), "\n")
if len(bookmarks) == 0 || bookmarks[0] == "" {
return "", nil
}
// Return the last bookmark (most recent)
return bookmarks[len(bookmarks)-1], nil
}
// GetLastSnapshot returns the most recent snapshot for the dataset.
func (c *Client) GetLastSnapshot() (*zfs.Dataset, error) {
ds, err := zfs.GetDataset(c.config.LocalDataset)
if err != nil {
return nil, fmt.Errorf("failed to get dataset: %v", err)
}
snapshots, err := ds.Snapshots()
if err != nil {
return nil, fmt.Errorf("failed to list snapshots: %v", err)
}
if len(snapshots) == 0 {
return nil, nil
}
// Return the last snapshot (most recent)
return snapshots[len(snapshots)-1], nil
}
// SendIncremental is kept for API compatibility - now just calls HTTP version
func (c *Client) SendIncremental(snapshot *zfs.Dataset, base string) error {
return c.SendIncrementalHTTP(snapshot, base)
}