Fix problem of run database

This commit is contained in:
Marcel M. Otte 2023-03-17 09:56:58 +01:00
parent 559e7f72b3
commit a78b11ad5d
9 changed files with 186 additions and 24 deletions

121
backive.puml Normal file
View File

@ -0,0 +1,121 @@
@startuml
namespace backive {
class Backup << (S,Aquamarine) >> {
- logger *log.Logger
+ Name string
+ TargetDevice string
+ TargetPath string
+ SourcePath string
+ ScriptPath <font color=blue>interface</font>{}
+ Frequency int
+ ExeUser string
+ Label string
+ CanRun() error
+ PrepareRun() error
+ Run() error
+ ShouldRun() bool
}
class Backups << (S,Aquamarine) >> {
+ FindBackupsForDevice(d Device) ([]*Backup, bool)
}
class Configuration << (S,Aquamarine) >> {
+ Settings Settings
+ Devices Devices
+ Backups Backups
+ Vconfig *viper.Viper
+ CreateViper()
+ Load()
}
class Database << (S,Aquamarine) >> {
- data <font color=blue>map</font>[string]<font color=blue>interface</font>{}
+ Save()
+ Load()
}
class Device << (S,Aquamarine) >> {
- isMounted bool
+ Name string
+ UUID string
+ OwnerUser string
+ Mount() error
+ Unmount() error
+ IsMounted() bool
}
class EventHandler << (S,Aquamarine) >> {
- ls net.Listener
- callbacks []<font color=blue>func</font>(<font color=blue>map</font>[string]string)
- process()
+ Init(socketPath string) error
+ Listen()
+ RegisterCallback(cb <font color=blue>func</font>(<font color=blue>map</font>[string]string) )
}
class MsgLvls << (S,Aquamarine) >> {
+ Error MsgLevel
+ Finish MsgLevel
+ Remind MsgLevel
+ Info MsgLevel
+ Debug MsgLevel
}
class Runs << (S,Aquamarine) >> {
- data <font color=blue>map</font>[string][]time.Time
+ Load(db Database)
+ Save(db Database)
+ RegisterRun(b *Backup)
+ LastRun(b *Backup) (time.Time, error)
}
class Settings << (S,Aquamarine) >> {
+ SystemMountPoint string
+ UserMountPoint string
+ UnixSocketLocation string
+ UIUnixSocketLocation string
+ LogLocation string
+ DbLocation string
}
class UIHandler << (S,Aquamarine) >> {
- ls net.Listener
- client net.Conn
+ Init(socketPath string) error
+ Listen()
+ DisplayMessage(header string, message string, level MsgLevel) error
}
class backive.Backups << (T, #FF7700) >> {
}
class backive.Devices << (T, #FF7700) >> {
}
class backive.MsgLevel << (T, #FF7700) >> {
}
}
namespace ui {
class uiSettings << (S,Aquamarine) >> {
- hideUntil time.Time
- globalLevel int
}
}
"__builtin__.int" #.. "backive.MsgLevel"
"backive.<font color=blue>map</font>[string]*Backup" #.. "backive.Backups"
"backive.<font color=blue>map</font>[string]*Device" #.. "backive.Devices"
@enduml

View File

@ -110,9 +110,7 @@ func (b *Backup) Run() error {
scriptWArgs = append(scriptWArgs, v.(string))
}
case []string:
for _, v := range slice {
scriptWArgs = append(scriptWArgs, v)
}
scriptWArgs = append(scriptWArgs, slice...)
case string:
scriptWArgs = append(scriptWArgs, slice)
default:
@ -173,24 +171,53 @@ type Runs struct {
// Load loads the data from the json database
func (r *Runs) Load(db Database) {
data := db.data["runs"]
if data != "" {
runerr := json.Unmarshal([]byte(db.data["runs"]), &r.data)
if runerr != nil {
panic(runerr)
if data != nil {
log.Println("Loading runs db")
switch d := data.(type) {
case string:
// be able to read the old version
log.Println("Loading legacy data")
runerr := json.Unmarshal([]byte(data.(string)), &r.data)
if runerr != nil {
panic(runerr)
}
case map[string]interface{}:
log.Println("Loading data")
if r.data == nil {
r.data = make(map[string][]time.Time)
}
raw := data.(map[string]interface{})
for k, v := range raw {
r.data[k] = make([]time.Time, 0)
for _, i := range v.([]interface{}) {
t, _ := time.Parse(time.RFC3339Nano, i.(string))
r.data[k] = append(r.data[k], t)
}
}
LogToJson(data)
default:
log.Printf("got data type: %s", d)
}
}
log.Println("Data loaded:")
LogToJson(r.data)
}
// Save saves the data into the json database
func (r *Runs) Save(db Database) {
if db.data == nil {
db.data = map[string]string{}
db.data = map[string]interface{}{}
}
str, err := json.Marshal(r.data)
db.data["runs"] = r.data
LogToJson(db.data)
}
func LogToJson(data interface{}) {
str, err := json.Marshal(data)
if err != nil {
panic(err)
}
db.data["runs"] = string(str)
log.Printf("Data: %s", str)
}
// ShouldRun Takes a backup key and returns a bool if a backup should run now.
@ -208,17 +235,21 @@ func (b *Backup) ShouldRun() bool {
if freq == 0 {
return true
}
if ok != nil && lr.Equal(time.Unix(0, 0)) {
return true
}
return false
}
// RegisterRun saves a date of a backup run into the internal storage
func (r *Runs) RegisterRun(b *Backup) {
if r.data == nil {
r.data = map[string][]time.Time{}
x := map[string][]time.Time{}
r.data = x
}
nbl, ok := r.data[b.Name]
if !ok {
nbl = make([]time.Time, 1)
nbl = make([]time.Time, 0)
}
nbl = append([]time.Time{time.Now()}, nbl...)
r.data[b.Name] = nbl

View File

@ -170,3 +170,5 @@ func TestRun(t *testing.T) {
return nil
}
}
// TODO: write a test for the lastRun method!

View File

@ -55,14 +55,19 @@ func defaultCallback(envMap map[string]string) {
log.Printf("Device: Name: %s, UUID: %s", dev.Name, dev.UUID)
backups, found := config.Backups.FindBackupsForDevice(*dev)
log.Println("Searching configured backups...")
bnames := make([]string, 0)
for _, v := range backups {
bnames = append(bnames, v.Name)
}
log.Printf("Found backups: %s", bnames)
if found {
// only mount device if we really have to do a backup!
dev.Mount()
log.Println("Device mounted.")
for _, backup := range backups {
log.Printf("Backup found: %s", backup.Name)
log.Printf("Backup running: %s", backup.Name)
err := backup.CanRun()
if err == nil {
// only mount device if we really have to do a backup!
dev.Mount()
log.Println("Device mounted.")
log.Println("Backup is able to run (config check passed).")
prepErr := backup.PrepareRun()
log.Println("Prepared run.")

View File

@ -70,12 +70,12 @@ func (c *Configuration) Load() {
panic("No configuration available!")
}
for k, v := range c.Backups {
log.Printf("Initializing backup '%s'\n", k)
//log.Printf("Initializing backup '%s'\n", k)
v.Name = k
log.Printf("Initialized backup '%s'\n", v.Name)
}
for k, v := range c.Devices {
log.Printf("Initializing device '%s'\n", k)
//log.Printf("Initializing device '%s'\n", k)
v.Name = k
log.Printf("Initialized device '%s'\n", v.Name)
}

View File

@ -12,7 +12,7 @@ var mockOsReadFile = os.ReadFile
// Database is a simple string to string mapping, where arbitrary strings can be stored and safed to disk or loaded
type Database struct {
data map[string]string
data map[string]interface{}
}
var dbPath = "/var/lib/backive/data.json"
@ -40,7 +40,8 @@ func (d *Database) Load() {
panic(rferr)
}
json.Unmarshal(data, &d.data)
} /*else if os.IsNotExist(err) {
// no data
}*/
} else if os.IsNotExist(err) {
// initialize db
d.data = make(map[string]interface{})
}
}

2
go.mod
View File

@ -48,5 +48,3 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 // indirect
)
replace github.com/qwc/backive => ./

3
go.work Normal file
View File

@ -0,0 +1,3 @@
go 1.19
use .

1
go.work.sum Normal file
View File

@ -0,0 +1 @@
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=