package main import ( "errors" "regexp" "time" 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 } } func (s *ZfsSnapshot) String() string { return s.fs.path + "@" + s.name } 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) }