package main import ( "bytes" "encoding/csv" "fmt" "log" "strings" ) type Box struct { Addr string `json:"addr"` User string `json:"user"` Key string `json:"key"` Name string `json:"-"` ssh *SSHConfig zfs *ZFSConfig } func (b *Box) ZFSGetLastSnapshot(path string) (s Snapshot, err error) { return b.ssh.getLastSnapshot(path) } func (b *Box) ZFSIsLastSnapshot(s Snapshot) bool { return b.ssh.isLastSnapshot(s) } func (b *Box) ZFSGetFirstSnapshot(path string) (s Snapshot, err error) { return b.ssh.getFirstSnapshot(path) } func (b *Box) ZFSGetNextSnapshot(src Snapshot) (next Snapshot, err error) { return b.ssh.getNextSnapshot(src) } func (b *Box) ZFSUpdateSnapshotList() (err error) { return b.ssh.getSnapshotList() } func (b *Box) ZFSGetSnapshotList() []Snapshot { return b.ssh.snapshot } func (b *Box) ZFSUpdateList() (err error) { b.zfs.M.Lock() if b.zfs.ZFSDeleted || b.zfs.ZFSAdded { b.zfs.ZFSInitialized = false } b.zfs.M.Unlock() err = b.ZFSInitialize() return } func (b *Box) ZFSIsZFS(path string) bool { err := b.ZFSInitialize() if err != nil { return false } b.zfs.M.Lock() defer b.zfs.M.Unlock() if _, ok := b.zfs.ZFSMap[path]; ok { return true } return false } func (b *Box) ZFSCreateZFS(path string) (err error) { err = b.ZFSInitialize() if err != nil { return } b.zfs.M.Lock() defer b.zfs.M.Unlock() p := strings.Split(path, `/`) var base string for _, d := range p { if base == "" { base = d } else { base = base + `/` + d } if _, ok := b.zfs.ZFSMap[base]; !ok { if *debugFlag { log.Printf("Box.ZFSCreateZFS : Creating %s:%s", b.Name, base) } _, err = b.SSHExec("zfs create -o mountpoint=none " + base) if err != nil { if *debugFlag { log.Printf("Box.ZFSCreateZFS : %s : SSHExec : %s", b.Name, err) } return } b.zfs.ZFSMap[base] = "none" b.zfs.ZFSAdded = true } } return } func (b *Box) ZFSInitialize() (err error) { b.zfs.M.Lock() defer b.zfs.M.Unlock() if b.zfs.ZFSInitialized { return nil } if *debugFlag { log.Printf("Box.ZFSInitialize : %s : Start", b.Name) } b.zfs.ZFSMap = make(map[string]string) var buf *bytes.Buffer buf, err = b.SSHExec("zfs list -H -o name,mountpoint") csvReader := csv.NewReader(buf) csvReader.Comma = '\t' csvReader.FieldsPerRecord = 2 csvData, err := csvReader.ReadAll() if err != nil { if *debugFlag { log.Printf("Box.ZFSInitialize : %s : csvReader.ReadAll() : %s", b.Name, err) } return err } for _, rec := range csvData { b.zfs.ZFSMap[rec[0]] = rec[1] } b.zfs.ZFSInitialized = true b.zfs.ZFSAdded = false b.zfs.ZFSDeleted = false return nil } func (b *Box) SSHExec(cmd string) (buf *bytes.Buffer, err error) { buf, err = b.ssh.exec(cmd) return } func (b *Box) ZFSTakeSnapshot(schedule, path string) (err error) { if *debugFlag { log.Printf("Box.ZFSTakeSnapshot : %s : taking snapshot on %s for %s", b.Name, path, schedule) } timestamp := cfg.Now.Format("2006-01-02_15.04.05") name := fmt.Sprintf("%s-%s--%s", schedule, timestamp, cfg.Zfsnap[schedule]) _, err = b.ssh.exec("zfs snapshot " + path + "@" + name) return }