add backupd
This commit is contained in:
parent
36282e7cea
commit
4c7741a337
56
cmd/backupd/backupd.go
Normal file
56
cmd/backupd/backupd.go
Normal file
@ -0,0 +1,56 @@
|
||||
// Binary backupd provides tarballs of /perm.
|
||||
package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/gokrazy/gokrazy"
|
||||
|
||||
"router7/internal/backup"
|
||||
"router7/internal/multilisten"
|
||||
"router7/internal/teelogger"
|
||||
)
|
||||
|
||||
var log = teelogger.NewConsole()
|
||||
|
||||
var httpListeners = multilisten.NewPool()
|
||||
|
||||
func updateListeners() error {
|
||||
hosts, err := gokrazy.PrivateInterfaceAddrs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
httpListeners.ListenAndServe(hosts, func(host string) multilisten.Listener {
|
||||
return &http.Server{Addr: net.JoinHostPort(host, "8077")}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func logic() error {
|
||||
http.HandleFunc("/backup.tar.gz", func(w http.ResponseWriter, r *http.Request) {
|
||||
if err := backup.Archive(w, "/perm"); err != nil {
|
||||
log.Printf("backup.tar.gz: %v", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
})
|
||||
updateListeners()
|
||||
ch := make(chan os.Signal, 1)
|
||||
signal.Notify(ch, syscall.SIGUSR1)
|
||||
for range ch {
|
||||
if err := updateListeners(); err != nil {
|
||||
log.Printf("updateListeners: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := logic(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
66
internal/backup/backup.go
Normal file
66
internal/backup/backup.go
Normal file
@ -0,0 +1,66 @@
|
||||
// Package backup generates tarballs of /perm.
|
||||
package backup
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func Archive(w io.Writer, dir string) error {
|
||||
gw, err := gzip.NewWriterLevel(w, gzip.BestSpeed)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer gw.Close()
|
||||
tw := tar.NewWriter(gw)
|
||||
|
||||
err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info == nil {
|
||||
return fmt.Errorf("filepath.Walk: nil os.FileInfo")
|
||||
}
|
||||
if !info.Mode().IsRegular() && !info.Mode().IsDir() {
|
||||
return nil // skip non-regular files/directories
|
||||
}
|
||||
if path == dir {
|
||||
return nil // skip root
|
||||
}
|
||||
rel, err := filepath.Rel(dir, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hdr, err := tar.FileInfoHeader(info, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hdr.Name = rel
|
||||
if err := tw.WriteHeader(hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.Mode().IsDir() {
|
||||
b, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := tw.Write(b); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tw.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
return gw.Close()
|
||||
}
|
55
internal/backup/backup_test.go
Normal file
55
internal/backup/backup_test.go
Normal file
@ -0,0 +1,55 @@
|
||||
package backup_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"router7/internal/backup"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestArchive(t *testing.T) {
|
||||
tmpin, err := ioutil.TempDir("", "backuptest")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpin)
|
||||
|
||||
if err := ioutil.WriteFile(filepath.Join(tmpin, "random.seed"), []byte{0xaa, 0xbb}, 0600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(filepath.Join(tmpin, "dhcp4d"), 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(filepath.Join(tmpin, "dhcp4d", "leases.json"), []byte("{}"), 0600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := backup.Archive(&buf, tmpin); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tmpout, err := ioutil.TempDir("", "backuptest")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpout)
|
||||
tar := exec.Command("tar", "xzf", "-", "-C", tmpout)
|
||||
tar.Stdin = &buf
|
||||
tar.Stderr = os.Stderr
|
||||
if err := tar.Run(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff := exec.Command("diff", "-ur", tmpin, tmpout)
|
||||
diff.Stdout = os.Stdout
|
||||
diff.Stderr = os.Stderr
|
||||
if err := diff.Run(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
@ -601,7 +601,9 @@ func Apply(dir, root string) error {
|
||||
|
||||
for _, process := range []string{
|
||||
"dyndns", // depends on the public IPv4 address
|
||||
"dnsd", // listens on private IPv4/IPv6 and public IPv6Net1
|
||||
"dnsd", // listens on private IPv4/IPv6
|
||||
"diagd", // listens on private IPv4/IPv6
|
||||
"backupd", // listens on private IPv4/IPv6
|
||||
} {
|
||||
if err := notify.Process("/user/"+process, syscall.SIGUSR1); err != nil {
|
||||
log.Printf("notifying %s: %v", process, err)
|
||||
|
Loading…
x
Reference in New Issue
Block a user