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)
|
||||||
|
}
|
||||||
|
}
|
@ -600,8 +600,10 @@ func Apply(dir, root string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, process := range []string{
|
for _, process := range []string{
|
||||||
"dyndns", // depends on the public IPv4 address
|
"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 {
|
if err := notify.Process("/user/"+process, syscall.SIGUSR1); err != nil {
|
||||||
log.Printf("notifying %s: %v", process, err)
|
log.Printf("notifying %s: %v", process, err)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user