Compare commits

..

4 Commits
v2 ... master

Author SHA1 Message Date
shoopea
26c324c43c fix out of bounds miscomputation 2023-09-10 18:43:14 +02:00
shoopea
2ca0695a1f fix zfs send for expired snapshots 2023-09-10 18:38:53 +02:00
shoopea
3b1d0fc850 prepare indirect zfs transfer and multi-transfer 2023-08-22 13:23:48 +02:00
e7ed6cb2fd Merge pull request 'v2' (#2) from v2 into master
Reviewed-on: #2
2023-08-21 20:03:11 +02:00
5 changed files with 64 additions and 48 deletions

View File

@ -84,7 +84,7 @@ func (a Addr) ValidSnapshots() ([]*ZfsSnapshot, error) {
} }
} }
func (a Addr) SetManaged(val bool) error { func (a Addr) SetManaged(managed bool) error {
log.WithFields(log.Fields{"addr": a}).Debugf("starting") log.WithFields(log.Fields{"addr": a}).Debugf("starting")
defer log.WithFields(log.Fields{"addr": a}).Debugf("done") defer log.WithFields(log.Fields{"addr": a}).Debugf("done")
@ -99,9 +99,9 @@ func (a Addr) SetManaged(val bool) error {
} else { } else {
fs.mx.Lock() fs.mx.Lock()
defer fs.mx.Unlock() defer fs.mx.Unlock()
if fs.managed != val { if fs.managed != managed {
var cmd string var cmd string
if val { if managed {
cmd = fmt.Sprintf("zfs set %s=+ %s", zfsManagedPropertyName, a.Path()) cmd = fmt.Sprintf("zfs set %s=+ %s", zfsManagedPropertyName, a.Path())
} else { } else {
cmd = fmt.Sprintf("zfs set %s=- %s", zfsManagedPropertyName, a.Path()) cmd = fmt.Sprintf("zfs set %s=- %s", zfsManagedPropertyName, a.Path())
@ -111,7 +111,7 @@ func (a Addr) SetManaged(val bool) error {
return err return err
} }
} }
fs.managed = val fs.managed = managed
return nil return nil
} }
} }

13
app.go
View File

@ -478,7 +478,7 @@ func (a *App) Transfer() error {
defer log.WithFields(log.Fields{"app": a.name}).Debugf("done") defer log.WithFields(log.Fields{"app": a.name}).Debugf("done")
for _, src := range a.sources { for _, src := range a.sources {
backedUp := false dests := make([]Addr, 0)
for _, dest := range a.destinations { for _, dest := range a.destinations {
dest2 := dest.Append("/" + src.Box() + "/" + src.Path()) dest2 := dest.Append("/" + src.Box() + "/" + src.Path())
if dest2.Online() { if dest2.Online() {
@ -486,18 +486,17 @@ func (a *App) Transfer() error {
log.WithFields(log.Fields{"app": a.name, "call": "Mkdir", "attr": dest, "error": err}).Errorf("") log.WithFields(log.Fields{"app": a.name, "call": "Mkdir", "attr": dest, "error": err}).Errorf("")
return err return err
} }
if err := TransferZfs(src, dest2); err != nil {
log.WithFields(log.Fields{"app": a.name, "call": "TransferZfs", "src": src, "dest": dest, "error": err}).Errorf("")
return err
}
if err := dest2.SetManaged(true); err != nil { if err := dest2.SetManaged(true); err != nil {
log.WithFields(log.Fields{"app": a.name, "call": "SetManaged", "src": src, "dest": dest, "error": err}).Errorf("") log.WithFields(log.Fields{"app": a.name, "call": "SetManaged", "src": src, "dest": dest, "error": err}).Errorf("")
return err return err
} }
backedUp = true dests = append(dests, dest2)
} }
} }
if backedUp { if n, err := TransferZfs(src, dests); err != nil {
log.WithFields(log.Fields{"app": a.name, "call": "TransferZfs", "src": src, "dests": dests, "error": err}).Errorf("")
return err
} else if n > 0 {
if err := src.SetBackedUp(true); err != nil { if err := src.SetBackedUp(true); err != nil {
log.WithFields(log.Fields{"app": a.name, "call": "SetBackedUp", "src": src, "error": err}).Errorf("") log.WithFields(log.Fields{"app": a.name, "call": "SetBackedUp", "src": src, "error": err}).Errorf("")
return err return err

60
box.go
View File

@ -139,22 +139,39 @@ func (b *Box) Exec(cmd string) (r string, err error) {
return s.Exec(cmd) return s.Exec(cmd)
} }
func TransferZfs(from, to Addr) error { func TransferZfs(from Addr, to []Addr) (int, error) {
log.WithFields(log.Fields{"from": from, "to": to}).Debugf("starting")
defer log.WithFields(log.Fields{"from": from, "to": to}).Debugf("done")
count := 0
dests := make([]Addr, 0)
for _, dest := range to {
if cfg.box[from.Box()].allowDirectConnect && cfg.box[dest.Box()].allowDirectConnect {
if err := TransferDirectZfs(from, dest); err != nil {
log.WithFields(log.Fields{"from": from, "to": to, "call": "TransferDirectZfs", "attr": dest, "error": err}).Errorf("")
return count, err
} else {
count++
}
} else {
dests = append(dests, dest)
}
}
return count, nil
}
func TransferDirectZfs(from, to Addr) error {
log.WithFields(log.Fields{"from": from, "to": to}).Debugf("starting") log.WithFields(log.Fields{"from": from, "to": to}).Debugf("starting")
defer log.WithFields(log.Fields{"from": from, "to": to}).Debugf("done") defer log.WithFields(log.Fields{"from": from, "to": to}).Debugf("done")
var ( var (
err error err error
fromSnapshots, toSnapshots []*ZfsSnapshot fromSnapshots, toSnapshots []*ZfsSnapshot
directTransfer bool
) )
if cfg.box[from.Box()].allowDirectConnect && cfg.box[to.Box()].allowDirectConnect {
directTransfer = true
} else {
directTransfer = false
}
if fromSnapshots, err = from.ValidSnapshots(); err != nil { if fromSnapshots, err = from.ValidSnapshots(); err != nil {
log.WithFields(log.Fields{"from": from, "to": to, "call": "ValidSnapshots", "attr": from, "error": err}).Errorf("") log.WithFields(log.Fields{"from": from, "to": to, "call": "ValidSnapshots", "attr": from, "error": err}).Errorf("")
return err return err
@ -171,7 +188,6 @@ func TransferZfs(from, to Addr) error {
if len(toSnapshots) == 0 { if len(toSnapshots) == 0 {
log.WithFields(log.Fields{"from": from, "to": to}).Debugf("initiating destination") log.WithFields(log.Fields{"from": from, "to": to}).Debugf("initiating destination")
if directTransfer {
if _, err := to.BoxExec("ssh " + from.Box() + " zfs send " + fromSnapshots[0].String() + " | zfs recv -F " + to.Path()); err != nil { if _, err := to.BoxExec("ssh " + from.Box() + " zfs send " + fromSnapshots[0].String() + " | zfs recv -F " + to.Path()); err != nil {
log.WithFields(log.Fields{"from": from, "to": to, "call": "BoxExec", "error": err}).Errorf("") log.WithFields(log.Fields{"from": from, "to": to, "call": "BoxExec", "error": err}).Errorf("")
return err return err
@ -179,21 +195,23 @@ func TransferZfs(from, to Addr) error {
newToSnapshot := &ZfsSnapshot{name: fromSnapshots[0].name, fs: cfg.box[to.Box()].zfs.filesystems[to.Path()]} newToSnapshot := &ZfsSnapshot{name: fromSnapshots[0].name, fs: cfg.box[to.Box()].zfs.filesystems[to.Path()]}
toSnapshots = append(toSnapshots, newToSnapshot) toSnapshots = append(toSnapshots, newToSnapshot)
cfg.box[to.Box()].zfs.filesystems[to.Path()].AddSnapshot(newToSnapshot) cfg.box[to.Box()].zfs.filesystems[to.Path()].AddSnapshot(newToSnapshot)
} else {
//handle indirect transfer
}
} }
fromFromSnapshotId := -1 fromFromSnapshotId := len(fromSnapshots) - 1
lastToSnapshot := toSnapshots[len(toSnapshots)-1] fromToSnapshotId := -1
log.WithFields(log.Fields{"from": from, "to": to}).Debugf("searching last snapshot %s", lastToSnapshot.String()) for fromFromSnapshotId >= 0 {
for id, v := range fromSnapshots { fromToSnapshotId = len(toSnapshots) - 1
if v.name == lastToSnapshot.name { for fromToSnapshotId >= 0 {
fromFromSnapshotId = id if fromSnapshots[fromFromSnapshotId].name == toSnapshots[fromToSnapshotId].name {
log.WithFields(log.Fields{"from": from, "to": to}).Debugf("found %s", v.String())
break break
} }
fromToSnapshotId = fromToSnapshotId - 1
}
if fromToSnapshotId >= 0 {
break
}
fromFromSnapshotId = fromFromSnapshotId - 1
} }
if fromFromSnapshotId == -1 { if fromFromSnapshotId == -1 {
@ -204,14 +222,10 @@ func TransferZfs(from, to Addr) error {
if fromFromSnapshotId < len(fromSnapshots)-1 { if fromFromSnapshotId < len(fromSnapshots)-1 {
log.WithFields(log.Fields{"from": from, "to": to}).Debugf("transfering from %s to %s", fromSnapshots[fromFromSnapshotId].name, fromSnapshots[len(fromSnapshots)-1].name) log.WithFields(log.Fields{"from": from, "to": to}).Debugf("transfering from %s to %s", fromSnapshots[fromFromSnapshotId].name, fromSnapshots[len(fromSnapshots)-1].name)
if directTransfer {
if _, err := to.BoxExec("ssh " + from.Box() + " zfs send -I " + fromSnapshots[fromFromSnapshotId].String() + " " + fromSnapshots[len(fromSnapshots)-1].String() + " | zfs recv -F " + to.Path()); err != nil { if _, err := to.BoxExec("ssh " + from.Box() + " zfs send -I " + fromSnapshots[fromFromSnapshotId].String() + " " + fromSnapshots[len(fromSnapshots)-1].String() + " | zfs recv -F " + to.Path()); err != nil {
log.WithFields(log.Fields{"from": from, "to": to, "call": "BoxExec", "error": err}).Errorf("") log.WithFields(log.Fields{"from": from, "to": to, "call": "BoxExec", "error": err}).Errorf("")
return err return err
} }
} else {
// handle indirect transfer
}
for _, v := range fromSnapshots[fromFromSnapshotId+1:] { for _, v := range fromSnapshots[fromFromSnapshotId+1:] {
cfg.box[to.Box()].zfs.filesystems[to.Path()].AddSnapshot(&ZfsSnapshot{name: v.name, fs: cfg.box[to.Box()].zfs.filesystems[to.Path()]}) cfg.box[to.Box()].zfs.filesystems[to.Path()].AddSnapshot(&ZfsSnapshot{name: v.name, fs: cfg.box[to.Box()].zfs.filesystems[to.Path()]})

View File

@ -1,7 +1,7 @@
// Code generated by version.sh (@generated) DO NOT EDIT. // Code generated by version.sh (@generated) DO NOT EDIT.
package main package main
var githash = "1a1713e" var githash = "2ca0695"
var branch = "v2" var branch = "master"
var buildstamp = "2023-08-21_12:35:47" var buildstamp = "2023-09-10_16:42:46"
var commits = "83" var commits = "87"
var version = "1a1713e-b83 - 2023-08-21_12:35:47" var version = "2ca0695-b87 - 2023-09-10_16:42:46"

3
zfs.go
View File

@ -311,6 +311,9 @@ func (fs *ZfsFs) AddSnapshot(s *ZfsSnapshot) error {
} }
func (fs *ZfsFs) ValidSnapshots() []*ZfsSnapshot { func (fs *ZfsFs) ValidSnapshots() []*ZfsSnapshot {
log.WithFields(log.Fields{"box": fs.zfs.box.name, "fs": fs.path}).Debugf("starting")
defer log.WithFields(log.Fields{"box": fs.zfs.box.name, "fs": fs.path}).Debugf("done")
tab := make([]*ZfsSnapshot, 0) tab := make([]*ZfsSnapshot, 0)
for _, s := range fs.snapshots { for _, s := range fs.snapshots {