Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option "--multi-fs" #3

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions cbackupmirror.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import coloredlogs
import logging
import sys

from executor.contexts import create_context

import rsync_system_backup as rsb

# Config
SYSLOG_HOST = "192.168.112.11"
SYSLOG_PORT = 514

BACKUP_SOURCE = "[email protected]:/data"
BACKUP_DESTINATION = "/data/backup-data/data"


def setup_logging():
coloredlogs.install(syslog=True)
log = logging.getLogger()

syslog = logging.handlers.SysLogHandler(address=(SYSLOG_HOST, SYSLOG_PORT))
log.addHandler(syslog)

return log


def do_backup():
log = logging.getLogger()

program_opts = {
'backup_enabled': True,
'snapshot_enabled': True,
'rotate_enabled': True,
'sudo_enabled': False,
'dry_run': False,
'multi_fs' : True,
'notifications_enabled': False,
'rsync_verbose_count': 1,
'rsync_show_progress': True,
'source_context': create_context(),
'source': BACKUP_SOURCE,
'destination': rsb.Destination(expression=BACKUP_DESTINATION)
}

try:
# Initialize the program with the command line
# options and execute the requested action(s).
b = rsb.RsyncSystemBackup(**program_opts).execute()
except Exception as e:
if isinstance(e, rsb.exceptions.RsyncSystemBackupError):
# Special handling when the backup disk isn't available.
if isinstance(e, rsb.exceptions.MissingBackupDiskError):
log.info("Skipping backup: %s", e)
return 1
# Known problems shouldn't produce
# an intimidating traceback to users.
log.error("Aborting due to error: %s", e)
else:
# Unhandled exceptions do get a traceback,
# because it may help fix programming errors.
log.exception("Aborting due to unhandled exception!")
return 1
else:
return 0


def main():

log = setup_logging()
log.info("Starting backup script")
return do_backup()


if __name__ == '__main__':
sys.exit(main())
40 changes: 35 additions & 5 deletions rsync_system_backup/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,16 @@ def dry_run(self):
""":data:`True` to simulate the backup without writing any files, :data:`False` otherwise."""
return False

@mutable_property
def checkum(self):
""":data:`True` to enable the checksum verification by rsync instead of usual time checks."""
return False

@mutable_property
def multi_fs(self):
""":data:`True` to allow rsync to cross filesystem boundaries, :data:`False` otherwise."""
return False

@lazy_property(writable=True)
def exclude_list(self):
"""
Expand Down Expand Up @@ -288,6 +298,21 @@ def sudo_enabled(self):
""":data:`True` to run ``rsync`` and snapshot creation with superuser privileges, :data:`False` otherwise."""
return True

@mutable_property
def rsync_verbose_count(self):
""":data: defaults to zero. Represents the number of -V arguments received"""
return 0

@mutable_property
def rsync_quiet_count(self):
""":data: defaults to zero. Represents the number of -Q arguments received"""
return 0

@mutable_property
def rsync_show_progress(self):
""":data: defaults to False. Will have rsync display transfer progress if True"""
return False

def execute(self):
"""
Execute the requested actions (backup, snapshot and/or rotate).
Expand Down Expand Up @@ -514,6 +539,14 @@ def transfer_changes(self):
if self.dry_run:
rsync_command.append('--dry-run')
rsync_command.append('--verbose')
for _ in range(self.rsync_verbose_count):
rsync_command.append('--verbose')
for _ in range(self.rsync_quiet_count):
rsync_command.append('--quiet')
if self.rsync_show_progress:
rsync_command.append('--progress')
if self.checkum:
rsync_command.append('--checksum')
# The following rsync options delete files in the backup
# destination that no longer exist on the local system.
# Due to snapshotting this won't cause data loss.
Expand All @@ -528,11 +561,8 @@ def transfer_changes(self):
rsync_command.append('--xattrs')
# The following rsync option avoids including mounted external
# drives like USB sticks in system backups.
#
# FIXME This will most likely be problematic for users with fancy
# partitioning schemes that e.g. mount /home to a different
# disk or partition.
rsync_command.append('--one-file-system')
if not self.multi_fs:
rsync_command.append('--one-file-system')
# The following rsync options exclude irrelevant directories (to my
# subjective mind) from the system backup.
for pattern in self.excluded_roots:
Expand Down
40 changes: 36 additions & 4 deletions rsync_system_backup/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@
create a backup or snapshot but it does run rsync with the --dry-run
option.

--multi-fs

Allow rsync to cross filesystem boundaries. (has the opposite effect
of rsync option "-x, --one-file-system").

-x, --exclude=PATTERN

Selectively exclude certain files from being included in the backup.
Expand All @@ -145,11 +150,23 @@

-v, --verbose

Make more noise (increase logging verbosity). Can be repeated.
Make more noise (increase logging verbosity for the python app). Can be repeated.

-V, --rsync-verbose

Make the rsync program more noisy. Can be repeated.

-q, --quiet

Make less noise (decrease logging verbosity). Can be repeated.
Make less noise (decrease logging verbosity for the python app). Can be repeated.

-Q, --rsync-quiet

Make the rsync program less noisy.

-p, --rsync-progress

Have rsync show transfer progress.

-h, --help

Expand Down Expand Up @@ -194,10 +211,11 @@ def main():
program_opts = dict()
dest_opts = dict()
try:
options, arguments = getopt.gnu_getopt(sys.argv[1:], 'bsrm:c:t:i:unx:fvqh', [
options, arguments = getopt.gnu_getopt(sys.argv[1:], 'bsrm:c:t:i:unx:fvqhVQp', [
'backup', 'snapshot', 'rotate', 'mount=', 'crypto=', 'tunnel=',
'ionice=', 'no-sudo', 'dry-run', 'exclude=', 'force',
'disable-notifications', 'verbose', 'quiet', 'help',
'disable-notifications', 'verbose', 'quiet', 'help', 'multi-fs',
'rsync-verbose', 'rsync-quiet', 'rsync-progress'
])
for option, value in options:
if option in ('-b', '--backup'):
Expand Down Expand Up @@ -237,12 +255,26 @@ def main():
elif option in ('-x', '--exclude'):
program_opts.setdefault('exclude_list', [])
program_opts['exclude_list'].append(value)
elif option == '--multi-fs':
program_opts['multi_fs'] = True
elif option == '--disable-notifications':
program_opts['notifications_enabled'] = False
elif option in ('-V', '--rsync-verbose'):
if 'rsync_verbose_count' not in program_opts:
program_opts['rsync_verbose_count'] = 1
else:
program_opts['rsync_verbose_count'] = program_opts['rsync_verbose_count'] + 1
elif option in ('-Q', '--rsync-quiet'):
if 'rsync_quiet_count' not in program_opts:
program_opts['rsync_quiet_count'] = 1
else:
program_opts['rsync_quiet_count'] = program_opts['rsync_quiet_count'] + 1
elif option in ('-v', '--verbose'):
coloredlogs.increase_verbosity()
elif option in ('-q', '--quiet'):
coloredlogs.decrease_verbosity()
elif option in ('-p', '--rsync-progress'):
program_opts['rsync_show_progress'] = True
elif option in ('-h', '--help'):
usage(__doc__)
return
Expand Down