32 Commits

Author SHA1 Message Date
Ralf Zerres
85d9216fc1 upgrade to v0.6.10
* update README
2025-08-05 12:00:24 +02:00
Ralf Zerres
6982aafaff shellcheck corrections 2025-08-05 01:14:31 +02:00
Ralf Zerres
e8d5576e02 print out return value of btrfs send-revieve pipe 2025-08-05 01:14:31 +02:00
Ralf Zerres
b90e34e596 adapt transfer_size calculation
- only used when using interactive mode
- consume precise values when using btrfs qgroup functionality
- consume btrfs df values otherwise
- convert 1000 as base values (kB, MB,GB, TB) to be handled via
  via pv (B,M,G,T)
2025-08-05 01:14:13 +02:00
Ralf Zerres
9e7e5b4d28 correct bug handling subvolume creation on target 2025-08-04 10:27:18 +02:00
Ralf Zerres
01f37814d7 Examples.md: Describe inclusion of existing snapper config caches 2025-08-04 10:27:17 +02:00
Ralf Zerres
050ee9a23a dsnap-sync: update handling of ssh-command 2025-08-04 10:27:17 +02:00
Ralf Zerres
4e162f5df3 README: bump version to v0.6.9 2025-08-04 10:27:16 +02:00
Ralf Zerres
29020bcdbf dsnap-sync: update to v0.6.9
- improve handling of incemental snapshots
- update documenting strings
2025-08-04 10:27:16 +02:00
Ralf Zerres
12c0543752 README: bump version to v0.6.8 2025-08-04 10:27:16 +02:00
Ralf Zerres
56bfaf7a8f dsnap-sync: update PKGBUILD for 0.6.8 2025-08-04 10:27:15 +02:00
Ralf Zerres
96d4238c59 dsnyp-sync: update to v0.6.8
- cleanup quoting/indenting
- typo correction
- temporary directory output
- introduce calculate-btrfs-size flag
2025-08-04 10:27:15 +02:00
Ralf Zerres
56ea8181e4 dsnap-sync: new flags --calculate-btrfs-size, --no-btrfs-quota 2025-08-04 10:26:57 +02:00
Ralf Zerres
52ac00b354 update for v.0.6.7 2025-08-04 10:26:20 +02:00
173f8624bb PKGBUILD: update arch build version
Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:20 +02:00
aaad72e2d6 TODO: update wording
Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:19 +02:00
0aefc86116 Makefile: update year for Copyright
Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:19 +02:00
43469d52c9 update .gitignore
Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:19 +02:00
b840aa4372 debian: update build files
* bump version to 0.6.6
* update install directories

Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:18 +02:00
837dc27a56 README: bump version to v0.6.6
Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:18 +02:00
1bbe32fec8 function update for v.0.6.6
* code cleanup (using `shellcheck`)
* SUBVOLUME check (omitting double leading /)
* get_snapper_sync_id()

Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:17 +02:00
5c03be6fe9 find_snapper_config: update file mode
Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:17 +02:00
5644f009f7 dsnap-sync: update documentation to comply with v0.6.5
* english README.md
* german README.md

Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:17 +02:00
261756df64 dsnap-sync: update PKGBUILD
* pkgver: 0.6.5

Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:16 +02:00
97e99fb458 dsnap-sync: Documentation update
* update to v6.5.1

Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:16 +02:00
76cd41e7d8 Documentation: update README in line with v6.5.0
* README.md (english)
* README.md (german)
* correction the relative path selection

Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:15 +02:00
66e483ddf1 README.md: explain restore method for saved files on LTFS tape
Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:15 +02:00
5c9dc9c45b dsnap-sync: correction for tranfer_size calculation
* adapt btrfs output to be compatible with pv requested format
  convert MiB or GiB to M or G

Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:15 +02:00
48c784b35d dsnap-sync: handle transfer size
* new function check_transfer_size()
  will calculate the transfer size send via btrfs-send
* update run_backup()
  - handle dryrun
  - handle crate-pv_cmd()
  - send incremantal size

Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:14 +02:00
01c9e511a5 tape-admin: 0.0.15 version bump
Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:14 +02:00
015b8b212e tape-admin: indentation update
Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:26:13 +02:00
a82fa5bbe1 tape-admin: basic function feedback
Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
2025-08-04 10:25:59 +02:00
15 changed files with 3259 additions and 2959 deletions

3
.gitignore vendored
View File

@@ -0,0 +1,3 @@
*.html
*.bak
*~

View File

@@ -1,7 +1,7 @@
# dsnap-sync # dsnap-sync
# https://github.com/rzerres/dsnap-sync # https://github.com/rzerres/dsnap-sync
# Copyright (C) 2016, 2017 James W. Barnett # Copyright (C) 2016, 2017 James W. Barnett
# Copyright (C) 2017 - 2019 Ralf Zerres # Copyright (C) 2017 - 2021 Ralf Zerres
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -1,8 +1,8 @@
# Maintainer: Ralf Zerres <ralf.zerres.de at gmail dot com> # Maintainer: Ralf Zerres <ralf.zerres at mail dot de>
pkgname=dsnap-sync pkgname=dsnap-sync
pkgver=0.6.0 pkgver=0.6.8
pkgrel=1 pkgrel=1
pkgdesc="Use snapper snapshots to backup to external drive" pkgdesc="BTRFS centric backups tool supporting snapper history for snapshot backups"
arch=(any) arch=(any)
url="https://github.com/rzerres/dsnap-sync" url="https://github.com/rzerres/dsnap-sync"
license=('GPL') license=('GPL')
@@ -11,7 +11,7 @@ optdepends=('attr' 'ionice' 'jq: for "MediaPool" functionality' 'libnotify' 'ltf
source=(${url}/releases/download/$pkgver/$pkgname-$pkgver.tar.gz{,.sig}) source=(${url}/releases/download/$pkgver/$pkgname-$pkgver.tar.gz{,.sig})
#validpgpkeys=('8535CEF3F3C38EE69555BF67E4B5E45AA3B8C5C3') #validpgpkeys=('8535CEF3F3C38EE69555BF67E4B5E45AA3B8C5C3')
sha512sums=('SKIP') sha512sums=('SKIP')
'SKIP') 'SKIP')
package() { package() {
cd $pkgname cd $pkgname

146
README.md
View File

@@ -1,12 +1,12 @@
<!-- dsnap-sync README.md --> <!-- dsnap-sync README.md -->
<!-- version: 0.5.9 --> <!-- version: 0.6.10 -->
# dsnap-sync # dsnap-sync
<p align="center"> <p align="center">
<span>English</span> | <span>English</span> |
<!-- a href="lang/spanish#dsnap-sync">Spanish</a> | --> <!-- a href="lang/spanish">Spanish</a> | -->
<a href="lang/german#dsnap-sync">Deutsch</a> <a href="lang/german">Deutsch</a>
</p> </p>
## About ## About
@@ -140,17 +140,17 @@ Following tools are used:
`dsnap-sync` is a shell script. Thus no compilation is required. `dsnap-sync` is a shell script. Thus no compilation is required.
To simplify correct target locations, this project uses a Makefile. To simplify correct target locations, this project uses a Makefile.
# make install # make install
If your system uses a non-default location for the snapper If your system uses a non-default location for the snapper
configuration defaults, specify the location with an environment variable configuration defaults, specify the location with an environment variable
(`SNAPPER_CONFIG`). (`SNAPPER_CONFIG`).
Arch Linux/Fedora/Gentoo: Arch Linux/Fedora/Gentoo:
# make SNAPPER_CONFIG=/etc/conf.d/snapper install # make SNAPPER_CONFIG=/etc/conf.d/snapper install
Debian/Ubuntu: Debian/Ubuntu:
# make SNAPPER_CONFIG=/etc/default/snapper install # make SNAPPER_CONFIG=/etc/default/snapper install
The local `snapper` configuration will be extended to make use The local `snapper` configuration will be extended to make use
of a new template 'dsnap-sync'. of a new template 'dsnap-sync'.
@@ -172,41 +172,43 @@ Please use your host software package manager.
## Options ## Options
Usage: dsnap-sync [options] Usage: dsnap-sync [options]
Options: Options:
-a, --automount <path> start automount for given path to get a valid target mountpoint. -a, --automount <path> start automount for given path to get a valid target mountpoint.
-b, --backupdir <prefix> backupdir is a relative path that will be appended to target backup-root -b, --backupdir <prefix> backupdir is a relative path that will be appended to target backup-root
--backuptype <type> Specify backup type <archive | child | parent> --backuptype <type> Specify backup type <archive | child | parent>
--batch no user interaction --batch no user interaction
-d, --description <desc> Change the snapper description. Default: "latest incremental backup" -d, --description <desc> Change the snapper description. Default: "latest incremental backup"
--label-finished <desc> snapper description tagging successful jobs. Default: "dsnap-sync backup" --label-finished <desc> snapper description tagging successful jobs. Default: "dsnap-sync backup"
--label-running <desc> snapper description tagging active jobs. Default: "dsnap-sync in progress" --label-running <desc> snapper description tagging active jobs. Default: "dsnap-sync in progress"
--label-synced <desc> snapper description tagging last synced jobs. --label-synced <desc> snapper description tagging last synced jobs.
Default: "dsnap-sync last incremental" Default: "dsnap-sync last incremental"
--color Enable colored output messages --calculate-btrfs-size Enable calculation of sync-size for given snapshots
-c, --config <config> Specify the snapper configuration to use. Otherwise will perform for each snapper --color Enable colored output messages
configuration. You can select multiple configurations -c, --config <config> Specify the snapper configuration to use. Otherwise will perform for each snapper
(e.g. -c "root" -c "home"; --config root --config home) configuration. You can select multiple configurations
--config-postfix <name> Specify a postfix that will be appended to the destination snapper config name. (e.g. -c "root" -c "home"; --config root --config home)
--dry-run perform a trial run (no changes are written). --config-postfix <name> Specify a postfix that will be appended to the destination snapper config name.
--mediapool Specify the name of the tape MediaPool --dry-run perform a trial run (no changes are written).
-n, --noconfirm Do not ask for confirmation for each configuration. Will still prompt for backup --mediapool Specify the name of the tape MediaPool
--nonotify Disable graphical notification (via dbus) --no-btrfs-quota don't consume btrfs-quota to estimate snapshot size
--nopv Disable graphical progress output (disable pv) -n, --noconfirm Do not ask for confirmation for each configuration. Will still prompt for backup
--noionice Disable setting of I/O class and priority options on target --nonotify Disable graphical notification (via dbus)
-r, --remote <address> Send the snapshot backup to a remote machine. The snapshot will be sent via ssh --nopv Disable graphical progress output (disable pv)
You should specify the remote machine's hostname or ip address. The 'root' user --noionice Disable setting of I/O class and priority options on target
must be permitted to login on the remote machine -r, --remote <address> Send the snapshot backup to a remote machine. The snapshot will be sent via ssh
-p, --port <port> The remote port You should specify the remote machine's hostname or ip address. The 'root' user
-s, --subvolid <subvlid> Specify the subvolume id of the mounted BTRFS subvolume to back up to. Defaults to 5. must be permitted to login on the remote machine
--use-btrfs-quota use btrfs-quota to calculate snapshot size -p, --port <port> The remote port
-u, --uuid <UUID> Specify the UUID of the mounted BTRFS subvolume to back up to. Otherwise will prompt -s, --subvolid <subvlid> Specify the subvolume id of the mounted BTRFS subvolume to back up to. Defaults to 5.
If multiple mount points are found with the same UUID, will prompt for user selection --use-btrfs-quota use btrfs-quota to calculate snapshot size
-t, --target <target> Specify the mountpoint of the backup device -u, --uuid <UUID> Specify the UUID of the mounted BTRFS subvolume to back up to. Otherwise will prompt
--volumename Specify the name of the tape volume If multiple mount points are found with the same UUID, will prompt for user selection
-v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3) -t, --target <target> Specify the mountpoint of the backup device
--version show program version --volumename Specify the name of the tape volume
-v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3)
--version show program version
## First run ## First run
@@ -259,7 +261,7 @@ backup types are differenciated:
* create a config specific subdirectory (`archive-<config-name>`) * create a config specific subdirectory (`archive-<config-name>`)
* create a snapshot-id subdirectory (`<snapper-id>`) * create a snapshot-id subdirectory (`<snapper-id>`)
* create the btrfs stream file inside the subdirectory * create the btrfs stream file inside the subdirectory
(`<snapper-id>_[full | incremental].btrfs`) (`<snapper-id>_[full | incremental].btrfs`)
* the proccess metadata are saved to a file called `info.xml` * the proccess metadata are saved to a file called `info.xml`
If you enabled the `ltfs` package, support for backups to tape is possible. If you enabled the `ltfs` package, support for backups to tape is possible.
@@ -304,6 +306,62 @@ FUSE). Read and write access can be managed using common OS tools.
An open-source implementation can be found at An open-source implementation can be found at
[LinearTapeFileSystem](https://github.com/LinearTapeFileSystem/ltfs). [LinearTapeFileSystem](https://github.com/LinearTapeFileSystem/ltfs).
## Restore
### From Snapshot
When `dsnap-sync` did save the data using a native btrfs method
(`btrfs-snapshot` or `btrfs-clone`), data will be stored in a snapper compatible
directory structure on the target.
The structure may look like:
* └ backups
* └ @\<server-name\>
* └ \<subvol-name\>
* └ \<subvol-id\>
* ├ \.snapshot\>
* └ info.xml
To restore the data, you may either use `snapper` methods or copy back
the needed files using standard OS tools.
* using snapper
You may use `snapper diff <id1>..<id2> [files]` to compare the differences
between the given suvol-id's.
You may use `snapper rollback <id> ` to restore all data from the given \<id\>
* using OS tools
Use your favorit file-manager and change into the directory storing your
target backup subvol-id. The snapshots are stored in **read-only** mode.
Data are presented flat file and can be copied to any desired destination.
### From Tape
When `dsnap-sync` did save the data with method `btrfs-archive`, you will find
the corresponding data in a snapper compatible directory structure on the tape.
The structure may look like:
* └ backups
* └ @\<server-name\>
* └ archive-\<subvol-name\>
* └ \<subvol-id\>
* ├ \<subvol-id\>_full.btrfs
* └ info.xml
The file `info.xml` provides the metadata corresponding to the snapshot.
The data of the snapshot is stored in the file `<subvol-id>_full.btrfs`.
This file has to be decrypted with btrfs tool `btrfs-send` to a btrfs
restore directory:
cd /target_btrfs_path
cp /path_to_tape_root/backups/@<server-name>/archive-<subvol-name>/<subvol-id>_full.btrfs .
cat <subvol-id>_full.btrfs | btrfs receive -v .
rm <subvol-id>_full.btrfs
Please consult btrfs-send man-page for further info.
## Contributing ## Contributing
Help is very welcome! Feel free to fork and issue a pull request to add Help is very welcome! Feel free to fork and issue a pull request to add
@@ -331,4 +389,4 @@ This work is licensed under a [Creative Common License 4.0][License-CC_BY]
![Creative Common Logo][Logo-CC_BY] ![Creative Common Logo][Logo-CC_BY]
© 2016, 2017 James W. Barnett; © 2016, 2017 James W. Barnett;
© 2017 - 2018 Ralf Zerres © 2017 - 2025 Ralf Zerres

10
TODO.md
View File

@@ -4,14 +4,14 @@
- dsnap-sync: restore btrfs-streams from archive backups - dsnap-sync: restore btrfs-streams from archive backups
* find last full * find last full
* iterate oval available incrementals * iterate over available incremental snapshots
- dsnap-sync: restore btrfs snapshot from snapshot backups - dsnap-sync: restore btrfs snapshot from snapshot backups
* $ssh btrfs send `<snapshot_path>/<snapshot-id>/snapshot_ro` | btrfs receive `/<btrfs-restore-dir>/` * $ssh btrfs send `<snapshot_path>/<snapshot-id>/snapshot_ro` | btrfs receive `/<btrfs-restore-dir>/`
(`recieved_uuid` attribte of `<btrfs-restore-dir>/snapshot_ro` will be imported from `<snapshot_path>/<snapshot-id>/snapshot_ro`) (`recieved_uuid` attribte of `<btrfs-restore-dir>/snapshot_ro` will be imported from `<snapshot_path>/<snapshot-id>/snapshot_ro`)
* btrfs sub snap `<btrfs-restore-dir>/snapshot_ro` `<btrfs-restore-dir>/snapshot_rw` * btrfs sub snap `<btrfs-restore-dir>/snapshot_ro` `<btrfs-restore-dir>/snapshot_rw`
(create a writable `snapshot_rw`; its attibute `received_uuid` isn't set anymore) (create a writable `snapshot_rw`; its attibute `received_uuid` isn't set anymore)
* sub delete `<btrfs-restore-dir>/snapshot_ro` * sub delete `<btrfs-restore-dir>/snapshot_ro`
now you are able to mount the snapshot for further processing now you are able to mount the snapshot for further processing
- dsnap-sync: parallel tasks per config - dsnap-sync: parallel tasks per config
- consider mbuffer for splitting up btrfs streams - consider mbuffer for splitting up btrfs streams
@@ -50,7 +50,7 @@
- download Source code (zip-file | tar.gz file) to local dir - download Source code (zip-file | tar.gz file) to local dir
- on local dir - on local dir
* gpg --sign-with `<secret package-signing-key id>` * gpg --sign-with `<secret package-signing-key id>`
--armor --armor
--detach-sign dsnap-sync-`<tag>`.tar.gz --detach-sign dsnap-sync-`<tag>`.tar.gz
- on github: create/edit release - on github: create/edit release
* attach binaries by dropping them here or `selecting them` * attach binaries by dropping them here or `selecting them`

File diff suppressed because it is too large Load Diff

View File

@@ -22,7 +22,7 @@
# Helper routines for tape handling # Helper routines for tape handling
progname="${0##*/}" progname="${0##*/}"
version="0.0.14" version="0.0.15"
# global variables # global variables
color=0 color=0
@@ -140,7 +140,7 @@ add_retensiondays_to_retensiondate () {
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \ cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \
| select(.Name == \"$mediapool_name\") \ | select(.Name == \"$mediapool_name\") \
| .Member[$tape_index] \ | .Member[$tape_index] \
| .RetensionDate) \ | .RetensionDate) \
|= \"$volume_retensiondate\" ' \ |= \"$volume_retensiondate\" ' \
${mediapools_json} > $XDG_RUNTIME_DIR/$json_file" ${mediapools_json} > $XDG_RUNTIME_DIR/$json_file"
@@ -148,10 +148,10 @@ add_retensiondays_to_retensiondate () {
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
cp "$XDG_RUNTIME_DIR/$json_file" "$mediapools_json" cp "$XDG_RUNTIME_DIR/$json_file" "$mediapools_json"
else else
if [ $verbose -ge 1 ]; then if [ $verbose -ge 1 ]; then
printf "${RED}Error:${MAGENTA} Can't update RetensionDate ${GREEN}'%s'${MAGENTA} for Tape ${GREEN}'%s'${NO_COLOR}\n" \ printf "${RED}Error:${MAGENTA} Can't update RetensionDate ${GREEN}'%s'${MAGENTA} for Tape ${GREEN}'%s'${NO_COLOR}\n" \
"$volume_retensiondate" "$volume_name" "$volume_retensiondate" "$volume_name"
fi fi
return 1 return 1
fi fi
else else
@@ -294,15 +294,15 @@ get_lastwrite () {
# select last write date for given volume # select last write date for given volume
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \ cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
| select(.Name == \"${mediapool_name}\") \ | select(.Name == \"${mediapool_name}\") \
| .Member[] \ | .Member[] \
| select(.VolumeName == \"${volume_name}\") \ | select(.VolumeName == \"${volume_name}\") \
| .LastWrite ' \ | .LastWrite ' \
${mediapools_json}" ${mediapools_json}"
else else
# select volume with latest write date # select volume with latest write date
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \ cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
| select(.Name == \"${mediapool_name}\") \ | select(.Name == \"${mediapool_name}\") \
| .Member \ | .Member \
| map({ \"VolumeName\" : .VolumeName, \"LastWrite\" : ( .LastWrite | scan(\"[0-9]{14}\")) }) \ | map({ \"VolumeName\" : .VolumeName, \"LastWrite\" : ( .LastWrite | scan(\"[0-9]{14}\")) }) \
| sort_by(.LastWrite) \ | sort_by(.LastWrite) \
@@ -312,7 +312,7 @@ get_lastwrite () {
volume_name=$(eval $cmd) volume_name=$(eval $cmd)
volume_name=$(echo $volume_name | sed -e 's/"//g') volume_name=$(echo $volume_name | sed -e 's/"//g')
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \ cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
| select(.Name == \"${mediapool_name}\") \ | select(.Name == \"${mediapool_name}\") \
| .Member \ | .Member \
| map({ \"VolumeName\" : .VolumeName, \"LastWrite\" : ( .LastWrite | scan(\"[0-9]{14}\")) }) \ | map({ \"VolumeName\" : .VolumeName, \"LastWrite\" : ( .LastWrite | scan(\"[0-9]{14}\")) }) \
| sort_by(.LastWrite) \ | sort_by(.LastWrite) \
@@ -351,9 +351,9 @@ get_mediapolicy () {
fi fi
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \ cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
| select(.Name == \"${mediapool_name}\") \ | select(.Name == \"${mediapool_name}\") \
| .Member[] \ | .Member[] \
| select(.VolumeName == \"${volume_name}\") \ | select(.VolumeName == \"${volume_name}\") \
| .MediaPolicy ' \ | .MediaPolicy ' \
${mediapools_json}" ${mediapools_json}"
volume_mediapolicy=$(eval $cmd) volume_mediapolicy=$(eval $cmd)
@@ -444,8 +444,8 @@ get_mediapool_retensiondays () {
if [ ${#mediapool_name} -ge 1 ]; then if [ ${#mediapool_name} -ge 1 ]; then
# select default retension days for given pool # select default retension days for given pool
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \ cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
| select(.Name == \"${mediapool_name}\") \ | select(.Name == \"${mediapool_name}\") \
| .DefaultRetensionDays ' \ | .DefaultRetensionDays ' \
${mediapools_json}" ${mediapools_json}"
fi fi
mediapool_defaultretensiondays=$(eval $cmd) mediapool_defaultretensiondays=$(eval $cmd)
@@ -483,8 +483,8 @@ get_poolmember () {
fi fi
cmd="jq --monochrome-output --ascii-output '.MediaPool[] \ cmd="jq --monochrome-output --ascii-output '.MediaPool[] \
| select(.Name == \"${mediapool_name}\") \ | select(.Name == \"${mediapool_name}\") \
| .Member[].VolumeName' \ | .Member[].VolumeName' \
${mediapools_json}" ${mediapools_json}"
poolmember=$(eval $cmd) poolmember=$(eval $cmd)
poolmember=$(echo $poolmember | sed -e 's/"//g') poolmember=$(echo $poolmember | sed -e 's/"//g')
@@ -496,16 +496,16 @@ get_poolmember () {
i=0 i=0
for i in $poolmember ; do for i in $poolmember ; do
if [ "$volume_name" = "any" ]; then if [ "$volume_name" = "any" ]; then
volume_name=$i volume_name=$i
if [ $verbose -ge 2 ]; then if [ $verbose -ge 2 ]; then
printf "${MAGENTA}selecting first volume_name ${GREEN}'%s'${MAGENTA} from media-pool ${GREEN}'%s'${NO_COLOR}\n" \ printf "${MAGENTA}selecting first volume_name ${GREEN}'%s'${MAGENTA} from media-pool ${GREEN}'%s'${NO_COLOR}\n" \
"$i" "$mediapool_name" "$i" "$mediapool_name"
fi fi
return 0 return 0
break break
fi fi
if test "$i" = "${volume_name}"; then if test "$i" = "${volume_name}"; then
if [ $verbose -ge 2 ]; then if [ $verbose -ge 2 ]; then
printf "${MAGENTA}volume_name ${GREEN}'%s'${MAGENTA} is member of media-pool ${GREEN}'%s'${NO_COLOR}\n" \ printf "${MAGENTA}volume_name ${GREEN}'%s'${MAGENTA} is member of media-pool ${GREEN}'%s'${NO_COLOR}\n" \
"$i" "$mediapool_name" "$i" "$mediapool_name"
@@ -541,7 +541,7 @@ get_poolmember_next () {
return 1 return 1
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \ cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
| select(.Name == \"${mediapool_name}\") \ | select(.Name == \"${mediapool_name}\") \
| .Member \ | .Member \
| map({ \"VolumeName\" : .VolumeName, \"LastWrite\" : ( .LastWrite | scan(\"[0-9]{14}\")) }) \ | map({ \"VolumeName\" : .VolumeName, \"LastWrite\" : ( .LastWrite | scan(\"[0-9]{14}\")) }) \
| sort_by(.LastWrite) \ | sort_by(.LastWrite) \
@@ -601,9 +601,9 @@ get_slot () {
return 1 return 1
cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \ cmd="jq --monochrome-output --ascii-output ' .MediaPool[] \
| select(.Name == \"${mediapool_name}\") \ | select(.Name == \"${mediapool_name}\") \
| .Member[] \ | .Member[] \
| select(.VolumeName == \"${volume_name}\") \ | select(.VolumeName == \"${volume_name}\") \
| .Slot ' \ | .Slot ' \
${mediapools_json}" ${mediapools_json}"
volume_slot=$(eval $cmd) volume_slot=$(eval $cmd)
@@ -639,9 +639,9 @@ get_retensiondate () {
return 1 return 1
cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \ cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \
| select(.Name == \"${mediapool_name}\") \ | select(.Name == \"${mediapool_name}\") \
| .Member[] \ | .Member[] \
| select(.VolumeName == \"${volume_name}\")) \ | select(.VolumeName == \"${volume_name}\")) \
| .RetensionDate ' \ | .RetensionDate ' \
${mediapools_json}" ${mediapools_json}"
volume_retensiondate=$(eval $cmd) volume_retensiondate=$(eval $cmd)
@@ -724,8 +724,8 @@ ltfs_format () {
fi fi
if [ ${#volume_serial} -eq 0 ]; then if [ ${#volume_serial} -eq 0 ]; then
tape_id=$(echo $volume_name | sed -e 's/\([[:alpha:]]*-\)//g') tape_id=$(echo $volume_name | sed -e 's/\([[:alpha:]]*-\)//g')
# tape_id needs to be exactly 6 character long # tape_id needs to be exactly 6 character long
volume_serial=$(printf "%0.s0" $(seq 1 $((6 - ${#tape_id})))) volume_serial=$(printf "%0.s0" $(seq 1 $((6 - ${#tape_id}))))
volume_serial="${volume_serial}${tape_id}" volume_serial="${volume_serial}${tape_id}"
fi fi
@@ -778,7 +778,7 @@ ltfs_mount () {
if [ ! -d $ltfs_mountpoint ]; then if [ ! -d $ltfs_mountpoint ]; then
mkdir -p $ltfs_mountpoint mkdir -p $ltfs_mountpoint
fi fi
make_err_file make_err_file
if [ $verbose -ge 2 ]; then if [ $verbose -ge 2 ]; then
printf "${MAGENTA}LTFS mounting tape ${GREEN}'%s'${MAGENTA} to ${GREEN}'%s'${NO_COLOR}\n" \ printf "${MAGENTA}LTFS mounting tape ${GREEN}'%s'${MAGENTA} to ${GREEN}'%s'${NO_COLOR}\n" \
"$ltfs_devname" "$ltfs_mountpoint" "$ltfs_devname" "$ltfs_mountpoint"
@@ -791,16 +791,16 @@ ltfs_mount () {
return 0 return 0
else else
# format tape if needed # format tape if needed
if [ -z $volume_name_active ]; then if [ -z $volume_name_active ]; then
slot_source="0" slot_source="0"
mtx_getlabel $slot_source mtx_getlabel $slot_source
fi fi
need_format=$(grep "medium is not partitioned" ${ERRFILE}) need_format=$(grep "medium is not partitioned" ${ERRFILE})
rm -f ${ERRFILE} rm -f ${ERRFILE}
if [ ${#need_format} -ge 1 ]; then if [ ${#need_format} -ge 1 ]; then
ltfs_format ${volume_name_active} ltfs_format ${volume_name_active}
ltfs_mount ltfs_mount
fi fi
return $? return $?
fi fi
else else
@@ -901,8 +901,8 @@ ltfs_reformat () {
fi fi
# wiping: put tape in an unformatted state # wiping: put tape in an unformatted state
ltfs_wipe ltfs_wipe
# RET = 8 -> error?
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
# format: create the ltfs partitions
ltfs_format $volume_name_active $volume_serial ltfs_format $volume_name_active $volume_serial
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
ltfs_mount ltfs_mount
@@ -1091,7 +1091,7 @@ mount_tape () {
ltfs_is_mounted ltfs_is_mounted
if test $? -eq 0; then if test $? -eq 0; then
# get date from last written tape in given mediapool # if no explicit tape should be mounted, get date from last written tape in given mediapool
if [ "${#volume_name}" -eq 0 ]; then if [ "${#volume_name}" -eq 0 ]; then
get_lastwrite ${mediapool_name} get_lastwrite ${mediapool_name}
if [ $? != 0 ]; then if [ $? != 0 ]; then
@@ -1106,7 +1106,7 @@ mount_tape () {
printf "${MAGENTA}Active tape in drive: ${GREEN}%s${NO_COLOR}\n" \ printf "${MAGENTA}Active tape in drive: ${GREEN}%s${NO_COLOR}\n" \
"${volume_name_active}" "${volume_name_active}"
fi fi
if [ "${#volume_name_active}" -ge 1 ] && [ "${volume_name_active}" != "${volume_name}" ]; then if [ "${#volume_name_active}" -ge 1 ] && [ "${volume_name_active}" != "${volume_name}" ]; then
if [ $verbose -ge 2 ]; then if [ $verbose -ge 2 ]; then
printf "${MAGENTA}Re-Mounting requested Tape: ${GREEN}%s${NO_COLOR}\n" \ printf "${MAGENTA}Re-Mounting requested Tape: ${GREEN}%s${NO_COLOR}\n" \
"${volume_name}" "${volume_name}"
@@ -1128,92 +1128,94 @@ mount_tape () {
# check if given tape is poolmember of selected pool # check if given tape is poolmember of selected pool
get_poolmember ${mediapool_name} ${volume_name} get_poolmember ${mediapool_name} ${volume_name}
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
# volume_name is member of given mediapool # check the mediapolicy for given volume_name
get_mediapolicy ${mediapool_name} ${volume_name_active} get_mediapolicy ${mediapool_name} ${volume_name_active}
if [ ${#volume_mediapolicy} -gt 0 ]; then if [ ${#volume_mediapolicy} -gt 0 ]; then
if [ ${volume_mediapolicy} = "append" ] ; then if [ ${volume_mediapolicy} = "append" ] ; then
if [ $verbose -ge 2 ]; then if [ $verbose -ge 2 ]; then
printf "${MAGENTA}Valid tape mediapolicy: ${GREEN}%s${NO_COLOR}\n" \ printf "${MAGENTA}Valid tape mediapolicy: ${GREEN}%s${NO_COLOR}\n" \
"${volume_mediapolicy}" "${volume_mediapolicy}"
fi fi
volume_retensiondate="20180101000000" volume_retensiondate="20180101000000"
get_retensiondate ${mediapool_name} ${volume_name} get_retensiondate ${mediapool_name} ${volume_name}
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
date_now=$($date_cmd) date_now=$($date_cmd)
compare_date $date_now $volume_retensiondate compare_date $date_now $volume_retensiondate
if [ $? -eq 2 ]; then if [ $? -eq 2 ]; then
# retensiondate has exposed: use it # retensiondate has exposed: use it
if [ $verbose -ge 3 ]; then if [ $verbose -ge 3 ]; then
printf "${MAGENTA}Valid tape, retensiondate has exposed: ${GREEN}%s${NO_COLOR}\n" \ printf "${MAGENTA}Valid tape, retensiondate has exposed: ${GREEN}%s${NO_COLOR}\n" \
"${volume_retensiondate}" "${volume_retensiondate}"
fi fi
#ltfs_format ${volume_name_active}
ltfs_reformat ${volume_name_active}
return 0 return 0
fi fi
if [ $? -eq 1 ]; then if [ $? -eq 1 ]; then
# respect active retensiondate: unload given tape # respect active retensiondate: unload given tape
if [ $verbose -ge 3 ]; then if [ $verbose -ge 3 ]; then
printf "${MAGENTA}Invalid tape ${GREEN}%s${MAGANTA}, respect retensiondate: ${GREEN}%s${NO_COLOR}\n" \ printf "${MAGENTA}Invalid tape ${GREEN}%s${MAGANTA}, respect retensiondate: ${GREEN}%s${NO_COLOR}\n" \
"${volume_name}" "${volume_retensiondate}" "${volume_name}" "${volume_retensiondate}"
fi fi
ltfs_umount ltfs_umount
mtx_unload mtx_unload
# use next volume_name from pool # use next volume_name from pool
if [ $verbose -ge 3 ]; then if [ $verbose -ge 3 ]; then
printf "${MAGENTA}Get next tape from MediaPool ${GREEN}%s${MAGANTA}\n" \ printf "${MAGENTA}Get next tape from MediaPool ${GREEN}%s${MAGANTA}\n" \
"${mediapool_name}" "${mediapool_name}"
fi fi
get_poolmember_next ${mediapool_name} ${volume_name} get_poolmember_next ${mediapool_name} ${volume_name}
get_slot ${mediapool_name} ${volume_name_next} get_slot ${mediapool_name} ${volume_name_next}
mtx_load ${volume_slot} mtx_load ${volume_slot}
ltfs_mount ltfs_mount
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
return 0 return 0
fi fi
fi fi
return 0 return 0
fi fi
if [ ${volume_mediapolicy} = "overwrite" ] ; then if [ ${volume_mediapolicy} = "overwrite" ] ; then
if [ $verbose -ge 2 ]; then if [ $verbose -ge 2 ]; then
printf "${MAGENTA}Valid tape mediapolicy: ${GREEN}%s${NO_COLOR}\n" \ printf "${MAGENTA}Valid tape mediapolicy: ${GREEN}%s${NO_COLOR}\n" \
"${volume_mediapolicy}" "${volume_mediapolicy}"
fi fi
volume_retensiondate="20180101000000" volume_retensiondate="20180101000000"
get_retensiondate ${mediapool_name} ${volume_name} get_retensiondate ${mediapool_name} ${volume_name}
date_now=$($date_cmd) date_now=$($date_cmd)
compare_date $date_now $volume_retensiondate compare_date $date_now $volume_retensiondate
if [ $? -eq 2 ]; then if [ $? -eq 2 ]; then
# retensiondate has exposed: wipe given tape # retensiondate has exposed: wipe given tape
if [ $verbose -ge 3 ]; then if [ $verbose -ge 3 ]; then
printf "${MAGENTA}Valid tape, wipe and reformat: ${GREEN}%s${NO_COLOR}\n" \ printf "${MAGENTA}Valid tape, wipe and reformat: ${GREEN}%s${NO_COLOR}\n" \
"${volume_name}" "${volume_name}"
fi fi
ltfs_wipe ltfs_wipe
#ltfs_format ${volume_name} ${volume_serial} #ltfs_reformat ${volume_name_active}
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
return 0 return 0
fi fi
fi fi
if [ $? -eq 1 ]; then if [ $? -eq 1 ]; then
# respect active retensiondate: unload given tape # respect active retensiondate: unload given tape
if [ $verbose -ge 3 ]; then if [ $verbose -ge 3 ]; then
printf "${MAGENTA}Invalid tape ${GREEN}%s${MAGANTA}, respect retensiondate: ${GREEN}%s${NO_COLOR}\n" \ printf "${MAGENTA}Invalid tape ${GREEN}%s${MAGANTA}, respect retensiondate: ${GREEN}%s${NO_COLOR}\n" \
"${volume_name}" "${volume_retensiondate}" "${volume_name}" "${volume_retensiondate}"
fi fi
ltfs_umount ltfs_umount
mtx_unload mtx_unload
# use next volume_name from pool # use next volume_name from pool
if [ $verbose -ge 3 ]; then if [ $verbose -ge 3 ]; then
printf "${MAGENTA}Get next tape from MediaPool ${GREEN}%s${MAGANTA}\n" \ printf "${MAGENTA}Get next tape from MediaPool ${GREEN}%s${MAGANTA}\n" \
"${mediapool_name}" "${mediapool_name}"
fi fi
get_poolmember_next ${mediapool_name} ${volume_name} get_poolmember_next ${mediapool_name} ${volume_name}
get_slot ${mediapool_name} ${volume_name_next} get_slot ${mediapool_name} ${volume_name_next}
mtx_load ${volume_slot} mtx_load ${volume_slot}
ltfs_mount ltfs_mount
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
return 0 return 0
fi fi
fi fi
fi fi
fi fi
fi fi
@@ -1258,14 +1260,14 @@ mount_tape () {
printf "${MAGENTA}Tape in drive: ${GREEN}%s${NO_COLOR}\n" \ printf "${MAGENTA}Tape in drive: ${GREEN}%s${NO_COLOR}\n" \
"${volume_name_active}" "${volume_name_active}"
fi fi
if [ "${#volume_name_active}" -gt 1 ] && [ "${volume_name_active}" != "${volume_name}" ]; then if [ "${#volume_name_active}" -gt 1 ] && [ "${volume_name_active}" != "${volume_name}" ]; then
if [ $verbose -ge 2 ]; then if [ $verbose -ge 2 ]; then
printf "${MAGENTA}Active tape ${GREEN}%s${MAGENTA} needs to be exchanged with ${GREEN}%s${NO_COLOR}\n" \ printf "${MAGENTA}Active tape ${GREEN}%s${MAGENTA} needs to be exchanged with ${GREEN}%s${NO_COLOR}\n" \
"${volume_name_active}" "${volume_name}" "${volume_name_active}" "${volume_name}"
fi fi
mtx_unload mtx_unload
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
mount_tape "${mediapool_name}" "${volume_name}" mount_tape "${mediapool_name}" "${volume_name}"
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
return 0 return 0
else else
@@ -1287,25 +1289,25 @@ mount_tape () {
get_mediapolicy ${mediapool_name} ${volume_name} get_mediapolicy ${mediapool_name} ${volume_name}
if [ ${#volume_mediapolicy} -gt 0 ]; then if [ ${#volume_mediapolicy} -gt 0 ]; then
if [ ${volume_mediapolicy} = "append" ] ; then if [ ${volume_mediapolicy} = "append" ] ; then
if [ $verbose -ge 2 ]; then if [ $verbose -ge 2 ]; then
printf "${MAGENTA}Valid tape mediapolicy: ${GREEN}%s${NO_COLOR}\n" \ printf "${MAGENTA}Valid tape mediapolicy: ${GREEN}%s${NO_COLOR}\n" \
"${volume_mediapolicy}" "${volume_mediapolicy}"
fi fi
#volume_retensiondate="20180101000000" #volume_retensiondate="20180101000000"
get_retensiondate ${mediapool_name} ${volume_name} get_retensiondate ${mediapool_name} ${volume_name}
date_now=$($date_cmd) date_now=$($date_cmd)
compare_date $date_now $volume_retensiondate compare_date $date_now $volume_retensiondate
RET=$? RET=$?
if [ $RET -eq 2 ]; then if [ $RET -eq 2 ]; then
if [ $verbose -ge 1 ]; then if [ $verbose -ge 1 ]; then
printf "${MAGENTA}RetensionDate has exposed, mount the tape\n" printf "${MAGENTA}RetensionDate has exposed, mount the tape${NO_COLOR}\n"
fi fi
ltfs_mount ltfs_mount
return 0 return 0
elif [ $RET -eq 1 ]; then elif [ $RET -eq 1 ]; then
if [ $verbose -ge 1 ]; then if [ $verbose -ge 1 ]; then
printf "${MAGENTA}Tape is bocked via RetensionDate.\n" printf "${MAGENTA}Tape is bocked via RetensionDate.\n"
fi fi
get_poolmember_next "${mediapool_name}" get_poolmember_next "${mediapool_name}"
if test $? -eq 0; then if test $? -eq 0; then
if [ $verbose -ge 2 ]; then if [ $verbose -ge 2 ]; then
@@ -1316,22 +1318,22 @@ mount_tape () {
mount_tape "${mediapool_name}" "${volume_name_next}" mount_tape "${mediapool_name}" "${volume_name_next}"
return 0 return 0
fi fi
fi fi
fi fi
if [ ${volume_mediapolicy} = "overwrite" ] ; then if [ ${volume_mediapolicy} = "overwrite" ] ; then
volume_retensiondate="20180101000000" volume_retensiondate="20180101000000"
get_retensiondate ${mediapool_name} ${volume_name} get_retensiondate ${mediapool_name} ${volume_name}
date_now=$($date_cmd) date_now=$($date_cmd)
compare_date $date_now $volume_retensiondate compare_date $date_now $volume_retensiondate
if [ $? -eq 2 ]; then if [ $? -eq 2 ]; then
# retensiondate has exposed: wipe given tape # retensiondate has exposed: wipe given tape
ltfs_wipe ltfs_wipe
#ltfs_format ${volume_name} ${volume_serial} ltfs_format ${volume_name} ${volume_serial}
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
return 0 return 0
fi fi
fi fi
if [ $? -eq 1 ]; then if [ $? -eq 1 ]; then
# respect active retensiondate: unload given tape # respect active retensiondate: unload given tape
mtx_unload mtx_unload
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
@@ -1384,9 +1386,9 @@ mtx_getlabel () {
"${MTX}" "${changer_device}" "${slot_source}" "${MTX}" "${changer_device}" "${slot_source}"
fi fi
volume_name_active=$(perl -ne ' volume_name_active=$(perl -ne '
/Data Transfer Element (\d+):Full \(Storage Element (\d+) Loaded\)(:VolumeTag =\s*(.+))?/ && print "$4\n";' ${TMPFILE}) /Data Transfer Element (\d+):Full \(Storage Element (\d+) Loaded\)(:VolumeTag =\s*(.+))?/ && print "$4\n";' ${TMPFILE})
volume_name_active=$(echo $volume_name_active | sed -e 's/ *$//g') volume_name_active=$(echo $volume_name_active | sed -e 's/ *$//g')
if [ $verbose -ge 2 ]; then if [ $verbose -ge 2 ] && [ ${#volume_name_active} -gt 0 ]; then
printf "${MAGENTA}Tape in slot ${GREEN}%s${MAGENTA} has Label: ${GREEN}%s${NO_COLOR}\n" \ printf "${MAGENTA}Tape in slot ${GREEN}%s${MAGENTA} has Label: ${GREEN}%s${NO_COLOR}\n" \
"${slot_source}" "${volume_name_active}" "${slot_source}" "${volume_name_active}"
fi fi
@@ -1397,8 +1399,8 @@ mtx_getlabel () {
"${MTX}" "${changer_device}" "${slot_source}" "${MTX}" "${changer_device}" "${slot_source}"
fi fi
volume_name=$(perl -ne ' volume_name=$(perl -ne '
/Storage Element ($ENV{"slot_source"}):Full( :VolumeTag=(.+))?/ && print "$3\n";' ${TMPFILE}) /Storage Element ($ENV{"slot_source"}):Full( :VolumeTag=(.+))?/ && print "$3\n";' ${TMPFILE})
volume_name=$(echo $volume_name | sed -e 's/ *$//g') volume_name=$(echo $volume_name | sed -e 's/ *$//g')
if [ $verbose -ge 2 ]; then if [ $verbose -ge 2 ]; then
printf "${MAGENTA}Tape in slot ${GREEN}%s${MAGENTA} has Label: ${GREEN}%s${NO_COLOR}\n" \ printf "${MAGENTA}Tape in slot ${GREEN}%s${MAGENTA} has Label: ${GREEN}%s${NO_COLOR}\n" \
"${slot_source}" "${volume_name}" "${slot_source}" "${volume_name}"
@@ -2030,7 +2032,7 @@ update_lastwrite () {
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \ cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \
| select(.Name == \"$mediapool_name\") \ | select(.Name == \"$mediapool_name\") \
| .Member[$tape_index] \ | .Member[$tape_index] \
| .LastWrite) \ | .LastWrite) \
|= \"$volume_lastwrite\" ' \ |= \"$volume_lastwrite\" ' \
${mediapools_json} > $XDG_RUNTIME_DIR/$json_file" ${mediapools_json} > $XDG_RUNTIME_DIR/$json_file"
@@ -2082,10 +2084,10 @@ update_mediapool_retensiondays () {
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
cp "$XDG_RUNTIME_DIR/$json_file" "$mediapools_json" cp "$XDG_RUNTIME_DIR/$json_file" "$mediapools_json"
else else
if [ $verbose -ge 1 ]; then if [ $verbose -ge 1 ]; then
printf "${RED}Error:${MAGENTA} Can't update DefaultRetensinDays ${GREEN}'%s'${MAGENTA} in media-pool file ${GREEN}'%s'${NO_COLOR}\n" \ printf "${RED}Error:${MAGENTA} Can't update DefaultRetensinDays ${GREEN}'%s'${MAGENTA} in media-pool file ${GREEN}'%s'${NO_COLOR}\n" \
"$mediapool_defaultretensiondays" "$mediapools_json" "$mediapool_defaultretensiondays" "$mediapools_json"
fi fi
return 1 return 1
fi fi
else else
@@ -2138,7 +2140,7 @@ update_retensiondate () {
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \ cmd="jq --monochrome-output --ascii-output '(.MediaPool[] \
| select(.Name == \"$mediapool_name\") \ | select(.Name == \"$mediapool_name\") \
| .Member[$tape_index] \ | .Member[$tape_index] \
| .RetensionDate) \ | .RetensionDate) \
|= \"$volume_retensiondate\" ' \ |= \"$volume_retensiondate\" ' \
${mediapools_json} > $XDG_RUNTIME_DIR/$json_file" ${mediapools_json} > $XDG_RUNTIME_DIR/$json_file"
@@ -2146,10 +2148,10 @@ update_retensiondate () {
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
cp "$XDG_RUNTIME_DIR/$json_file" "$mediapools_json" cp "$XDG_RUNTIME_DIR/$json_file" "$mediapools_json"
else else
if [ $verbose -ge 1 ]; then if [ $verbose -ge 1 ]; then
printf "${RED}Error:${MAGENTA} Can't update RetensionDate ${GREEN}'%s'${MAGENTA} for Tape ${GREEN}'%s'${NO_COLOR}\n" \ printf "${RED}Error:${MAGENTA} Can't update RetensionDate ${GREEN}'%s'${MAGENTA} for Tape ${GREEN}'%s'${NO_COLOR}\n" \
"$volume_retensiondate" "$volume_name" "$volume_retensiondate" "$volume_name"
fi fi
return 1 return 1
fi fi
else else
@@ -2171,62 +2173,62 @@ Usage: $progname [options]
Options: Options:
--add-retensiondays add RetensionDays to LastWrite attribute for given TapeName in Pool (JSON-File) --add-retensiondays add RetensionDays to LastWrite attribute for given TapeName in Pool (JSON-File)
(input attribute: <mediapool> <volume_name> <days>) (input attribute: <mediapool> <volume_name> <days>)
--color Enable colored output messages --color Enable colored output messages
--get-lastwrite extract LastWrite attribute from given Pool member (JSON-File) --get-lastwrite extract LastWrite attribute from given Pool member (JSON-File)
(input attribute: <mediapool> [<volume_name>]) (input attribute: <mediapool> [<volume_name>])
without given volume_name, extract Pool member that was last witten to without given volume_name, extract Pool member that was last witten to
--get-mediapool-name extract MediaPool name for given VolumeName from configuration (JSON-File) --get-mediapool-name extract MediaPool name for given VolumeName from configuration (JSON-File)
(input attribute: <volume_name>) (input attribute: <volume_name>)
--get-mediapools extract MediaPool names from configuration (JSON-File) --get-mediapools extract MediaPool names from configuration (JSON-File)
--get-mediapolicy extract MediaPolicy attribute from Pool configuration (JSON-File) --get-mediapolicy extract MediaPolicy attribute from Pool configuration (JSON-File)
(input attribute: <mediapool> [<volume_name>]) (input attribute: <mediapool> [<volume_name>])
--get-poolmember extract VolumeName attribute from Pool configuration (JSON-File) --get-poolmember extract VolumeName attribute from Pool configuration (JSON-File)
(input attribute: <mediapool> [<volume_name>]) (input attribute: <mediapool> [<volume_name>])
--get-poolmember-next extract VolumeName for next usable Pool member (JSON-File) --get-poolmember-next extract VolumeName for next usable Pool member (JSON-File)
(input attribute: <mediapool> [volume_name]) (input attribute: <mediapool> [volume_name])
--get-retensiondate extract RetensionDate attribute from Pool configuration (JSON-File) --get-retensiondate extract RetensionDate attribute from Pool configuration (JSON-File)
(input attribute: <mediapool> [<volume_name>]) (input attribute: <mediapool> [<volume_name>])
--get-retensiondays extract DefaultRetensionDays attribute from Pool configuration (JSON-File) --get-retensiondays extract DefaultRetensionDays attribute from Pool configuration (JSON-File)
(input attribute: <mediapool>) (input attribute: <mediapool>)
--get-slot extract Slot attribute from Pool configuration (JSON-File) --get-slot extract Slot attribute from Pool configuration (JSON-File)
(input attribute: <mediapool> [<volume_name>]) (input attribute: <mediapool> [<volume_name>])
--ltfs-getattribute report ltfs extended attribute for mounted tape --ltfs-getattribute report ltfs extended attribute for mounted tape
(input attribute: <ltfs_attribute>) (input attribute: <ltfs_attribute>)
--ltfs-format format tape --ltfs-format format tape
(input attribute: <volume_name> <tape_id>) (input attribute: <volume_name> <tape_id>)
--ltfs-is-mounted returns true, if ltfs tape is already mounted --ltfs-is-mounted returns true, if ltfs tape is already mounted
--ltfs-mount mount a ltfs tape (returns true on success) --ltfs-mount mount a ltfs tape (returns true on success)
--ltfs-reformat reformat mounted tape --ltfs-reformat reformat mounted tape
(input attribute: [<volume_name>]) (input attribute: [<volume_name>])
--ltfs-umount unmount a ltfs tape (returns true on success) --ltfs-umount unmount a ltfs tape (returns true on success)
--media-change Update RetensionDate for last written Pool-Tape and und exchange tapes in slots --media-change Update RetensionDate for last written Pool-Tape and und exchange tapes in slots
(input attribute: <mediapool> [<volume_name>]) (input attribute: <mediapool> [<volume_name>])
--mtx-exchange exchange tapes in slots --mtx-exchange exchange tapes in slots
(input attribute: <slot_source> <slot_target>) (input attribute: <slot_source> <slot_target>)
--mtx-getlabel report tape label/barcode for tape in drive --mtx-getlabel report tape label/barcode for tape in drive
(input attribute: <slot_source>) (input attribute: <slot_source>)
--mtx-inventory run inquriy task for tape-changer --mtx-inventory run inquriy task for tape-changer
--mtx-load load a tape to target slot --mtx-load load a tape to target slot
(input attribute: <slot_source>) (input attribute: <slot_source>)
--mtx-status list changer slot status --mtx-status list changer slot status
--mtx-transfer transfer a tape to target slot --mtx-transfer transfer a tape to target slot
(input attribute: <slot_source> <slot_target>) (input attribute: <slot_source> <slot_target>)
--mtx-unload unload a tape --mtx-unload unload a tape
(input attribute: slot_source drive) (input attribute: slot_source drive)
--mount make tape accessible for OS --mount make tape accessible for OS
(input attribute: <mediapool_name> [<volume_name>]) (input attribute: <mediapool_name> [<volume_name>])
-q, --quiet Be quiet -q, --quiet Be quiet
--update-lastwrite update LastWrite attribute for given TapeName in Pool (JSON-File) --update-lastwrite update LastWrite attribute for given TapeName in Pool (JSON-File)
if no datestring is specified, use "now" if no datestring is specified, use "now"
(input attribute: <mediapool> <volume_name> [<YYYYMMDDHHMMSS> ) (input attribute: <mediapool> <volume_name> [<YYYYMMDDHHMMSS> )
--update-retensiondate update RetensionDate attribute for given TapeName in Pool (JSON-File) --update-retensiondate update RetensionDate attribute for given TapeName in Pool (JSON-File)
if no datestring is specified, use "now" if no datestring is specified, use "now"
(input attribute: <mediapool> <volume_name> [<YYYYMMDDHHMMSS> ) (input attribute: <mediapool> <volume_name> [<YYYYMMDDHHMMSS> )
--update-retensiondays update DefaultRetensionDays attribute for given Pool (JSON-File) --update-retensiondays update DefaultRetensionDays attribute for given Pool (JSON-File)
(input attribute: <mediapool>) (input attribute: <mediapool>)
--use-mtx use mtx loader handling. If not specified, all mtx commands will use --use-mtx use mtx loader handling. If not specified, all mtx commands will use
default device ($default_changer_device) default device ($default_changer_device)
-v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3) -v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3)
--version show program version --version show program version
EOF EOF
@@ -2273,7 +2275,7 @@ case $cmd in
"${volume_name}" "${volume_date}" "${volume_name}" "${volume_date}"
fi fi
fi fi
;; ;;
get-lastwrite) get-lastwrite)
valid_member=0 valid_member=0
get_lastwrite "${mediapool_name}" "${volume_name}" get_lastwrite "${mediapool_name}" "${volume_name}"
@@ -2289,7 +2291,7 @@ case $cmd in
fi fi
fi fi
fi fi
;; ;;
get-mediapolicy) get-mediapolicy)
get_mediapolicy "${mediapool_name}" "${volume_name}" get_mediapolicy "${mediapool_name}" "${volume_name}"
if test $? -gt 0; then if test $? -gt 0; then
@@ -2300,7 +2302,7 @@ case $cmd in
"${volume_name}" "${volume_mediapolicy}" "${volume_name}" "${volume_mediapolicy}"
fi fi
fi fi
;; ;;
get-mediapool-name) get-mediapool-name)
get_mediapool_name "${volume_name}" get_mediapool_name "${volume_name}"
if test $? -gt 0; then if test $? -gt 0; then
@@ -2311,7 +2313,7 @@ case $cmd in
"${mediapool_name}" "${mediapool_name}"
fi fi
fi fi
;; ;;
get-mediapools) get-mediapools)
get_mediapool_names get_mediapool_names
if test $? -gt 0; then if test $? -gt 0; then
@@ -2322,7 +2324,7 @@ case $cmd in
"${mediapool_names}" "${mediapool_names}"
fi fi
fi fi
;; ;;
get-poolmember) get-poolmember)
valid_member=0 valid_member=0
get_poolmember "${mediapool_name}" "${volume_name}" get_poolmember "${mediapool_name}" "${volume_name}"
@@ -2335,7 +2337,7 @@ case $cmd in
fi fi
valid_member=1 valid_member=1
fi fi
;; ;;
get-poolmember-next) get-poolmember-next)
valid_member=0 valid_member=0
get_poolmember_next "${mediapool_name}" "${volume_name}" get_poolmember_next "${mediapool_name}" "${volume_name}"
@@ -2347,7 +2349,7 @@ case $cmd in
"${mediapool_name}" "${volume_name_next}" "${mediapool_name}" "${volume_name_next}"
fi fi
fi fi
;; ;;
get-mediapool-retensiondays) get-mediapool-retensiondays)
get_mediapool_retensiondays "${mediapool_name}" get_mediapool_retensiondays "${mediapool_name}"
if test $? -gt 0; then if test $? -gt 0; then
@@ -2358,7 +2360,7 @@ case $cmd in
"${mediapool_name}" "${mediapool_defaultretensiondays}" "${mediapool_name}" "${mediapool_defaultretensiondays}"
fi fi
fi fi
;; ;;
get-retensiondate) get-retensiondate)
get_retensiondate "${mediapool_name}" "${volume_name}" get_retensiondate "${mediapool_name}" "${volume_name}"
if test $? -gt 0; then if test $? -gt 0; then
@@ -2371,7 +2373,7 @@ case $cmd in
"${volume_name}" "${volume_date}" "${volume_name}" "${volume_date}"
fi fi
fi fi
;; ;;
get-slot) get-slot)
get_slot "${mediapool_name}" "${volume_name}" get_slot "${mediapool_name}" "${volume_name}"
if test $? -eq 0; then if test $? -eq 0; then
@@ -2381,7 +2383,7 @@ case $cmd in
fi fi
fi fi
exit $? exit $?
;; ;;
ltfs-format) ltfs-format)
ltfs_format "${volume_name}" "${tape_id}" ltfs_format "${volume_name}" "${tape_id}"
if test $? -gt 0; then if test $? -gt 0; then
@@ -2405,78 +2407,72 @@ case $cmd in
fi fi
;; ;;
ltfs-is-mounted) ltfs-is-mounted)
if ! $quiet; then
printf "${MAGENTA}LTFS tape mount checke\n"
fi
ltfs_is_mounted ltfs_is_mounted
if test $? -gt 0; then if test $? -gt 0; then
exit 1 exit 1
else
if ! $quiet; then
printf "${MAGENTA}LTFS Tape is-mounted: ${GREEN}true${NO_COLOR}\n"
fi
fi fi
;; ;;
ltfs-mount) ltfs-mount)
if ! $quiet; then
printf "${MAGENTA}LTFS mount Tape\n"
fi
ltfs_mount ltfs_mount
if test $? -gt 0; then if test $? -gt 0; then
exit 1 exit 1
else
if ! $quiet; then
printf "${MAGENTA}LTFS Tape mount: ${GREEN}true${NO_COLOR}\n"
fi
fi fi
;; ;;
ltfs-reformat) ltfs-reformat)
if ! $quiet; then
printf "${MAGENTA}LTFS Tape reformat: ${GREEN}%s${NO_COLOR}\n" \
"${volume_name}"
fi
ltfs_reformat "${volume_name}" ltfs_reformat "${volume_name}"
if test $? -gt 0; then if test $? -gt 0; then
return 1 return 1
else
if ! $quiet; then
printf "${MAGENTA}LTFS Tape reformat: ${GREEN}%s${NO_COLOR}\n" \
"${volume_name}"
fi
fi fi
;; ;;
ltfs-umount) ltfs-umount)
if ! $quiet; then
printf "${MAGENTA}LTFS Tape unmount: ${GREEN}true${NO_COLOR}\n"
fi
ltfs_umount ltfs_umount
if test $? -gt 0; then if test $? -gt 0; then
exit 1 exit 1
else
if ! $quiet; then
printf "${MAGENTA}LTFS Tape unmount: ${GREEN}true${NO_COLOR}\n"
fi
fi fi
;; ;;
media-change) media-change)
if ! $quiet; then
if [ ${#volume_name} -ge 1 ]; then
printf "${MAGENTA}Media change in pool: ${GREEN}%s${NO_COLOR} (Volume-Name: ${GREEN}%s${NO_COLOR})\n" \
"${mediapool_name}" "${volume_name}"
else
printf "${MAGENTA}Media change in pool: ${GREEN}%s${NO_COLOR}\n" \
"${mediapool_name}"
fi
fi
media_change $mediapool_name $volume_name media_change $mediapool_name $volume_name
if test $? -gt 0; then if test $? -gt 0; then
return 1 return 1
else
if ! $quiet; then
if [ ${#volume_name} -ge 1 ]; then
printf "${MAGENTA}Media changed in pool: ${GREEN}%s${NO_COLOR} (Volume-Name: ${GREEN}%s${NO_COLOR})\n" \
"${mediapool_name}" "${volume_name}"
else
printf "${MAGENTA}Media changed in pool: ${GREEN}%s${NO_COLOR}\n" \
"${mediapool_name}"
fi
fi
fi fi
;; ;;
mount) mount)
mount_tape "${mediapool_name}" "${volume_name}" if ! $quiet; then
if test $? -gt 0; then if test ${#volume_name} -ge 1; then
exit 1 printf "${MAGENTA}Mount tape ${GREEN}'%s'${MAGENTA} for ${GREEN}'%s'${NO_COLOR}\n" \
else "${volume_name}" "${mediapool_name}"
if ! $quiet; then else
if test ${#volume_name} -ge 1; then printf "${MAGENTA}Mount next tape for mediapool ${GREEN}'%s'${NO_COLOR}\n" \
printf "${MAGENTA}Tape ${GREEN}'%s'${MAGENTA} for ${GREEN}'%s'${MAGENTA} mounted${NO_COLOR}\n" \ "${mediapool_name}"
"${volume_name}" "${mediapool_name}"
else
printf "${MAGENTA}Next tape for mediapool ${GREEN}'%s'${MAGENTA} mounted${NO_COLOR}\n" \
"${mediapool_name}"
fi
fi fi
fi fi
;; mount_tape "${mediapool_name}" "${volume_name}"
if test $? -gt 0; then
exit 1
fi
;;
mtx-exchange) mtx-exchange)
mtx_exchange "${slot_source}" "${slot_target}" mtx_exchange "${slot_source}" "${slot_target}"
exit $? exit $?
@@ -2519,7 +2515,7 @@ case $cmd in
fi fi
fi fi
fi fi
;; ;;
update-mediapool-retensiondays) update-mediapool-retensiondays)
update_mediapool_retensiondays "${mediapool_name}" "${mediapool_defaultretensiondays}" update_mediapool_retensiondays "${mediapool_name}" "${mediapool_defaultretensiondays}"
if test $? -gt 0; then if test $? -gt 0; then
@@ -2530,7 +2526,7 @@ case $cmd in
"${mediapool_name}" "${mediapool_defaultretensiondays}" "${mediapool_name}" "${mediapool_defaultretensiondays}"
fi fi
fi fi
;; ;;
update-retensiondate) update-retensiondate)
update_retensiondate "${mediapool_name}" "${volume_name}" "${date_string}" update_retensiondate "${mediapool_name}" "${volume_name}" "${date_string}"
if test $? -gt 0; then if test $? -gt 0; then
@@ -2545,5 +2541,5 @@ case $cmd in
fi fi
fi fi
fi fi
;; ;;
esac esac

37
debian/changelog vendored
View File

@@ -1,37 +0,0 @@
dsnap-sync (0.6.4) unstable; urgency=low
[Ralf Zerres]
* branch: master
-- Ralf Zerres <rzerres@networkx.de> Thu, 14 Mar 2019 09:20:02 +0100
dsnap-sync (0.6.0) unstable; urgency=low
[Ralf Zerres]
* branch: master
* multi-config: handling of multiple configurations as a group
* btrfs-archive: full and incremental stream files
* tape: handling of LTFS tapes
* ionice: optional use in target streams
-- Ralf Zerres <rzerres@networkx.de> Sat, 21 Sep 2018 20:00:00 +0200
dsnap-sync (0.5.9) unstable; urgency=low
[Ralf Zerres]
* branch: wip-d2d
* initial tape-admin wrapper
* automounter support for target devices
* bugfixes
* btrfs quota to read valid snapshot size / change size
* color handling in verbosity-levels
-- Ralf Zerres <rzerres@networkx.de> Sat, 25 Aug 2018 20:00:00 +0200
dsnap-sync (0.5.3) unstable; urgency=low
[Ralf Zerres]
* initial package
* adapt compilation to support ubuntu bionic
-- Ralf Zerres <rzerres@networkx.de> Fri, 1 Jun 2018 21:00:01 +0000

1
debian/compat vendored
View File

@@ -1 +0,0 @@
10

25
debian/control vendored
View File

@@ -1,25 +0,0 @@
Source: dsnap-sync
Section: admin
Priority: optional
Maintainer: Networkx GmbH <support@networkx.de>
Build-Depends: debhelper (>= 10), dh-exec
Uploaders: Ralf Zerres <ralf.zerres@networkx.de>
Standards-Version: 4.1.4.1
Homepage: https://github.com/rzerres/dsnap-sync.git
Package: dsnap-sync
Architecture: amd64
Conflicts: snap-sync
Depends: dash, snapper, btrfs-progs, systemd
Suggests: pv, libnotify-bin, mtx, jq, ltfs
Description: Backup and synchronize btrfs filesystems
dsnap-sync is designed to backup btrfs formated filesystems. It takes
advantage of the specific snapshots functionality btrfs offers and i
combines it with managemnet functionality of snapper.
.
dsnap-sync creates backups as btrfs-snapshots on a selectable target
device. Plug in and mount any btrfs-formatted device to your system.
Supported devices may be either local USB drives, but can be as well
remote accessible RAID drives. If possible the backup process will send
incremental snapshots to the target drive. If the snapshot will be
stored on a remote host, it is secured with ssh.

View File

@@ -1,3 +0,0 @@
bin/
etc/
usr/

22
debian/rules vendored
View File

@@ -1,22 +0,0 @@
#!/usr/bin/make -f
# debian/rules
# -*- mode: makefile; coding: utf-8 -*-
export DH_VERBOSE=1
#export DESTROOT=$(CURDIR)/debian/dsnap-sync
export DESTDIR=$(CURDIR)/debian/dsnap-sync
%:
# dh $@ --sourcedirectory=src
dh $@
#override_dh_auto_configure:
# dh_auto_configure --sourcedirectory=src -- --prefix=/usr
override_dh_auto_install:
dh_auto_install -- prefix=/usr
#override_dh_install:
# dh_install
# dh_missing --fail-missing

0
find_snapper_config Normal file → Executable file
View File

View File

@@ -1,8 +1,14 @@
<!-- dsnap-sync README.md --> <!-- dsnap-sync README.md -->
<!-- version: 0.5.9 --> <!-- version: 0.6.9 -->
# dsnap-sync # dsnap-sync
<p align="center">
<span>English</span> |
<a href="../..">Englisch</a>
<!-- a href="../spanish">Spanisch</a> | -->
</p>
## Über ## Über
`dsnap-sync` ist konzipiert, um Backups für btrfs formatierte Dateisysteme `dsnap-sync` ist konzipiert, um Backups für btrfs formatierte Dateisysteme
@@ -138,17 +144,17 @@ Folgende Tools werden verwendet:
erforderlich. Über ein Makefile wird die Installation an den erforderlich. Über ein Makefile wird die Installation an den
richtigen Ziel-Pfad gesteuert. richtigen Ziel-Pfad gesteuert.
# make install # make install
Sollte Ihr System einen unüblichen Speicherort für die snapper Sollte Ihr System einen unüblichen Speicherort für die snapper
Konfigurationen verwenden, kann der Pfad in einer Umgebungs-Variable Konfigurationen verwenden, kann der Pfad in einer Umgebungs-Variable
für die Installation einbezogen werden (`SNAPPER_CONFIG`). für die Installation einbezogen werden (`SNAPPER_CONFIG`).
Arch Linux/Fedora/Gentoo: Arch Linux/Fedora/Gentoo:
# make SNAPPER_CONFIG=/etc/conf.d/snapper install # make SNAPPER_CONFIG=/etc/conf.d/snapper install
Debian/Ubuntu: Debian/Ubuntu:
# make SNAPPER_CONFIG=/etc/default/snapper install # make SNAPPER_CONFIG=/etc/default/snapper install
Die lokalen `snapper` Konfiguration werden um ein neues Template Die lokalen `snapper` Konfiguration werden um ein neues Template
'dsnap-sync' ergänzt. 'dsnap-sync' ergänzt.
@@ -172,41 +178,42 @@ Software Paket Manager.
## Optionen ## Optionen
Usage: dsnap-sync [options] Usage: dsnap-sync [options]
Options: Options:
-a, --automount <path> start automount for given path to get a valid target mountpoint. -a, --automount <path> start automount for given path to get a valid target mountpoint.
-b, --backupdir <prefix> backupdir is a relative path that will be appended to target backup-root -b, --backupdir <prefix> backupdir is a relative path that will be appended to target backup-root
--backuptype <type> Specify backup type <archive | child | parent> --backuptype <type> Specify backup type <archive | child | parent>
--batch no user interaction --batch no user interaction
-d, --description <desc> Change the snapper description. Default: "latest incremental backup" -d, --description <desc> Change the snapper description. Default: "latest incremental backup"
--label-finished <desc> snapper description tagging successful jobs. Default: "dsnap-sync backup" --label-finished <desc> snapper description tagging successful jobs. Default: "dsnap-sync backup"
--label-running <desc> snapper description tagging active jobs. Default: "dsnap-sync in progress" --label-running <desc> snapper description tagging active jobs. Default: "dsnap-sync in progress"
--label-synced <desc> snapper description tagging last synced jobs. --label-synced <desc> snapper description tagging last synced jobs.
Default: "dsnap-sync last incremental" Default: "dsnap-sync last incremental"
--color Enable colored output messages --calculate-btrfs-size Enable calculation of sync-size for given snapshots
-c, --config <config> Specify the snapper configuration to use. Otherwise will perform for each snapper --color Enable colored output messages
configuration. You can select multiple configurations -c, --config <config> Specify the snapper configuration to use. Otherwise will perform for each snapper
(e.g. -c "root" -c "home"; --config root --config home) configuration. You can select multiple configurations
--config-postfix <name> Specify a postfix that will be appended to the destination snapper config name. (e.g. -c "root" -c "home"; --config root --config home)
--dry-run perform a trial run (no changes are written). --config-postfix <name> Specify a postfix that will be appended to the destination snapper config name.
--mediapool Specify the name of the tape MediaPool --dry-run perform a trial run (no changes are written).
-n, --noconfirm Do not ask for confirmation for each configuration. Will still prompt for backup --mediapool Specify the name of the tape MediaPool
--nonotify Disable graphical notification (via dbus) -n, --noconfirm Do not ask for confirmation for each configuration. Will still prompt for backup
--nopv Disable graphical progress output (disable pv) --nonotify Disable graphical notification (via dbus)
--noionice Disable setting of I/O class and priority options on target --nopv Disable graphical progress output (disable pv)
-r, --remote <address> Send the snapshot backup to a remote machine. The snapshot will be sent via ssh --noionice Disable setting of I/O class and priority options on target
You should specify the remote machine's hostname or ip address. The 'root' user -r, --remote <address> Send the snapshot backup to a remote machine. The snapshot will be sent via ssh
must be permitted to login on the remote machine You should specify the remote machine's hostname or ip address. The 'root' user
-p, --port <port> The remote port must be permitted to login on the remote machine
-s, --subvolid <subvlid> Specify the subvolume id of the mounted BTRFS subvolume to back up to. Defaults to 5. -p, --port <port> The remote port
--use-btrfs-quota use btrfs-quota to calculate snapshot size -s, --subvolid <subvlid> Specify the subvolume id of the mounted BTRFS subvolume to back up to. Defaults to 5.
-u, --uuid <UUID> Specify the UUID of the mounted BTRFS subvolume to back up to. Otherwise will prompt --use-btrfs-quota use btrfs-quota to calculate snapshot size
If multiple mount points are found with the same UUID, will prompt for user selection -u, --uuid <UUID> Specify the UUID of the mounted BTRFS subvolume to back up to. Otherwise will prompt
-t, --target <target> Specify the mountpoint of the backup device If multiple mount points are found with the same UUID, will prompt for user selection
--volumename Specify the name of the tape volume -t, --target <target> Specify the mountpoint of the backup device
-v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3) --volumename Specify the name of the tape volume
--version show program version -v, --verbose Be verbose on what's going on (min: --verbose=1, max: --verbose=3)
--version show program version
## Erster Sicherungslauf ## Erster Sicherungslauf
@@ -264,7 +271,7 @@ sorgen. Folgende Sicherungstypen werden unterschieden:
* ein Unterverzeichnis des Konfigurations-Namens (`archive-<config-name>`) * ein Unterverzeichnis des Konfigurations-Namens (`archive-<config-name>`)
* ein Unterverzeichnis der Snapshot-ID (`<snapper-id>`) * ein Unterverzeichnis der Snapshot-ID (`<snapper-id>`)
* der aktuelle btrfs Stream wird im Unterverzeichnis abgelegt * der aktuelle btrfs Stream wird im Unterverzeichnis abgelegt
(`<snapper-id>_[full | incremental].btrfs`) (`<snapper-id>_[full | incremental].btrfs`)
* die Metadaten des Prozesses werden in der Datei `info.xml` abgelegt * die Metadaten des Prozesses werden in der Datei `info.xml` abgelegt
Steht `ltfs` zur Verfügung, ist ein Backup auf Bänder möglich. Steht `ltfs` zur Verfügung, ist ein Backup auf Bänder möglich.
@@ -326,6 +333,66 @@ dann mit den gewohnten Betriebssystem Tools. Eine Open-Source Implementierung
finden Sie z.B. unter finden Sie z.B. unter
[LinearTapeFileSystem](https://github.com/LinearTapeFileSystem/ltfs). [LinearTapeFileSystem](https://github.com/LinearTapeFileSystem/ltfs).
## Rücksicherung (restore)
### Dateisystem (target)
Wurden Daten mit einer nativen btrfs Methode (`btrfs-snapshot`,
`btrfs-clone`) gesichert, befinden sie sich in einer `snapper` kompatiblen
Verzeichnisstruktur auf dem gewählten Target.
Diese Struktur könnte so aussehen:
* └ backups
* └ @\<server-name\>
* └ \<subvol-name\>
* └ \<subvol-id\>
* ├ \.snapshot\>
* └ info.xml
Um Daten zurückzusichern, können Sie entweder native `snapper` Methoden verwenden,
oder auf Betriebssystem Programme zurückgreifen.
* native snapper Methoden
Verwenden Sie `snapper diff <id1>..<id2> [Dateien]`, um Unterschiede in den
gewählten subvol-id's aufzuzeigen.
Verwenden Sie `snapper rollback <id>`, um alle Daten der Sicherung (\<subvol-id\>)
an den Ursprungsort zurückzusichern.
* Betriebssystem Programme
Verwenden Sie Ihren bevorzugten Datei-Manager und wechseln Sie in das
Verzeichnis, in dem sich die Daten des gewünschten Backups (\<subvol-id\>)
befinden. Die Daten wurden als **read-only** Snapshot gesichert.
Sie können von hier aus in jedes gewünsche Zielverzeichnis kopiert werden.
### Band-Sicherung (tape)
Wurden Daten mit der Methode `btrfs-archive` gesichert, speichert `dsnap-sync`
diese in einer `snapper` kompatiblen Datei-Struktur auf dem Band.
Dies Struktur könnte so aussehen:
* └ backups
* └ @\<server-name\>
* └ archive-\<subvol-name\>
* └ \<subvol-id\>
* ├ \<subvol-id\>_full.btrfs
* └ info.xml
In der Datei `info.xml` werden die Metadaten zum Snapshot gespeichert.
Die Bewegungsdaten des snapshots befinden sich in der Datei `\<subvol-id\>_full.btrfs`.
Diese Datei muss mit dem btrfs programm `btrfs-send` auf ein btrfs Verzeichnis zurück
geschrieben werden:
cd /target_btrfs_path
cp /path_to_tape_root/backups/@<server-name>/archive-<subvol-name>/<subvol-id>_full.btrfs .
cat <subvol-id>_full.btrfs | btrfs receive -v .
rm <subvol-id>_full.btrfs
Die man-page zu `btrfs-send` enthält weiterführende Informationen.
## Mitarbeit ## Mitarbeit
Hilfe ist sehr willkommen! Gerne könnt Ihr das Projekt forken und PR's einreichen, Hilfe ist sehr willkommen! Gerne könnt Ihr das Projekt forken und PR's einreichen,
@@ -357,4 +424,4 @@ Diese Arbeit ist unter der [Creative Common License 4.0][License-CC_BY] lizensie
![Creative Common Logo][Logo-CC_BY] ![Creative Common Logo][Logo-CC_BY]
© 2016, 2017 James W. Barnett; © 2016, 2017 James W. Barnett;
© 2017 - 2018 Ralf Zerres © 2017 - 2023 Ralf Zerres

View File

@@ -1,5 +1,25 @@
# Examples # Examples
## Snapper configs cache
To integrate already existing snapshop subfolders located on a given
filesystem, you need to add the snapper config name to the config
file. Then restart the snapper service to reread the config list.
```
[root@dwsbackup dsnap-sync]# cat /etc/conf.d/snapper
## Path: System/Snapper
## Type: string
## Default: ""
# List of snapper configurations.
#SNAPPER_CONFIGS="root data.dwssrv1 home.dwssrv1 machines.dwssrv1 root.dwssrv1 libvirt.dwssrv1 data2.dwssrv1 lxd.dwssrv1 archiv2.dwssrv1 archiv3.dwssrv1 root.dwssrv2"
SNAPPER_CONFIGS="root data.dwssrv1"
[root@dwsbackup dsnap-snyc]# systemctl restart snapperd
```
## Automounter ## Automounter
`dsnap-sync` will take advantage of systemd automount units to incorporate external, `dsnap-sync` will take advantage of systemd automount units to incorporate external,