78 lines
2.4 KiB
Go
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, datasetName, base string) error {
|
|
return c.SendIncrementalHTTP(snapshot, datasetName, base)
|
|
}
|