backup/box.go
2021-11-14 15:58:47 +08:00

164 lines
3.1 KiB
Go

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
}