incus-sentinel/main.go

212 lines
5.3 KiB
Go

package main
import (
"context"
"fmt"
"log"
"os"
"gitea.ceperka.net/rosti/incus-sentinel/http_notifier"
"gitea.ceperka.net/rosti/incus-sentinel/incus"
"gitea.ceperka.net/rosti/incus-sentinel/scheduler"
"github.com/urfave/cli/v3"
)
func main() {
cmd := &cli.Command{
Name: "incus-sentinel",
Usage: "Keeps an eye on sync and backups of Incus instances",
Commands: []*cli.Command{
{
Name: "list",
Usage: "List all instances with their sync and backup settings",
Flags: []cli.Flag{},
Action: func(c context.Context, cmd *cli.Command) error {
i := incus.NewIncusDriver()
insts, err := i.GetInstances("")
if err != nil {
return err
}
for _, inst := range insts {
s := inst.Sentinel()
if s.Backup || s.Sync {
fmt.Printf("%s\n", inst.Name)
fmt.Printf(" Backup: %t (%s)\n", s.Backup, s.BackupSchedule)
fmt.Printf(" Sync: %t (%s)\n", s.Sync, s.SyncSchedule)
if s.Sync {
fmt.Printf(" Sync Target: %s (pool: %s, suffix: %s)\n", s.SyncTargetRemote, s.SyncTargetPool, s.SyncTargetInstanceSuffix)
}
}
}
return nil
},
},
{
Name: "list-volumes",
Usage: "List all volumes with their sync and backup settings",
Flags: []cli.Flag{},
Action: func(c context.Context, cmd *cli.Command) error {
i := incus.NewIncusDriver()
vols, err := i.GetVolumes("")
if err != nil {
return err
}
for _, vol := range vols {
s := vol.Sentinel()
if s.Backup || s.Sync {
fmt.Printf("%s/%s/%s\n", vol.Project, vol.Pool, vol.Name)
fmt.Printf(" Backup: %t (%s, %s)\n", s.Backup, s.BackupMode, s.BackupSchedule)
fmt.Printf(" Sync: %t (%s)\n", s.Sync, s.SyncSchedule)
if s.Sync {
fmt.Printf(" Sync Target: %s (pool: %s, suffix: %s)\n", s.SyncTargetRemote, s.SyncTargetPool, s.SyncTargetVolumeSuffix)
}
}
}
return nil
},
},
{
Name: "sync",
Usage: "Syncs all instances where sync is enabled",
Flags: []cli.Flag{},
Action: func(c context.Context, cmd *cli.Command) error {
i := incus.NewIncusDriver()
insts, err := i.GetInstances("")
if err != nil {
return err
}
for _, inst := range insts {
s := inst.Sentinel()
if s.Sync {
fmt.Println(".. syncing", inst.Name)
err := i.Sync(inst.Project, inst.Name, fmt.Sprintf("%s%s", inst.Name, s.SyncTargetInstanceSuffix), s.SyncTargetRemote, s.SyncTargetPool)
if err != nil {
return err
}
}
}
return nil
},
},
{
Name: "sync-volumes",
Usage: "Syncs all volumes where sync is enabled",
Flags: []cli.Flag{},
Action: func(c context.Context, cmd *cli.Command) error {
i := incus.NewIncusDriver()
vols, err := i.GetVolumes("")
if err != nil {
return err
}
for _, vol := range vols {
s := vol.Sentinel()
if s.Sync {
fmt.Printf(".. syncing %s/%s/%s\n", vol.Project, vol.Pool, vol.Name)
targetPool := vol.Pool
if s.SyncTargetPool != "" {
targetPool = s.SyncTargetPool
}
err := i.SyncVolume(vol.Project, vol.Pool, vol.Name, s.SyncTargetRemote, targetPool, fmt.Sprintf("%s%s", vol.Name, s.SyncTargetVolumeSuffix))
if err != nil {
return err
}
}
}
return nil
},
},
{
Name: "backup",
Usage: "Backs up all instances where backup is enabled",
Flags: []cli.Flag{},
Action: func(c context.Context, cmd *cli.Command) error {
i := incus.NewIncusDriver()
insts, err := i.GetInstances("")
if err != nil {
return err
}
for _, inst := range insts {
s := inst.Sentinel()
if s.Backup {
fmt.Println(".. backing up", inst.Name)
err := i.Backup(inst.Project, inst.Name, []string{})
if err != nil {
return err
}
}
}
return nil
},
},
{
Name: "backup-volumes",
Usage: "Backs up all volumes where backup is enabled",
Flags: []cli.Flag{},
Action: func(c context.Context, cmd *cli.Command) error {
i := incus.NewIncusDriver()
vols, err := i.GetVolumes("")
if err != nil {
return err
}
for _, vol := range vols {
s := vol.Sentinel()
if s.Backup {
fmt.Printf(".. backing up %s/%s/%s\n", vol.Project, vol.Pool, vol.Name)
if s.BackupMode == "dir" {
err := i.BackupVolumeDir(vol.Project, vol.Pool, vol.Name, []string{})
if err != nil {
return err
}
} else if s.BackupMode == "native" {
err := i.BackupVolumeNative(vol.Project, vol.Pool, vol.Name, []string{})
if err != nil {
return err
}
} else {
return fmt.Errorf("invalid backup mode: %s", s.BackupMode)
}
}
}
return nil
},
},
{
Name: "run",
Usage: "Runs the sentinel that syncs and backs up instances based on their configuration",
Flags: []cli.Flag{},
Action: func(c context.Context, cmd *cli.Command) error {
i := incus.NewIncusDriver()
n := http_notifier.NewNotifier()
s := scheduler.NewScheduler(i, n)
err := s.Run()
if err != nil {
return err
}
return nil
},
},
},
}
if err := cmd.Run(context.Background(), os.Args); err != nil {
log.Fatal(err)
}
}