179 lines
4.7 KiB
Go
179 lines
4.7 KiB
Go
// Command zfs-restore is a CLI tool for restoring ZFS snapshots from a backup server.
|
|
// It provides commands for listing, restoring, and mounting snapshots.
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"sort"
|
|
|
|
"git.ma-al.com/goc_marek/zfs/internal/restore"
|
|
)
|
|
|
|
func main() {
|
|
if len(os.Args) < 2 {
|
|
printUsage()
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Load configuration from environment and .env file
|
|
cfg := restore.LoadConfig()
|
|
client := restore.New(cfg.ClientID, cfg.APIKey, cfg.ServerURL)
|
|
|
|
command := os.Args[1]
|
|
|
|
switch command {
|
|
case "list":
|
|
snapshots, err := client.ListSnapshots()
|
|
if err != nil {
|
|
fmt.Printf("Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
client.DisplaySnapshots(snapshots)
|
|
|
|
case "restore":
|
|
if len(os.Args) < 4 {
|
|
fmt.Println("Usage: zfs-restore restore <snapshot-number> <target-dataset> [--force]")
|
|
os.Exit(1)
|
|
}
|
|
|
|
snapshots, err := client.ListSnapshots()
|
|
if err != nil {
|
|
fmt.Printf("Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Sort by timestamp (newest first)
|
|
sort.Slice(snapshots, func(i, j int) bool {
|
|
return snapshots[i].Timestamp.After(snapshots[j].Timestamp)
|
|
})
|
|
|
|
// Parse snapshot number
|
|
var snapNum int
|
|
fmt.Sscanf(os.Args[2], "%d", &snapNum)
|
|
|
|
if snapNum < 1 || snapNum > len(snapshots) {
|
|
fmt.Printf("Invalid snapshot number. Use 'list' to see available snapshots.\n")
|
|
os.Exit(1)
|
|
}
|
|
|
|
snapshot := snapshots[snapNum-1]
|
|
targetDataset := os.Args[3]
|
|
force := len(os.Args) > 4 && os.Args[4] == "--force"
|
|
|
|
if err := client.RestoreSnapshot(snapshot, targetDataset, force); err != nil {
|
|
fmt.Printf("Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
case "save":
|
|
if len(os.Args) < 4 {
|
|
fmt.Println("Usage: zfs-restore save <snapshot-number> <output-file>")
|
|
os.Exit(1)
|
|
}
|
|
|
|
snapshots, err := client.ListSnapshots()
|
|
if err != nil {
|
|
fmt.Printf("Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
sort.Slice(snapshots, func(i, j int) bool {
|
|
return snapshots[i].Timestamp.After(snapshots[j].Timestamp)
|
|
})
|
|
|
|
var snapNum int
|
|
fmt.Sscanf(os.Args[2], "%d", &snapNum)
|
|
|
|
if snapNum < 1 || snapNum > len(snapshots) {
|
|
fmt.Printf("Invalid snapshot number.\n")
|
|
os.Exit(1)
|
|
}
|
|
|
|
snapshot := snapshots[snapNum-1]
|
|
outputFile := os.Args[3]
|
|
|
|
if err := client.RestoreToFile(snapshot, outputFile); err != nil {
|
|
fmt.Printf("Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
case "mount":
|
|
if len(os.Args) < 4 {
|
|
fmt.Println("Usage: zfs-restore mount <dataset> <mountpoint>")
|
|
os.Exit(1)
|
|
}
|
|
|
|
dataset := os.Args[2]
|
|
mountpoint := os.Args[3]
|
|
|
|
if err := client.MountSnapshot(dataset, mountpoint); err != nil {
|
|
fmt.Printf("Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
case "latest":
|
|
if len(os.Args) < 3 {
|
|
fmt.Println("Usage: zfs-restore latest <target-dataset> [--force]")
|
|
os.Exit(1)
|
|
}
|
|
|
|
snapshots, err := client.ListSnapshots()
|
|
if err != nil {
|
|
fmt.Printf("Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
if len(snapshots) == 0 {
|
|
fmt.Println("No snapshots available")
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Sort and get latest
|
|
sort.Slice(snapshots, func(i, j int) bool {
|
|
return snapshots[i].Timestamp.After(snapshots[j].Timestamp)
|
|
})
|
|
|
|
latest := snapshots[0]
|
|
targetDataset := os.Args[2]
|
|
force := len(os.Args) > 3 && os.Args[3] == "--force"
|
|
|
|
fmt.Printf("Restoring latest snapshot from %s\n", latest.Timestamp.Format("2006-01-02 15:04:05"))
|
|
|
|
if err := client.RestoreSnapshot(latest, targetDataset, force); err != nil {
|
|
fmt.Printf("Error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
case "help", "-h", "--help":
|
|
printUsage()
|
|
|
|
default:
|
|
fmt.Printf("Unknown command: %s\n", command)
|
|
printUsage()
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func printUsage() {
|
|
fmt.Println("ZFS Snapshot Restore Tool")
|
|
fmt.Println("\nUsage: zfs-restore [command] [options]")
|
|
fmt.Println("\nCommands:")
|
|
fmt.Println(" list - List available snapshots")
|
|
fmt.Println(" restore <#> <dataset> [--force] - Restore snapshot to ZFS dataset")
|
|
fmt.Println(" latest <dataset> [--force] - Restore most recent snapshot")
|
|
fmt.Println(" save <#> <file> - Save snapshot to file")
|
|
fmt.Println(" mount <dataset> <mountpoint> - Mount restored dataset")
|
|
fmt.Println(" help - Show this help message")
|
|
fmt.Println("\nExamples:")
|
|
fmt.Println(" zfs-restore list")
|
|
fmt.Println(" zfs-restore restore 1 tank/restored")
|
|
fmt.Println(" zfs-restore latest tank/restored --force")
|
|
fmt.Println(" zfs-restore save 2 backup.zfs.gz")
|
|
fmt.Println(" zfs-restore mount tank/restored /mnt/restore")
|
|
fmt.Println("\nEnvironment Variables (can be set in .env file):")
|
|
fmt.Println(" CLIENT_ID - Client identifier (default: client1)")
|
|
fmt.Println(" API_KEY - API key for authentication (default: secret123)")
|
|
fmt.Println(" SERVER_URL - Backup server URL (default: http://localhost:8080)")
|
|
}
|