deprecate direct calls to sshconfig
This commit is contained in:
parent
0f4fca35f3
commit
119d069083
52
app.go
52
app.go
@ -18,10 +18,10 @@ type AppConfig struct {
|
|||||||
|
|
||||||
func (a AppConfig) getTime() time.Time {
|
func (a AppConfig) getTime() time.Time {
|
||||||
for _, v := range a.Sources {
|
for _, v := range a.Sources {
|
||||||
return cfg.Box[v.Box()].ssh.now
|
return cfg.Box[v.Box()].GetTime()
|
||||||
}
|
}
|
||||||
for _, v := range a.Destinations {
|
for _, v := range a.Destinations {
|
||||||
return cfg.Box[v.Box()].ssh.now
|
return cfg.Box[v.Box()].GetTime()
|
||||||
}
|
}
|
||||||
return time.Now()
|
return time.Now()
|
||||||
}
|
}
|
||||||
@ -37,10 +37,10 @@ func (a AppConfig) getSchedule() (string, error) {
|
|||||||
refreshSnapshot[v.Box()] = true
|
refreshSnapshot[v.Box()] = true
|
||||||
}
|
}
|
||||||
for k, _ := range refreshSnapshot {
|
for k, _ := range refreshSnapshot {
|
||||||
err := cfg.Box[k].ssh.getSnapshotList()
|
err := cfg.Box[k].ZFSUpdateSnapshotList()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.getSchedule : %s : getSnapshotList(%s) : %s", a.Name, k, err)
|
log.Printf("AppConfig.getSchedule : %s : ZFSUpdateSnapshotList(%s) : %s", a.Name, k, err)
|
||||||
}
|
}
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -95,7 +95,7 @@ func (a AppConfig) needYearlySnapshot() bool {
|
|||||||
re := regexp.MustCompile(`^yearly-(?P<Date>[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}.[0-9]{2}.[0-9]{2})--([0-9]+[ymwdhMs]{1}|forever)$`)
|
re := regexp.MustCompile(`^yearly-(?P<Date>[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}.[0-9]{2}.[0-9]{2})--([0-9]+[ymwdhMs]{1}|forever)$`)
|
||||||
for _, src := range a.Sources {
|
for _, src := range a.Sources {
|
||||||
timeSource[string(src)] = make(map[time.Time]struct{})
|
timeSource[string(src)] = make(map[time.Time]struct{})
|
||||||
for _, snap := range cfg.Box[src.Box()].ssh.snapshot {
|
for _, snap := range cfg.Box[src.Box()].ZFSGetSnapshotList() {
|
||||||
if src.Path() == snap.Path() {
|
if src.Path() == snap.Path() {
|
||||||
if re.MatchString(snap.Name()) {
|
if re.MatchString(snap.Name()) {
|
||||||
dateString := re.ReplaceAllString(snap.Name(), "${Date}")
|
dateString := re.ReplaceAllString(snap.Name(), "${Date}")
|
||||||
@ -157,7 +157,7 @@ func (a AppConfig) needMonthlySnapshot() bool {
|
|||||||
re := regexp.MustCompile(`^(yearly|monthly)-(?P<Date>[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}.[0-9]{2}.[0-9]{2})--([0-9]+[ymwdhMs]{1}|forever)$`)
|
re := regexp.MustCompile(`^(yearly|monthly)-(?P<Date>[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}.[0-9]{2}.[0-9]{2})--([0-9]+[ymwdhMs]{1}|forever)$`)
|
||||||
for _, src := range a.Sources {
|
for _, src := range a.Sources {
|
||||||
timeSource[string(src)] = make(map[time.Time]struct{})
|
timeSource[string(src)] = make(map[time.Time]struct{})
|
||||||
for _, snap := range cfg.Box[src.Box()].ssh.snapshot {
|
for _, snap := range cfg.Box[src.Box()].ZFSGetSnapshotList() {
|
||||||
if src.Path() == snap.Path() {
|
if src.Path() == snap.Path() {
|
||||||
if re.MatchString(snap.Name()) {
|
if re.MatchString(snap.Name()) {
|
||||||
dateString := re.ReplaceAllString(snap.Name(), "${Date}")
|
dateString := re.ReplaceAllString(snap.Name(), "${Date}")
|
||||||
@ -219,7 +219,7 @@ func (a AppConfig) needWeeklySnapshot() bool {
|
|||||||
re := regexp.MustCompile(`^(yearly|monthly|weekly)-(?P<Date>[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}.[0-9]{2}.[0-9]{2})--([0-9]+[ymwdhMs]{1}|forever)$`)
|
re := regexp.MustCompile(`^(yearly|monthly|weekly)-(?P<Date>[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}.[0-9]{2}.[0-9]{2})--([0-9]+[ymwdhMs]{1}|forever)$`)
|
||||||
for _, src := range a.Sources {
|
for _, src := range a.Sources {
|
||||||
timeSource[string(src)] = make(map[time.Time]struct{})
|
timeSource[string(src)] = make(map[time.Time]struct{})
|
||||||
for _, snap := range cfg.Box[src.Box()].ssh.snapshot {
|
for _, snap := range cfg.Box[src.Box()].ZFSGetSnapshotList() {
|
||||||
if src.Path() == snap.Path() {
|
if src.Path() == snap.Path() {
|
||||||
if re.MatchString(snap.Name()) {
|
if re.MatchString(snap.Name()) {
|
||||||
dateString := re.ReplaceAllString(snap.Name(), "${Date}")
|
dateString := re.ReplaceAllString(snap.Name(), "${Date}")
|
||||||
@ -283,7 +283,7 @@ func (a AppConfig) needDailySnapshot() bool {
|
|||||||
re := regexp.MustCompile(`^(yearly|monthly|weekly|daily)-(?P<Date>[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}.[0-9]{2}.[0-9]{2})--([0-9]+[ymwdhMs]{1}|forever)$`)
|
re := regexp.MustCompile(`^(yearly|monthly|weekly|daily)-(?P<Date>[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}.[0-9]{2}.[0-9]{2})--([0-9]+[ymwdhMs]{1}|forever)$`)
|
||||||
for _, src := range a.Sources {
|
for _, src := range a.Sources {
|
||||||
timeSource[string(src)] = make(map[time.Time]struct{})
|
timeSource[string(src)] = make(map[time.Time]struct{})
|
||||||
for _, snap := range cfg.Box[src.Box()].ssh.snapshot {
|
for _, snap := range cfg.Box[src.Box()].ZFSGetSnapshotList() {
|
||||||
if src.Path() == snap.Path() {
|
if src.Path() == snap.Path() {
|
||||||
if re.MatchString(snap.Name()) {
|
if re.MatchString(snap.Name()) {
|
||||||
dateString := re.ReplaceAllString(snap.Name(), "${Date}")
|
dateString := re.ReplaceAllString(snap.Name(), "${Date}")
|
||||||
@ -345,7 +345,7 @@ func (a AppConfig) needHourlySnapshot() bool {
|
|||||||
re := regexp.MustCompile(`^(yearly|monthly|weekly|daily|hourly)-(?P<Date>[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}.[0-9]{2}.[0-9]{2})--([0-9]+[ymwdhMs]{1}|forever)$`)
|
re := regexp.MustCompile(`^(yearly|monthly|weekly|daily|hourly)-(?P<Date>[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}.[0-9]{2}.[0-9]{2})--([0-9]+[ymwdhMs]{1}|forever)$`)
|
||||||
for _, src := range a.Sources {
|
for _, src := range a.Sources {
|
||||||
timeSource[string(src)] = make(map[time.Time]struct{})
|
timeSource[string(src)] = make(map[time.Time]struct{})
|
||||||
for _, snap := range cfg.Box[src.Box()].ssh.snapshot {
|
for _, snap := range cfg.Box[src.Box()].ZFSGetSnapshotList() {
|
||||||
if src.Path() == snap.Path() {
|
if src.Path() == snap.Path() {
|
||||||
if re.MatchString(snap.Name()) {
|
if re.MatchString(snap.Name()) {
|
||||||
dateString := re.ReplaceAllString(snap.Name(), "${Date}")
|
dateString := re.ReplaceAllString(snap.Name(), "${Date}")
|
||||||
@ -391,12 +391,12 @@ func (a AppConfig) CheckZFS() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, src := range a.Sources {
|
for _, src := range a.Sources {
|
||||||
if !cfg.Box[src.Box()].ssh.isZFS(src.Path()) {
|
if !cfg.Box[src.Box()].ZFSIsZFS(src.Path()) {
|
||||||
return fmt.Errorf("No path %s on source", string(src))
|
return fmt.Errorf("No path %s on source", string(src))
|
||||||
}
|
}
|
||||||
for _, dest := range a.Destinations {
|
for _, dest := range a.Destinations {
|
||||||
if !cfg.Box[dest.Box()].ssh.isZFS(dest.Path() + "/" + src.Box() + "/" + src.Path()) {
|
if !cfg.Box[dest.Box()].ZFSIsZFS(dest.Path() + "/" + src.Box() + "/" + src.Path()) {
|
||||||
err := cfg.Box[dest.Box()].ssh.createZFS(dest.Path() + "/" + src.Box() + "/" + src.Path())
|
err := cfg.Box[dest.Box()].ZFSCreateZFS(dest.Path() + "/" + src.Box() + "/" + src.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.CheckZFS : %s : Error creating %s on %s", a.Name, dest.Path()+"/"+src.Box()+"/"+src.Path(), dest.Box())
|
log.Printf("AppConfig.CheckZFS : %s : Error creating %s on %s", a.Name, dest.Path()+"/"+src.Box()+"/"+src.Path(), dest.Box())
|
||||||
@ -417,7 +417,7 @@ func (a AppConfig) ExecBefore(schedule string) error {
|
|||||||
for k, v := range a.Before {
|
for k, v := range a.Before {
|
||||||
re := regexp.MustCompile(k)
|
re := regexp.MustCompile(k)
|
||||||
if re.MatchString(schedule) {
|
if re.MatchString(schedule) {
|
||||||
err := cfg.Box[v.Box()].ssh.exec(v.Path())
|
err := cfg.Box[v.Box()].SSHExec(v.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.ExecBefore : %s : Error executing %s", a.Name, string(v))
|
log.Printf("AppConfig.ExecBefore : %s : Error executing %s", a.Name, string(v))
|
||||||
@ -437,7 +437,7 @@ func (a AppConfig) ExecAfter(schedule string) error {
|
|||||||
for k, v := range a.After {
|
for k, v := range a.After {
|
||||||
re := regexp.MustCompile(k)
|
re := regexp.MustCompile(k)
|
||||||
if re.MatchString(schedule) {
|
if re.MatchString(schedule) {
|
||||||
err := cfg.Box[v.Box()].ssh.exec(v.Path())
|
err := cfg.Box[v.Box()].SSHExec(v.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.ExecAfter : %s : Error executing %s on %s", a.Name, v.Path(), v.Box())
|
log.Printf("AppConfig.ExecAfter : %s : Error executing %s on %s", a.Name, v.Path(), v.Box())
|
||||||
@ -463,7 +463,7 @@ func (a AppConfig) TakeSnapshot(schedule string) error {
|
|||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.TakeSnapshot : %s : taking snapshot on %s for %s", a.Name, k, v)
|
log.Printf("AppConfig.TakeSnapshot : %s : taking snapshot on %s for %s", a.Name, k, v)
|
||||||
}
|
}
|
||||||
err := cfg.Box[k].ssh.exec("zfsnap snapshot -p " + schedule + "- -a " + cfg.Zfsnap[schedule] + v)
|
err := cfg.Box[k].SSHExec("zfsnap snapshot -p " + schedule + "- -a " + cfg.Zfsnap[schedule] + v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.TakeSnapshot : %s : Error executing zfsnap on %s", a.Name, k)
|
log.Printf("AppConfig.TakeSnapshot : %s : Error executing zfsnap on %s", a.Name, k)
|
||||||
@ -491,7 +491,7 @@ func (a AppConfig) RefreshSnapshot() error {
|
|||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.RefreshSnapshot : %s : refreshing snapshots for source %s", a.Name, k)
|
log.Printf("AppConfig.RefreshSnapshot : %s : refreshing snapshots for source %s", a.Name, k)
|
||||||
}
|
}
|
||||||
err := cfg.Box[k].ssh.getSnapshotList()
|
err := cfg.Box[k].ZFSUpdateSnapshotList()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.RefreshSnapshot : %s : Error getting snapshots on %s", a.Name, k)
|
log.Printf("AppConfig.RefreshSnapshot : %s : Error getting snapshots on %s", a.Name, k)
|
||||||
@ -512,12 +512,12 @@ func (a AppConfig) SendSnapshots() error {
|
|||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.SendSnapshots : %s : Sending snapshots from %s to %s", a.Name, string(src), string(dest))
|
log.Printf("AppConfig.SendSnapshots : %s : Sending snapshots from %s to %s", a.Name, string(src), string(dest))
|
||||||
}
|
}
|
||||||
dLastSnapshot, err := cfg.Box[dest.Box()].ssh.getLastSnapshot(dest.Path() + "/" + src.Box() + "/" + src.Path())
|
dLastSnapshot, err := cfg.Box[dest.Box()].ZFSGetLastSnapshot(dest.Path() + "/" + src.Box() + "/" + src.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.SendSnapshots : %s : No snapshot for %s on %s", a.Name, string(src), dest.Box())
|
log.Printf("AppConfig.SendSnapshots : %s : No snapshot for %s on %s", a.Name, string(src), dest.Box())
|
||||||
}
|
}
|
||||||
sFirstSnapshot, err := cfg.Box[src.Box()].ssh.getFirstSnapshot(src.Path())
|
sFirstSnapshot, err := cfg.Box[src.Box()].ZFSGetFirstSnapshot(src.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.SendSnapshots : %s : No snapshot for %s", a.Name, string(src))
|
log.Printf("AppConfig.SendSnapshots : %s : No snapshot for %s", a.Name, string(src))
|
||||||
@ -527,7 +527,7 @@ func (a AppConfig) SendSnapshots() error {
|
|||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.SendSnapshots : %s : Initializing snapshot on %s from %s", a.Name, dest.Box(), string(sFirstSnapshot))
|
log.Printf("AppConfig.SendSnapshots : %s : Initializing snapshot on %s from %s", a.Name, dest.Box(), string(sFirstSnapshot))
|
||||||
}
|
}
|
||||||
err = cfg.Box[dest.Box()].ssh.exec("ssh " + cfg.Box[src.Box()].User + "@" + src.Box() + " zfs send " + string(sFirstSnapshot) + " | zfs recv -F " + dest.Path() + "/" + src.Box() + "/" + src.Path())
|
err = cfg.Box[dest.Box()].SSHExec("ssh " + cfg.Box[src.Box()].User + "@" + src.Box() + " zfs send " + string(sFirstSnapshot) + " | zfs recv -F " + dest.Path() + "/" + src.Box() + "/" + src.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.SendSnapshots : %s : Initializing snapshot on %s from %s failed (%s)", a.Name, dest.Box(), string(sFirstSnapshot), err)
|
log.Printf("AppConfig.SendSnapshots : %s : Initializing snapshot on %s from %s failed (%s)", a.Name, dest.Box(), string(sFirstSnapshot), err)
|
||||||
@ -536,13 +536,13 @@ func (a AppConfig) SendSnapshots() error {
|
|||||||
}
|
}
|
||||||
var sCurrSnapshot Snapshot
|
var sCurrSnapshot Snapshot
|
||||||
sNextSnapshot := sFirstSnapshot
|
sNextSnapshot := sFirstSnapshot
|
||||||
for !cfg.Box[src.Box()].ssh.isLastSnapshot(sNextSnapshot) {
|
for !cfg.Box[src.Box()].ZFSIsLastSnapshot(sNextSnapshot) {
|
||||||
sCurrSnapshot = sNextSnapshot
|
sCurrSnapshot = sNextSnapshot
|
||||||
sNextSnapshot, err = cfg.Box[src.Box()].ssh.getNextSnapshot(sNextSnapshot)
|
sNextSnapshot, err = cfg.Box[src.Box()].ZFSGetNextSnapshot(sNextSnapshot)
|
||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.SendSnapshots : %s : Sending incrementally %s to %s", a.Name, string(sNextSnapshot), dest.Box())
|
log.Printf("AppConfig.SendSnapshots : %s : Sending incrementally %s to %s", a.Name, string(sNextSnapshot), dest.Box())
|
||||||
}
|
}
|
||||||
err = cfg.Box[dest.Box()].ssh.exec("ssh " + cfg.Box[src.Box()].User + "@" + src.Box() + " zfs send -I " + string(sCurrSnapshot) + " " + string(sNextSnapshot) + " | zfs recv " + dest.Path() + "/" + src.Box() + "/" + src.Path())
|
err = cfg.Box[dest.Box()].SSHExec("ssh " + cfg.Box[src.Box()].User + "@" + src.Box() + " zfs send -I " + string(sCurrSnapshot) + " " + string(sNextSnapshot) + " | zfs recv " + dest.Path() + "/" + src.Box() + "/" + src.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.SendSnapshots : %s : Sending snapshot on %s from %s failed (%s)", a.Name, dest.Box(), string(sNextSnapshot), err)
|
log.Printf("AppConfig.SendSnapshots : %s : Sending snapshot on %s from %s failed (%s)", a.Name, dest.Box(), string(sNextSnapshot), err)
|
||||||
@ -560,13 +560,13 @@ func (a AppConfig) SendSnapshots() error {
|
|||||||
}
|
}
|
||||||
var sCurrSnapshot Snapshot
|
var sCurrSnapshot Snapshot
|
||||||
sNextSnapshot := Snapshot(string(dLastSnapshot)[len(dest.Path())+len(src.Box())+2:])
|
sNextSnapshot := Snapshot(string(dLastSnapshot)[len(dest.Path())+len(src.Box())+2:])
|
||||||
for !cfg.Box[src.Box()].ssh.isLastSnapshot(sNextSnapshot) {
|
for !cfg.Box[src.Box()].ZFSIsLastSnapshot(sNextSnapshot) {
|
||||||
sCurrSnapshot = sNextSnapshot
|
sCurrSnapshot = sNextSnapshot
|
||||||
sNextSnapshot, err = cfg.Box[src.Box()].ssh.getNextSnapshot(sNextSnapshot)
|
sNextSnapshot, err = cfg.Box[src.Box()].ZFSGetNextSnapshot(sNextSnapshot)
|
||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.SendSnapshots : %s : Sending incrementally %s to %s", a.Name, string(sNextSnapshot), dest.Box())
|
log.Printf("AppConfig.SendSnapshots : %s : Sending incrementally %s to %s", a.Name, string(sNextSnapshot), dest.Box())
|
||||||
}
|
}
|
||||||
err = cfg.Box[dest.Box()].ssh.exec("ssh " + cfg.Box[src.Box()].User + "@" + src.Box() + " zfs send -I " + string(sCurrSnapshot) + " " + string(sNextSnapshot) + " | zfs recv " + dest.Path() + "/" + src.Box() + "/" + src.Path())
|
err = cfg.Box[dest.Box()].SSHExec("ssh " + cfg.Box[src.Box()].User + "@" + src.Box() + " zfs send -I " + string(sCurrSnapshot) + " " + string(sNextSnapshot) + " | zfs recv " + dest.Path() + "/" + src.Box() + "/" + src.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.SendSnapshots : %s : Sending snapshot on %s from %s failed (%s)", a.Name, dest.Box(), string(sNextSnapshot), err)
|
log.Printf("AppConfig.SendSnapshots : %s : Sending snapshot on %s from %s failed (%s)", a.Name, dest.Box(), string(sNextSnapshot), err)
|
||||||
@ -598,7 +598,7 @@ func (a AppConfig) CleanupSnapshot() error {
|
|||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.CleanupSnapshot : %s : cleaning snapshots on %s for%s", a.Name, k, v)
|
log.Printf("AppConfig.CleanupSnapshot : %s : cleaning snapshots on %s for%s", a.Name, k, v)
|
||||||
}
|
}
|
||||||
err := cfg.Box[k].ssh.exec("zfsnap destroy -p hourly- -p daily- -p weekly- -p monthly- -p yearly-" + v)
|
err := cfg.Box[k].SSHExec("zfsnap destroy -p hourly- -p daily- -p weekly- -p monthly- -p yearly-" + v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if *debugFlag {
|
if *debugFlag {
|
||||||
log.Printf("AppConfig.CleanupSnapshot : %s : Error executing zfsnap on %s", a.Name, k)
|
log.Printf("AppConfig.CleanupSnapshot : %s : Error executing zfsnap on %s", a.Name, k)
|
||||||
|
180
backup.go
180
backup.go
@ -1,32 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
Zfsnap map[string]string `json:"zfsnap"`
|
|
||||||
Box map[string]*BoxConfig `json:"box"`
|
|
||||||
Apps []AppConfig `json:apps`
|
|
||||||
Timezone string `json:"timezone"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type BoxConfig struct {
|
|
||||||
Addr string `json:"addr"`
|
|
||||||
User string `json:"user"`
|
|
||||||
Key string `json:"key"`
|
|
||||||
ssh *SSHConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
appFlag = flag.String("app", "", "run specific app")
|
appFlag = flag.String("app", "", "run specific app")
|
||||||
cfgFile = flag.String("config", "config.json", "config file")
|
cfgFile = flag.String("config", "config.json", "config file")
|
||||||
@ -37,165 +16,6 @@ var (
|
|||||||
cfg Config
|
cfg Config
|
||||||
)
|
)
|
||||||
|
|
||||||
//Load config from file
|
|
||||||
func (c *Config) Load() error {
|
|
||||||
if *debugFlag {
|
|
||||||
log.Printf("SSHConfig.Load : Start")
|
|
||||||
}
|
|
||||||
b, err := ioutil.ReadFile(*cfgFile)
|
|
||||||
if err != nil {
|
|
||||||
if *debugFlag {
|
|
||||||
log.Printf("Config.Load : ioutil.ReadFile(%s) : %s", *cfgFile, err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(b, &c)
|
|
||||||
if err != nil {
|
|
||||||
if *debugFlag {
|
|
||||||
log.Printf("Config.Load : json.Unmarshal : %s", err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range c.Box {
|
|
||||||
s := &SSHConfig{
|
|
||||||
logged: false,
|
|
||||||
name: k,
|
|
||||||
}
|
|
||||||
v.ssh = s
|
|
||||||
keyRaw, err := ioutil.ReadFile(v.Key)
|
|
||||||
if err != nil {
|
|
||||||
if *debugFlag {
|
|
||||||
log.Printf("Config.Load : ioutil.ReadFile(%s) : %s", k, err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
key, err := ssh.ParseRawPrivateKey(keyRaw)
|
|
||||||
if err != nil {
|
|
||||||
if *debugFlag {
|
|
||||||
log.Printf("Config.Load : ssh.ParseRawPrivateKey(%s) : %s", k, err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.signer, err = ssh.NewSignerFromKey(key)
|
|
||||||
if err != nil {
|
|
||||||
if *debugFlag {
|
|
||||||
log.Printf("Config.Load : ssh.NewSignerFromKey(%s) : %s", k, err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.config = &ssh.ClientConfig{
|
|
||||||
User: v.User,
|
|
||||||
Auth: []ssh.AuthMethod{
|
|
||||||
ssh.PublicKeys(s.signer),
|
|
||||||
},
|
|
||||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
|
||||||
}
|
|
||||||
|
|
||||||
s.client, err = ssh.Dial("tcp", v.Addr, s.config)
|
|
||||||
if err != nil {
|
|
||||||
if *debugFlag {
|
|
||||||
log.Printf("Config.Load : ssh.Dial(%s) : %s", k, err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
session, err := s.client.NewSession()
|
|
||||||
if err != nil {
|
|
||||||
if *debugFlag {
|
|
||||||
log.Printf("Config.Load : client.NewSession(%s) : %s", k, err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var b bytes.Buffer
|
|
||||||
session.Stdout = &b
|
|
||||||
|
|
||||||
err = session.Run("TZ=\"" + cfg.Timezone + "\" zfsnap --version")
|
|
||||||
if err != nil {
|
|
||||||
if *debugFlag {
|
|
||||||
log.Printf("Config.Load : client.NewSession(%s) : %s", k, err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if *debugFlag {
|
|
||||||
log.Printf("Config.Load : logged into %s : %s", k, b.String())
|
|
||||||
}
|
|
||||||
session.Close()
|
|
||||||
s.logged = true
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, box := range c.Box {
|
|
||||||
err = box.ssh.getTime()
|
|
||||||
if err != nil {
|
|
||||||
if *debugFlag {
|
|
||||||
log.Printf("Config.Load : ssh.getTime() : %s", err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, app := range c.Apps {
|
|
||||||
for _, src := range app.Sources {
|
|
||||||
if !src.Valid() {
|
|
||||||
return fmt.Errorf("Source not valid : %s", string(src))
|
|
||||||
}
|
|
||||||
if _, ok := cfg.Box[src.Box()]; !ok {
|
|
||||||
return fmt.Errorf("No box defined for source : %s", string(src))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, dest := range app.Destinations {
|
|
||||||
if !dest.Valid() {
|
|
||||||
return fmt.Errorf("Destination not valid : %s", string(dest))
|
|
||||||
}
|
|
||||||
if _, ok := cfg.Box[dest.Box()]; !ok {
|
|
||||||
return fmt.Errorf("No box defined for destination : %s", string(dest))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for val, before := range app.Before {
|
|
||||||
_, err = regexp.Compile(val)
|
|
||||||
if err != nil {
|
|
||||||
if *debugFlag {
|
|
||||||
log.Printf("Config.Load : invalid regex : %s", val)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !before.Valid() {
|
|
||||||
return fmt.Errorf("Before not valid : %s", string(before))
|
|
||||||
}
|
|
||||||
if _, ok := cfg.Box[before.Box()]; !ok {
|
|
||||||
return fmt.Errorf("No box defined for before : %s", string(before))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for val, after := range app.After {
|
|
||||||
_, err = regexp.Compile(val)
|
|
||||||
if err != nil {
|
|
||||||
if *debugFlag {
|
|
||||||
log.Printf("Config.Load : invalid regex : %s", val)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !after.Valid() {
|
|
||||||
return fmt.Errorf("After not valid : %s", string(after))
|
|
||||||
}
|
|
||||||
if _, ok := cfg.Box[after.Box()]; !ok {
|
|
||||||
return fmt.Errorf("No box defined for after : %s", string(after))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//Close config
|
|
||||||
func (c *Config) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
58
box.go
Normal file
58
box.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type Box struct {
|
||||||
|
Addr string `json:"addr"`
|
||||||
|
User string `json:"user"`
|
||||||
|
Key string `json:"key"`
|
||||||
|
ssh *SSHConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Box) ZFSGetLastSnapshot(path string) (s Snapshot, err error) {
|
||||||
|
return b.ssh.getLastSnapshot(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Box) ZFSIsLastSnapshot(s Snapshot) bool {
|
||||||
|
return b.ssh.isLastSnapshot(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Box) ZFSGetFirstSnapshot(path string) (s Snapshot, err error) {
|
||||||
|
return b.ssh.getFirstSnapshot(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Box) ZFSGetNextSnapshot(src Snapshot) (next Snapshot, err error) {
|
||||||
|
return b.ssh.getNextSnapshot(src)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Box) ZFSUpdateSnapshotList() (err error) {
|
||||||
|
return b.ssh.getSnapshotList()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Box) ZFSGetSnapshotList() []Snapshot {
|
||||||
|
return b.ssh.snapshot
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Box) ZFSUpdateList() (err error) {
|
||||||
|
return b.ssh.getZFSList()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Box) ZFSIsZFS(path string) bool {
|
||||||
|
return b.ssh.isZFS(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Box) ZFSCreateZFS(path string) (err error) {
|
||||||
|
return b.ssh.createZFS(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Box) GetTime() time.Time {
|
||||||
|
return b.ssh.now
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Box) UpdateTime() (err error) {
|
||||||
|
return b.ssh.getTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Box) SSHExec(cmd string) (err error) {
|
||||||
|
return b.ssh.exec(cmd)
|
||||||
|
}
|
178
config.go
Normal file
178
config.go
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Zfsnap map[string]string `json:"zfsnap"`
|
||||||
|
Box map[string]*Box `json:"box"`
|
||||||
|
Apps []AppConfig `json:apps`
|
||||||
|
Timezone string `json:"timezone"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//Load config from file
|
||||||
|
func (c *Config) Load() error {
|
||||||
|
if *debugFlag {
|
||||||
|
log.Printf("SSHConfig.Load : Start")
|
||||||
|
}
|
||||||
|
b, err := ioutil.ReadFile(*cfgFile)
|
||||||
|
if err != nil {
|
||||||
|
if *debugFlag {
|
||||||
|
log.Printf("Config.Load : ioutil.ReadFile(%s) : %s", *cfgFile, err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(b, &c)
|
||||||
|
if err != nil {
|
||||||
|
if *debugFlag {
|
||||||
|
log.Printf("Config.Load : json.Unmarshal : %s", err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range c.Box {
|
||||||
|
s := &SSHConfig{
|
||||||
|
logged: false,
|
||||||
|
name: k,
|
||||||
|
}
|
||||||
|
v.ssh = s
|
||||||
|
keyRaw, err := ioutil.ReadFile(v.Key)
|
||||||
|
if err != nil {
|
||||||
|
if *debugFlag {
|
||||||
|
log.Printf("Config.Load : ioutil.ReadFile(%s) : %s", k, err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := ssh.ParseRawPrivateKey(keyRaw)
|
||||||
|
if err != nil {
|
||||||
|
if *debugFlag {
|
||||||
|
log.Printf("Config.Load : ssh.ParseRawPrivateKey(%s) : %s", k, err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.signer, err = ssh.NewSignerFromKey(key)
|
||||||
|
if err != nil {
|
||||||
|
if *debugFlag {
|
||||||
|
log.Printf("Config.Load : ssh.NewSignerFromKey(%s) : %s", k, err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.config = &ssh.ClientConfig{
|
||||||
|
User: v.User,
|
||||||
|
Auth: []ssh.AuthMethod{
|
||||||
|
ssh.PublicKeys(s.signer),
|
||||||
|
},
|
||||||
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||||
|
}
|
||||||
|
|
||||||
|
s.client, err = ssh.Dial("tcp", v.Addr, s.config)
|
||||||
|
if err != nil {
|
||||||
|
if *debugFlag {
|
||||||
|
log.Printf("Config.Load : ssh.Dial(%s) : %s", k, err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
session, err := s.client.NewSession()
|
||||||
|
if err != nil {
|
||||||
|
if *debugFlag {
|
||||||
|
log.Printf("Config.Load : client.NewSession(%s) : %s", k, err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
session.Stdout = &b
|
||||||
|
|
||||||
|
err = session.Run("TZ=\"" + cfg.Timezone + "\" zfsnap --version")
|
||||||
|
if err != nil {
|
||||||
|
if *debugFlag {
|
||||||
|
log.Printf("Config.Load : client.NewSession(%s) : %s", k, err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if *debugFlag {
|
||||||
|
log.Printf("Config.Load : logged into %s : %s", k, b.String())
|
||||||
|
}
|
||||||
|
session.Close()
|
||||||
|
s.logged = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, box := range c.Box {
|
||||||
|
err = box.ssh.getTime()
|
||||||
|
if err != nil {
|
||||||
|
if *debugFlag {
|
||||||
|
log.Printf("Config.Load : ssh.getTime() : %s", err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, app := range c.Apps {
|
||||||
|
for _, src := range app.Sources {
|
||||||
|
if !src.Valid() {
|
||||||
|
return fmt.Errorf("Source not valid : %s", string(src))
|
||||||
|
}
|
||||||
|
if _, ok := cfg.Box[src.Box()]; !ok {
|
||||||
|
return fmt.Errorf("No box defined for source : %s", string(src))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, dest := range app.Destinations {
|
||||||
|
if !dest.Valid() {
|
||||||
|
return fmt.Errorf("Destination not valid : %s", string(dest))
|
||||||
|
}
|
||||||
|
if _, ok := cfg.Box[dest.Box()]; !ok {
|
||||||
|
return fmt.Errorf("No box defined for destination : %s", string(dest))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for val, before := range app.Before {
|
||||||
|
_, err = regexp.Compile(val)
|
||||||
|
if err != nil {
|
||||||
|
if *debugFlag {
|
||||||
|
log.Printf("Config.Load : invalid regex : %s", val)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !before.Valid() {
|
||||||
|
return fmt.Errorf("Before not valid : %s", string(before))
|
||||||
|
}
|
||||||
|
if _, ok := cfg.Box[before.Box()]; !ok {
|
||||||
|
return fmt.Errorf("No box defined for before : %s", string(before))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for val, after := range app.After {
|
||||||
|
_, err = regexp.Compile(val)
|
||||||
|
if err != nil {
|
||||||
|
if *debugFlag {
|
||||||
|
log.Printf("Config.Load : invalid regex : %s", val)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !after.Valid() {
|
||||||
|
return fmt.Errorf("After not valid : %s", string(after))
|
||||||
|
}
|
||||||
|
if _, ok := cfg.Box[after.Box()]; !ok {
|
||||||
|
return fmt.Errorf("No box defined for after : %s", string(after))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//Close config
|
||||||
|
func (c *Config) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
3
generate.go
Normal file
3
generate.go
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
//go:generate bash ./version.sh
|
6
version.go
Normal file
6
version.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Code generated by version.sh (@generated) DO NOT EDIT.
|
||||||
|
package main
|
||||||
|
var githash = "0f4fca3"
|
||||||
|
var buildstamp = "2021-11-14_02:51:24"
|
||||||
|
var commits = "17"
|
||||||
|
var version = "0f4fca3-b17 - 2021-11-14_02:51:24"
|
13
version.sh
Normal file
13
version.sh
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Get the version.
|
||||||
|
githash=`git rev-parse --short HEAD`
|
||||||
|
buildstamp=`date -u '+%Y-%m-%d_%H:%M:%S'`
|
||||||
|
commits=`git rev-list --count master`
|
||||||
|
# Write out the package.
|
||||||
|
cat << EOF > version.go
|
||||||
|
// Code generated by version.sh (@generated) DO NOT EDIT.
|
||||||
|
package main
|
||||||
|
var githash = "$githash"
|
||||||
|
var buildstamp = "$buildstamp"
|
||||||
|
var commits = "$commits"
|
||||||
|
var version = "$githash-b$commits - $buildstamp"
|
||||||
|
EOF
|
Loading…
Reference in New Issue
Block a user