more details

This commit is contained in:
shoopea 2021-10-18 22:13:04 +08:00
parent 9347ba08cd
commit 26e4b56507

248
app.go
View File

@ -385,19 +385,9 @@ func (a AppConfig) needHourlySnapshot() bool {
return true return true
} }
func (a AppConfig) RunAppBackup() error { func (a AppConfig) CheckZFS() error {
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Start", a.Name) log.Printf("AppConfig.CheckZFS : %s : Start", a.Name)
}
schedule, err := a.getSchedule()
if err != nil {
if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Error getting schedule : %s", a.Name, err)
}
return err
}
if schedule == "" {
return nil
} }
for _, src := range a.Sources { for _, src := range a.Sources {
@ -409,87 +399,142 @@ func (a AppConfig) RunAppBackup() error {
err := cfg.Box[dest.Box()].ssh.createZFS(dest.Path() + "/" + src.Box() + "/" + src.Path()) err := cfg.Box[dest.Box()].ssh.createZFS(dest.Path() + "/" + src.Box() + "/" + src.Path())
if err != nil { if err != nil {
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Error creating %s on %s", a.Name, dest.Path()+"/"+src.Box()+"/"+src.Path(), dest.Box()) log.Printf("AppConfig.CheckZFS : %s : Error creating %s on %s", a.Name, dest.Path()+"/"+src.Box()+"/"+src.Path(), dest.Box())
} }
return err return err
} }
} }
} }
} }
return nil
}
func (a AppConfig) ExecBefore(schedule string) error {
if *debugFlag {
log.Printf("AppConfig.ExecBefore : %s : Start %s", a.Name, schedule)
}
for k, v := range a.Before { for k, v := range a.Before {
re := regexp.MustCompile(k) re := regexp.MustCompile(k)
if re.MatchString(schedule) { if re.MatchString(schedule) {
err := cfg.Box[v.Box()].ssh.exec(v.Path()) err := cfg.Box[v.Box()].ssh.exec(v.Path())
if err != nil { if err != nil {
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Error executing %s", a.Name, string(v)) log.Printf("AppConfig.ExecBefore : %s : Error executing %s", a.Name, string(v))
}
return err
}
}
}
return nil
}
func (a AppConfig) ExecAfter(schedule string) error {
if *debugFlag {
log.Printf("AppConfig.ExecAfter : %s : Start %s", a.Name, schedule)
}
for k, v := range a.After {
re := regexp.MustCompile(k)
if re.MatchString(schedule) {
err := cfg.Box[v.Box()].ssh.exec(v.Path())
if err != nil {
if *debugFlag {
log.Printf("AppConfig.ExecAfter : %s : Error executing %s on %s", a.Name, v.Path(), v.Box())
} }
return err return err
} }
} }
} }
refreshSnapshot := make(map[string]bool) return nil
}
func (a AppConfig) TakeSnapshot(schedule string) error {
if *debugFlag {
log.Printf("AppConfig.TakeSnapshot : %s : Start %s", a.Name, schedule)
}
takeSnapshot := make(map[string]string) takeSnapshot := make(map[string]string)
delSnapshot := make(map[string]string) delSnapshot := make(map[string]string)
for _, v := range a.Sources { for _, v := range a.Sources {
takeSnapshot[v.Box()] = takeSnapshot[v.Box()] + " " + v.Path() takeSnapshot[v.Box()] = takeSnapshot[v.Box()] + " " + v.Path()
refreshSnapshot[v.Box()] = true
for _, v2 := range a.Destinations { for _, v2 := range a.Destinations {
delSnapshot[v2.Box()] = delSnapshot[v2.Box()] + " " + v2.Path() + "/" + v.Box() + "/" + v.Path() delSnapshot[v2.Box()] = delSnapshot[v2.Box()] + " " + v2.Path() + "/" + v.Box() + "/" + v.Path()
} }
} }
for k, v := range takeSnapshot { for k, v := range takeSnapshot {
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : taking snapshot on %s for %s", a.Name, k, v) log.Printf("AppConfig.TakeSnapshot : %s : taking snapshot on %s for %s", a.Name, k, v)
} }
err := cfg.Box[k].ssh.exec("/usr/sbin/zfsnap snapshot -p " + schedule + "- -a " + cfg.Zfsnap[schedule] + v) err := cfg.Box[k].ssh.exec("/usr/sbin/zfsnap snapshot -p " + schedule + "- -a " + cfg.Zfsnap[schedule] + v)
if err != nil { if err != nil {
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Error executing zfsnap on %s", a.Name, k) log.Printf("AppConfig.TakeSnapshot : %s : Error executing zfsnap on %s", a.Name, k)
} }
return err return err
} }
} }
return nil
}
func (a AppConfig) RefreshSnapshot() error {
if *debugFlag {
log.Printf("AppConfig.RefreshSnapshot : %s : Start", a.Name)
}
refreshSnapshot := make(map[string]struct{})
for _, v := range a.Sources {
refreshSnapshot[v.Box()] = struct{}{}
}
for _, v := range a.Destinations { for _, v := range a.Destinations {
refreshSnapshot[v.Box()] = true refreshSnapshot[v.Box()] = struct{}{}
} }
for k, _ := range refreshSnapshot { for k, _ := range refreshSnapshot {
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : refreshing snapshots for source %s", a.Name, k) log.Printf("AppConfig.RefreshSnapshot : %s : refreshing snapshots for source %s", a.Name, k)
} }
err := cfg.Box[k].ssh.getSnapshotList() err := cfg.Box[k].ssh.getSnapshotList()
if err != nil { if err != nil {
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Error getting snapshots on %s", a.Name, k) log.Printf("AppConfig.RefreshSnapshot : %s : Error getting snapshots on %s", a.Name, k)
} }
return err return err
} }
} }
return nil
}
func (a AppConfig) SendSnapshots() error {
if *debugFlag {
log.Printf("AppConfig.SendSnapshots : %s : Start", a.Name)
}
for _, src := range a.Sources { for _, src := range a.Sources {
for _, dest := range a.Destinations { for _, dest := range a.Destinations {
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Sending snapshots from %s to %s", a.Name, string(src), string(dest)) log.Printf("AppConfig.SendSnapshots : %s : Sending snapshots from %s to %s", a.Name, string(src), string(dest))
} }
dLastSnapshot, err := cfg.Box[dest.Box()].ssh.getLastSnapshot(dest.Path() + "/" + src.Box() + "/" + src.Path()) dLastSnapshot, err := cfg.Box[dest.Box()].ssh.getLastSnapshot(dest.Path() + "/" + src.Box() + "/" + src.Path())
if err != nil { if err != nil {
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : No snapshot for %s on %s", a.Name, string(src), dest.Box()) log.Printf("AppConfig.SendSnapshots : %s : No snapshot for %s on %s", a.Name, string(src), dest.Box())
} }
sFirstSnapshot, err := cfg.Box[src.Box()].ssh.getFirstSnapshot(src.Path()) sFirstSnapshot, err := cfg.Box[src.Box()].ssh.getFirstSnapshot(src.Path())
if err != nil { if err != nil {
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : No snapshot for %s", a.Name, string(src)) log.Printf("AppConfig.SendSnapshots : %s : No snapshot for %s", a.Name, string(src))
} }
return err return err
} }
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Initializing snapshot on %s from %s", a.Name, dest.Box(), string(sFirstSnapshot)) log.Printf("AppConfig.SendSnapshots : %s : Initializing snapshot on %s from %s", a.Name, dest.Box(), string(sFirstSnapshot))
} }
err = cfg.Box[dest.Box()].ssh.exec("/usr/bin/ssh root@" + src.Box() + " /sbin/zfs send " + string(sFirstSnapshot) + " | /sbin/zfs recv -F " + dest.Path() + "/" + src.Box() + "/" + src.Path()) err = cfg.Box[dest.Box()].ssh.exec("/usr/bin/ssh " + cfg.Box[src.Box()].User + "@" + src.Box() + " /sbin/zfs send " + string(sFirstSnapshot) + " | /sbin/zfs recv -F " + dest.Path() + "/" + src.Box() + "/" + src.Path())
if err != nil { if err != nil {
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Initializing snapshot on %s from %s failed (%s)", a.Name, dest.Box(), string(sFirstSnapshot), err) log.Printf("AppConfig.SendSnapshots : %s : Initializing snapshot on %s from %s failed (%s)", a.Name, dest.Box(), string(sFirstSnapshot), err)
} }
return err return err
} }
@ -499,23 +544,23 @@ func (a AppConfig) RunAppBackup() error {
sCurrSnapshot = sNextSnapshot sCurrSnapshot = sNextSnapshot
sNextSnapshot, err = cfg.Box[src.Box()].ssh.getNextSnapshot(sNextSnapshot) sNextSnapshot, err = cfg.Box[src.Box()].ssh.getNextSnapshot(sNextSnapshot)
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Sending incrementally %s to %s", a.Name, string(sNextSnapshot), dest.Box()) log.Printf("AppConfig.SendSnapshots : %s : Sending incrementally %s to %s", a.Name, string(sNextSnapshot), dest.Box())
} }
err = cfg.Box[dest.Box()].ssh.exec("/usr/bin/ssh root@" + src.Box() + " /sbin/zfs send -I " + string(sCurrSnapshot) + " " + string(sNextSnapshot) + " | /sbin/zfs recv " + dest.Path() + "/" + src.Box() + "/" + src.Path()) err = cfg.Box[dest.Box()].ssh.exec("/usr/bin/ssh " + cfg.Box[src.Box()].User + "@" + src.Box() + " /sbin/zfs send -I " + string(sCurrSnapshot) + " " + string(sNextSnapshot) + " | /sbin/zfs recv " + dest.Path() + "/" + src.Box() + "/" + src.Path())
if err != nil { if err != nil {
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Sending snapshot on %s from %s failed (%s)", a.Name, dest.Box(), string(sNextSnapshot), err) log.Printf("AppConfig.SendSnapshots : %s : Sending snapshot on %s from %s failed (%s)", a.Name, dest.Box(), string(sNextSnapshot), err)
} }
return err return err
} }
} }
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : All snapshots sent for %s", a.Name, string(src)) log.Printf("AppConfig.SendSnapshots : %s : All snapshots sent for %s", a.Name, string(src))
} }
} else { } else {
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Last snapshot on %s is %s", a.Name, dest.Box(), string(dLastSnapshot)) log.Printf("AppConfig.SendSnapshots : %s : Last snapshot on %s is %s", a.Name, dest.Box(), string(dLastSnapshot))
} }
var sCurrSnapshot Snapshot var sCurrSnapshot Snapshot
sNextSnapshot := Snapshot(string(dLastSnapshot)[len(string(dest))+2:]) sNextSnapshot := Snapshot(string(dLastSnapshot)[len(string(dest))+2:])
@ -523,12 +568,12 @@ func (a AppConfig) RunAppBackup() error {
sCurrSnapshot = sNextSnapshot sCurrSnapshot = sNextSnapshot
sNextSnapshot, err = cfg.Box[src.Box()].ssh.getNextSnapshot(sNextSnapshot) sNextSnapshot, err = cfg.Box[src.Box()].ssh.getNextSnapshot(sNextSnapshot)
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Sending incrementally %s to %s", a.Name, string(sNextSnapshot), dest.Box()) log.Printf("AppConfig.SendSnapshots : %s : Sending incrementally %s to %s", a.Name, string(sNextSnapshot), dest.Box())
} }
err = cfg.Box[dest.Box()].ssh.exec("/usr/bin/ssh root@" + src.Box() + " /sbin/zfs send -I " + string(sCurrSnapshot) + " " + string(sNextSnapshot) + " | /sbin/zfs recv " + dest.Path() + "/" + src.Box() + "/" + src.Path()) err = cfg.Box[dest.Box()].ssh.exec("/usr/bin/ssh " + cfg.Box[src.Box()].User + "@" + src.Box() + " /sbin/zfs send -I " + string(sCurrSnapshot) + " " + string(sNextSnapshot) + " | /sbin/zfs recv " + dest.Path() + "/" + src.Box() + "/" + src.Path())
if err != nil { if err != nil {
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Sending snapshot on %s from %s failed (%s)", a.Name, dest.Box(), string(sNextSnapshot), err) log.Printf("AppConfig.SendSnapshots : %s : Sending snapshot on %s from %s failed (%s)", a.Name, dest.Box(), string(sNextSnapshot), err)
} }
return err return err
} }
@ -536,41 +581,102 @@ func (a AppConfig) RunAppBackup() error {
} }
} }
} }
for k, v := range takeSnapshot { return nil
if *debugFlag { }
log.Printf("AppConfig.RunAppBackup : %s : cleaning snapshot on %s for %s", a.Name, k, v)
} func (a AppConfig) CleanupSnapshot() error {
err := cfg.Box[k].ssh.exec("/usr/sbin/zfsnap destroy -p hourly- -p daily- -p weekly- -p monthly- -p yearly- " + v) if *debugFlag {
if err != nil { log.Printf("AppConfig.CleanupSnapshot : %s : Start]", a.Name)
if *debugFlag { }
log.Printf("AppConfig.RunAppBackup : %s : Error executing zfsnap on %s", a.Name, k)
} cleanupSnapshot := make(map[string]string)
return err
} for _, dest := range a.Destinations {
} for _, src := range a.Sources {
for k, v := range delSnapshot { cleanupSnapshot[src.Box()] = cleanupSnapshot[src.Box()] + " " + src.Path()
if *debugFlag { cleanupSnapshot[dest.Box()] = cleanupSnapshot[dest.Box()] + " " + dest.Path() + "/" + src.Box() + "/" + src.Path()
log.Printf("AppConfig.RunAppBackup : %s : cleaning snapshot on %s for %s", a.Name, k, v) }
} }
err := cfg.Box[k].ssh.exec("/usr/sbin/zfsnap destroy -p hourly- -p daily- -p weekly- -p monthly- -p yearly- " + v)
if err != nil { for k, v := range cleanupSnapshot {
if *debugFlag { if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Error executing zfsnap on %s", a.Name, k) log.Printf("AppConfig.CleanupSnapshot : %s : cleaning snapshots on %s for%s", a.Name, k, v)
} }
return err err := cfg.Box[k].ssh.exec("/usr/sbin/zfsnap destroy -p hourly- -p daily- -p weekly- -p monthly- -p yearly-" + v)
} if err != nil {
} if *debugFlag {
for k, v := range a.After { log.Printf("AppConfig.CleanupSnapshot : %s : Error executing zfsnap on %s", a.Name, k)
re := regexp.MustCompile(k) }
if re.MatchString(schedule) { return err
err := cfg.Box[v.Box()].ssh.exec(v.Path()) }
if err != nil { }
if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Error executing %s on %s", a.Name, v.Path(), v.Box()) return nil
} }
return err
} func (a AppConfig) RunAppBackup() error {
} if *debugFlag {
} log.Printf("AppConfig.RunAppBackup : %s : Start", a.Name)
}
schedule, err := a.getSchedule()
if err != nil {
if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : Error getting schedule : %s", a.Name, err)
}
return err
}
if schedule != "" {
err = a.CheckZFS()
if err != nil {
if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : CheckZFS : %s", a.Name, err)
}
return err
}
err = a.ExecBefore(schedule)
if err != nil {
if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : ExecBefore : %s", a.Name, err)
}
return err
}
}
err = a.RefreshSnapshot()
if err != nil {
if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : RefreshSnapshot : %s", a.Name, err)
}
return err
}
err = a.SendSnapshots()
if err != nil {
if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : SendSnapshots : %s", a.Name, err)
}
return err
}
if schedule != "" {
err = a.ExecAfter(schedule)
if err != nil {
if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : ExecAfter : %s", a.Name, err)
}
return err
}
}
err = a.CleanupSnapshot()
if err != nil {
if *debugFlag {
log.Printf("AppConfig.RunAppBackup : %s : RefreshSnapshot : %s", a.Name, err)
}
return err
}
return nil return nil
} }