added restic mount, waits for Ctrl+C to unmount

This commit is contained in:
Paul Wilde 2024-08-23 12:04:27 +01:00
parent 88492d5c85
commit 02f8c0f98b
18 changed files with 63 additions and 51 deletions

View file

@ -10,10 +10,10 @@ import extract
proc initRepo(nc: NorgConfig, repo: Repository): int = proc initRepo(nc: NorgConfig, repo: Repository): int =
return runDiscard genCommand(cmd = "init", repo = repo.path, others = nc.args.others) return runDiscard genCommand(cmd = "init", repo = repo.path, further_args = nc.args.further_args)
proc listArchives(nc: NorgConfig, repo: Repository): int = proc listArchives(nc: NorgConfig, repo: Repository): int =
return run genCommand(cmd = "list", repo = repo.path, others = nc.args.others) return run genCommand(cmd = "list", repo = repo.path, further_args = nc.args.further_args)
proc compactRepo(nc: NorgConfig, repo: Repository): int = proc compactRepo(nc: NorgConfig, repo: Repository): int =
echo "Not Yet Implemented." echo "Not Yet Implemented."
@ -26,23 +26,29 @@ proc checkRepo(nc: NorgConfig, repo: Repository): int =
proc execute*(nc: NorgConfig, repo: Repository) = proc execute*(nc: NorgConfig, repo: Repository) =
case nc.args.command case nc.args.command
of INIT: of INIT:
echo "Initializing repo: ", repo.label
discard initRepo(nc, repo) discard initRepo(nc, repo)
of CREATE: of CREATE:
run_actions(norg_config.actions.before_backup) run_actions(norg_config.actions.before_backup)
echo "Creating archive on ", repo.label
discard createBackup(nc, repo) discard createBackup(nc, repo)
run_actions(norg_config.actions.after_backup) run_actions(norg_config.actions.after_backup)
of LIST: of LIST:
echo "Listing Archives on ", repo.label
discard listArchives(nc, repo) discard listArchives(nc, repo)
of MOUNT: of MOUNT:
echo "Mounting Archive from ", repo.label
discard mountArchive(nc, repo) discard mountArchive(nc, repo)
of UMOUNT: of UMOUNT:
discard unmountArchive(nc) discard unmountArchive(nc)
of EXTRACT: of EXTRACT:
run_actions(norg_config.actions.before_extract) run_actions(norg_config.actions.before_extract)
echo "Extracting archive from ", repo.label
discard extractArchive(nc, repo) discard extractArchive(nc, repo)
run_actions(norg_config.actions.after_extract) run_actions(norg_config.actions.after_extract)
of PRUNE: of PRUNE:
run_actions(norg_config.actions.before_prune) run_actions(norg_config.actions.before_prune)
echo "Pruning repo: ", repo.label
discard pruneRepo(nc, repo) discard pruneRepo(nc, repo)
run_actions(norg_config.actions.after_prune) run_actions(norg_config.actions.after_prune)
of COMPACT: of COMPACT:

View file

@ -17,8 +17,8 @@ proc genArchiveName(): string =
return fmt"{hostname}-{ts}" return fmt"{hostname}-{ts}"
proc createArchive(nc: NorgConfig, repo: Repository, archivename: string, retry: int = 0): int = proc createArchive(nc: NorgConfig, repo: Repository, archivename: string, retry: int = 0): int =
let others = concat(nc.source_directories, nc.args.others) let further_args = concat(nc.source_directories, nc.args.further_args)
let res = run genCommand(cmd = "create", repo = archivename, others = others) let res = run genCommand(cmd = "create", repo = archivename, further_args = further_args)
if res != 0: if res != 0:
sleep 15 * 1000 # 15 seconds sleep 15 * 1000 # 15 seconds
if retry == nc.retries: if retry == nc.retries:

View file

@ -5,8 +5,8 @@ import ../model/command_type
import ../utils/run import ../utils/run
export run export run
proc genCommand*(cmd: string, repo: string, others: seq[string]): string = proc genCommand*(cmd: string, repo: string, further_args: seq[string]): string =
let args = others.join(" ") let args = further_args.join(" ")
let cmd = fmt"{BORG_BIN} {cmd} {repo} {args}" let cmd = fmt"{BORG_BIN} {cmd} {repo} {args}"
return cmd return cmd

View file

@ -10,15 +10,15 @@ proc isEmpty(dir: string): bool =
return count == 0 return count == 0
proc extractArchive*(nc: NorgConfig, repo: Repository): int = proc extractArchive*(nc: NorgConfig, repo: Repository): int =
let archive = fmt"{repo.path}::{nc.args.others[0]}" let archive = fmt"{repo.path}::{nc.args.further_args[0]}"
var others = nc.args.others[1..^1] var further_args = nc.args.further_args[1..^1]
if nc.args.extract_destination != "": if nc.args.extract_destination != "":
discard existsOrCreateDir(nc.args.extract_destination) discard existsOrCreateDir(nc.args.extract_destination)
setCurrentDir(nc.args.extract_destination) setCurrentDir(nc.args.extract_destination)
let dir = getCurrentDir() let dir = getCurrentDir()
if dir.isEmpty(): if dir.isEmpty():
echo "Restoring..." echo "Restoring..."
let ok = run genCommand(cmd = "extract", repo = archive, others = others) let ok = run genCommand(cmd = "extract", repo = archive, further_args = further_args)
return ok return ok
else: else:
echo "Not restoring to non-empty destination\r\nPlease use the --destination flag" echo "Not restoring to non-empty destination\r\nPlease use the --destination flag"

View file

@ -3,17 +3,17 @@ import execute
import strformat import strformat
proc mountArchive*(nc: NorgConfig, repo: Repository): int = proc mountArchive*(nc: NorgConfig, repo: Repository): int =
let archive = repo.path & "::" & nc.args.others[0] let archive = repo.path & "::" & nc.args.further_args[0]
let others = nc.args.others[1..^1] let further_args = nc.args.further_args[1..^1]
let ok = runDiscard genCommand(cmd = "mount", repo = archive, others = others) let ok = runDiscard genCommand(cmd = "mount", repo = archive, further_args = further_args)
if ok == 0: if ok == 0:
echo fmt"Mounted {archive} at {others[0]}" echo fmt"Mounted {archive} at {further_args[0]}"
else: else:
echo "Failed to mount ", archive echo "Failed to mount ", archive
proc unmountArchive*(nc: NorgConfig): int = proc unmountArchive*(nc: NorgConfig): int =
let ok = runDiscard genCommand(cmd = "umount", repo = "", others = nc.args.others) let ok = runDiscard genCommand(cmd = "umount", repo = "", further_args = nc.args.further_args)
if ok == 0: if ok == 0:
echo "Unmounted ", nc.args.others[0] echo "Unmounted ", nc.args.further_args[0]
else: else:
echo "Failed to unmount ", nc.args.others[0] echo "Failed to unmount ", nc.args.further_args[0]

View file

@ -14,6 +14,6 @@ proc addPruneOptions(cmd: var string, maintenance: Maintenance) =
""" """
proc pruneRepo*(nc: NorgConfig, repo: Repository): int = proc pruneRepo*(nc: NorgConfig, repo: Repository): int =
var cmd = genCommand(cmd = "prune", repo = repo.path, others = nc.args.others) var cmd = genCommand(cmd = "prune", repo = repo.path, further_args = nc.args.further_args)
cmd.addPruneOptions(nc.maintenance) cmd.addPruneOptions(nc.maintenance)
return run cmd return run cmd

View file

@ -6,23 +6,26 @@ type
config_file*: string config_file*: string
extract_destination*: string extract_destination*: string
command*: Command command*: Command
others*: seq[string] repository*: string
further_args*: seq[string]
var norg_args*: NorgArgs = NorgArgs() var norg_args*: NorgArgs = NorgArgs()
proc parseArgs*() = proc parseArgs*() =
var p = newParser: var p = newParser:
help("Norg\r\nA portable borg backup wrapper utility") help("Norg\r\nA portable borg backup wrapper utility")
option("-c", "--config", help="Config file to use", required = true) option("-c", "--config", help="Config file to use.", required = true)
option("-d", "--destination", help="Destination when extracting backup", required = false) option("-d", "--destination", help="Destination when extracting backup", required = false)
arg("borg_cmd", default=some("list")) option("-r", "--repository", help="Define an explicit repository to work on by either label or path.", required = false)
arg("others", nargs = -1) arg("command", help="The command to run, defaults to 'create' which will perform a backup.", default=some("create"))
arg("further_args", nargs = -1, help="Any further arguments to send onto borg or restic.")
try: try:
var opts = p.parse(commandLineParams()) var opts = p.parse(commandLineParams())
norg_args.config_file = opts.config norg_args.config_file = opts.config
norg_args.extract_destination = opts.destination norg_args.extract_destination = opts.destination
norg_args.command = opts.borg_cmd.toCommand() norg_args.command = opts.command.toCommand()
norg_args.others = opts.others norg_args.repository = opts.repository
norg_args.further_args = opts.further_args
except ShortCircuit as err: except ShortCircuit as err:
if err.flag == "argparse_help": if err.flag == "argparse_help":

View file

@ -16,7 +16,6 @@ proc parseSourceDirectories*(in_conf: TomlValueRef): seq[string] =
norg_config.source_directories.add(dir.getStr()) norg_config.source_directories.add(dir.getStr())
return src_dirs return src_dirs
proc parseRepositories*(rep_conf: TomlValueRef): seq[Repository] = proc parseRepositories*(rep_conf: TomlValueRef): seq[Repository] =
var repos: seq[Repository] = @[] var repos: seq[Repository] = @[]
for r in rep_conf.getElems(): for r in rep_conf.getElems():
@ -27,7 +26,8 @@ proc parseRepositories*(rep_conf: TomlValueRef): seq[Repository] =
if rtable.hasKey("tool"): if rtable.hasKey("tool"):
repo.tool = rtable["tool"].getStr("borg").toBackupTool() repo.tool = rtable["tool"].getStr("borg").toBackupTool()
repos.add(repo) repos.add(repo)
echo repos if norg_config.args.repository != "":
repos = repos.findRepository(norg_config.args.repository)
return repos return repos
proc parseEncryption*(enc_conf: TomlValueRef) = proc parseEncryption*(enc_conf: TomlValueRef) =
@ -36,7 +36,6 @@ proc parseEncryption*(enc_conf: TomlValueRef) =
setEncryptionPassphraseFile(enc_conf{"encryption_passphrase_file"}.getStr("")) setEncryptionPassphraseFile(enc_conf{"encryption_passphrase_file"}.getStr(""))
setEncryptionPassCommand(enc_conf{"encryption_passcommand"}.getStr("")) setEncryptionPassCommand(enc_conf{"encryption_passcommand"}.getStr(""))
proc parseConfigFile*(file: string): NorgConfig = proc parseConfigFile*(file: string): NorgConfig =
norg_config = newNorgConfig() norg_config = newNorgConfig()
let in_conf = parsetoml.parseFile(file) let in_conf = parsetoml.parseFile(file)

View file

@ -1,8 +1,8 @@
import notifier_type import notifier_type
import uptimekuma_type import ../notifier/uptimekuma_notifier
export notifier_type export notifier_type
export uptimekuma_type export uptimekuma_notifier
type type
Notifiers* = object Notifiers* = object

View file

@ -1,3 +1,4 @@
import sugar
import tool_type import tool_type
export tool_type export tool_type
@ -8,3 +9,9 @@ type
label*: string label*: string
tool*: BackupTool tool*: BackupTool
proc findRepository*(repos: seq[Repository], r: string): seq[Repository] =
let repo = collect:
for item in repos:
if item.label == r or item.path == r:
item
return repo

View file

@ -1,5 +1,5 @@
import state_type import ../model/state_type
import notifier_type import ../model/notifier_type
import strformat import strformat
import ../utils/httprequest import ../utils/httprequest

View file

@ -10,8 +10,8 @@ import sequtils
import os import os
proc createArchive(nc: NorgConfig, repo: Repository, retry: int = 0): int = proc createArchive(nc: NorgConfig, repo: Repository, retry: int = 0): int =
let others = concat(nc.source_directories, nc.args.others) let further_args = concat(nc.source_directories, nc.args.further_args)
let res = run genCommand(cmd = "backup", repo = repo.path, others = others) let res = run genCommand(cmd = "backup", repo = repo.path, further_args = further_args)
if res != 0: if res != 0:
sleep 15 * 1000 # 15 seconds sleep 15 * 1000 # 15 seconds
if retry == nc.retries: if retry == nc.retries:

View file

@ -5,8 +5,8 @@ import ../model/command_type
import ../utils/run import ../utils/run
export run export run
proc genCommand*(cmd: string, repo: string, others: seq[string]): string = proc genCommand*(cmd: string, repo: string, further_args: seq[string]): string =
let args = others.join(" ") let args = further_args.join(" ")
let cmd = fmt"{RESTIC_BIN} {cmd} -r {repo} {args}" let cmd = fmt"{RESTIC_BIN} {cmd} -r {repo} {args}"
return cmd return cmd

View file

@ -2,5 +2,5 @@ import ../model/config_type
import execute import execute
proc initRepo*(nc: NorgConfig, repo: Repository): int = proc initRepo*(nc: NorgConfig, repo: Repository): int =
return runDiscard genCommand(cmd = "init", repo = repo.path, others = nc.args.others) return runDiscard genCommand(cmd = "init", repo = repo.path, further_args = nc.args.further_args)

View file

@ -2,6 +2,6 @@ import ../model/config_type
import execute import execute
proc listSnapshots*(nc: NorgConfig, repo: Repository): int = proc listSnapshots*(nc: NorgConfig, repo: Repository): int =
return run genCommand(cmd = "snapshots", repo = repo.path, others = nc.args.others) return run genCommand(cmd = "snapshots", repo = repo.path, further_args = nc.args.further_args)

View file

@ -3,17 +3,10 @@ import execute
import strformat import strformat
proc mountSnapshot*(nc: NorgConfig, repo: Repository): int = proc mountSnapshot*(nc: NorgConfig, repo: Repository): int =
let snapshot = repo.path & "::" & nc.args.others[0] #let further_args = nc.args.further_args[1..^1]
let others = nc.args.others[1..^1] let further_args = nc.args.further_args
let ok = runDiscard genCommand(cmd = "mount", repo = snapshot, others = others) let ok = runDiscard genCommand(cmd = "mount", repo = repo.path, further_args = further_args)
if ok == 0: if ok == 0:
echo fmt"Mounted {snapshot} at {others[0]}" echo fmt"Mounted {repo.path} at {further_args[0]}"
else: else:
echo "Failed to mount ", snapshot echo "Failed to mount ", repo.path
proc unmountSnapshot*(nc: NorgConfig): int =
let ok = runDiscard genCommand(cmd = "umount", repo = "", others = nc.args.others)
if ok == 0:
echo "Unmounted ", nc.args.others[0]
else:
echo "Failed to unmount ", nc.args.others[0]

View file

@ -14,6 +14,6 @@ proc addPruneOptions(cmd: var string, maintenance: Maintenance) =
""" """
proc pruneRepo*(nc: NorgConfig, repo: Repository): int = proc pruneRepo*(nc: NorgConfig, repo: Repository): int =
var cmd = genCommand(cmd = "prune", repo = repo.path, others = nc.args.others) var cmd = genCommand(cmd = "prune", repo = repo.path, further_args = nc.args.further_args)
cmd.addPruneOptions(nc.maintenance) cmd.addPruneOptions(nc.maintenance)
return run cmd return run cmd

View file

@ -11,23 +11,27 @@ import prune
proc execute*(nc: NorgConfig, repo: Repository) = proc execute*(nc: NorgConfig, repo: Repository) =
case nc.args.command case nc.args.command
of INIT: of INIT:
echo "Initializing repo: ", repo.label
discard initRepo(nc, repo) discard initRepo(nc, repo)
of CREATE: of CREATE:
run_actions(norg_config.actions.before_backup) run_actions(norg_config.actions.before_backup)
echo "Backing up to ", repo.label
discard createBackup(nc, repo) discard createBackup(nc, repo)
run_actions(norg_config.actions.after_backup) run_actions(norg_config.actions.after_backup)
of LIST: of LIST:
echo "Listing Snapshots at ", repo.label
discard listSnapshots(nc, repo) discard listSnapshots(nc, repo)
of MOUNT: of MOUNT:
echo "Mounting Snapshot from ", repo.label
discard mountSnapshot(nc, repo) discard mountSnapshot(nc, repo)
of UMOUNT:
discard unmountSnapshot(nc)
of EXTRACT: of EXTRACT:
run_actions(norg_config.actions.before_extract) run_actions(norg_config.actions.before_extract)
echo "Extracting backup from ", repo.label
discard extractArchive(nc, repo) discard extractArchive(nc, repo)
run_actions(norg_config.actions.after_extract) run_actions(norg_config.actions.after_extract)
of PRUNE: of PRUNE:
run_actions(norg_config.actions.before_prune) run_actions(norg_config.actions.before_prune)
echo "Pruning repo: ", repo.label
discard pruneRepo(nc, repo) discard pruneRepo(nc, repo)
run_actions(norg_config.actions.after_prune) run_actions(norg_config.actions.after_prune)
else: else: