2021-10-16 15:39:54 +02:00
|
|
|
package main
|
|
|
|
|
2023-06-29 22:58:24 +02:00
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"regexp"
|
|
|
|
"time"
|
2021-10-16 15:39:54 +02:00
|
|
|
|
2023-06-29 22:58:24 +02:00
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
func SnapshotName(schedule string, now time.Time) string {
|
|
|
|
log.WithFields(log.Fields{"schedule": schedule, "now": now}).Debugf("starting")
|
|
|
|
log.WithFields(log.Fields{"schedule": schedule, "now": now}).Debugf("done")
|
|
|
|
|
|
|
|
return schedule + "-" + now.Format(zfsSnapshotDatePattern) + "--" + cfg.ScheduleDuration[schedule]
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ZfsSnapshot) Valid() bool {
|
|
|
|
log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name}).Debugf("starting")
|
|
|
|
defer log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name}).Debugf("done")
|
|
|
|
|
|
|
|
re := regexp.MustCompile(zfsSnapshotPattern)
|
|
|
|
return re.MatchString(s.name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ZfsSnapshot) Schedule() (string, error) {
|
|
|
|
log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name}).Debugf("starting")
|
|
|
|
defer log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name}).Debugf("done")
|
|
|
|
|
|
|
|
if !s.Valid() {
|
|
|
|
err := errors.New("invalid name")
|
|
|
|
log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name, "call": "Valid", "error": err}).Errorf("")
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
re := regexp.MustCompile(zfsSnapshotPattern)
|
|
|
|
|
|
|
|
return re.ReplaceAllString(s.name, "${Schedule}"), nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ZfsSnapshot) Expiration() (time.Time, error) {
|
|
|
|
log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name}).Debugf("starting")
|
|
|
|
defer log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name}).Debugf("done")
|
|
|
|
|
|
|
|
if !s.Valid() {
|
|
|
|
err := errors.New("invalid name")
|
|
|
|
log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name, "call": "Valid", "error": err}).Errorf("")
|
|
|
|
return time.Now(), err
|
|
|
|
}
|
|
|
|
|
|
|
|
re := regexp.MustCompile(zfsSnapshotPattern)
|
|
|
|
|
|
|
|
expirationString := re.ReplaceAllString(s.name, "${Expiration}")
|
|
|
|
|
|
|
|
timestampTime, err := s.Timestamp()
|
|
|
|
if err != nil {
|
|
|
|
log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name, "call": "Timestamp", "error": err}).Errorf("")
|
|
|
|
return time.Now(), err
|
|
|
|
}
|
|
|
|
|
|
|
|
return Expiration(timestampTime, expirationString)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ZfsSnapshot) Timestamp() (time.Time, error) {
|
|
|
|
log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name}).Debugf("starting")
|
|
|
|
defer log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name}).Debugf("done")
|
|
|
|
|
|
|
|
t := time.Now()
|
|
|
|
|
|
|
|
if !s.Valid() {
|
|
|
|
err := errors.New("invalid name")
|
|
|
|
log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name, "call": "Valid", "error": err}).Errorf("")
|
|
|
|
return t, err
|
|
|
|
}
|
|
|
|
|
|
|
|
re := regexp.MustCompile(zfsSnapshotPattern)
|
|
|
|
|
|
|
|
timestampString := re.ReplaceAllString(s.name, "${Timestamp}")
|
|
|
|
timestampTime, err := time.ParseInLocation(zfsSnapshotDatePattern, timestampString, cfg.timezone)
|
|
|
|
if err != nil {
|
|
|
|
log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name, "call": "time.Parse", "attr": timestampString, "error": err}).Errorf("")
|
|
|
|
return t, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return timestampTime, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *ZfsSnapshot) Expired(now time.Time) (bool, error) {
|
|
|
|
log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name}).Debugf("starting")
|
|
|
|
defer log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name}).Debugf("done")
|
|
|
|
|
|
|
|
if !s.Valid() {
|
|
|
|
err := errors.New("invalid name")
|
|
|
|
log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name, "call": "Valid", "error": err}).Errorf("")
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
expirationTime, err := s.Expiration()
|
|
|
|
if err != nil {
|
|
|
|
log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name, "call": "Timestamp", "error": err}).Errorf("")
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if now.After(expirationTime) {
|
|
|
|
return true, nil
|
|
|
|
} else {
|
|
|
|
return false, nil
|
|
|
|
}
|
2021-10-16 15:39:54 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-06-29 22:58:24 +02:00
|
|
|
func (s *ZfsSnapshot) String() string {
|
|
|
|
return s.fs.path + "@" + s.name
|
2021-10-16 15:39:54 +02:00
|
|
|
}
|
|
|
|
|
2023-06-29 22:58:24 +02:00
|
|
|
func (s *ZfsSnapshot) Delete() error {
|
|
|
|
log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name}).Debugf("starting")
|
|
|
|
defer log.WithFields(log.Fields{"box": s.fs.zfs.box.name, "fs": s.fs.path, "name": s.name}).Debugf("done")
|
|
|
|
|
|
|
|
return s.fs.DelSnapshot(s.name)
|
2021-10-16 15:39:54 +02:00
|
|
|
}
|