Initial commit

This commit is contained in:
Nicolas Wavrant 2018-01-15 21:36:01 +01:00
commit 996da02e01
8 changed files with 170 additions and 0 deletions

0
backupclient/__init__.py Normal file
View File

View File

View File

@ -0,0 +1,43 @@
import os
import sys
import yaml
from ..src import backup_manager
CONFIG_FILE_LIST = [
'.backup-client.cfg',
'~/.backup-client.cfg',
'/etc/backup-client.cfg',
]
manager_impl_dict = {
'rsync': backup_manager.RsyncBackupManager,
'rdiff-backup': backup_manager.RdiffBackupManager,
}
def main():
for filename in CONFIG_FILE_LIST:
if os.path.exists(filename):
with open(filename) as f:
config = yaml.load(f.read())
break
else:
print('No configuration file found')
sys.exit(1)
try:
backup_manager = manager_impl_dict[config['copy_tool']](
config['copy_tool'],
config['path_list'],
config['remote_path'],
config.get('extra_args', []),
config.get('dry_run', False),
)
except KeyError as e:
print('Option %s not found in configuration file %s' % (e, filename))
sys.exit(1)
except AttributeError as e:
print(e)
sys.exit(1)
backup_manager.start()

View File

View File

@ -0,0 +1,77 @@
import os
import subprocess
import sys
class BackupManager:
def __init__(self, copy_binary, path_list, remote_path, extra_args, dry_run):
self.copy_binary = copy_binary
self.remote_path = remote_path
self.extra_args = extra_args
self.dry_run = dry_run
self.path_list = []
for path in path_list:
path = os.path.abspath(
os.path.expanduser(
os.path.expandvars(path)))
if not os.path.exists(path):
raise AttributeError('Path %s doesn\'t exist' % path)
self.path_list.append(path)
def _build_command_list(self):
raise NotImplementedError()
def start(self):
command_list = self._build_command_list()
for command in command_list:
print('Running : %s' % ' '.join(command))
subprocess.call(
command,
stdout=sys.stdout,
)
class RsyncBackupManager(BackupManager):
def _build_command_list(self):
command_list = []
hostname = os.uname().nodename
short_option_list = '-az'
if self.dry_run:
short_option_list += 'n'
for path in self.path_list:
command_list.append((
self.copy_binary,
short_option_list,
'--relative',
*self.extra_args,
path,
self.remote_path + '/' + hostname,
))
return command_list
class RdiffBackupManager(BackupManager):
def _build_command_list(self):
command_list = []
hostname = os.uname().nodename
if self.dry_run:
self.extra_args.append('--compare-hash')
for path in self.path_list:
command_list.append((
self.copy_binary,
'--create-full-path',
*self.extra_args,
path,
self.remote_path + '/' + hostname,
))
return command_list

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
pyyaml

22
sample/backup-client.cfg Normal file
View File

@ -0,0 +1,22 @@
# Tool used for backuping files.
# Supported values are 'rsync' and 'rdiff-backup'
copy_tool: 'rsync'
# Destination where the files will be sent.
# It can be a remote schema, or a local path.
# remote_path: '/tmp'
remote_path: 'backup@example.com:~'
# Extra argument to pass to the backup command.
# See the man of rsync/rdiff-backup for knowing
# which options are supported
#extra_args:
# - -e
# - ssh -p 2222
# List of local directories/files to backup
path_list:
- /home/user/
# Dry run
#dry_run: true

27
setup.py Normal file
View File

@ -0,0 +1,27 @@
import os
from setuptools import find_packages, setup
# Utility function to read the README file.
# Used for the long_description. It's nice, because now 1) we have a top level
# README file and 2) it's easier to type in the README file than to put a raw
# string in below ...
def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read()
setup(
name = "backupclient",
version = "0.1",
packages = find_packages(),
author = "Nicolas Wavrant",
author_email = "nicolas.wavrant@gmail.com",
description = ("A backup client command. It is a wrapper over rsync and rdiff-backup with a config file parser, to automate backups."),
license = "BSD",
entry_points = {
'console_scripts': [
'backupclient=backupclient.bin.backupclient:main',
],
},
install_requires = [
'pyyaml',
],
)