118 lines
3.7 KiB
Go
118 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
)
|
|
|
|
// windowJob raw-copies a byte window [srcBase,srcBase+size) of the source
|
|
// disk onto [dstBase,dstBase+size) of the target, through the same
|
|
// push/pull block-diff engine `sync` uses. Used for boot regions and for
|
|
// partitions cloned with method "raw".
|
|
type windowJob struct {
|
|
srcPath, dstPath string
|
|
srcBase, dstBase int64
|
|
size int64
|
|
bothLocal bool
|
|
blockSize int64
|
|
cfg *SyncConfig
|
|
srcHost, srcUser string
|
|
dstHost, dstUser string
|
|
srcRemoteBin string
|
|
dstRemoteBin string
|
|
srcSudo, dstSudo bool
|
|
}
|
|
|
|
func runWindowTransfer(srcCtrl, dstCtrl *Controller, j windowJob) error {
|
|
pp := newProgressPrinter(j.blockSize)
|
|
cb := transferCallbacks{onProgress: pp.print}
|
|
|
|
pushReq := CtrlMsg{
|
|
Path: j.srcPath, Base: j.srcBase, PeerBase: j.dstBase, Size: j.size, BlockSize: j.blockSize,
|
|
PeerHost: j.dstHost, PeerUser: j.dstUser, PeerPath: j.dstPath, PeerLocal: j.bothLocal,
|
|
RemoteBin: j.dstRemoteBin, SSHBin: j.cfg.SSHBin, SSHOpts: j.cfg.SSHOpts,
|
|
ConnectTimeoutSec: j.cfg.ConnectTimeoutSec, Sudo: j.dstSudo,
|
|
}
|
|
ok, reason, err := srcCtrl.ConnectPush(pushReq, cb)
|
|
if err != nil {
|
|
pp.finish()
|
|
return err
|
|
}
|
|
if !ok {
|
|
pp.finish()
|
|
fmt.Fprintf(os.Stderr, " push not possible (%s); pulling instead ...\n", reason)
|
|
pullReq := CtrlMsg{
|
|
Path: j.dstPath, Base: j.dstBase, PeerBase: j.srcBase, Size: j.size, BlockSize: j.blockSize,
|
|
PeerHost: j.srcHost, PeerUser: j.srcUser, PeerPath: j.srcPath, PeerLocal: j.bothLocal,
|
|
RemoteBin: j.srcRemoteBin, SSHBin: j.cfg.SSHBin, SSHOpts: j.cfg.SSHOpts,
|
|
ConnectTimeoutSec: j.cfg.ConnectTimeoutSec, Sudo: j.srcSudo,
|
|
}
|
|
ok2, reason2, err2 := dstCtrl.ConnectPull(pullReq, cb)
|
|
if err2 != nil {
|
|
pp.finish()
|
|
return err2
|
|
}
|
|
if !ok2 {
|
|
pp.finish()
|
|
return fmt.Errorf("no direct connection either way (push: %s; pull: %s)", reason, reason2)
|
|
}
|
|
}
|
|
pp.finish()
|
|
return nil
|
|
}
|
|
|
|
// cloneCtx carries the transport context for an fs-image partition clone.
|
|
type cloneCtx struct {
|
|
srcPath, dstPath string
|
|
bothLocal bool
|
|
cfg *SyncConfig
|
|
srcHost, srcUser string
|
|
dstHost, dstUser string
|
|
srcRemoteBin string
|
|
dstRemoteBin string
|
|
srcSudo, dstSudo bool
|
|
}
|
|
|
|
// runFSImagePartition streams a filesystem image for one partition, trying
|
|
// push (source drives) then pull (dest drives).
|
|
func runFSImagePartition(srcCtrl, dstCtrl *Controller, pp plannedPart, c cloneCtx) error {
|
|
opts := fsCloneOpts{FSType: pp.FSType, Tool: pp.Tool, SizeBytes: pp.SrcSizeB, ShrinkToBytes: pp.ShrinkToB}
|
|
prog := newProgressPrinter(1 << 20)
|
|
cb := transferCallbacks{onProgress: prog.printBytes}
|
|
|
|
pushReq := CtrlMsg{
|
|
Method: "fs-image", PartIndex: pp.Num, Options: opts.encode(),
|
|
Path: c.srcPath, PeerPath: c.dstPath, PeerLocal: c.bothLocal,
|
|
PeerHost: c.dstHost, PeerUser: c.dstUser,
|
|
RemoteBin: c.dstRemoteBin, SSHBin: c.cfg.SSHBin, SSHOpts: c.cfg.SSHOpts,
|
|
ConnectTimeoutSec: c.cfg.ConnectTimeoutSec, Sudo: c.dstSudo,
|
|
}
|
|
ok, reason, err := srcCtrl.ClonePartition(pushReq, cb)
|
|
if err != nil {
|
|
prog.finish()
|
|
return err
|
|
}
|
|
if !ok {
|
|
prog.finish()
|
|
fmt.Fprintf(os.Stderr, " fs-image push not possible (%s); pulling instead ...\n", reason)
|
|
pullReq := CtrlMsg{
|
|
Method: "fs-image", Reason: "pull", PartIndex: pp.Num, Options: opts.encode(),
|
|
Path: c.dstPath, PeerPath: c.srcPath, PeerLocal: c.bothLocal,
|
|
PeerHost: c.srcHost, PeerUser: c.srcUser,
|
|
RemoteBin: c.srcRemoteBin, SSHBin: c.cfg.SSHBin, SSHOpts: c.cfg.SSHOpts,
|
|
ConnectTimeoutSec: c.cfg.ConnectTimeoutSec, Sudo: c.srcSudo,
|
|
}
|
|
ok2, reason2, err2 := dstCtrl.ClonePartition(pullReq, cb)
|
|
if err2 != nil {
|
|
prog.finish()
|
|
return err2
|
|
}
|
|
if !ok2 {
|
|
prog.finish()
|
|
return fmt.Errorf("fs-image failed both ways (push: %s; pull: %s)", reason, reason2)
|
|
}
|
|
}
|
|
prog.finish()
|
|
return nil
|
|
}
|