mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
[wip] Remote borg repository
This commit is contained in:
parent
9f5b826078
commit
d43a86b136
2 changed files with 60 additions and 23 deletions
|
@ -891,6 +891,10 @@ backup:
|
||||||
action_help: List available local backup archives
|
action_help: List available local backup archives
|
||||||
api: GET /backup/archives
|
api: GET /backup/archives
|
||||||
arguments:
|
arguments:
|
||||||
|
-r:
|
||||||
|
full: --repos
|
||||||
|
help: List archives in these repositories
|
||||||
|
nargs: "*"
|
||||||
-i:
|
-i:
|
||||||
full: --with-info
|
full: --with-info
|
||||||
help: Show backup information for each archive
|
help: Show backup information for each archive
|
||||||
|
|
|
@ -1889,42 +1889,75 @@ class TarBackupMethod(BackupMethod):
|
||||||
class BorgBackupMethod(BackupMethod):
|
class BorgBackupMethod(BackupMethod):
|
||||||
|
|
||||||
def __init__(self, repo=None):
|
def __init__(self, repo=None):
|
||||||
super(TarBackupMethod, self).__init__(repo)
|
super(BorgBackupMethod, self).__init__(repo)
|
||||||
|
|
||||||
if not self.repo.domain:
|
if not self.repo.domain:
|
||||||
filesystem.mkdir(self.repo.path, parent=True)
|
filesystem.mkdir(self.repo.path, parent=True)
|
||||||
else:
|
|
||||||
#Todo Initialize remote repo
|
cmd = ['borg', 'init', self.repo.location]
|
||||||
pass
|
|
||||||
|
if self.repo.quota:
|
||||||
|
cmd += ['--storage-quota', self.repo.quota]
|
||||||
|
borg = self._run_borg_command(cmd)
|
||||||
|
return_code = borg.wait()
|
||||||
|
if return_code:
|
||||||
|
raise YunohostError('backup_borg_init_error')
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def method_name(self):
|
def method_name(self):
|
||||||
return 'borg'
|
return 'borg'
|
||||||
|
|
||||||
|
def need_mount(self):
|
||||||
|
return True
|
||||||
|
|
||||||
def backup(self):
|
def backup(self):
|
||||||
""" Backup prepared files with borg """
|
""" Backup prepared files with borg """
|
||||||
super(BorgBackupMethod, self).backup()
|
|
||||||
|
|
||||||
for path in self.manager.paths_to_backup:
|
archive = self.repo.location + '::' + self.name
|
||||||
source = path['source']
|
cmd = ['borg', 'create', archive, './']
|
||||||
dest = os.path.join(self.repo.path, path['dest'])
|
borg = self._run_borg_command(cmd)
|
||||||
if source == dest:
|
return_code = borg.wait()
|
||||||
logger.debug("Files already copyed")
|
if return_code:
|
||||||
return
|
raise YunohostError('backup_borg_mount_error')
|
||||||
|
|
||||||
dest_parent = os.path.dirname(dest)
|
def mount(self, restore_manager):
|
||||||
if not os.path.exists(dest_parent):
|
""" Extract and mount needed files with borg """
|
||||||
filesystem.mkdir(dest_parent, 0o750, True, uid='admin')
|
super(BorgBackupMethod, self).mount(restore_manager)
|
||||||
|
|
||||||
if os.path.isdir(source):
|
# Export as tar needed files through a pipe
|
||||||
shutil.copytree(source, dest)
|
archive = self.repo.location + '::' + self.name
|
||||||
else:
|
cmd = ['borg', 'export-tar', archive, '-']
|
||||||
shutil.copy(source, dest)
|
borg = self._run_borg_command(cmd, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
# TODO run borg create command
|
# And uncompress it into the working directory
|
||||||
raise YunohostError('backup_borg_not_implemented')
|
untar = subprocess.Popen(['tar', 'x'], cwd=self.work_dir, stdin=borg.stdout)
|
||||||
|
borg_return_code = borg.wait()
|
||||||
|
untar_return_code = untar.wait()
|
||||||
|
if borg_return_code + untar_return_code != 0:
|
||||||
|
err = untar.communicate()[1]
|
||||||
|
raise YunohostError('backup_borg_backup_error')
|
||||||
|
|
||||||
|
def _run_borg_command(self, cmd, stdout=None):
|
||||||
|
env = dict(os.environ)
|
||||||
|
|
||||||
|
if self.repo.domain:
|
||||||
|
# TODO Use the best/good key
|
||||||
|
private_key = "/root/.ssh/ssh_host_ed25519_key"
|
||||||
|
|
||||||
|
# Don't check ssh fingerprint strictly the first time
|
||||||
|
# TODO improve this by publishing and checking this with DNS
|
||||||
|
strict = 'yes' if self.repo.domain in open('/root/.ssh/known_hosts').read() else 'no'
|
||||||
|
env['BORG_RSH'] = "ssh -i %s -oStrictHostKeyChecking=%s"
|
||||||
|
env['BORG_RSH'] = env['BORG_RSH'] % (private_key, strict)
|
||||||
|
|
||||||
|
# In case, borg need a passphrase to get access to the repo
|
||||||
|
if self.repo.passphrase:
|
||||||
|
cmd += ['-e', 'repokey']
|
||||||
|
env['BORG_PASSPHRASE'] = self.repo.passphrase
|
||||||
|
|
||||||
|
return subprocess.Popen(cmd, env=env, stdout=stdout)
|
||||||
|
|
||||||
def mount(self, mnt_path):
|
|
||||||
raise YunohostError('backup_borg_not_implemented')
|
|
||||||
|
|
||||||
|
|
||||||
class CustomBackupMethod(BackupMethod):
|
class CustomBackupMethod(BackupMethod):
|
||||||
|
@ -1943,7 +1976,7 @@ class CustomBackupMethod(BackupMethod):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def method_name(self):
|
def method_name(self):
|
||||||
return 'borg'
|
return 'custom'
|
||||||
|
|
||||||
def need_mount(self):
|
def need_mount(self):
|
||||||
"""Call the backup_method hook to know if we need to organize files
|
"""Call the backup_method hook to know if we need to organize files
|
||||||
|
|
Loading…
Add table
Reference in a new issue