package main import ( "errors" "fmt" "regexp" "strings" log "github.com/sirupsen/logrus" ) type Addr string var ( reBox = regexp.MustCompile(`^[a-zA-Z0-9\-_\.]+$`) rePath = regexp.MustCompile(`^(/){0,1}[a-zA-Z0-9\-_\.]+(/[a-zA-Z0-9\-_\.]+)+$`) ) func (a Addr) Box() string { s := strings.Split(string(a), `:`) box := s[0] if reBox.MatchString(box) { return box } else { return "" } } func (a Addr) Path() string { s := strings.Split(string(a), `:`) path := s[1] if rePath.MatchString(path) { return path } else { return "" } } func (a Addr) Append(path string) Addr { newPath := a.Path() + path if rePath.MatchString(newPath) { return Addr(a.Box() + ":" + newPath) } else { return "" } } func (a Addr) BoxExec(cmd string) (string, 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 { return b.Exec(cmd) } } func (a Addr) Exec() (string, error) { log.WithFields(log.Fields{"addr": a}).Debugf("starting") defer log.WithFields(log.Fields{"addr": a}).Debugf("done") return a.BoxExec(a.Path()) } func (a Addr) ValidSnapshots() ([]*ZfsSnapshot, 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 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, "error": err}).Errorf("") return nil, err } } } func (a Addr) SetManaged(managed 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 != managed { var cmd string if managed { 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 = managed 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(), "error": err}).Errorf("") return err } else { return b.zfs.Mkdir(a.Path()) } } func (a Addr) String() string { return string(a) } func (a Addr) Online() bool { 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 { return false } else { return b.online } }