zfs_replication_exporter/zfs_replication_exporter.go

104 lines
2.0 KiB
Go

package main
import (
"flag"
"fmt"
"io"
"log"
"os"
"strings"
"time"
"golang.org/x/crypto/ssh"
"xinu.tv/thumbnailer/auth"
"xinu.tv/thumbnailer/scp"
)
var (
host = flag.String("host", "localhost:22", "host:port to scp from")
user = flag.String("user", os.Getenv("USER"), "ssh user")
)
func checkFatal(err error) {
if err != nil {
log.Fatal(err)
}
}
func progress(w io.Writer, r io.Reader, size int64) error {
const (
chunkSize = 1 << 10
width = 50
)
var err error
total, bLast := int64(0), int64(0)
tLast := time.Now()
defer fmt.Println()
for {
var n int64
n, err = io.CopyN(w, r, chunkSize)
total += n
bLast += n
if time.Since(tLast) > (300 * time.Millisecond) {
kbps := float64(bLast) / time.Since(tLast).Seconds() / 1024
frac := int(total * width / size)
fmt.Printf("\rDownloaded: %s>%s| %.2f Kb/s", strings.Repeat("=", frac),
strings.Repeat(" ", width-frac), kbps)
tLast = time.Now()
bLast = 0
}
if err != nil {
break
}
}
if err == io.EOF {
return nil
}
return err
}
var sink, _ = os.Create(os.DevNull)
func main() {
flag.Parse()
ams, err := auth.NewPublicKey()
checkFatal(err)
// An SSH client is represented with a ClientConn.
//
// To authenticate with the remote server you must pass at least one
// implementation of ClientAuth via the Auth field in ClientConfig.
config := &ssh.ClientConfig{
User: *user,
Auth: ams,
// TODO(wathiede); use FixedHostKey?
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
client, err := ssh.Dial("tcp", *host, config)
checkFatal(err)
for _, fn := range flag.Args() {
log.Println("Fetching", fn)
// Each ClientConn can support multiple interactive sessions,
// represented by a Session.
session, err := client.NewSession()
checkFatal(err)
f, err := scp.ScpFrom(session, fn)
if err != nil {
log.Println(err)
continue
}
log.Println(f.Name, f.Perm, f.Size)
err = progress(sink, f, f.Size)
checkFatal(err)
checkFatal(f.Close())
checkFatal(session.Close())
}
}