mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
[fix] Syntax and import error
This commit is contained in:
parent
c2783e452a
commit
e8c0be1e56
5 changed files with 143 additions and 75 deletions
|
@ -1021,6 +1021,9 @@ backup:
|
||||||
arguments:
|
arguments:
|
||||||
name:
|
name:
|
||||||
help: Name of the local backup archive
|
help: Name of the local backup archive
|
||||||
|
-r:
|
||||||
|
full: --repository
|
||||||
|
help: The archive repository (local borg repo use by default)
|
||||||
--system:
|
--system:
|
||||||
help: List of system parts to restore (or all if none is given)
|
help: List of system parts to restore (or all if none is given)
|
||||||
nargs: "*"
|
nargs: "*"
|
||||||
|
|
89
share/config_backup_timer.toml
Normal file
89
share/config_backup_timer.toml
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
|
||||||
|
version = "1.0"
|
||||||
|
i18n = "repository_config"
|
||||||
|
[main]
|
||||||
|
name.en = ""
|
||||||
|
[main.main]
|
||||||
|
name.en = ""
|
||||||
|
optional = false
|
||||||
|
# if method == "tar": question["value"] = False
|
||||||
|
[main.main.description]
|
||||||
|
type = "string"
|
||||||
|
default = ""
|
||||||
|
|
||||||
|
[main.main.is_remote]
|
||||||
|
type = "boolean"
|
||||||
|
yes = true
|
||||||
|
no = false
|
||||||
|
visible = "creation"
|
||||||
|
default = "no"
|
||||||
|
|
||||||
|
[main.main.domain]
|
||||||
|
type = "string"
|
||||||
|
visible = "creation && is_remote"
|
||||||
|
pattern.regexp = '^([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+((xn--)?[^\W_]{2,})$'
|
||||||
|
pattern.error = 'domain_error' # TODO "Please provide a valid domain"
|
||||||
|
default = ""
|
||||||
|
# FIXME: can't be a domain of this instances ?
|
||||||
|
|
||||||
|
[main.main.is_shf]
|
||||||
|
help = ""
|
||||||
|
type = "boolean"
|
||||||
|
yes = true
|
||||||
|
no = false
|
||||||
|
visible = "creation && is_remote"
|
||||||
|
default = false
|
||||||
|
|
||||||
|
[main.main.public_key]
|
||||||
|
type = "alert"
|
||||||
|
style = "info"
|
||||||
|
visible = "creation && is_remote && ! is_shf"
|
||||||
|
|
||||||
|
[main.main.alert]
|
||||||
|
help = ''
|
||||||
|
type = "tags"
|
||||||
|
visible = "is_remote && is_shf"
|
||||||
|
pattern.regexp = '^[\w\+.-]+@([^\W_A-Z]+([-]*[^\W_A-Z]+)*\.)+((xn--)?[^\W_]{2,})$'
|
||||||
|
pattern.error = "alert_error"
|
||||||
|
default = []
|
||||||
|
# "value": alert,
|
||||||
|
|
||||||
|
[main.main.alert_delay]
|
||||||
|
help = ''
|
||||||
|
type = "number"
|
||||||
|
visible = "is_remote && is_shf"
|
||||||
|
min = 1
|
||||||
|
default = 7
|
||||||
|
|
||||||
|
[main.main.quota]
|
||||||
|
type = "string"
|
||||||
|
visible = "is_remote && is_shf"
|
||||||
|
pattern.regexp = '^\d+[MGT]$'
|
||||||
|
pattern.error = '' # TODO ""
|
||||||
|
default = ""
|
||||||
|
|
||||||
|
[main.main.port]
|
||||||
|
type = "number"
|
||||||
|
visible = "is_remote && !is_shf"
|
||||||
|
min = 1
|
||||||
|
max = 65535
|
||||||
|
default = 22
|
||||||
|
|
||||||
|
[main.main.user]
|
||||||
|
type = "string"
|
||||||
|
visible = "is_remote && !is_shf"
|
||||||
|
default = ""
|
||||||
|
|
||||||
|
[main.main.method]
|
||||||
|
type = "select"
|
||||||
|
# "value": method,
|
||||||
|
choices.borg = "BorgBackup (recommended)"
|
||||||
|
choices.tar = "Legacy tar archive mechanism"
|
||||||
|
default = "borg"
|
||||||
|
visible = "!is_remote"
|
||||||
|
|
||||||
|
[main.main.path]
|
||||||
|
type = "path"
|
||||||
|
visible = "!is_remote or (is_remote and !is_shf)"
|
||||||
|
default = "/home/yunohost.backup/archives"
|
||||||
|
|
|
@ -32,13 +32,12 @@ import csv
|
||||||
import tempfile
|
import tempfile
|
||||||
import re
|
import re
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
from datetime import datetime
|
|
||||||
from packaging import version
|
from packaging import version
|
||||||
|
|
||||||
from moulinette import Moulinette, m18n
|
from moulinette import Moulinette, m18n
|
||||||
from moulinette.utils import filesystem
|
from moulinette.utils import filesystem
|
||||||
from moulinette.utils.log import getActionLogger
|
from moulinette.utils.log import getActionLogger
|
||||||
from moulinette.utils.filesystem import mkdir, write_to_yaml, read_yaml, write_to_file
|
from moulinette.utils.filesystem import mkdir, write_to_yaml, read_yaml, write_to_file, rm
|
||||||
from moulinette.utils.process import check_output
|
from moulinette.utils.process import check_output
|
||||||
|
|
||||||
import yunohost.domain
|
import yunohost.domain
|
||||||
|
@ -64,7 +63,7 @@ from yunohost.tools import (
|
||||||
from yunohost.regenconf import regen_conf
|
from yunohost.regenconf import regen_conf
|
||||||
from yunohost.log import OperationLogger, is_unit_operation
|
from yunohost.log import OperationLogger, is_unit_operation
|
||||||
from yunohost.repository import BackupRepository, BackupArchive
|
from yunohost.repository import BackupRepository, BackupArchive
|
||||||
from yunohost.config import ConfigPanel
|
from yunohost.utils.config import ConfigPanel
|
||||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||||
from yunohost.utils.packages import ynh_packages_version
|
from yunohost.utils.packages import ynh_packages_version
|
||||||
from yunohost.utils.filesystem import free_space_in_directory, disk_usage, binary_to_human
|
from yunohost.utils.filesystem import free_space_in_directory, disk_usage, binary_to_human
|
||||||
|
@ -74,7 +73,6 @@ ARCHIVES_PATH = f"{BACKUP_PATH}/archives"
|
||||||
APP_MARGIN_SPACE_SIZE = 100 # In MB
|
APP_MARGIN_SPACE_SIZE = 100 # In MB
|
||||||
CONF_MARGIN_SPACE_SIZE = 10 # IN MB
|
CONF_MARGIN_SPACE_SIZE = 10 # IN MB
|
||||||
POSTINSTALL_ESTIMATE_SPACE_SIZE = 5 # In MB
|
POSTINSTALL_ESTIMATE_SPACE_SIZE = 5 # In MB
|
||||||
MB_ALLOWED_TO_ORGANIZE = 10
|
|
||||||
logger = getActionLogger("yunohost.backup")
|
logger = getActionLogger("yunohost.backup")
|
||||||
|
|
||||||
|
|
||||||
|
@ -367,6 +365,14 @@ class BackupManager:
|
||||||
filesystem.rm(self.work_dir, recursive=True, force=True)
|
filesystem.rm(self.work_dir, recursive=True, force=True)
|
||||||
filesystem.mkdir(self.work_dir, 0o750, parents=True, uid="admin")
|
filesystem.mkdir(self.work_dir, 0o750, parents=True, uid="admin")
|
||||||
|
|
||||||
|
def clean_work_dir(self, umount=True):
|
||||||
|
|
||||||
|
if umount and not _recursive_umount(self.work_dir):
|
||||||
|
raise YunohostError("backup_cleaning_failed")
|
||||||
|
|
||||||
|
if self.is_tmp_work_dir:
|
||||||
|
rm(self.work_dir, True, True)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Backup target management #
|
# Backup target management #
|
||||||
#
|
#
|
||||||
|
@ -875,18 +881,19 @@ class RestoreManager:
|
||||||
return restore_manager.result
|
return restore_manager.result
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, method="tar"):
|
def __init__(self, archive):
|
||||||
"""
|
"""
|
||||||
RestoreManager constructor
|
RestoreManager constructor
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
name -- (string) Archive name
|
archive -- (BackupArchive) The archive to restore
|
||||||
method -- (string) Method name to use to mount the archive
|
|
||||||
"""
|
"""
|
||||||
# Retrieve and open the archive
|
# Retrieve and open the archive
|
||||||
# FIXME this way to get the info is not compatible with copy or custom
|
# FIXME this way to get the info is not compatible with copy or custom
|
||||||
|
self.archive = archive
|
||||||
|
|
||||||
# backup methods
|
# backup methods
|
||||||
self.info = backup_info(name, with_details=True)
|
self.info = archive.info() # FIXME with_details=True
|
||||||
|
|
||||||
from_version = self.info.get("from_yunohost_version", "")
|
from_version = self.info.get("from_yunohost_version", "")
|
||||||
# Remove any '~foobar' in the version ... c.f ~alpha, ~beta version during
|
# Remove any '~foobar' in the version ... c.f ~alpha, ~beta version during
|
||||||
|
@ -896,9 +903,6 @@ class RestoreManager:
|
||||||
if not from_version or version.parse(from_version) < version.parse("4.2.0"):
|
if not from_version or version.parse(from_version) < version.parse("4.2.0"):
|
||||||
raise YunohostValidationError("restore_backup_too_old")
|
raise YunohostValidationError("restore_backup_too_old")
|
||||||
|
|
||||||
self.archive_path = self.info["path"]
|
|
||||||
self.name = name
|
|
||||||
self.method = BackupMethod.create(method, self)
|
|
||||||
self.targets = BackupRestoreTargetsManager()
|
self.targets = BackupRestoreTargetsManager()
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -913,32 +917,6 @@ class RestoreManager:
|
||||||
|
|
||||||
return len(successful_apps) != 0 or len(successful_system) != 0
|
return len(successful_apps) != 0 or len(successful_system) != 0
|
||||||
|
|
||||||
def _read_info_files(self):
|
|
||||||
"""
|
|
||||||
Read the info file from inside an archive
|
|
||||||
"""
|
|
||||||
# Retrieve backup info
|
|
||||||
info_file = os.path.join(self.work_dir, "info.json")
|
|
||||||
try:
|
|
||||||
with open(info_file, "r") as f:
|
|
||||||
self.info = json.load(f)
|
|
||||||
|
|
||||||
# Historically, "system" was "hooks"
|
|
||||||
|
|
||||||
if "system" not in self.info.keys():
|
|
||||||
self.info["system"] = self.info["hooks"]
|
|
||||||
except IOError:
|
|
||||||
logger.debug("unable to load '%s'", info_file, exc_info=1)
|
|
||||||
raise YunohostError(
|
|
||||||
"backup_archive_cant_retrieve_info_json", archive=self.archive_path
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
logger.debug(
|
|
||||||
"restoring from backup '%s' created on %s",
|
|
||||||
self.name,
|
|
||||||
datetime.utcfromtimestamp(self.info["created_at"]),
|
|
||||||
)
|
|
||||||
|
|
||||||
def _postinstall_if_needed(self):
|
def _postinstall_if_needed(self):
|
||||||
"""
|
"""
|
||||||
Post install yunohost if needed
|
Post install yunohost if needed
|
||||||
|
@ -1041,10 +1019,8 @@ class RestoreManager:
|
||||||
|
|
||||||
for hook_path in hook_paths:
|
for hook_path in hook_paths:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Adding restoration script '%s' to the system "
|
f"Adding restoration script '{hook_path}' to the system "
|
||||||
"from the backup archive '%s'",
|
f"from the backup archive '{self.archive.archive_path}'"
|
||||||
hook_path,
|
|
||||||
self.archive_path,
|
|
||||||
)
|
)
|
||||||
self.method.copy(hook_path, custom_restore_hook_folder)
|
self.method.copy(hook_path, custom_restore_hook_folder)
|
||||||
|
|
||||||
|
@ -1096,7 +1072,7 @@ class RestoreManager:
|
||||||
this archive
|
this archive
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.work_dir = os.path.join(BACKUP_PATH, "tmp", self.name)
|
self.work_dir = os.path.join(BACKUP_PATH, "tmp", self.archive.name)
|
||||||
|
|
||||||
if os.path.ismount(self.work_dir):
|
if os.path.ismount(self.work_dir):
|
||||||
logger.debug("An already mounting point '%s' already exists", self.work_dir)
|
logger.debug("An already mounting point '%s' already exists", self.work_dir)
|
||||||
|
@ -1120,9 +1096,7 @@ class RestoreManager:
|
||||||
|
|
||||||
filesystem.mkdir(self.work_dir, parents=True)
|
filesystem.mkdir(self.work_dir, parents=True)
|
||||||
|
|
||||||
self.method.extract()
|
self.archive.extract()
|
||||||
|
|
||||||
self._read_info_files()
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Space computation / checks #
|
# Space computation / checks #
|
||||||
|
@ -1736,7 +1710,7 @@ def backup_create(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def backup_restore(name, system=[], apps=[], force=False):
|
def backup_restore(name, repository, system=[], apps=[], force=False):
|
||||||
"""
|
"""
|
||||||
Restore from a local backup archive
|
Restore from a local backup archive
|
||||||
|
|
||||||
|
@ -1757,6 +1731,9 @@ def backup_restore(name, system=[], apps=[], force=False):
|
||||||
system = []
|
system = []
|
||||||
apps = []
|
apps = []
|
||||||
|
|
||||||
|
if not repository:
|
||||||
|
repository = "local-borg"
|
||||||
|
|
||||||
#
|
#
|
||||||
# Initialize #
|
# Initialize #
|
||||||
#
|
#
|
||||||
|
@ -1766,7 +1743,10 @@ def backup_restore(name, system=[], apps=[], force=False):
|
||||||
elif name.endswith(".tar"):
|
elif name.endswith(".tar"):
|
||||||
name = name[: -len(".tar")]
|
name = name[: -len(".tar")]
|
||||||
|
|
||||||
restore_manager = RestoreManager(name)
|
repo = BackupRepository(repository)
|
||||||
|
archive = BackupArchive(name, repo)
|
||||||
|
|
||||||
|
restore_manager = RestoreManager(archive)
|
||||||
|
|
||||||
restore_manager.set_system_targets(system)
|
restore_manager.set_system_targets(system)
|
||||||
restore_manager.set_apps_targets(apps)
|
restore_manager.set_apps_targets(apps)
|
||||||
|
@ -1827,7 +1807,7 @@ def backup_list(repositories=[], with_info=False, human_readable=False):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: BackupRepository(name).list(with_info)
|
name: BackupRepository(name).list_archives(with_info)
|
||||||
|
|
||||||
for name in repositories or BackupRepository.list(full=False)
|
for name in repositories or BackupRepository.list(full=False)
|
||||||
}
|
}
|
||||||
|
@ -1862,7 +1842,7 @@ def backup_info(name, repository=None, with_details=False, human_readable=False)
|
||||||
repo = BackupRepository(repository)
|
repo = BackupRepository(repository)
|
||||||
archive = BackupArchive(name, repo)
|
archive = BackupArchive(name, repo)
|
||||||
|
|
||||||
return archive.info()
|
return archive.info(with_details=with_details, human_readable=human_readable)
|
||||||
|
|
||||||
|
|
||||||
def backup_delete(name, repository):
|
def backup_delete(name, repository):
|
||||||
|
@ -1969,7 +1949,7 @@ class BackupTimer(ConfigPanel):
|
||||||
Description=Run backup {self.entity} regularly
|
Description=Run backup {self.entity} regularly
|
||||||
|
|
||||||
[Timer]
|
[Timer]
|
||||||
OnCalendar={values['schedule']}
|
OnCalendar={self.values['schedule']}
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=timers.target
|
WantedBy=timers.target
|
||||||
|
@ -1982,7 +1962,7 @@ After=network.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
ExecStart=/usr/bin/yunohost backup create -n '{self.entity}' -r '{repo}' --system --apps ; /usr/bin/yunohost backup prune -n '{self.entity}'
|
ExecStart=/usr/bin/yunohost backup create -n '{self.entity}' -r '{self.repositories}' --system --apps ; /usr/bin/yunohost backup prune -n '{self.entity}'
|
||||||
User=root
|
User=root
|
||||||
Group=root
|
Group=root
|
||||||
""")
|
""")
|
||||||
|
|
|
@ -30,6 +30,7 @@ import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import tarfile
|
import tarfile
|
||||||
import tempfile
|
import tempfile
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
from moulinette import Moulinette, m18n
|
from moulinette import Moulinette, m18n
|
||||||
from moulinette.core import MoulinetteError
|
from moulinette.core import MoulinetteError
|
||||||
|
@ -38,7 +39,7 @@ from moulinette.utils.filesystem import read_file, rm, mkdir
|
||||||
from moulinette.utils.network import download_text
|
from moulinette.utils.network import download_text
|
||||||
from datetime import timedelta, datetime
|
from datetime import timedelta, datetime
|
||||||
|
|
||||||
|
import yunohost.repositories
|
||||||
from yunohost.utils.config import ConfigPanel
|
from yunohost.utils.config import ConfigPanel
|
||||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||||
from yunohost.utils.filesystem import disk_usage, binary_to_human, free_space_in_directory
|
from yunohost.utils.filesystem import disk_usage, binary_to_human, free_space_in_directory
|
||||||
|
@ -48,6 +49,7 @@ logger = getActionLogger('yunohost.repository')
|
||||||
REPOSITORIES_DIR = '/etc/yunohost/repositories'
|
REPOSITORIES_DIR = '/etc/yunohost/repositories'
|
||||||
CACHE_INFO_DIR = "/var/cache/yunohost/{repository}"
|
CACHE_INFO_DIR = "/var/cache/yunohost/{repository}"
|
||||||
REPOSITORY_CONFIG_PATH = "/usr/share/yunohost/other/config_repository.toml"
|
REPOSITORY_CONFIG_PATH = "/usr/share/yunohost/other/config_repository.toml"
|
||||||
|
MB_ALLOWED_TO_ORGANIZE = 10
|
||||||
# TODO split ConfigPanel.get to extract "Format result" part and be able to override it
|
# TODO split ConfigPanel.get to extract "Format result" part and be able to override it
|
||||||
# TODO Migration
|
# TODO Migration
|
||||||
# TODO Remove BackupRepository.get_or_create()
|
# TODO Remove BackupRepository.get_or_create()
|
||||||
|
@ -240,7 +242,7 @@ class BackupRepository(ConfigPanel):
|
||||||
|
|
||||||
return {self.shortname: result}
|
return {self.shortname: result}
|
||||||
|
|
||||||
def list(self, with_info):
|
def list_archives(self, with_info):
|
||||||
archives = self.list_archive_name()
|
archives = self.list_archive_name()
|
||||||
if with_info:
|
if with_info:
|
||||||
d = {}
|
d = {}
|
||||||
|
@ -343,14 +345,14 @@ class BackupArchive:
|
||||||
|
|
||||||
# Cast
|
# Cast
|
||||||
if self.repo.method_name == 'tar':
|
if self.repo.method_name == 'tar':
|
||||||
self.__class__ = TarBackupArchive
|
self.__class__ = yunohost.repositories.tar.TarBackupArchive
|
||||||
elif self.repo.method_name == 'borg':
|
elif self.repo.method_name == 'borg':
|
||||||
self.__class__ = BorgBackupArchive
|
self.__class__ = yunohost.repositories.borg.BorgBackupArchive
|
||||||
else:
|
else:
|
||||||
self.__class__ = HookBackupArchive
|
self.__class__ = yunohost.repositories.hook.HookBackupArchive
|
||||||
|
|
||||||
# Assert archive exists
|
# Assert archive exists
|
||||||
if not isinstance(self.manager, BackupManager) and self.name not in self.repo.list():
|
if self.manager.__class__.__name__ != "BackupManager" and self.name not in self.repo.list_archives():
|
||||||
raise YunohostValidationError("backup_archive_name_unknown", name=name)
|
raise YunohostValidationError("backup_archive_name_unknown", name=name)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -439,17 +441,17 @@ class BackupArchive:
|
||||||
yield f"{leading_dot}apps/{app}"
|
yield f"{leading_dot}apps/{app}"
|
||||||
|
|
||||||
def _get_info_string(self):
|
def _get_info_string(self):
|
||||||
archive_file = "%s/%s.tar" % (self.repo.path, self.name)
|
self.archive_file = "%s/%s.tar" % (self.repo.path, self.name)
|
||||||
|
|
||||||
# Check file exist (even if it's a broken symlink)
|
# Check file exist (even if it's a broken symlink)
|
||||||
if not os.path.lexists(archive_file):
|
if not os.path.lexists(self.archive_file):
|
||||||
archive_file += ".gz"
|
self.archive_file += ".gz"
|
||||||
if not os.path.lexists(archive_file):
|
if not os.path.lexists(self.archive_file):
|
||||||
raise YunohostValidationError("backup_archive_name_unknown", name=self.name)
|
raise YunohostValidationError("backup_archive_name_unknown", name=self.name)
|
||||||
|
|
||||||
# If symlink, retrieve the real path
|
# If symlink, retrieve the real path
|
||||||
if os.path.islink(archive_file):
|
if os.path.islink(self.archive_file):
|
||||||
archive_file = os.path.realpath(archive_file)
|
archive_file = os.path.realpath(self.archive_file)
|
||||||
|
|
||||||
# Raise exception if link is broken (e.g. on unmounted external storage)
|
# Raise exception if link is broken (e.g. on unmounted external storage)
|
||||||
if not os.path.exists(archive_file):
|
if not os.path.exists(archive_file):
|
||||||
|
@ -470,7 +472,7 @@ class BackupArchive:
|
||||||
self.extract("./info.json")
|
self.extract("./info.json")
|
||||||
else:
|
else:
|
||||||
raise YunohostError(
|
raise YunohostError(
|
||||||
"backup_archive_cant_retrieve_info_json", archive=archive_file
|
"backup_archive_cant_retrieve_info_json", archive=self.archive_file
|
||||||
)
|
)
|
||||||
shutil.move(os.path.join(info_dir, "info.json"), info_file)
|
shutil.move(os.path.join(info_dir, "info.json"), info_file)
|
||||||
finally:
|
finally:
|
||||||
|
@ -482,7 +484,7 @@ class BackupArchive:
|
||||||
logger.debug("unable to load '%s'", info_file, exc_info=1)
|
logger.debug("unable to load '%s'", info_file, exc_info=1)
|
||||||
raise YunohostError('backup_invalid_archive')
|
raise YunohostError('backup_invalid_archive')
|
||||||
|
|
||||||
def info(self):
|
def info(self, with_details, human_readable):
|
||||||
|
|
||||||
info_json = self._get_info_string()
|
info_json = self._get_info_string()
|
||||||
if not self._info_json:
|
if not self._info_json:
|
||||||
|
@ -498,14 +500,14 @@ class BackupArchive:
|
||||||
size = info.get("size", 0)
|
size = info.get("size", 0)
|
||||||
if not size:
|
if not size:
|
||||||
tar = tarfile.open(
|
tar = tarfile.open(
|
||||||
archive_file, "r:gz" if archive_file.endswith(".gz") else "r"
|
self.archive_file, "r:gz" if self.archive_file.endswith(".gz") else "r"
|
||||||
)
|
)
|
||||||
size = reduce(
|
size = reduce(
|
||||||
lambda x, y: getattr(x, "size", x) + getattr(y, "size", y), tar.getmembers()
|
lambda x, y: getattr(x, "size", x) + getattr(y, "size", y), tar.getmembers()
|
||||||
)
|
)
|
||||||
tar.close()
|
tar.close()
|
||||||
result = {
|
result = {
|
||||||
"path": repo.archive_path,
|
"path": self.repo.archive_path,
|
||||||
"created_at": datetime.utcfromtimestamp(info["created_at"]),
|
"created_at": datetime.utcfromtimestamp(info["created_at"]),
|
||||||
"description": info["description"],
|
"description": info["description"],
|
||||||
"size": size,
|
"size": size,
|
||||||
|
@ -546,17 +548,11 @@ class BackupArchive:
|
||||||
|
|
||||||
return info
|
return info
|
||||||
|
|
||||||
# TODO move this in BackupManager ?????
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
"""
|
"""
|
||||||
Umount sub directories of working dirextories and delete it if temporary
|
Umount sub directories of working dirextories and delete it if temporary
|
||||||
"""
|
"""
|
||||||
if self.need_organized_files():
|
self.manager.clean_work_dir(self.need_organized_files())
|
||||||
if not _recursive_umount(self.work_dir):
|
|
||||||
raise YunohostError("backup_cleaning_failed")
|
|
||||||
|
|
||||||
if self.manager.is_tmp_work_dir:
|
|
||||||
rm(self.work_dir, True, True)
|
|
||||||
|
|
||||||
def _organize_files(self):
|
def _organize_files(self):
|
||||||
"""
|
"""
|
||||||
|
@ -573,7 +569,7 @@ class BackupArchive:
|
||||||
for path in self.manager.paths_to_backup:
|
for path in self.manager.paths_to_backup:
|
||||||
src = path["source"]
|
src = path["source"]
|
||||||
|
|
||||||
if self.manager is RestoreManager:
|
if self.manager.__class__.__name__ != "RestoreManager":
|
||||||
# TODO Support to run this before a restore (and not only before
|
# TODO Support to run this before a restore (and not only before
|
||||||
# backup). To do that RestoreManager.unorganized_work_dir should
|
# backup). To do that RestoreManager.unorganized_work_dir should
|
||||||
# be implemented
|
# be implemented
|
||||||
|
|
Loading…
Add table
Reference in a new issue