diff --git a/addr.go b/addr.go index cec14ae..37727ae 100644 --- a/addr.go +++ b/addr.go @@ -2,6 +2,7 @@ package main import ( "errors" + "fmt" "regexp" "strings" @@ -50,7 +51,7 @@ func (a Addr) BoxExec(cmd string) (string, error) { if b, ok := cfg.box[a.Box()]; !ok { err := errors.New("box doesn't exist") - log.WithFields(log.Fields{"addr": a, "box": a.Box()}).Errorf("") + log.WithFields(log.Fields{"addr": a, "box": a.Box(), "error": err}).Errorf("") return "", err } else { return b.Exec(cmd) @@ -70,26 +71,78 @@ func (a Addr) ValidSnapshots() ([]*ZfsSnapshot, error) { if b, ok := cfg.box[a.Box()]; !ok { err := errors.New("box doesn't exist") - log.WithFields(log.Fields{"addr": a, "box": a.Box()}).Errorf("") + log.WithFields(log.Fields{"addr": a, "box": a.Box(), "error": err}).Errorf("") return nil, err } else { if fs, ok := b.zfs.filesystems[a.Path()]; ok { return fs.ValidSnapshots(), nil } else { err := errors.New("path doesn't exist") - log.WithFields(log.Fields{"addr": a}).Errorf("") + log.WithFields(log.Fields{"addr": a, "error": err}).Errorf("") return nil, err } } } +func (a Addr) SetManaged(val bool) error { + log.WithFields(log.Fields{"addr": a}).Debugf("starting") + defer log.WithFields(log.Fields{"addr": a}).Debugf("done") + + if b, ok := cfg.box[a.Box()]; !ok { + err := errors.New("box doesn't exist") + log.WithFields(log.Fields{"addr": a, "box": a.Box(), "error": err}).Errorf("") + return err + } else if fs, ok := b.zfs.filesystems[a.Path()]; !ok { + err := errors.New("path doesn't exist") + log.WithFields(log.Fields{"addr": a, "path": a.Path(), "error": err}).Errorf("") + return err + } else { + fs.mx.Lock() + defer fs.mx.Unlock() + if fs.managed != val { + var cmd string + if val { + cmd = fmt.Sprintf("zfs set %s=+ %s", zfsManagedPropertyName, a.Path()) + } else { + cmd = fmt.Sprintf("zfs set %s=- %s", zfsManagedPropertyName, a.Path()) + } + if _, err := b.Exec(cmd); err != nil { + log.WithFields(log.Fields{"addr": a, "call": "Exec", "attr": cmd, "error": err}).Errorf("") + return err + } + } + fs.managed = val + return nil + } +} + +func (a Addr) SetBackedUp(val bool) error { + log.WithFields(log.Fields{"addr": a}).Debugf("starting") + defer log.WithFields(log.Fields{"addr": a}).Debugf("done") + + if b, ok := cfg.box[a.Box()]; !ok { + err := errors.New("box doesn't exist") + log.WithFields(log.Fields{"addr": a, "box": a.Box(), "error": err}).Errorf("") + return err + } else if fs, ok := b.zfs.filesystems[a.Path()]; !ok { + err := errors.New("path doesn't exist") + log.WithFields(log.Fields{"addr": a, "path": a.Path(), "error": err}).Errorf("") + return err + } else { + fs.mx.Lock() + defer fs.mx.Unlock() + fs.backedUp = val + return nil + } +} + func (a Addr) Mkdir() error { log.WithFields(log.Fields{"addr": a}).Debugf("starting") defer log.WithFields(log.Fields{"addr": a}).Debugf("done") if b, ok := cfg.box[a.Box()]; !ok { err := errors.New("box doesn't exist") - log.WithFields(log.Fields{"addr": a, "box": a.Box()}).Errorf("") + log.WithFields(log.Fields{"addr": a, "box": a.Box(), "error": err}).Errorf("") return err } else { return b.zfs.Mkdir(a.Path()) diff --git a/app.go b/app.go index d47e467..5e3d67d 100644 --- a/app.go +++ b/app.go @@ -302,6 +302,13 @@ func (a *App) Run(now time.Time) error { } } + for _, src := range a.sources { + if err := src.SetManaged(true); err != nil { + log.WithFields(log.Fields{"app": a.name, "call": "src.SetManaged", "error": err}).Errorf("") + return err + } + } + if err := a.Transfer(); err != nil { log.WithFields(log.Fields{"app": a.name, "call": "Transfer", "error": err}).Errorf("") return err @@ -481,8 +488,17 @@ func (a *App) Transfer() error { log.WithFields(log.Fields{"app": a.name, "call": "TransferZfs", "src": src, "dest": dest, "error": err}).Errorf("") return err } + if err := dest.SetManaged(true); err != nil { + log.WithFields(log.Fields{"app": a.name, "call": "SetManaged", "src": src, "dest": dest, "error": err}).Errorf("") + return err + } } } + if err := src.SetBackedUp(true); err != nil { + log.WithFields(log.Fields{"app": a.name, "call": "SetBackedUp", "src": src, "error": err}).Errorf("") + return err + } + } return nil diff --git a/backup.go b/backup.go index 34fae3d..335257b 100644 --- a/backup.go +++ b/backup.go @@ -61,6 +61,12 @@ func main() { cfg.Run(e) + cfg.Cleanup(e) + + if err := e.Send(); err != nil { + log.Printf("Cannot send email (%s)", err) + } + os.Exit(0) } diff --git a/config.go b/config.go index a7ac8ed..77f8a7e 100644 --- a/config.go +++ b/config.go @@ -202,6 +202,44 @@ func (c *Config) Run(e *Email) { return } +func (c *Config) Cleanup(e *Email) { + log.WithFields(log.Fields{}).Debugf("starting") + defer log.WithFields(log.Fields{}).Debugf("done") + + for _, a := range cfg.apps { + for _, src := range a.sources { + if b, ok := c.box[src.Box()]; ok { + if fs, ok := b.zfs.filesystems[src.Path()]; ok { + fs.srcApps = append(fs.srcApps, a) + } + } + for _, dest := range a.destinations { + if b, ok := c.box[src.Box()]; ok { + if fs, ok := b.zfs.filesystems[dest.Append("/"+src.Box()+"/"+src.Path()).Path()]; ok { + fs.destApps = append(fs.destApps, a) + } + } + } + } + } + + for _, b := range cfg.box { + if b.online { + for _, fs := range b.zfs.filesystems { + if len(fs.srcApps) > 0 && !fs.backedUp { + log.WithFields(log.Fields{"box": b.name, "fs": fs.path}).Warnf("not backed up") + e.AddItem(fmt.Sprintf(" - Src : Folder not backed up (%s)", b.name+":"+fs.path)) + } + if len(fs.destApps) == 0 && !fs.backedUp && fs.managed { + log.WithFields(log.Fields{"box": b.name, "fs": fs.path}).Warnf("managed") + e.AddItem(fmt.Sprintf(" - Dest : Folder managed (%s)", b.name+":"+fs.path)) + } + } + } + } + +} + func (c *Config) Stop(e *Email) { log.WithFields(log.Fields{}).Debugf("starting") defer log.WithFields(log.Fields{}).Debugf("done") diff --git a/email.go b/email.go index 28af944..a5cf92d 100644 --- a/email.go +++ b/email.go @@ -41,6 +41,10 @@ func (e *Email) Send() error { log.WithFields(log.Fields{}).Debugf("starting") defer log.WithFields(log.Fields{}).Debugf("done") + if len(e.items) == 0 { + return nil + } + body := " - " + e.items[0] for _, item := range e.items[1:] { body = body + "\r\n" + item diff --git a/version.go b/version.go index 0888b02..a022ab1 100644 --- a/version.go +++ b/version.go @@ -1,7 +1,7 @@ // Code generated by version.sh (@generated) DO NOT EDIT. package main -var githash = "e07c1c4" +var githash = "24a5e66" var branch = "v2" -var buildstamp = "2023-07-01_20:33:58" -var commits = "65" -var version = "e07c1c4-b65 - 2023-07-01_20:33:58" +var buildstamp = "2023-07-31_08:12:46" +var commits = "66" +var version = "24a5e66-b66 - 2023-07-31_08:12:46" diff --git a/zfs.go b/zfs.go index 347618c..1caa9bc 100644 --- a/zfs.go +++ b/zfs.go @@ -23,9 +23,11 @@ type BoxZfs struct { type ZfsFs struct { path string managed bool + backedUp bool zfs *BoxZfs snapshots map[string]*ZfsSnapshot - apps []*App + srcApps []*App + destApps []*App mx sync.Mutex } @@ -200,7 +202,8 @@ func (z *BoxZfs) Mkdir(path string) error { managed: false, zfs: z, snapshots: make(map[string]*ZfsSnapshot), - apps: make([]*App, 0), + srcApps: make([]*App, 0), + destApps: make([]*App, 0), } z.filesystems[newPath] = fs }