mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
autopep8 + a few manual tweaks
This commit is contained in:
parent
fb010765bd
commit
115b557b67
34 changed files with 341 additions and 286 deletions
|
@ -137,7 +137,7 @@ def app_fetchlist(url=None, name=None):
|
|||
else:
|
||||
appslists_to_be_fetched = appslists.keys()
|
||||
|
||||
import requests # lazy loading this module for performance reasons
|
||||
import requests # lazy loading this module for performance reasons
|
||||
# Fetch all appslists to be fetched
|
||||
for name in appslists_to_be_fetched:
|
||||
|
||||
|
@ -172,7 +172,7 @@ def app_fetchlist(url=None, name=None):
|
|||
appslist = appslist_request.text
|
||||
try:
|
||||
json.loads(appslist)
|
||||
except ValueError, e:
|
||||
except ValueError as e:
|
||||
logger.error(m18n.n('appslist_retrieve_bad_format',
|
||||
appslist=name))
|
||||
continue
|
||||
|
@ -542,7 +542,7 @@ def app_change_url(operation_logger, auth, app, domain, path):
|
|||
raise YunohostError("app_change_url_failed_nginx_reload", nginx_errors=nginx_errors)
|
||||
|
||||
logger.success(m18n.n("app_change_url_success",
|
||||
app=app, domain=domain, path=path))
|
||||
app=app, domain=domain, path=path))
|
||||
|
||||
hook_callback('post_app_change_url', args=args_list, env=env_dict)
|
||||
|
||||
|
@ -701,7 +701,6 @@ def app_install(operation_logger, auth, app, label=None, args=None, no_remove_on
|
|||
from yunohost.hook import hook_add, hook_remove, hook_exec, hook_callback
|
||||
from yunohost.log import OperationLogger
|
||||
|
||||
|
||||
# Fetch or extract sources
|
||||
try:
|
||||
os.listdir(INSTALL_TMP)
|
||||
|
@ -758,7 +757,7 @@ def app_install(operation_logger, auth, app, label=None, args=None, no_remove_on
|
|||
env_dict["YNH_APP_INSTANCE_NUMBER"] = str(instance_number)
|
||||
|
||||
# Start register change on system
|
||||
operation_logger.extra.update({'env':env_dict})
|
||||
operation_logger.extra.update({'env': env_dict})
|
||||
operation_logger.related_to = [s for s in operation_logger.related_to if s[0] != "app"]
|
||||
operation_logger.related_to.append(("app", app_id))
|
||||
operation_logger.start()
|
||||
|
@ -816,8 +815,8 @@ def app_install(operation_logger, auth, app, label=None, args=None, no_remove_on
|
|||
|
||||
# Execute remove script
|
||||
operation_logger_remove = OperationLogger('remove_on_failed_install',
|
||||
[('app', app_instance_name)],
|
||||
env=env_dict_remove)
|
||||
[('app', app_instance_name)],
|
||||
env=env_dict_remove)
|
||||
operation_logger_remove.start()
|
||||
|
||||
remove_retcode = hook_exec(
|
||||
|
@ -944,7 +943,6 @@ def app_addaccess(auth, apps, users=[]):
|
|||
|
||||
for app in apps:
|
||||
|
||||
|
||||
app_settings = _get_app_settings(app)
|
||||
if not app_settings:
|
||||
continue
|
||||
|
@ -957,7 +955,7 @@ def app_addaccess(auth, apps, users=[]):
|
|||
|
||||
# Start register change on system
|
||||
related_to = [('app', app)]
|
||||
operation_logger= OperationLogger('app_addaccess', related_to)
|
||||
operation_logger = OperationLogger('app_addaccess', related_to)
|
||||
operation_logger.start()
|
||||
|
||||
allowed_users = set()
|
||||
|
@ -1020,7 +1018,7 @@ def app_removeaccess(auth, apps, users=[]):
|
|||
|
||||
# Start register change on system
|
||||
related_to = [('app', app)]
|
||||
operation_logger= OperationLogger('app_removeaccess', related_to)
|
||||
operation_logger = OperationLogger('app_removeaccess', related_to)
|
||||
operation_logger.start()
|
||||
|
||||
if remove_all:
|
||||
|
@ -1034,7 +1032,7 @@ def app_removeaccess(auth, apps, users=[]):
|
|||
if allowed_user not in users:
|
||||
allowed_users.add(allowed_user)
|
||||
|
||||
operation_logger.related_to += [ ('user', x) for x in allowed_users ]
|
||||
operation_logger.related_to += [('user', x) for x in allowed_users]
|
||||
operation_logger.flush()
|
||||
new_users = ','.join(allowed_users)
|
||||
app_setting(app, 'allowed_users', new_users)
|
||||
|
@ -1069,7 +1067,7 @@ def app_clearaccess(auth, apps):
|
|||
|
||||
# Start register change on system
|
||||
related_to = [('app', app)]
|
||||
operation_logger= OperationLogger('app_clearaccess', related_to)
|
||||
operation_logger = OperationLogger('app_clearaccess', related_to)
|
||||
operation_logger.start()
|
||||
|
||||
if 'mode' in app_settings:
|
||||
|
@ -1126,7 +1124,7 @@ def app_makedefault(operation_logger, auth, app, domain=None):
|
|||
|
||||
if domain is None:
|
||||
domain = app_domain
|
||||
operation_logger.related_to.append(('domain',domain))
|
||||
operation_logger.related_to.append(('domain', domain))
|
||||
elif domain not in domain_list(auth)['domains']:
|
||||
raise YunohostError('domain_unknown')
|
||||
|
||||
|
@ -1218,7 +1216,7 @@ def app_register_url(auth, app, domain, path):
|
|||
|
||||
# This line can't be moved on top of file, otherwise it creates an infinite
|
||||
# loop of import with tools.py...
|
||||
from domain import _get_conflicting_apps, _normalize_domain_path
|
||||
from .domain import _get_conflicting_apps, _normalize_domain_path
|
||||
|
||||
domain, path = _normalize_domain_path(domain, path)
|
||||
|
||||
|
@ -1569,10 +1567,10 @@ def app_config_show_panel(app):
|
|||
parsed_values[key] = value
|
||||
|
||||
return_code = hook_exec(config_script,
|
||||
args=["show"],
|
||||
env=env,
|
||||
stdout_callback=parse_stdout,
|
||||
)
|
||||
args=["show"],
|
||||
env=env,
|
||||
stdout_callback=parse_stdout,
|
||||
)
|
||||
|
||||
if return_code != 0:
|
||||
raise Exception("script/config show return value code: %s (considered as an error)", return_code)
|
||||
|
@ -1656,9 +1654,9 @@ def app_config_apply(app, args):
|
|||
logger.warning("Ignore key '%s' from arguments because it is not in the config", key)
|
||||
|
||||
return_code = hook_exec(config_script,
|
||||
args=["apply"],
|
||||
env=env,
|
||||
)
|
||||
args=["apply"],
|
||||
env=env,
|
||||
)
|
||||
|
||||
if return_code != 0:
|
||||
raise Exception("'script/config apply' return value code: %s (considered as an error)", return_code)
|
||||
|
@ -2185,7 +2183,6 @@ def _parse_action_args_in_yunohost_format(args, action_args, auth=None):
|
|||
elif arg_type == 'password':
|
||||
msignals.display(m18n.n('good_practices_about_user_password'))
|
||||
|
||||
|
||||
try:
|
||||
input_string = msignals.prompt(ask_string, is_password)
|
||||
except NotImplementedError:
|
||||
|
@ -2385,7 +2382,7 @@ def _install_appslist_fetch_cron():
|
|||
with open(cron_job_file, "w") as f:
|
||||
f.write('\n'.join(cron_job))
|
||||
|
||||
_set_permissions(cron_job_file, "root", "root", 0755)
|
||||
_set_permissions(cron_job_file, "root", "root", 0o755)
|
||||
|
||||
|
||||
# FIXME - Duplicate from certificate.py, should be moved into a common helper
|
||||
|
@ -2431,7 +2428,7 @@ def _write_appslist_list(appslist_lists):
|
|||
json.dump(appslist_lists, f)
|
||||
except Exception as e:
|
||||
raise YunohostError("Error while writing list of appslist %s: %s" %
|
||||
(APPSLISTS_JSON, str(e)), __raw_msg__=True)
|
||||
(APPSLISTS_JSON, str(e)), __raw_msg__=True)
|
||||
|
||||
|
||||
def _register_new_appslist(url, name):
|
||||
|
@ -2541,7 +2538,7 @@ def _patch_php5(app_folder):
|
|||
continue
|
||||
|
||||
c = "sed -i -e 's@/etc/php5@/etc/php/7.0@g' " \
|
||||
"-e 's@/var/run/php5-fpm@/var/run/php/php7.0-fpm@g' " \
|
||||
"-e 's@php5@php7.0@g' " \
|
||||
"%s" % filename
|
||||
"-e 's@/var/run/php5-fpm@/var/run/php/php7.0-fpm@g' " \
|
||||
"-e 's@php5@php7.0@g' " \
|
||||
"%s" % filename
|
||||
os.system(c)
|
||||
|
|
|
@ -52,6 +52,7 @@ from yunohost.monitor import binary_to_human
|
|||
from yunohost.tools import tools_postinstall
|
||||
from yunohost.service import service_regen_conf
|
||||
from yunohost.log import OperationLogger
|
||||
from functools import reduce
|
||||
|
||||
BACKUP_PATH = '/home/yunohost.backup'
|
||||
ARCHIVES_PATH = '%s/archives' % BACKUP_PATH
|
||||
|
@ -63,6 +64,7 @@ logger = getActionLogger('yunohost.backup')
|
|||
|
||||
|
||||
class BackupRestoreTargetsManager(object):
|
||||
|
||||
"""
|
||||
BackupRestoreTargetsManager manage the targets
|
||||
in BackupManager and RestoreManager
|
||||
|
@ -176,6 +178,7 @@ class BackupRestoreTargetsManager(object):
|
|||
|
||||
|
||||
class BackupManager():
|
||||
|
||||
"""
|
||||
This class collect files to backup in a list and apply one or several
|
||||
backup method on it.
|
||||
|
@ -267,9 +270,9 @@ class BackupManager():
|
|||
self.work_dir = os.path.join(BACKUP_PATH, 'tmp', name)
|
||||
self._init_work_dir()
|
||||
|
||||
###########################################################################
|
||||
# Misc helpers #
|
||||
###########################################################################
|
||||
#
|
||||
# Misc helpers #
|
||||
#
|
||||
|
||||
@property
|
||||
def info(self):
|
||||
|
@ -321,16 +324,16 @@ class BackupManager():
|
|||
# FIXME replace isdir by exists ? manage better the case where the path
|
||||
# exists
|
||||
if not os.path.isdir(self.work_dir):
|
||||
filesystem.mkdir(self.work_dir, 0750, parents=True, uid='admin')
|
||||
filesystem.mkdir(self.work_dir, 0o750, parents=True, uid='admin')
|
||||
elif self.is_tmp_work_dir:
|
||||
logger.debug("temporary directory for backup '%s' already exists",
|
||||
self.work_dir)
|
||||
# FIXME May be we should clean the workdir here
|
||||
raise YunohostError('backup_output_directory_not_empty')
|
||||
|
||||
###########################################################################
|
||||
# Backup target management #
|
||||
###########################################################################
|
||||
#
|
||||
# Backup target management #
|
||||
#
|
||||
|
||||
def set_system_targets(self, system_parts=[]):
|
||||
"""
|
||||
|
@ -380,9 +383,9 @@ class BackupManager():
|
|||
logger.warning(m18n.n('backup_with_no_restore_script_for_app', app=app))
|
||||
self.targets.set_result("apps", app, "Warning")
|
||||
|
||||
###########################################################################
|
||||
# Management of files to backup / "The CSV" #
|
||||
###########################################################################
|
||||
#
|
||||
# Management of files to backup / "The CSV" #
|
||||
#
|
||||
|
||||
def _import_to_list_to_backup(self, tmp_csv):
|
||||
"""
|
||||
|
@ -465,9 +468,9 @@ class BackupManager():
|
|||
logger.error(m18n.n('backup_csv_addition_failed'))
|
||||
self.csv_file.close()
|
||||
|
||||
###########################################################################
|
||||
# File collection from system parts and apps #
|
||||
###########################################################################
|
||||
#
|
||||
# File collection from system parts and apps #
|
||||
#
|
||||
|
||||
def collect_files(self):
|
||||
"""
|
||||
|
@ -602,7 +605,7 @@ class BackupManager():
|
|||
|
||||
restore_hooks_dir = os.path.join(self.work_dir, "hooks", "restore")
|
||||
if not os.path.exists(restore_hooks_dir):
|
||||
filesystem.mkdir(restore_hooks_dir, mode=0750,
|
||||
filesystem.mkdir(restore_hooks_dir, mode=0o750,
|
||||
parents=True, uid='admin')
|
||||
|
||||
restore_hooks = hook_list("restore")["hooks"]
|
||||
|
@ -668,7 +671,7 @@ class BackupManager():
|
|||
logger.debug(m18n.n('backup_running_app_script', app=app))
|
||||
try:
|
||||
# Prepare backup directory for the app
|
||||
filesystem.mkdir(tmp_app_bkp_dir, 0750, True, uid='admin')
|
||||
filesystem.mkdir(tmp_app_bkp_dir, 0o750, True, uid='admin')
|
||||
|
||||
# Copy the app settings to be able to call _common.sh
|
||||
shutil.copytree(app_setting_path, settings_dir)
|
||||
|
@ -702,9 +705,9 @@ class BackupManager():
|
|||
filesystem.rm(tmp_script, force=True)
|
||||
filesystem.rm(env_dict["YNH_BACKUP_CSV"], force=True)
|
||||
|
||||
###########################################################################
|
||||
# Actual backup archive creation / method management #
|
||||
###########################################################################
|
||||
#
|
||||
# Actual backup archive creation / method management #
|
||||
#
|
||||
|
||||
def add(self, method):
|
||||
"""
|
||||
|
@ -776,6 +779,7 @@ class BackupManager():
|
|||
|
||||
|
||||
class RestoreManager():
|
||||
|
||||
"""
|
||||
RestoreManager allow to restore a past backup archive
|
||||
|
||||
|
@ -824,9 +828,9 @@ class RestoreManager():
|
|||
self.method = BackupMethod.create(method)
|
||||
self.targets = BackupRestoreTargetsManager()
|
||||
|
||||
###########################################################################
|
||||
# Misc helpers #
|
||||
###########################################################################
|
||||
#
|
||||
# Misc helpers #
|
||||
#
|
||||
|
||||
@property
|
||||
def success(self):
|
||||
|
@ -876,7 +880,7 @@ class RestoreManager():
|
|||
domain = f.readline().rstrip()
|
||||
except IOError:
|
||||
logger.debug("unable to retrieve current_host from the backup",
|
||||
exc_info=1)
|
||||
exc_info=1)
|
||||
# FIXME include the current_host by default ?
|
||||
raise YunohostError('backup_invalid_archive')
|
||||
|
||||
|
@ -902,9 +906,9 @@ class RestoreManager():
|
|||
logger.warning(m18n.n('restore_cleaning_failed'))
|
||||
filesystem.rm(self.work_dir, True, True)
|
||||
|
||||
###########################################################################
|
||||
# Restore target manangement #
|
||||
###########################################################################
|
||||
#
|
||||
# Restore target manangement #
|
||||
#
|
||||
|
||||
def set_system_targets(self, system_parts=[]):
|
||||
"""
|
||||
|
@ -980,9 +984,9 @@ class RestoreManager():
|
|||
self.info['apps'].keys(),
|
||||
unknown_error)
|
||||
|
||||
###########################################################################
|
||||
# Archive mounting #
|
||||
###########################################################################
|
||||
#
|
||||
# Archive mounting #
|
||||
#
|
||||
|
||||
def mount(self):
|
||||
"""
|
||||
|
@ -1023,9 +1027,9 @@ class RestoreManager():
|
|||
|
||||
self._read_info_files()
|
||||
|
||||
###########################################################################
|
||||
# Space computation / checks #
|
||||
###########################################################################
|
||||
#
|
||||
# Space computation / checks #
|
||||
#
|
||||
|
||||
def _compute_needed_space(self):
|
||||
"""
|
||||
|
@ -1082,13 +1086,13 @@ class RestoreManager():
|
|||
return True
|
||||
elif free_space > needed_space:
|
||||
# TODO Add --force options to avoid the error raising
|
||||
raise YunohostError('restore_may_be_not_enough_disk_space', free_space=free_space, needed_space=needed_space, margin=margin)
|
||||
raise YunohostError('restore_may_be_not_enough_disk_space', free_space=free_space, needed_space=needed_space, margin=margin)
|
||||
else:
|
||||
raise YunohostError('restore_not_enough_disk_space', free_space=free_space, needed_space=needed_space, margin=margin)
|
||||
|
||||
###########################################################################
|
||||
# "Actual restore" (reverse step of the backup collect part) #
|
||||
###########################################################################
|
||||
#
|
||||
# "Actual restore" (reverse step of the backup collect part) #
|
||||
#
|
||||
|
||||
def restore(self):
|
||||
"""
|
||||
|
@ -1104,7 +1108,6 @@ class RestoreManager():
|
|||
# Apply dirty patch to redirect php5 file on php7
|
||||
self._patch_backup_csv_file()
|
||||
|
||||
|
||||
self._restore_system()
|
||||
self._restore_apps()
|
||||
finally:
|
||||
|
@ -1130,7 +1133,7 @@ class RestoreManager():
|
|||
contains_php5 = True
|
||||
row['source'] = row['source'].replace('/etc/php5', '/etc/php/7.0') \
|
||||
.replace('/var/run/php5-fpm', '/var/run/php/php7.0-fpm') \
|
||||
.replace('php5','php7')
|
||||
.replace('php5', 'php7')
|
||||
|
||||
newlines.append(row)
|
||||
except (IOError, OSError, csv.Error) as e:
|
||||
|
@ -1260,7 +1263,7 @@ class RestoreManager():
|
|||
|
||||
# Check if the app has a restore script
|
||||
app_restore_script_in_archive = os.path.join(app_scripts_in_archive,
|
||||
'restore')
|
||||
'restore')
|
||||
if not os.path.isfile(app_restore_script_in_archive):
|
||||
logger.warning(m18n.n('unrestore_app', app=app_instance_name))
|
||||
self.targets.set_result("apps", app_instance_name, "Warning")
|
||||
|
@ -1273,7 +1276,7 @@ class RestoreManager():
|
|||
app_instance_name)
|
||||
app_scripts_new_path = os.path.join(app_settings_new_path, 'scripts')
|
||||
shutil.copytree(app_settings_in_archive, app_settings_new_path)
|
||||
filesystem.chmod(app_settings_new_path, 0400, 0400, True)
|
||||
filesystem.chmod(app_settings_new_path, 0o400, 0o400, True)
|
||||
filesystem.chown(app_scripts_new_path, 'admin', None, True)
|
||||
|
||||
# Copy the app scripts to a writable temporary folder
|
||||
|
@ -1281,7 +1284,7 @@ class RestoreManager():
|
|||
# in the backup method ?
|
||||
tmp_folder_for_app_restore = tempfile.mkdtemp(prefix='restore')
|
||||
copytree(app_scripts_in_archive, tmp_folder_for_app_restore)
|
||||
filesystem.chmod(tmp_folder_for_app_restore, 0550, 0550, True)
|
||||
filesystem.chmod(tmp_folder_for_app_restore, 0o550, 0o550, True)
|
||||
filesystem.chown(tmp_folder_for_app_restore, 'admin', None, True)
|
||||
restore_script = os.path.join(tmp_folder_for_app_restore, 'restore')
|
||||
|
||||
|
@ -1298,7 +1301,7 @@ class RestoreManager():
|
|||
raise_on_error=True,
|
||||
env=env_dict)
|
||||
except:
|
||||
msg = m18n.n('restore_app_failed',app=app_instance_name)
|
||||
msg = m18n.n('restore_app_failed', app=app_instance_name)
|
||||
logger.exception(msg)
|
||||
operation_logger.error(msg)
|
||||
|
||||
|
@ -1314,8 +1317,8 @@ class RestoreManager():
|
|||
env_dict_remove["YNH_APP_INSTANCE_NUMBER"] = str(app_instance_nb)
|
||||
|
||||
operation_logger = OperationLogger('remove_on_failed_restore',
|
||||
[('app', app_instance_name)],
|
||||
env=env_dict_remove)
|
||||
[('app', app_instance_name)],
|
||||
env=env_dict_remove)
|
||||
operation_logger.start()
|
||||
|
||||
# Execute remove script
|
||||
|
@ -1359,12 +1362,13 @@ class RestoreManager():
|
|||
|
||||
return env_var
|
||||
|
||||
###############################################################################
|
||||
# Backup methods #
|
||||
###############################################################################
|
||||
#
|
||||
# Backup methods #
|
||||
#
|
||||
|
||||
|
||||
class BackupMethod(object):
|
||||
|
||||
"""
|
||||
BackupMethod is an abstract class that represents a way to backup and
|
||||
restore a list of files.
|
||||
|
@ -1637,7 +1641,7 @@ class BackupMethod(object):
|
|||
if size > MB_ALLOWED_TO_ORGANIZE:
|
||||
try:
|
||||
i = msignals.prompt(m18n.n('backup_ask_for_copying_if_needed',
|
||||
answers='y/N', size=str(size)))
|
||||
answers='y/N', size=str(size)))
|
||||
except NotImplemented:
|
||||
raise YunohostError('backup_unable_to_organize_files')
|
||||
else:
|
||||
|
@ -1646,7 +1650,7 @@ class BackupMethod(object):
|
|||
|
||||
# Copy unbinded path
|
||||
logger.debug(m18n.n('backup_copying_to_organize_the_archive',
|
||||
size=str(size)))
|
||||
size=str(size)))
|
||||
for path in paths_needed_to_be_copied:
|
||||
dest = os.path.join(self.work_dir, path['dest'])
|
||||
if os.path.isdir(path['source']):
|
||||
|
@ -1686,6 +1690,7 @@ class BackupMethod(object):
|
|||
|
||||
|
||||
class CopyBackupMethod(BackupMethod):
|
||||
|
||||
"""
|
||||
This class just do an uncompress copy of each file in a location, and
|
||||
could be the inverse for restoring
|
||||
|
@ -1712,7 +1717,7 @@ class CopyBackupMethod(BackupMethod):
|
|||
|
||||
dest_parent = os.path.dirname(dest)
|
||||
if not os.path.exists(dest_parent):
|
||||
filesystem.mkdir(dest_parent, 0750, True, uid='admin')
|
||||
filesystem.mkdir(dest_parent, 0o750, True, uid='admin')
|
||||
|
||||
if os.path.isdir(source):
|
||||
shutil.copytree(source, dest)
|
||||
|
@ -1747,6 +1752,7 @@ class CopyBackupMethod(BackupMethod):
|
|||
|
||||
|
||||
class TarBackupMethod(BackupMethod):
|
||||
|
||||
"""
|
||||
This class compress all files to backup in archive.
|
||||
"""
|
||||
|
@ -1777,7 +1783,7 @@ class TarBackupMethod(BackupMethod):
|
|||
"""
|
||||
|
||||
if not os.path.exists(self.repo):
|
||||
filesystem.mkdir(self.repo, 0750, parents=True, uid='admin')
|
||||
filesystem.mkdir(self.repo, 0o750, parents=True, uid='admin')
|
||||
|
||||
# Check free space in output
|
||||
self._check_is_enough_free_space()
|
||||
|
@ -1895,6 +1901,7 @@ class BorgBackupMethod(BackupMethod):
|
|||
|
||||
|
||||
class CustomBackupMethod(BackupMethod):
|
||||
|
||||
"""
|
||||
This class use a bash script/hook "backup_method" to do the
|
||||
backup/restore operations. A user can add his own hook inside
|
||||
|
@ -1958,9 +1965,9 @@ class CustomBackupMethod(BackupMethod):
|
|||
self.manager.description]
|
||||
|
||||
|
||||
###############################################################################
|
||||
# "Front-end" #
|
||||
###############################################################################
|
||||
#
|
||||
# "Front-end" #
|
||||
#
|
||||
|
||||
def backup_create(name=None, description=None, methods=[],
|
||||
output_directory=None, no_compress=False,
|
||||
|
@ -1980,9 +1987,9 @@ def backup_create(name=None, description=None, methods=[],
|
|||
|
||||
# TODO: Add a 'clean' argument to clean output directory
|
||||
|
||||
###########################################################################
|
||||
# Validate / parse arguments #
|
||||
###########################################################################
|
||||
#
|
||||
# Validate / parse arguments #
|
||||
#
|
||||
|
||||
# Validate there is no archive with the same name
|
||||
if name and name in backup_list()['archives']:
|
||||
|
@ -1995,7 +2002,7 @@ def backup_create(name=None, description=None, methods=[],
|
|||
# Check for forbidden folders
|
||||
if output_directory.startswith(ARCHIVES_PATH) or \
|
||||
re.match(r'^/(|(bin|boot|dev|etc|lib|root|run|sbin|sys|usr|var)(|/.*))$',
|
||||
output_directory):
|
||||
output_directory):
|
||||
raise YunohostError('backup_output_directory_forbidden')
|
||||
|
||||
# Check that output directory is empty
|
||||
|
@ -2017,9 +2024,9 @@ def backup_create(name=None, description=None, methods=[],
|
|||
system = []
|
||||
apps = []
|
||||
|
||||
###########################################################################
|
||||
# Intialize #
|
||||
###########################################################################
|
||||
#
|
||||
# Intialize #
|
||||
#
|
||||
|
||||
# Create yunohost archives directory if it does not exists
|
||||
_create_archive_dir()
|
||||
|
@ -2044,9 +2051,9 @@ def backup_create(name=None, description=None, methods=[],
|
|||
backup_manager.set_system_targets(system)
|
||||
backup_manager.set_apps_targets(apps)
|
||||
|
||||
###########################################################################
|
||||
# Collect files and put them in the archive #
|
||||
###########################################################################
|
||||
#
|
||||
# Collect files and put them in the archive #
|
||||
#
|
||||
|
||||
# Collect files to be backup (by calling app backup script / system hooks)
|
||||
backup_manager.collect_files()
|
||||
|
@ -2074,9 +2081,9 @@ def backup_restore(auth, name, system=[], apps=[], force=False):
|
|||
apps -- List of application names to restore
|
||||
"""
|
||||
|
||||
###########################################################################
|
||||
# Validate / parse arguments #
|
||||
###########################################################################
|
||||
#
|
||||
# Validate / parse arguments #
|
||||
#
|
||||
|
||||
# If no --system or --apps given, restore everything
|
||||
if system is None and apps is None:
|
||||
|
@ -2105,9 +2112,9 @@ def backup_restore(auth, name, system=[], apps=[], force=False):
|
|||
# TODO Partial app restore could not work if ldap is not restored before
|
||||
# TODO repair mysql if broken and it's a complete restore
|
||||
|
||||
###########################################################################
|
||||
# Initialize #
|
||||
###########################################################################
|
||||
#
|
||||
# Initialize #
|
||||
#
|
||||
|
||||
restore_manager = RestoreManager(name)
|
||||
|
||||
|
@ -2116,9 +2123,9 @@ def backup_restore(auth, name, system=[], apps=[], force=False):
|
|||
|
||||
restore_manager.assert_enough_free_space()
|
||||
|
||||
###########################################################################
|
||||
# Mount the archive then call the restore for each system part / app #
|
||||
###########################################################################
|
||||
#
|
||||
# Mount the archive then call the restore for each system part / app #
|
||||
#
|
||||
|
||||
restore_manager.mount()
|
||||
restore_manager.restore()
|
||||
|
@ -2156,7 +2163,7 @@ def backup_list(with_info=False, human_readable=False):
|
|||
except ValueError:
|
||||
continue
|
||||
result.append(name)
|
||||
result.sort(key=lambda x: os.path.getctime(os.path.join(ARCHIVES_PATH, x+".tar.gz")))
|
||||
result.sort(key=lambda x: os.path.getctime(os.path.join(ARCHIVES_PATH, x + ".tar.gz")))
|
||||
|
||||
if result and with_info:
|
||||
d = OrderedDict()
|
||||
|
@ -2194,7 +2201,7 @@ def backup_info(name, with_details=False, human_readable=False):
|
|||
# Raise exception if link is broken (e.g. on unmounted external storage)
|
||||
if not os.path.exists(archive_file):
|
||||
raise YunohostError('backup_archive_broken_link',
|
||||
path=archive_file)
|
||||
path=archive_file)
|
||||
|
||||
info_file = "%s/%s.info.json" % (ARCHIVES_PATH, name)
|
||||
|
||||
|
@ -2259,7 +2266,7 @@ def backup_delete(name):
|
|||
"""
|
||||
if name not in backup_list()["archives"]:
|
||||
raise YunohostError('backup_archive_name_unknown',
|
||||
name=name)
|
||||
name=name)
|
||||
|
||||
hook_callback('pre_backup_delete', args=[name])
|
||||
|
||||
|
@ -2277,9 +2284,9 @@ def backup_delete(name):
|
|||
|
||||
logger.success(m18n.n('backup_deleted'))
|
||||
|
||||
###############################################################################
|
||||
# Misc helpers #
|
||||
###############################################################################
|
||||
#
|
||||
# Misc helpers #
|
||||
#
|
||||
|
||||
|
||||
def _create_archive_dir():
|
||||
|
@ -2288,7 +2295,7 @@ def _create_archive_dir():
|
|||
if os.path.lexists(ARCHIVES_PATH):
|
||||
raise YunohostError('backup_output_symlink_dir_broken', path=ARCHIVES_PATH)
|
||||
|
||||
os.mkdir(ARCHIVES_PATH, 0750)
|
||||
os.mkdir(ARCHIVES_PATH, 0o750)
|
||||
|
||||
|
||||
def _call_for_each_path(self, callback, csv_path=None):
|
||||
|
|
|
@ -80,9 +80,9 @@ DNS_RESOLVERS = [
|
|||
"80.67.188.188" # LDN
|
||||
]
|
||||
|
||||
###############################################################################
|
||||
# Front-end stuff #
|
||||
###############################################################################
|
||||
#
|
||||
# Front-end stuff #
|
||||
#
|
||||
|
||||
|
||||
def certificate_status(auth, domain_list, full=False):
|
||||
|
@ -149,7 +149,7 @@ def _certificate_install_selfsigned(domain_list, force=False):
|
|||
for domain in domain_list:
|
||||
|
||||
operation_logger = OperationLogger('selfsigned_cert_install', [('domain', domain)],
|
||||
args={'force': force})
|
||||
args={'force': force})
|
||||
|
||||
# Paths of files and folder we'll need
|
||||
date_tag = datetime.utcnow().strftime("%Y%m%d.%H%M%S")
|
||||
|
@ -215,10 +215,10 @@ def _certificate_install_selfsigned(domain_list, force=False):
|
|||
crt_pem.write(ca_pem.read())
|
||||
|
||||
# Set appropriate permissions
|
||||
_set_permissions(new_cert_folder, "root", "root", 0755)
|
||||
_set_permissions(key_file, "root", "ssl-cert", 0640)
|
||||
_set_permissions(crt_file, "root", "ssl-cert", 0640)
|
||||
_set_permissions(conf_file, "root", "root", 0600)
|
||||
_set_permissions(new_cert_folder, "root", "root", 0o755)
|
||||
_set_permissions(key_file, "root", "ssl-cert", 0o640)
|
||||
_set_permissions(crt_file, "root", "ssl-cert", 0o640)
|
||||
_set_permissions(conf_file, "root", "root", 0o600)
|
||||
|
||||
# Actually enable the certificate we created
|
||||
_enable_certificate(domain, new_cert_folder)
|
||||
|
@ -273,8 +273,8 @@ def _certificate_install_letsencrypt(auth, domain_list, force=False, no_checks=F
|
|||
for domain in domain_list:
|
||||
|
||||
operation_logger = OperationLogger('letsencrypt_cert_install', [('domain', domain)],
|
||||
args={'force': force, 'no_checks': no_checks,
|
||||
'staging': staging})
|
||||
args={'force': force, 'no_checks': no_checks,
|
||||
'staging': staging})
|
||||
logger.info(
|
||||
"Now attempting install of certificate for domain %s!", domain)
|
||||
|
||||
|
@ -298,6 +298,7 @@ def _certificate_install_letsencrypt(auth, domain_list, force=False, no_checks=F
|
|||
logger.error(msg)
|
||||
operation_logger.error(msg)
|
||||
|
||||
|
||||
def certificate_renew(auth, domain_list, force=False, no_checks=False, email=False, staging=False):
|
||||
"""
|
||||
Renew Let's Encrypt certificate for given domains (all by default)
|
||||
|
@ -367,8 +368,8 @@ def certificate_renew(auth, domain_list, force=False, no_checks=False, email=Fal
|
|||
for domain in domain_list:
|
||||
|
||||
operation_logger = OperationLogger('letsencrypt_cert_renew', [('domain', domain)],
|
||||
args={'force': force, 'no_checks': no_checks,
|
||||
'staging': staging, 'email': email})
|
||||
args={'force': force, 'no_checks': no_checks,
|
||||
'staging': staging, 'email': email})
|
||||
|
||||
logger.info(
|
||||
"Now attempting renewing of certificate for domain %s !", domain)
|
||||
|
@ -401,9 +402,10 @@ def certificate_renew(auth, domain_list, force=False, no_checks=False, email=Fal
|
|||
logger.error("Sending email with details to root ...")
|
||||
_email_renewing_failed(domain, e, stack.getvalue())
|
||||
|
||||
###############################################################################
|
||||
# Back-end stuff #
|
||||
###############################################################################
|
||||
#
|
||||
# Back-end stuff #
|
||||
#
|
||||
|
||||
|
||||
def _install_cron():
|
||||
cron_job_file = "/etc/cron.daily/yunohost-certificate-renew"
|
||||
|
@ -412,7 +414,7 @@ def _install_cron():
|
|||
f.write("#!/bin/bash\n")
|
||||
f.write("yunohost domain cert-renew --email\n")
|
||||
|
||||
_set_permissions(cron_job_file, "root", "root", 0755)
|
||||
_set_permissions(cron_job_file, "root", "root", 0o755)
|
||||
|
||||
|
||||
def _email_renewing_failed(domain, exception_message, stack):
|
||||
|
@ -517,8 +519,8 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False):
|
|||
if not os.path.exists(TMP_FOLDER):
|
||||
os.makedirs(TMP_FOLDER)
|
||||
|
||||
_set_permissions(WEBROOT_FOLDER, "root", "www-data", 0650)
|
||||
_set_permissions(TMP_FOLDER, "root", "root", 0640)
|
||||
_set_permissions(WEBROOT_FOLDER, "root", "www-data", 0o650)
|
||||
_set_permissions(TMP_FOLDER, "root", "root", 0o640)
|
||||
|
||||
# Regen conf for dnsmasq if needed
|
||||
_regen_dnsmasq_if_needed()
|
||||
|
@ -529,7 +531,7 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False):
|
|||
|
||||
domain_key_file = "%s/%s.pem" % (TMP_FOLDER, domain)
|
||||
_generate_key(domain_key_file)
|
||||
_set_permissions(domain_key_file, "root", "ssl-cert", 0640)
|
||||
_set_permissions(domain_key_file, "root", "ssl-cert", 0o640)
|
||||
|
||||
_prepare_certificate_signing_request(domain, domain_key_file, TMP_FOLDER)
|
||||
|
||||
|
@ -563,7 +565,7 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False):
|
|||
|
||||
raise YunohostError('certmanager_cert_signing_failed')
|
||||
|
||||
import requests # lazy loading this module for performance reasons
|
||||
import requests # lazy loading this module for performance reasons
|
||||
try:
|
||||
intermediate_certificate = requests.get(INTERMEDIATE_CERTIFICATE_URL, timeout=30).text
|
||||
except requests.exceptions.Timeout as e:
|
||||
|
@ -585,12 +587,12 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False):
|
|||
|
||||
os.makedirs(new_cert_folder)
|
||||
|
||||
_set_permissions(new_cert_folder, "root", "root", 0655)
|
||||
_set_permissions(new_cert_folder, "root", "root", 0o655)
|
||||
|
||||
# Move the private key
|
||||
domain_key_file_finaldest = os.path.join(new_cert_folder, "key.pem")
|
||||
shutil.move(domain_key_file, domain_key_file_finaldest)
|
||||
_set_permissions(domain_key_file_finaldest, "root", "ssl-cert", 0640)
|
||||
_set_permissions(domain_key_file_finaldest, "root", "ssl-cert", 0o640)
|
||||
|
||||
# Write the cert
|
||||
domain_cert_file = os.path.join(new_cert_folder, "crt.pem")
|
||||
|
@ -599,7 +601,7 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False):
|
|||
f.write(signed_certificate)
|
||||
f.write(intermediate_certificate)
|
||||
|
||||
_set_permissions(domain_cert_file, "root", "ssl-cert", 0640)
|
||||
_set_permissions(domain_cert_file, "root", "ssl-cert", 0o640)
|
||||
|
||||
if staging:
|
||||
return
|
||||
|
@ -614,7 +616,7 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False):
|
|||
|
||||
|
||||
def _prepare_certificate_signing_request(domain, key_file, output_folder):
|
||||
from OpenSSL import crypto # lazy loading this module for performance reasons
|
||||
from OpenSSL import crypto # lazy loading this module for performance reasons
|
||||
# Init a request
|
||||
csr = crypto.X509Req()
|
||||
|
||||
|
@ -645,7 +647,7 @@ def _get_status(domain):
|
|||
if not os.path.isfile(cert_file):
|
||||
raise YunohostError('certmanager_no_cert_file', domain=domain, file=cert_file)
|
||||
|
||||
from OpenSSL import crypto # lazy loading this module for performance reasons
|
||||
from OpenSSL import crypto # lazy loading this module for performance reasons
|
||||
try:
|
||||
cert = crypto.load_certificate(
|
||||
crypto.FILETYPE_PEM, open(cert_file).read())
|
||||
|
@ -735,19 +737,19 @@ def _get_status(domain):
|
|||
"ACME_eligible": ACME_eligible
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Misc small stuff ... #
|
||||
###############################################################################
|
||||
#
|
||||
# Misc small stuff ... #
|
||||
#
|
||||
|
||||
|
||||
def _generate_account_key():
|
||||
logger.debug("Generating account key ...")
|
||||
_generate_key(ACCOUNT_KEY_FILE)
|
||||
_set_permissions(ACCOUNT_KEY_FILE, "root", "root", 0400)
|
||||
_set_permissions(ACCOUNT_KEY_FILE, "root", "root", 0o400)
|
||||
|
||||
|
||||
def _generate_key(destination_path):
|
||||
from OpenSSL import crypto # lazy loading this module for performance reasons
|
||||
from OpenSSL import crypto # lazy loading this module for performance reasons
|
||||
k = crypto.PKey()
|
||||
k.generate_key(crypto.TYPE_RSA, KEY_SIZE)
|
||||
|
||||
|
@ -836,7 +838,7 @@ def _dns_ip_match_public_ip(public_ip, domain):
|
|||
|
||||
|
||||
def _domain_is_accessible_through_HTTP(ip, domain):
|
||||
import requests # lazy loading this module for performance reasons
|
||||
import requests # lazy loading this module for performance reasons
|
||||
try:
|
||||
requests.head("http://" + ip, headers={"Host": domain}, timeout=10)
|
||||
except requests.exceptions.Timeout as e:
|
||||
|
|
|
@ -3,7 +3,9 @@ import glob
|
|||
from yunohost.tools import Migration
|
||||
from moulinette.utils.filesystem import chown
|
||||
|
||||
|
||||
class MyMigration(Migration):
|
||||
|
||||
"Change certificates group permissions from 'metronome' to 'ssl-cert'"
|
||||
|
||||
all_certificate_files = glob.glob("/etc/yunohost/certs/*/*.pem")
|
||||
|
|
|
@ -16,6 +16,7 @@ logger = getActionLogger('yunohost.migration')
|
|||
|
||||
|
||||
class MyMigration(Migration):
|
||||
|
||||
"Migrate Dyndns stuff from MD5 TSIG to SHA512 TSIG"
|
||||
|
||||
def backward(self):
|
||||
|
@ -70,7 +71,7 @@ class MyMigration(Migration):
|
|||
os.system("mv /etc/yunohost/dyndns/*+165* /tmp")
|
||||
|
||||
raise YunohostError('migrate_tsig_failed', domain=domain,
|
||||
error_code=str(r.status_code), error=error)
|
||||
error_code=str(r.status_code), error=error)
|
||||
|
||||
# remove old certificates
|
||||
os.system("mv /etc/yunohost/dyndns/*+157* /tmp")
|
||||
|
@ -87,4 +88,3 @@ class MyMigration(Migration):
|
|||
|
||||
logger.info(m18n.n('migrate_tsig_end'))
|
||||
return
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ YUNOHOST_PACKAGES = ["yunohost", "yunohost-admin", "moulinette", "ssowat"]
|
|||
|
||||
|
||||
class MyMigration(Migration):
|
||||
|
||||
"Upgrade the system to Debian Stretch and Yunohost 3.0"
|
||||
|
||||
mode = "manual"
|
||||
|
@ -168,11 +169,11 @@ class MyMigration(Migration):
|
|||
# - switch yunohost's repo to forge
|
||||
for f in sources_list:
|
||||
command = "sed -i -e 's@ jessie @ stretch @g' " \
|
||||
"-e '/backports/ s@^#*@#@' " \
|
||||
"-e 's@ jessie/updates @ stretch/updates @g' " \
|
||||
"-e 's@ jessie-updates @ stretch-updates @g' " \
|
||||
"-e 's@repo.yunohost@forge.yunohost@g' " \
|
||||
"{}".format(f)
|
||||
"-e '/backports/ s@^#*@#@' " \
|
||||
"-e 's@ jessie/updates @ stretch/updates @g' " \
|
||||
"-e 's@ jessie-updates @ stretch-updates @g' " \
|
||||
"-e 's@repo.yunohost@forge.yunohost@g' " \
|
||||
"{}".format(f)
|
||||
os.system(command)
|
||||
|
||||
def get_apps_equivs_packages(self):
|
||||
|
@ -286,7 +287,7 @@ class MyMigration(Migration):
|
|||
# Create tmp directory if it does not exists
|
||||
tmp_dir = os.path.join("/tmp/", self.name)
|
||||
if not os.path.exists(tmp_dir):
|
||||
os.mkdir(tmp_dir, 0700)
|
||||
os.mkdir(tmp_dir, 0o700)
|
||||
|
||||
for f in self.files_to_keep:
|
||||
dest_file = f.strip('/').replace("/", "_")
|
||||
|
|
|
@ -19,6 +19,7 @@ MIGRATION_COMMENT = "; YunoHost note : this file was automatically moved from {}
|
|||
|
||||
|
||||
class MyMigration(Migration):
|
||||
|
||||
"Migrate php5-fpm 'pool' conf files to php7 stuff"
|
||||
|
||||
def migrate(self):
|
||||
|
@ -58,7 +59,7 @@ class MyMigration(Migration):
|
|||
_run_service_command("enable", "php7.0-fpm")
|
||||
os.system("systemctl stop php5-fpm")
|
||||
os.system("systemctl disable php5-fpm")
|
||||
os.system("rm /etc/logrotate.d/php5-fpm") # We remove this otherwise the logrotate cron will be unhappy
|
||||
os.system("rm /etc/logrotate.d/php5-fpm") # We remove this otherwise the logrotate cron will be unhappy
|
||||
|
||||
# Get list of nginx conf file
|
||||
nginx_conf_files = glob.glob("/etc/nginx/conf.d/*.d/*.conf")
|
||||
|
|
|
@ -11,6 +11,7 @@ logger = getActionLogger('yunohost.migration')
|
|||
|
||||
|
||||
class MyMigration(Migration):
|
||||
|
||||
"Migrate DBs from Postgresql 9.4 to 9.6 after migrating to Stretch"
|
||||
|
||||
def migrate(self):
|
||||
|
|
|
@ -15,7 +15,9 @@ from yunohost.tools import Migration
|
|||
logger = getActionLogger('yunohost.migration')
|
||||
SMALL_PWD_LIST = ["yunohost", "olinuxino", "olinux", "raspberry", "admin", "root", "test", "rpi"]
|
||||
|
||||
|
||||
class MyMigration(Migration):
|
||||
|
||||
"Synchronize admin and root passwords"
|
||||
|
||||
def migrate(self):
|
||||
|
|
|
@ -8,8 +8,10 @@ from moulinette.utils.log import getActionLogger
|
|||
from moulinette.utils.filesystem import mkdir, rm
|
||||
|
||||
from yunohost.tools import Migration
|
||||
from yunohost.service import service_regen_conf, _get_conf_hashes, \
|
||||
_calculate_hash, _run_service_command
|
||||
from yunohost.service import service_regen_conf, \
|
||||
_get_conf_hashes, \
|
||||
_calculate_hash, \
|
||||
_run_service_command
|
||||
from yunohost.settings import settings_set
|
||||
from yunohost.utils.error import YunohostError
|
||||
|
||||
|
@ -19,6 +21,7 @@ SSHD_CONF = '/etc/ssh/sshd_config'
|
|||
|
||||
|
||||
class MyMigration(Migration):
|
||||
|
||||
"""
|
||||
This is the first step of a couple of migrations that ensure SSH conf is
|
||||
managed by YunoHost (even if the "from_script" flag is present, which was
|
||||
|
@ -48,7 +51,7 @@ class MyMigration(Migration):
|
|||
|
||||
# Create sshd_config.d dir
|
||||
if not os.path.exists(SSHD_CONF + '.d'):
|
||||
mkdir(SSHD_CONF + '.d', 0755, uid='root', gid='root')
|
||||
mkdir(SSHD_CONF + '.d', 0o755, uid='root', gid='root')
|
||||
|
||||
# Here, we make it so that /etc/ssh/sshd_config is managed
|
||||
# by the regen conf (in particular in the case where the
|
||||
|
|
|
@ -3,7 +3,8 @@ import re
|
|||
from moulinette.utils.log import getActionLogger
|
||||
|
||||
from yunohost.tools import Migration
|
||||
from yunohost.service import service_regen_conf, _get_conf_hashes, \
|
||||
from yunohost.service import service_regen_conf, \
|
||||
_get_conf_hashes, \
|
||||
_calculate_hash
|
||||
from yunohost.settings import settings_set, settings_get
|
||||
from yunohost.utils.error import YunohostError
|
||||
|
@ -12,7 +13,9 @@ logger = getActionLogger('yunohost.migration')
|
|||
|
||||
SSHD_CONF = '/etc/ssh/sshd_config'
|
||||
|
||||
|
||||
class MyMigration(Migration):
|
||||
|
||||
"""
|
||||
In this second step, the admin is asked if it's okay to use
|
||||
the recommended SSH configuration - which also implies
|
||||
|
|
|
@ -115,8 +115,8 @@ def domain_add(operation_logger, auth, domain, dyndns=False):
|
|||
service_regen_conf(names=['nginx', 'metronome', 'dnsmasq', 'postfix'])
|
||||
app_ssowatconf(auth)
|
||||
|
||||
except Exception, e:
|
||||
from sys import exc_info;
|
||||
except Exception as e:
|
||||
from sys import exc_info
|
||||
t, v, tb = exc_info()
|
||||
|
||||
# Force domain removal silently
|
||||
|
|
|
@ -104,7 +104,7 @@ def _dyndns_available(provider, domain):
|
|||
except MoulinetteError as e:
|
||||
logger.error(str(e))
|
||||
raise YunohostError('dyndns_could_not_check_available',
|
||||
domain=domain, provider=provider)
|
||||
domain=domain, provider=provider)
|
||||
|
||||
return r == u"Domain %s is available" % domain
|
||||
|
||||
|
@ -149,7 +149,7 @@ def dyndns_subscribe(operation_logger, subscribe_host="dyndns.yunohost.org", dom
|
|||
with open(key_file) as f:
|
||||
key = f.readline().strip().split(' ', 6)[-1]
|
||||
|
||||
import requests # lazy loading this module for performance reasons
|
||||
import requests # lazy loading this module for performance reasons
|
||||
# Send subscription
|
||||
try:
|
||||
r = requests.post('https://%s/key/%s?key_algo=hmac-sha512' % (subscribe_host, base64.b64encode(key)), data={'subdomain': domain}, timeout=30)
|
||||
|
@ -211,7 +211,7 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None,
|
|||
exception=e,
|
||||
number=migration.number,
|
||||
name=migration.name),
|
||||
exc_info=1)
|
||||
exc_info=1)
|
||||
return
|
||||
|
||||
# Extract 'host', e.g. 'nohost.me' from 'foo.nohost.me'
|
||||
|
@ -225,7 +225,6 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None,
|
|||
'zone %s' % host,
|
||||
]
|
||||
|
||||
|
||||
old_ipv4 = check_output("dig @%s +short %s" % (dyn_host, domain)).strip() or None
|
||||
old_ipv6 = check_output("dig @%s +short aaaa %s" % (dyn_host, domain)).strip() or None
|
||||
|
||||
|
@ -252,7 +251,7 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None,
|
|||
logger.info("Updated needed, going on...")
|
||||
|
||||
dns_conf = _build_dns_conf(domain)
|
||||
del dns_conf["extra"] # Ignore records from the 'extra' category
|
||||
del dns_conf["extra"] # Ignore records from the 'extra' category
|
||||
|
||||
# Delete the old records for all domain/subdomains
|
||||
|
||||
|
@ -273,7 +272,7 @@ def dyndns_update(operation_logger, dyn_host="dyndns.yunohost.org", domain=None,
|
|||
# should be muc.the.domain.tld. or the.domain.tld
|
||||
if record["value"] == "@":
|
||||
record["value"] = domain
|
||||
record["value"] = record["value"].replace(";","\;")
|
||||
record["value"] = record["value"].replace(";", "\;")
|
||||
|
||||
action = "update add {name}.{domain}. {ttl} {type} {value}".format(domain=domain, **record)
|
||||
action = action.replace(" @.", " ")
|
||||
|
|
|
@ -374,10 +374,10 @@ def firewall_upnp(action='status', no_refresh=False):
|
|||
try:
|
||||
# Add new port mapping
|
||||
upnpc.addportmapping(port, protocol, upnpc.lanaddr,
|
||||
port, 'yunohost firewall: port %d' % port, '')
|
||||
port, 'yunohost firewall: port %d' % port, '')
|
||||
except:
|
||||
logger.debug('unable to add port %d using UPnP',
|
||||
port, exc_info=1)
|
||||
port, exc_info=1)
|
||||
enabled = False
|
||||
|
||||
if enabled != firewall['uPnP']['enabled']:
|
||||
|
|
|
@ -354,7 +354,7 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False,
|
|||
# prepend environment variables
|
||||
cmd = '{0} {1}'.format(
|
||||
' '.join(['{0}={1}'.format(k, shell_quote(v))
|
||||
for k, v in env.items()]), cmd)
|
||||
for k, v in env.items()]), cmd)
|
||||
command.append(cmd.format(script=cmd_script, args=cmd_args))
|
||||
|
||||
if logger.isEnabledFor(log.DEBUG):
|
||||
|
@ -369,8 +369,8 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False,
|
|||
)
|
||||
|
||||
if stdinfo:
|
||||
callbacks = ( callbacks[0], callbacks[1],
|
||||
lambda l: logger.info(l.rstrip()))
|
||||
callbacks = (callbacks[0], callbacks[1],
|
||||
lambda l: logger.info(l.rstrip()))
|
||||
|
||||
logger.debug("About to run the command '%s'" % command)
|
||||
|
||||
|
|
|
@ -283,6 +283,7 @@ def is_unit_operation(entities=['app', 'domain', 'service', 'user'],
|
|||
|
||||
|
||||
class OperationLogger(object):
|
||||
|
||||
"""
|
||||
Instances of this class represents unit operation done on the ynh instance.
|
||||
|
||||
|
@ -423,7 +424,7 @@ class OperationLogger(object):
|
|||
else:
|
||||
if is_api:
|
||||
msg = "<strong>" + m18n.n('log_link_to_failed_log',
|
||||
name=self.name, desc=desc) + "</strong>"
|
||||
name=self.name, desc=desc) + "</strong>"
|
||||
else:
|
||||
msg = m18n.n('log_help_to_get_failed_log', name=self.name,
|
||||
desc=desc)
|
||||
|
|
|
@ -288,7 +288,7 @@ def monitor_system(units=None, human_readable=False):
|
|||
else:
|
||||
raise YunohostError('unit_unknown', unit=u)
|
||||
|
||||
if len(units) == 1 and type(result[units[0]]) is not str:
|
||||
if len(units) == 1 and not isinstance(result[units[0]], str):
|
||||
return result[units[0]]
|
||||
return result
|
||||
|
||||
|
@ -404,7 +404,7 @@ def monitor_enable(with_stats=False):
|
|||
|
||||
"""
|
||||
from yunohost.service import (service_status, service_enable,
|
||||
service_start)
|
||||
service_start)
|
||||
|
||||
glances = service_status('glances')
|
||||
if glances['status'] != 'running':
|
||||
|
@ -414,7 +414,7 @@ def monitor_enable(with_stats=False):
|
|||
|
||||
# Install crontab
|
||||
if with_stats:
|
||||
# day: every 5 min # week: every 1 h # month: every 4 h #
|
||||
# day: every 5 min # week: every 1 h # month: every 4 h #
|
||||
rules = ('*/5 * * * * root {cmd} day >> /dev/null\n'
|
||||
'3 * * * * root {cmd} week >> /dev/null\n'
|
||||
'6 */4 * * * root {cmd} month >> /dev/null').format(
|
||||
|
@ -431,7 +431,7 @@ def monitor_disable():
|
|||
|
||||
"""
|
||||
from yunohost.service import (service_status, service_disable,
|
||||
service_stop)
|
||||
service_stop)
|
||||
|
||||
glances = service_status('glances')
|
||||
if glances['status'] != 'inactive':
|
||||
|
|
|
@ -151,6 +151,7 @@ def service_stop(names):
|
|||
raise YunohostError('service_stop_failed', service=name, logs=_get_journalctl_logs(name))
|
||||
logger.debug(m18n.n('service_already_stopped', service=name))
|
||||
|
||||
|
||||
@is_unit_operation()
|
||||
def service_enable(operation_logger, names):
|
||||
"""
|
||||
|
@ -377,7 +378,7 @@ def service_regen_conf(operation_logger, names=[], with_diff=False, force=False,
|
|||
if not names:
|
||||
operation_logger.name_parameter_override = 'all'
|
||||
elif len(names) != 1:
|
||||
operation_logger.name_parameter_override = str(len(operation_logger.related_to))+'_services'
|
||||
operation_logger.name_parameter_override = str(len(operation_logger.related_to)) + '_services'
|
||||
operation_logger.start()
|
||||
|
||||
# Clean pending conf directory
|
||||
|
@ -389,7 +390,7 @@ def service_regen_conf(operation_logger, names=[], with_diff=False, force=False,
|
|||
shutil.rmtree(os.path.join(PENDING_CONF_DIR, name),
|
||||
ignore_errors=True)
|
||||
else:
|
||||
filesystem.mkdir(PENDING_CONF_DIR, 0755, True)
|
||||
filesystem.mkdir(PENDING_CONF_DIR, 0o755, True)
|
||||
|
||||
# Format common hooks arguments
|
||||
common_args = [1 if force else 0, 1 if dry_run else 0]
|
||||
|
@ -400,7 +401,7 @@ def service_regen_conf(operation_logger, names=[], with_diff=False, force=False,
|
|||
def _pre_call(name, priority, path, args):
|
||||
# create the pending conf directory for the service
|
||||
service_pending_path = os.path.join(PENDING_CONF_DIR, name)
|
||||
filesystem.mkdir(service_pending_path, 0755, True, uid='root')
|
||||
filesystem.mkdir(service_pending_path, 0o755, True, uid='root')
|
||||
|
||||
# return the arguments to pass to the script
|
||||
return pre_args + [service_pending_path, ]
|
||||
|
@ -418,7 +419,7 @@ def service_regen_conf(operation_logger, names=[], with_diff=False, force=False,
|
|||
|
||||
if not names:
|
||||
raise YunohostError('service_regenconf_failed',
|
||||
services=', '.join(pre_result['failed']))
|
||||
services=', '.join(pre_result['failed']))
|
||||
|
||||
# Set the processing method
|
||||
_regen = _process_regen_conf if not dry_run else lambda *a, **k: True
|
||||
|
@ -603,7 +604,7 @@ def _run_service_command(action, service):
|
|||
cmd = 'systemctl %s %s' % (action, service)
|
||||
|
||||
need_lock = services[service].get('need_lock', False) \
|
||||
and action in ['start', 'stop', 'restart', 'reload']
|
||||
and action in ['start', 'stop', 'restart', 'reload']
|
||||
|
||||
try:
|
||||
# Launch the command
|
||||
|
@ -637,10 +638,10 @@ def _give_lock(action, service, p):
|
|||
else:
|
||||
systemctl_PID_name = "ControlPID"
|
||||
|
||||
cmd_get_son_PID ="systemctl show %s -p %s" % (service, systemctl_PID_name)
|
||||
cmd_get_son_PID = "systemctl show %s -p %s" % (service, systemctl_PID_name)
|
||||
son_PID = 0
|
||||
# As long as we did not found the PID and that the command is still running
|
||||
while son_PID == 0 and p.poll() == None:
|
||||
while son_PID == 0 and p.poll() is None:
|
||||
# Call systemctl to get the PID
|
||||
# Output of the command is e.g. ControlPID=1234
|
||||
son_PID = subprocess.check_output(cmd_get_son_PID.split()) \
|
||||
|
@ -657,11 +658,12 @@ def _give_lock(action, service, p):
|
|||
|
||||
return son_PID
|
||||
|
||||
|
||||
def _remove_lock(PID_to_remove):
|
||||
# FIXME ironically not concurrency safe because it's not atomic...
|
||||
|
||||
PIDs = filesystem.read_file(MOULINETTE_LOCK).split("\n")
|
||||
PIDs_to_keep = [ PID for PID in PIDs if int(PID) != PID_to_remove ]
|
||||
PIDs_to_keep = [PID for PID in PIDs if int(PID) != PID_to_remove]
|
||||
filesystem.write_to_file(MOULINETTE_LOCK, '\n'.join(PIDs_to_keep))
|
||||
|
||||
|
||||
|
@ -775,6 +777,7 @@ def _find_previous_log_file(file):
|
|||
|
||||
return None
|
||||
|
||||
|
||||
def _get_files_diff(orig_file, new_file, as_string=False, skip_header=True):
|
||||
"""Compare two files and return the differences
|
||||
|
||||
|
@ -919,22 +922,22 @@ def _process_regen_conf(system_conf, new_conf=None, save=True):
|
|||
backup_dir = os.path.dirname(backup_path)
|
||||
|
||||
if not os.path.isdir(backup_dir):
|
||||
filesystem.mkdir(backup_dir, 0755, True)
|
||||
filesystem.mkdir(backup_dir, 0o755, True)
|
||||
|
||||
shutil.copy2(system_conf, backup_path)
|
||||
logger.debug(m18n.n('service_conf_file_backed_up',
|
||||
conf=system_conf, backup=backup_path))
|
||||
conf=system_conf, backup=backup_path))
|
||||
|
||||
try:
|
||||
if not new_conf:
|
||||
os.remove(system_conf)
|
||||
logger.debug(m18n.n('service_conf_file_removed',
|
||||
conf=system_conf))
|
||||
conf=system_conf))
|
||||
else:
|
||||
system_dir = os.path.dirname(system_conf)
|
||||
|
||||
if not os.path.isdir(system_dir):
|
||||
filesystem.mkdir(system_dir, 0755, True)
|
||||
filesystem.mkdir(system_dir, 0o755, True)
|
||||
|
||||
shutil.copyfile(new_conf, system_conf)
|
||||
logger.debug(m18n.n('service_conf_file_updated',
|
||||
|
|
|
@ -88,12 +88,12 @@ def settings_set(key, value):
|
|||
if key_type == "bool":
|
||||
if not isinstance(value, bool):
|
||||
raise YunohostError('global_settings_bad_type_for_setting', setting=key,
|
||||
received_type=type(value).__name__, expected_type=key_type)
|
||||
received_type=type(value).__name__, expected_type=key_type)
|
||||
elif key_type == "int":
|
||||
if not isinstance(value, int) or isinstance(value, bool):
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
value=int(value)
|
||||
value = int(value)
|
||||
except:
|
||||
raise YunohostError('global_settings_bad_type_for_setting',
|
||||
setting=key,
|
||||
|
@ -101,19 +101,19 @@ def settings_set(key, value):
|
|||
expected_type=key_type)
|
||||
else:
|
||||
raise YunohostError('global_settings_bad_type_for_setting', setting=key,
|
||||
received_type=type(value).__name__, expected_type=key_type)
|
||||
received_type=type(value).__name__, expected_type=key_type)
|
||||
elif key_type == "string":
|
||||
if not isinstance(value, basestring):
|
||||
raise YunohostError('global_settings_bad_type_for_setting', setting=key,
|
||||
received_type=type(value).__name__, expected_type=key_type)
|
||||
received_type=type(value).__name__, expected_type=key_type)
|
||||
elif key_type == "enum":
|
||||
if value not in settings[key]["choices"]:
|
||||
raise YunohostError('global_settings_bad_choice_for_enum', setting=key,
|
||||
received_type=type(value).__name__,
|
||||
expected_type=", ".join(settings[key]["choices"]))
|
||||
received_type=type(value).__name__,
|
||||
expected_type=", ".join(settings[key]["choices"]))
|
||||
else:
|
||||
raise YunohostError('global_settings_unknown_type', setting=key,
|
||||
unknown_type=key_type)
|
||||
unknown_type=key_type)
|
||||
|
||||
settings[key]["value"] = value
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ def user_ssh_add_key(auth, username, key, comment):
|
|||
# create empty file to set good permissions
|
||||
write_to_file(authorized_keys_file, "")
|
||||
chown(authorized_keys_file, uid=user["uid"][0])
|
||||
chmod(authorized_keys_file, 0600)
|
||||
chmod(authorized_keys_file, 0o600)
|
||||
|
||||
authorized_keys_content = read_file(authorized_keys_file)
|
||||
|
||||
|
|
|
@ -7,12 +7,14 @@ sys.path.append("..")
|
|||
def pytest_addoption(parser):
|
||||
parser.addoption("--yunodebug", action="store_true", default=False)
|
||||
|
||||
###############################################################################
|
||||
# Tweak translator to raise exceptions if string keys are not defined #
|
||||
###############################################################################
|
||||
#
|
||||
# Tweak translator to raise exceptions if string keys are not defined #
|
||||
#
|
||||
|
||||
|
||||
old_translate = moulinette.core.Translator.translate
|
||||
|
||||
|
||||
def new_translate(self, key, *args, **kwargs):
|
||||
|
||||
if key not in self._translations[self.default_locale].keys():
|
||||
|
@ -21,14 +23,15 @@ def new_translate(self, key, *args, **kwargs):
|
|||
return old_translate(self, key, *args, **kwargs)
|
||||
moulinette.core.Translator.translate = new_translate
|
||||
|
||||
|
||||
def new_m18nn(self, key, *args, **kwargs):
|
||||
return self._namespaces[self._current_namespace].translate(key, *args, **kwargs)
|
||||
|
||||
moulinette.core.Moulinette18n.n = new_m18nn
|
||||
|
||||
###############################################################################
|
||||
# Init the moulinette to have the cli loggers stuff #
|
||||
###############################################################################
|
||||
#
|
||||
# Init the moulinette to have the cli loggers stuff #
|
||||
#
|
||||
|
||||
|
||||
def pytest_cmdline_main(config):
|
||||
|
|
|
@ -17,7 +17,7 @@ APPSLISTS_JSON = '/etc/yunohost/appslists.json'
|
|||
def setup_function(function):
|
||||
|
||||
# Clear all appslist
|
||||
files = glob.glob(REPO_PATH+"/*")
|
||||
files = glob.glob(REPO_PATH + "/*")
|
||||
for f in files:
|
||||
os.remove(f)
|
||||
|
||||
|
@ -42,9 +42,9 @@ def cron_job_is_there():
|
|||
return r == 0
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Test listing of appslists and registering of appslists #
|
||||
###############################################################################
|
||||
#
|
||||
# Test listing of appslists and registering of appslists #
|
||||
#
|
||||
|
||||
|
||||
def test_appslist_list_empty():
|
||||
|
@ -103,9 +103,9 @@ def test_appslist_list_register_conflict_url():
|
|||
assert "plopette" not in appslist_dict.keys()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Test fetching of appslists #
|
||||
###############################################################################
|
||||
#
|
||||
# Test fetching of appslists #
|
||||
#
|
||||
|
||||
|
||||
def test_appslist_fetch():
|
||||
|
@ -244,9 +244,9 @@ def test_appslist_fetch_timeout():
|
|||
app_fetchlist()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Test remove of appslist #
|
||||
###############################################################################
|
||||
#
|
||||
# Test remove of appslist #
|
||||
#
|
||||
|
||||
|
||||
def test_appslist_remove():
|
||||
|
@ -274,9 +274,9 @@ def test_appslist_remove_unknown():
|
|||
app_removelist("dummy")
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Test migration from legacy appslist system #
|
||||
###############################################################################
|
||||
#
|
||||
# Test migration from legacy appslist system #
|
||||
#
|
||||
|
||||
|
||||
def add_legacy_cron(name, url):
|
||||
|
|
|
@ -22,6 +22,7 @@ def setup_function(function):
|
|||
except:
|
||||
pass
|
||||
|
||||
|
||||
def teardown_function(function):
|
||||
|
||||
try:
|
||||
|
@ -50,18 +51,18 @@ def test_urlavailable():
|
|||
def test_registerurl():
|
||||
|
||||
app_install(auth, "./tests/apps/register_url_app_ynh",
|
||||
args="domain=%s&path=%s" % (maindomain, "/urlregisterapp"))
|
||||
args="domain=%s&path=%s" % (maindomain, "/urlregisterapp"))
|
||||
|
||||
assert not domain_url_available(auth, maindomain, "/urlregisterapp")
|
||||
|
||||
# Try installing at same location
|
||||
with pytest.raises(YunohostError):
|
||||
app_install(auth, "./tests/apps/register_url_app_ynh",
|
||||
args="domain=%s&path=%s" % (maindomain, "/urlregisterapp"))
|
||||
args="domain=%s&path=%s" % (maindomain, "/urlregisterapp"))
|
||||
|
||||
|
||||
def test_registerurl_baddomain():
|
||||
|
||||
with pytest.raises(YunohostError):
|
||||
app_install(auth, "./tests/apps/register_url_app_ynh",
|
||||
args="domain=%s&path=%s" % ("yolo.swag", "/urlregisterapp"))
|
||||
args="domain=%s&path=%s" % ("yolo.swag", "/urlregisterapp"))
|
||||
|
|
|
@ -22,6 +22,7 @@ AUTH_IDENTIFIER = ('ldap', 'ldap-anonymous')
|
|||
AUTH_PARAMETERS = {'uri': 'ldap://localhost:389', 'base_dn': 'dc=yunohost,dc=org'}
|
||||
auth = None
|
||||
|
||||
|
||||
def setup_function(function):
|
||||
|
||||
global maindomain
|
||||
|
@ -87,9 +88,9 @@ def teardown_function(function):
|
|||
shutil.rmtree("/opt/test_backup_output_directory")
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Helpers #
|
||||
###############################################################################
|
||||
#
|
||||
# Helpers #
|
||||
#
|
||||
|
||||
def app_is_installed(app):
|
||||
|
||||
|
@ -111,6 +112,7 @@ def backup_test_dependencies_are_met():
|
|||
|
||||
return True
|
||||
|
||||
|
||||
def tmp_backup_directory_is_empty():
|
||||
|
||||
if not os.path.exists("/home/yunohost.backup/tmp/"):
|
||||
|
@ -118,6 +120,7 @@ def tmp_backup_directory_is_empty():
|
|||
else:
|
||||
return len(os.listdir('/home/yunohost.backup/tmp/')) == 0
|
||||
|
||||
|
||||
def clean_tmp_backup_directory():
|
||||
|
||||
if tmp_backup_directory_is_empty():
|
||||
|
@ -125,10 +128,10 @@ def clean_tmp_backup_directory():
|
|||
|
||||
mount_lines = subprocess.check_output("mount").split("\n")
|
||||
|
||||
points_to_umount = [ line.split(" ")[2]
|
||||
for line in mount_lines
|
||||
if len(line) >= 3
|
||||
and line.split(" ")[2].startswith("/home/yunohost.backup/tmp") ]
|
||||
points_to_umount = [line.split(" ")[2]
|
||||
for line in mount_lines
|
||||
if len(line) >= 3
|
||||
and line.split(" ")[2].startswith("/home/yunohost.backup/tmp")]
|
||||
|
||||
for point in reversed(points_to_umount):
|
||||
os.system("umount %s" % point)
|
||||
|
@ -138,6 +141,7 @@ def clean_tmp_backup_directory():
|
|||
|
||||
shutil.rmtree("/home/yunohost.backup/tmp/")
|
||||
|
||||
|
||||
def reset_ssowat_conf():
|
||||
|
||||
# Make sure we have a ssowat
|
||||
|
@ -191,9 +195,10 @@ def add_archive_system_from_2p4():
|
|||
os.system("cp ./tests/apps/backup_system_from_2p4/backup.tar.gz \
|
||||
/home/yunohost.backup/archives/backup_system_from_2p4.tar.gz")
|
||||
|
||||
###############################################################################
|
||||
# System backup #
|
||||
###############################################################################
|
||||
#
|
||||
# System backup #
|
||||
#
|
||||
|
||||
|
||||
def test_backup_only_ldap():
|
||||
|
||||
|
@ -220,9 +225,10 @@ def test_backup_system_part_that_does_not_exists(mocker):
|
|||
m18n.n.assert_any_call('backup_hook_unknown', hook="yolol")
|
||||
m18n.n.assert_any_call('backup_nothings_done')
|
||||
|
||||
###############################################################################
|
||||
# System backup and restore #
|
||||
###############################################################################
|
||||
#
|
||||
# System backup and restore #
|
||||
#
|
||||
|
||||
|
||||
def test_backup_and_restore_all_sys():
|
||||
|
||||
|
@ -250,9 +256,9 @@ def test_backup_and_restore_all_sys():
|
|||
assert os.path.exists("/etc/ssowat/conf.json")
|
||||
|
||||
|
||||
###############################################################################
|
||||
# System restore from 2.4 #
|
||||
###############################################################################
|
||||
#
|
||||
# System restore from 2.4 #
|
||||
#
|
||||
|
||||
@pytest.mark.with_system_archive_from_2p4
|
||||
def test_restore_system_from_Ynh2p4(monkeypatch, mocker):
|
||||
|
@ -265,19 +271,20 @@ def test_restore_system_from_Ynh2p4(monkeypatch, mocker):
|
|||
# Restore system archive from 2.4
|
||||
try:
|
||||
backup_restore(auth, name=backup_list()["archives"][1],
|
||||
system=[],
|
||||
apps=None,
|
||||
force=True)
|
||||
system=[],
|
||||
apps=None,
|
||||
force=True)
|
||||
finally:
|
||||
# Restore system as it was
|
||||
backup_restore(auth, name=backup_list()["archives"][0],
|
||||
system=[],
|
||||
apps=None,
|
||||
force=True)
|
||||
system=[],
|
||||
apps=None,
|
||||
force=True)
|
||||
|
||||
#
|
||||
# App backup #
|
||||
#
|
||||
|
||||
###############################################################################
|
||||
# App backup #
|
||||
###############################################################################
|
||||
|
||||
@pytest.mark.with_backup_recommended_app_installed
|
||||
def test_backup_script_failure_handling(monkeypatch, mocker):
|
||||
|
@ -300,6 +307,7 @@ def test_backup_script_failure_handling(monkeypatch, mocker):
|
|||
|
||||
m18n.n.assert_any_call('backup_app_failed', app='backup_recommended_app')
|
||||
|
||||
|
||||
@pytest.mark.with_backup_recommended_app_installed
|
||||
def test_backup_not_enough_free_space(monkeypatch, mocker):
|
||||
|
||||
|
@ -385,6 +393,7 @@ def test_backup_with_different_output_directory():
|
|||
assert len(archives_info["system"].keys()) == 1
|
||||
assert "conf_ssh" in archives_info["system"].keys()
|
||||
|
||||
|
||||
@pytest.mark.clean_opt_dir
|
||||
def test_backup_with_no_compress():
|
||||
# Create the backup
|
||||
|
@ -396,15 +405,15 @@ def test_backup_with_no_compress():
|
|||
assert os.path.exists("/opt/test_backup_output_directory/info.json")
|
||||
|
||||
|
||||
###############################################################################
|
||||
# App restore #
|
||||
###############################################################################
|
||||
#
|
||||
# App restore #
|
||||
#
|
||||
|
||||
@pytest.mark.with_wordpress_archive_from_2p4
|
||||
def test_restore_app_wordpress_from_Ynh2p4():
|
||||
|
||||
backup_restore(auth, system=None, name=backup_list()["archives"][0],
|
||||
apps=["wordpress"])
|
||||
apps=["wordpress"])
|
||||
|
||||
|
||||
@pytest.mark.with_wordpress_archive_from_2p4
|
||||
|
@ -422,7 +431,7 @@ def test_restore_app_script_failure_handling(monkeypatch, mocker):
|
|||
|
||||
with pytest.raises(YunohostError):
|
||||
backup_restore(auth, system=None, name=backup_list()["archives"][0],
|
||||
apps=["wordpress"])
|
||||
apps=["wordpress"])
|
||||
|
||||
m18n.n.assert_any_call('restore_app_failed', app='wordpress')
|
||||
m18n.n.assert_any_call('restore_nothings_done')
|
||||
|
@ -443,12 +452,12 @@ def test_restore_app_not_enough_free_space(monkeypatch, mocker):
|
|||
|
||||
with pytest.raises(YunohostError):
|
||||
backup_restore(auth, system=None, name=backup_list()["archives"][0],
|
||||
apps=["wordpress"])
|
||||
apps=["wordpress"])
|
||||
|
||||
m18n.n.assert_any_call('restore_not_enough_disk_space',
|
||||
free_space=0,
|
||||
margin=ANY,
|
||||
needed_space=ANY)
|
||||
free_space=0,
|
||||
margin=ANY,
|
||||
needed_space=ANY)
|
||||
assert not _is_installed("wordpress")
|
||||
|
||||
|
||||
|
@ -462,7 +471,7 @@ def test_restore_app_not_in_backup(mocker):
|
|||
|
||||
with pytest.raises(YunohostError):
|
||||
backup_restore(auth, system=None, name=backup_list()["archives"][0],
|
||||
apps=["yoloswag"])
|
||||
apps=["yoloswag"])
|
||||
|
||||
m18n.n.assert_any_call('backup_archive_app_not_found', app="yoloswag")
|
||||
assert not _is_installed("wordpress")
|
||||
|
@ -475,14 +484,14 @@ def test_restore_app_already_installed(mocker):
|
|||
assert not _is_installed("wordpress")
|
||||
|
||||
backup_restore(auth, system=None, name=backup_list()["archives"][0],
|
||||
apps=["wordpress"])
|
||||
apps=["wordpress"])
|
||||
|
||||
assert _is_installed("wordpress")
|
||||
|
||||
mocker.spy(m18n, "n")
|
||||
with pytest.raises(YunohostError):
|
||||
backup_restore(auth, system=None, name=backup_list()["archives"][0],
|
||||
apps=["wordpress"])
|
||||
apps=["wordpress"])
|
||||
|
||||
m18n.n.assert_any_call('restore_already_installed_app', app="wordpress")
|
||||
m18n.n.assert_any_call('restore_nothings_done')
|
||||
|
@ -531,9 +540,10 @@ def _test_backup_and_restore_app(app):
|
|||
|
||||
assert app_is_installed(app)
|
||||
|
||||
###############################################################################
|
||||
# Some edge cases #
|
||||
###############################################################################
|
||||
#
|
||||
# Some edge cases #
|
||||
#
|
||||
|
||||
|
||||
def test_restore_archive_with_no_json(mocker):
|
||||
|
||||
|
@ -555,10 +565,9 @@ def test_backup_binds_are_readonly(monkeypatch):
|
|||
self.manager = backup_manager
|
||||
self._organize_files()
|
||||
|
||||
|
||||
confssh = os.path.join(self.work_dir, "conf/ssh")
|
||||
output = subprocess.check_output("touch %s/test 2>&1 || true" % confssh,
|
||||
shell=True, env={'LANG' : 'en_US.UTF-8'})
|
||||
shell=True, env={'LANG': 'en_US.UTF-8'})
|
||||
|
||||
assert "Read-only file system" in output
|
||||
|
||||
|
@ -568,7 +577,7 @@ def test_backup_binds_are_readonly(monkeypatch):
|
|||
self.clean()
|
||||
|
||||
monkeypatch.setattr("yunohost.backup.BackupMethod.mount_and_backup",
|
||||
custom_mount_and_backup)
|
||||
custom_mount_and_backup)
|
||||
|
||||
# Create the backup
|
||||
backup_create(system=[])
|
||||
|
|
|
@ -53,6 +53,7 @@ def test_appchangeurl():
|
|||
|
||||
check_changeurl_app("/newchangeurl")
|
||||
|
||||
|
||||
def test_appchangeurl_sameurl():
|
||||
install_changeurl_app("/changeurl")
|
||||
check_changeurl_app("/changeurl")
|
||||
|
|
|
@ -18,7 +18,8 @@ def teardown_function(function):
|
|||
|
||||
|
||||
def test_settings_get_bool():
|
||||
assert settings_get("example.bool") == True
|
||||
assert settings_get("example.bool")
|
||||
|
||||
|
||||
def test_settings_get_full_bool():
|
||||
assert settings_get("example.bool", True) == {"type": "bool", "value": True, "default": True, "description": "Example boolean option"}
|
||||
|
@ -27,6 +28,7 @@ def test_settings_get_full_bool():
|
|||
def test_settings_get_int():
|
||||
assert settings_get("example.int") == 42
|
||||
|
||||
|
||||
def test_settings_get_full_int():
|
||||
assert settings_get("example.int", True) == {"type": "int", "value": 42, "default": 42, "description": "Example int option"}
|
||||
|
||||
|
@ -34,6 +36,7 @@ def test_settings_get_full_int():
|
|||
def test_settings_get_string():
|
||||
assert settings_get("example.string") == "yolo swag"
|
||||
|
||||
|
||||
def test_settings_get_full_string():
|
||||
assert settings_get("example.string", True) == {"type": "string", "value": "yolo swag", "default": "yolo swag", "description": "Example string option"}
|
||||
|
||||
|
@ -41,6 +44,7 @@ def test_settings_get_full_string():
|
|||
def test_settings_get_enum():
|
||||
assert settings_get("example.enum") == "a"
|
||||
|
||||
|
||||
def test_settings_get_full_enum():
|
||||
assert settings_get("example.enum", True) == {"type": "enum", "value": "a", "default": "a", "description": "Example enum option", "choices": ["a", "b", "c"]}
|
||||
|
||||
|
@ -152,7 +156,6 @@ def test_reset_all_backup():
|
|||
assert settings_after_modification == json.load(open(old_settings_backup_path, "r"))
|
||||
|
||||
|
||||
|
||||
def test_unknown_keys():
|
||||
unknown_settings_path = SETTINGS_PATH_OTHER_LOCATION % "unknown"
|
||||
unknown_setting = {
|
||||
|
|
|
@ -136,7 +136,7 @@ def tools_adminpw(auth, new_password, check_strength=True):
|
|||
new_hash = _hash_user_password(new_password)
|
||||
|
||||
try:
|
||||
auth.update("cn=admin", { "userPassword": new_hash, })
|
||||
auth.update("cn=admin", {"userPassword": new_hash, })
|
||||
except:
|
||||
logger.exception('unable to change admin password')
|
||||
raise YunohostError('admin_password_change_failed')
|
||||
|
@ -265,7 +265,7 @@ def _is_inside_container():
|
|||
stderr=subprocess.STDOUT)
|
||||
|
||||
out, _ = p.communicate()
|
||||
container = ['lxc','lxd','docker']
|
||||
container = ['lxc', 'lxd', 'docker']
|
||||
return out.split()[0] in container
|
||||
|
||||
|
||||
|
@ -323,7 +323,6 @@ def tools_postinstall(operation_logger, domain, password, ignore_dyndns=False,
|
|||
else:
|
||||
dyndns = False
|
||||
|
||||
|
||||
operation_logger.start()
|
||||
logger.info(m18n.n('yunohost_installing'))
|
||||
|
||||
|
@ -539,7 +538,7 @@ def tools_upgrade(operation_logger, auth, ignore_apps=False, ignore_packages=Fal
|
|||
# If API call
|
||||
if is_api:
|
||||
critical_packages = ("moulinette", "yunohost",
|
||||
"yunohost-admin", "ssowat", "python")
|
||||
"yunohost-admin", "ssowat", "python")
|
||||
critical_upgrades = set()
|
||||
|
||||
for pkg in cache.get_changes():
|
||||
|
@ -575,7 +574,6 @@ def tools_upgrade(operation_logger, auth, ignore_apps=False, ignore_packages=Fal
|
|||
else:
|
||||
logger.info(m18n.n('packages_no_upgrade'))
|
||||
|
||||
|
||||
if not ignore_apps:
|
||||
try:
|
||||
app_upgrade(auth)
|
||||
|
@ -719,7 +717,7 @@ def _check_if_vulnerable_to_meltdown():
|
|||
try:
|
||||
call = subprocess.Popen("bash %s --batch json --variant 3" %
|
||||
SCRIPT_PATH, shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
|
||||
output, _ = call.communicate()
|
||||
|
@ -815,12 +813,12 @@ def tools_migrations_list(pending=False, done=False):
|
|||
migrations = [m for m in migrations if m.number > last_migration]
|
||||
|
||||
# Reduce to dictionnaries
|
||||
migrations = [{ "id": migration.id,
|
||||
"number": migration.number,
|
||||
"name": migration.name,
|
||||
"mode": migration.mode,
|
||||
"description": migration.description,
|
||||
"disclaimer": migration.disclaimer } for migration in migrations ]
|
||||
migrations = [{"id": migration.id,
|
||||
"number": migration.number,
|
||||
"name": migration.name,
|
||||
"mode": migration.mode,
|
||||
"description": migration.description,
|
||||
"disclaimer": migration.disclaimer} for migration in migrations]
|
||||
|
||||
return {"migrations": migrations}
|
||||
|
||||
|
@ -914,7 +912,7 @@ def tools_migrations_migrate(target=None, skip=False, auto=False, accept_disclai
|
|||
accept_disclaimer = False
|
||||
|
||||
# Start register change on system
|
||||
operation_logger= OperationLogger('tools_migrations_migrate_' + mode)
|
||||
operation_logger = OperationLogger('tools_migrations_migrate_' + mode)
|
||||
operation_logger.start()
|
||||
|
||||
if not skip:
|
||||
|
@ -934,9 +932,9 @@ def tools_migrations_migrate(target=None, skip=False, auto=False, accept_disclai
|
|||
# migration failed, let's stop here but still update state because
|
||||
# we managed to run the previous ones
|
||||
msg = m18n.n('migrations_migration_has_failed',
|
||||
exception=e,
|
||||
number=migration.number,
|
||||
name=migration.name)
|
||||
exception=e,
|
||||
number=migration.number,
|
||||
name=migration.name)
|
||||
logger.error(msg, exc_info=1)
|
||||
operation_logger.error(msg)
|
||||
break
|
||||
|
@ -967,6 +965,7 @@ def tools_migrations_migrate(target=None, skip=False, auto=False, accept_disclai
|
|||
|
||||
write_to_json(MIGRATIONS_STATE_PATH, state)
|
||||
|
||||
|
||||
def tools_migrations_state():
|
||||
"""
|
||||
Show current migration state
|
||||
|
@ -1009,7 +1008,7 @@ def _get_migrations_list():
|
|||
migrations = []
|
||||
|
||||
try:
|
||||
import data_migrations
|
||||
from . import data_migrations
|
||||
except ImportError:
|
||||
# not data migrations present, return empty list
|
||||
return migrations
|
||||
|
@ -1032,7 +1031,7 @@ def _get_migration_by_name(migration_name):
|
|||
"""
|
||||
|
||||
try:
|
||||
import data_migrations
|
||||
from . import data_migrations
|
||||
except ImportError:
|
||||
raise AssertionError("Unable to find migration with name %s" % migration_name)
|
||||
|
||||
|
@ -1051,7 +1050,7 @@ def _load_migration(migration_file):
|
|||
number, name = migration_id.split("_", 1)
|
||||
|
||||
logger.debug(m18n.n('migrations_loading_migration',
|
||||
number=number, name=name))
|
||||
number=number, name=name))
|
||||
|
||||
try:
|
||||
# this is python builtin method to import a module using a name, we
|
||||
|
@ -1064,7 +1063,8 @@ def _load_migration(migration_file):
|
|||
traceback.print_exc()
|
||||
|
||||
raise YunohostError('migrations_error_failed_to_load_migration',
|
||||
number=number, name=name)
|
||||
number=number, name=name)
|
||||
|
||||
|
||||
def _skip_all_migrations():
|
||||
"""
|
||||
|
@ -1115,4 +1115,3 @@ class Migration(object):
|
|||
@property
|
||||
def description(self):
|
||||
return m18n.n("migration_description_%s" % self.id)
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ from yunohost.log import is_unit_operation
|
|||
|
||||
logger = getActionLogger('yunohost.user')
|
||||
|
||||
|
||||
def user_list(auth, fields=None):
|
||||
"""
|
||||
List users
|
||||
|
@ -98,7 +99,7 @@ def user_list(auth, fields=None):
|
|||
|
||||
@is_unit_operation([('username', 'user')])
|
||||
def user_create(operation_logger, auth, username, firstname, lastname, mail, password,
|
||||
mailbox_quota="0"):
|
||||
mailbox_quota="0"):
|
||||
"""
|
||||
Create user
|
||||
|
||||
|
@ -262,8 +263,8 @@ def user_delete(operation_logger, auth, username, purge=False):
|
|||
|
||||
@is_unit_operation([('username', 'user')], exclude=['auth', 'change_password'])
|
||||
def user_update(operation_logger, auth, username, firstname=None, lastname=None, mail=None,
|
||||
change_password=None, add_mailforward=None, remove_mailforward=None,
|
||||
add_mailalias=None, remove_mailalias=None, mailbox_quota=None):
|
||||
change_password=None, add_mailforward=None, remove_mailforward=None,
|
||||
add_mailalias=None, remove_mailalias=None, mailbox_quota=None):
|
||||
"""
|
||||
Update user informations
|
||||
|
||||
|
@ -466,18 +467,23 @@ def user_info(auth, username):
|
|||
#
|
||||
import yunohost.ssh
|
||||
|
||||
|
||||
def user_ssh_allow(auth, username):
|
||||
return yunohost.ssh.user_ssh_allow(auth, username)
|
||||
|
||||
|
||||
def user_ssh_disallow(auth, username):
|
||||
return yunohost.ssh.user_ssh_disallow(auth, username)
|
||||
|
||||
|
||||
def user_ssh_list_keys(auth, username):
|
||||
return yunohost.ssh.user_ssh_list_keys(auth, username)
|
||||
|
||||
|
||||
def user_ssh_add_key(auth, username, key, comment):
|
||||
return yunohost.ssh.user_ssh_add_key(auth, username, key, comment)
|
||||
|
||||
|
||||
def user_ssh_remove_key(auth, username, key):
|
||||
return yunohost.ssh.user_ssh_remove_key(auth, username, key)
|
||||
|
||||
|
@ -485,6 +491,7 @@ def user_ssh_remove_key(auth, username, key):
|
|||
# End SSH subcategory
|
||||
#
|
||||
|
||||
|
||||
def _convertSize(num, suffix=''):
|
||||
for unit in ['K', 'M', 'G', 'T', 'P', 'E', 'Z']:
|
||||
if abs(num) < 1024.0:
|
||||
|
@ -520,6 +527,3 @@ def _hash_user_password(password):
|
|||
|
||||
salt = '$6$' + salt + '$'
|
||||
return '{CRYPT}' + crypt.crypt(str(password), salt)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -22,12 +22,14 @@
|
|||
from moulinette.core import MoulinetteError
|
||||
from moulinette import m18n
|
||||
|
||||
|
||||
class YunohostError(MoulinetteError):
|
||||
|
||||
"""Yunohost base exception"""
|
||||
|
||||
def __init__(self, key, __raw_msg__=False, *args, **kwargs):
|
||||
if __raw_msg__:
|
||||
msg = key
|
||||
else:
|
||||
msg = m18n.n(key, *args, **kwargs)
|
||||
super(YunohostError, self).__init__(msg, __raw_msg__=True)
|
||||
|
||||
|
|
|
@ -20,10 +20,12 @@
|
|||
"""
|
||||
import os
|
||||
|
||||
|
||||
def free_space_in_directory(dirpath):
|
||||
stat = os.statvfs(dirpath)
|
||||
return stat.f_frsize * stat.f_bavail
|
||||
|
||||
|
||||
def space_used_by_directory(dirpath):
|
||||
stat = os.statvfs(dirpath)
|
||||
return stat.f_frsize * stat.f_blocks
|
||||
|
|
|
@ -71,7 +71,7 @@ def get_gateway():
|
|||
return addr.popitem()[1] if len(addr) == 1 else None
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
|
||||
|
||||
def _extract_inet(string, skip_netmask=False, skip_loopback=True):
|
||||
|
|
|
@ -33,6 +33,7 @@ logger = logging.getLogger('yunohost.utils.packages')
|
|||
# Exceptions -----------------------------------------------------------------
|
||||
|
||||
class PackageException(Exception):
|
||||
|
||||
"""Base exception related to a package
|
||||
|
||||
Represent an exception related to the package named `pkgname`. If no
|
||||
|
@ -50,16 +51,19 @@ class PackageException(Exception):
|
|||
|
||||
|
||||
class UnknownPackage(PackageException):
|
||||
|
||||
"""The package is not found in the cache."""
|
||||
message_key = 'package_unknown'
|
||||
|
||||
|
||||
class UninstalledPackage(PackageException):
|
||||
|
||||
"""The package is not installed."""
|
||||
message_key = 'package_not_installed'
|
||||
|
||||
|
||||
class InvalidSpecifier(ValueError):
|
||||
|
||||
"""An invalid specifier was found."""
|
||||
|
||||
|
||||
|
@ -68,6 +72,7 @@ class InvalidSpecifier(ValueError):
|
|||
# See: https://github.com/pypa/packaging
|
||||
|
||||
class Specifier(object):
|
||||
|
||||
"""Unique package version specifier
|
||||
|
||||
Restrict a package version according to the `spec`. It must be a string
|
||||
|
@ -257,6 +262,7 @@ class Specifier(object):
|
|||
|
||||
|
||||
class SpecifierSet(object):
|
||||
|
||||
"""A set of package version specifiers
|
||||
|
||||
Combine several Specifier separated by a comma. It allows to restrict
|
||||
|
|
|
@ -38,9 +38,11 @@ STRENGTH_LEVELS = [
|
|||
(12, 1, 1, 1, 1),
|
||||
]
|
||||
|
||||
|
||||
def assert_password_is_strong_enough(profile, password):
|
||||
PasswordValidator(profile).validate(password)
|
||||
|
||||
|
||||
class PasswordValidator(object):
|
||||
|
||||
def __init__(self, profile):
|
||||
|
@ -157,7 +159,7 @@ class PasswordValidator(object):
|
|||
# and the strength of the password (e.g. [11, 2, 7, 2, 0])
|
||||
# and compare the values 1-by-1.
|
||||
# If one False is found, the password does not satisfy the level
|
||||
if False in [s>=c for s, c in zip(strength, level_criterias)]:
|
||||
if False in [s >= c for s, c in zip(strength, level_criterias)]:
|
||||
break
|
||||
# Otherwise, the strength of the password is at least of the current level.
|
||||
strength_level = level + 1
|
||||
|
@ -186,7 +188,7 @@ if __name__ == '__main__':
|
|||
if len(sys.argv) < 2:
|
||||
import getpass
|
||||
pwd = getpass.getpass("")
|
||||
#print("usage: password.py PASSWORD")
|
||||
# print("usage: password.py PASSWORD")
|
||||
else:
|
||||
pwd = sys.argv[1]
|
||||
status, msg = PasswordValidator('user').validation_summary(pwd)
|
||||
|
|
|
@ -5,6 +5,7 @@ import json
|
|||
|
||||
from yunohost.utils.error import YunohostError
|
||||
|
||||
|
||||
def yunopaste(data):
|
||||
|
||||
paste_server = "https://paste.yunohost.org"
|
||||
|
|
Loading…
Add table
Reference in a new issue