initial commit
This commit is contained in:
+221
@@ -0,0 +1,221 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func GetLocalNode() NodeInfo {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
return cfg.Node
|
||||
}
|
||||
|
||||
func UpdateLocalNode(n NodeInfo) error {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if n.Hostname != "" {
|
||||
cfg.Node.Hostname = n.Hostname
|
||||
}
|
||||
if n.Description != "" {
|
||||
cfg.Node.Description = n.Description
|
||||
}
|
||||
if n.ResticPassword != "" {
|
||||
cfg.Node.ResticPassword = n.ResticPassword
|
||||
}
|
||||
return persist()
|
||||
}
|
||||
|
||||
// GetResticPassword returns the node-wide restic repository password used to
|
||||
// encrypt/decrypt every restic backup target on this node.
|
||||
func GetResticPassword() string {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
return cfg.Node.ResticPassword
|
||||
}
|
||||
|
||||
func GetUpdateHistory() []UpdateRecord {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
result := make([]UpdateRecord, len(cfg.Node.UpdateHistory))
|
||||
copy(result, cfg.Node.UpdateHistory)
|
||||
return result
|
||||
}
|
||||
|
||||
func GetUpdateRecord(id string) (UpdateRecord, error) {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
for _, r := range cfg.Node.UpdateHistory {
|
||||
if r.ID == id {
|
||||
return r, nil
|
||||
}
|
||||
}
|
||||
return UpdateRecord{}, errors.New("update record not found")
|
||||
}
|
||||
|
||||
func AddUpdateRecord(r UpdateRecord) (UpdateRecord, error) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
r.ID = fmt.Sprintf("upd_%d", time.Now().UnixNano())
|
||||
r.Timestamp = time.Now().UTC()
|
||||
cfg.Node.UpdateHistory = append(cfg.Node.UpdateHistory, r)
|
||||
return r, persist()
|
||||
}
|
||||
|
||||
func DeleteUpdateRecord(id string) error {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
for i, r := range cfg.Node.UpdateHistory {
|
||||
if r.ID == id {
|
||||
cfg.Node.UpdateHistory = append(cfg.Node.UpdateHistory[:i], cfg.Node.UpdateHistory[i+1:]...)
|
||||
return persist()
|
||||
}
|
||||
}
|
||||
return errors.New("update record not found")
|
||||
}
|
||||
|
||||
func GetNodeBackupConfig() BackupConfig {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
return cfg.Node.Backup
|
||||
}
|
||||
|
||||
func UpdateNodeBackupConfig(bc BackupConfig) error {
|
||||
mu.Lock()
|
||||
history := cfg.Node.Backup.History
|
||||
cfg.Node.Backup = bc
|
||||
cfg.Node.Backup.History = history
|
||||
err := persist()
|
||||
mu.Unlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
SyncSchedule()
|
||||
return nil
|
||||
}
|
||||
|
||||
func AppendNodeBackupExecution(ex BackupExecution) error {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
cfg.Node.Backup.History = append(cfg.Node.Backup.History, ex)
|
||||
now := time.Now().UTC()
|
||||
cfg.Node.Backup.LastRun = &now
|
||||
for i, t := range cfg.Node.Backup.Targets {
|
||||
if t.ID == ex.TargetID {
|
||||
cfg.Node.Backup.Targets[i].LastRun = &now
|
||||
break
|
||||
}
|
||||
}
|
||||
return persist()
|
||||
}
|
||||
|
||||
// GetNodeBackupTargets lists the node's individual backup target definitions.
|
||||
func GetNodeBackupTargets() []BackupTarget {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
result := make([]BackupTarget, len(cfg.Node.Backup.Targets))
|
||||
copy(result, cfg.Node.Backup.Targets)
|
||||
return result
|
||||
}
|
||||
|
||||
// GetNodeBackupTarget returns a single node backup target by ID.
|
||||
func GetNodeBackupTarget(tid string) (BackupTarget, error) {
|
||||
mu.RLock()
|
||||
defer mu.RUnlock()
|
||||
for _, t := range cfg.Node.Backup.Targets {
|
||||
if t.ID == tid {
|
||||
return t, nil
|
||||
}
|
||||
}
|
||||
return BackupTarget{}, errors.New("backup target not found")
|
||||
}
|
||||
|
||||
// AddNodeBackupTarget creates a new backup target definition for the node.
|
||||
func AddNodeBackupTarget(t BackupTarget) (BackupTarget, error) {
|
||||
if err := validateBackupTarget(t); err != nil {
|
||||
return BackupTarget{}, err
|
||||
}
|
||||
mu.Lock()
|
||||
t.ID = fmt.Sprintf("bt_%d", time.Now().UnixNano())
|
||||
cfg.Node.Backup.Targets = append(cfg.Node.Backup.Targets, t)
|
||||
err := persist()
|
||||
mu.Unlock()
|
||||
if err != nil {
|
||||
return BackupTarget{}, err
|
||||
}
|
||||
SyncSchedule()
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// UpdateNodeBackupTarget replaces an existing node backup target definition.
|
||||
func UpdateNodeBackupTarget(tid string, t BackupTarget) (BackupTarget, error) {
|
||||
if err := validateBackupTarget(t); err != nil {
|
||||
return BackupTarget{}, err
|
||||
}
|
||||
mu.Lock()
|
||||
found := false
|
||||
for i, existing := range cfg.Node.Backup.Targets {
|
||||
if existing.ID == tid {
|
||||
t.ID = tid
|
||||
t.LastRun = existing.LastRun
|
||||
cfg.Node.Backup.Targets[i] = t
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
mu.Unlock()
|
||||
return BackupTarget{}, errors.New("backup target not found")
|
||||
}
|
||||
err := persist()
|
||||
mu.Unlock()
|
||||
if err != nil {
|
||||
return BackupTarget{}, err
|
||||
}
|
||||
SyncSchedule()
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// DeleteNodeBackupTarget removes a node backup target definition.
|
||||
func DeleteNodeBackupTarget(tid string) error {
|
||||
mu.Lock()
|
||||
found := false
|
||||
for i, t := range cfg.Node.Backup.Targets {
|
||||
if t.ID == tid {
|
||||
cfg.Node.Backup.Targets = append(cfg.Node.Backup.Targets[:i], cfg.Node.Backup.Targets[i+1:]...)
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
mu.Unlock()
|
||||
return errors.New("backup target not found")
|
||||
}
|
||||
err := persist()
|
||||
mu.Unlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
SyncSchedule()
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunNodeBackup runs the node's backup for the given target IDs (nil/empty
|
||||
// means all targets), appending an execution record per target.
|
||||
func RunNodeBackup(targetIDs []string) error {
|
||||
bc := GetNodeBackupConfig()
|
||||
targets := filterTargets(bc.Targets, targetIDs)
|
||||
if len(targets) == 0 {
|
||||
return errors.New("no matching backup targets")
|
||||
}
|
||||
sourcePath := bc.SourcePath
|
||||
if sourcePath == "" {
|
||||
sourcePath = ConfigPath()
|
||||
}
|
||||
results := RunBackup("node", targets, sourcePath)
|
||||
for _, ex := range results {
|
||||
_ = AppendNodeBackupExecution(ex)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user