From a20281ebfcdc118660a7602624e4ef15bb3e54b1 Mon Sep 17 00:00:00 2001 From: ljf Date: Mon, 4 Jun 2018 18:57:00 +0200 Subject: [PATCH] [enh] Operational unit for backup regenconf, migrations and others --- src/yunohost/app.py | 28 ++++++++++++++++++++++++++++ src/yunohost/backup.py | 38 ++++++++++++++++++++++++++++++++++---- src/yunohost/service.py | 7 ++++++- src/yunohost/tools.py | 19 ++++++++++++++++--- 4 files changed, 84 insertions(+), 8 deletions(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index df36ccdf7..4273471a0 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -623,6 +623,7 @@ def app_upgrade(auth, app=[], url=None, file=None): # Start register change on system related_to = [('app', app_instance_name)] uo = UnitOperation('app_upgrade', related_to, env=env_dict) + uo.start() # Execute App upgrade script os.system('chown -hR admin: %s' % INSTALL_TMP) @@ -918,6 +919,8 @@ def app_addaccess(auth, apps, users=[]): apps = [apps, ] for app in apps: + + app_settings = _get_app_settings(app) if not app_settings: continue @@ -927,6 +930,12 @@ def app_addaccess(auth, apps, users=[]): app_settings['mode'] = 'private' if app_settings['mode'] == 'private': + + # Start register change on system + related_to = [('app', app)] + uo= UnitOperation('app_addaccess', related_to) + uo.start() + allowed_users = set() if 'allowed_users' in app_settings: allowed_users = set(app_settings['allowed_users'].split(',')) @@ -939,11 +948,14 @@ def app_addaccess(auth, apps, users=[]): logger.warning(m18n.n('user_unknown', user=allowed_user)) continue allowed_users.add(allowed_user) + uo.related_to.add(('user', allowed_user)) new_users = ','.join(allowed_users) app_setting(app, 'allowed_users', new_users) hook_callback('post_app_addaccess', args=[app, new_users]) + uo.success() + result[app] = allowed_users app_ssowatconf(auth) @@ -980,6 +992,12 @@ def app_removeaccess(auth, apps, users=[]): allowed_users = set() if app_settings.get('skipped_uris', '') != '/': + + # Start register change on system + related_to = [('app', app)] + uo= UnitOperation('app_removeaccess', related_to) + uo.start() + if remove_all: pass elif 'allowed_users' in app_settings: @@ -991,12 +1009,15 @@ def app_removeaccess(auth, apps, users=[]): if allowed_user not in users: allowed_users.add(allowed_user) + uo.related_to += [ ('user', x) for x in allowed_users ] new_users = ','.join(allowed_users) app_setting(app, 'allowed_users', new_users) hook_callback('post_app_removeaccess', args=[app, new_users]) result[app] = allowed_users + uo.success() + app_ssowatconf(auth) return {'allowed_users': result} @@ -1020,6 +1041,11 @@ def app_clearaccess(auth, apps): if not app_settings: continue + # Start register change on system + related_to = [('app', app)] + uo= UnitOperation('app_clearaccess', related_to) + uo.start() + if 'mode' in app_settings: app_setting(app, 'mode', delete=True) @@ -1028,6 +1054,8 @@ def app_clearaccess(auth, apps): hook_callback('post_app_clearaccess', args=[app]) + uo.success() + app_ssowatconf(auth) diff --git a/src/yunohost/backup.py b/src/yunohost/backup.py index 15c793802..c4b61f1f2 100644 --- a/src/yunohost/backup.py +++ b/src/yunohost/backup.py @@ -1125,9 +1125,14 @@ class RestoreManager(): if system_targets == []: return + # Start register change on system + uo = UnitOperation('backup_restore_system') + uo.start() + logger.info(m18n.n('restore_running_hooks')) env_dict = self._get_env_var() + uo.extra.env = env_dict ret = hook_callback('restore', system_targets, args=[self.work_dir], @@ -1137,9 +1142,16 @@ class RestoreManager(): for part in ret['succeed'].keys(): self.targets.set_result("system", part, "Success") + error_part = [] for part in ret['failed'].keys(): logger.error(m18n.n('restore_system_part_failed', part=part)) self.targets.set_result("system", part, "Error") + error_part.append(part) + + if ret['failed']: + uo.error(m18n.n('restore_system_part_failed', part=', '.join(error_part))) + else: + uo.success() service_regen_conf() @@ -1187,6 +1199,11 @@ class RestoreManager(): else: shutil.copy2(s, d) + # Start register change on system + related_to = [('app', app_instance_name)] + uo = UnitOperation('backup_restore_app', related_to) + uo.start() + # Check if the app is not already installed if _is_installed(app_instance_name): logger.error(m18n.n('restore_already_installed_app', @@ -1229,6 +1246,8 @@ class RestoreManager(): # Prepare env. var. to pass to script env_dict = self._get_env_var(app_instance_name) + uo.extra.env = env_dict + # Execute app restore script hook_exec(restore_script, args=[app_backup_in_archive, app_instance_name], @@ -1237,8 +1256,10 @@ class RestoreManager(): env=env_dict, user="root") except: - logger.exception(m18n.n('restore_app_failed', - app=app_instance_name)) + msg = m18n.n('restore_app_failed',app=app_instance_name) + logger.exception(msg) + uo.error(msg) + self.targets.set_result("apps", app_instance_name, "Error") remove_script = os.path.join(app_scripts_in_archive, 'remove') @@ -1250,12 +1271,20 @@ class RestoreManager(): env_dict_remove["YNH_APP_INSTANCE_NAME"] = app_instance_name env_dict_remove["YNH_APP_INSTANCE_NUMBER"] = str(app_instance_nb) + uo = UnitOperation('remove_on_failed_restore', + [('app', app_instance_name)], + env=env_dict_remove) + uo.start() + # Execute remove script # TODO: call app_remove instead if hook_exec(remove_script, args=[app_instance_name], env=env_dict_remove, user="root") != 0: - logger.warning(m18n.n('app_not_properly_removed', - app=app_instance_name)) + msg = m18n.n('app_not_properly_removed', app=app_instance_name) + logger.warning(msg) + uo.error(msg) + else: + uo.success() # Cleaning app directory shutil.rmtree(app_settings_new_path, ignore_errors=True) @@ -1263,6 +1292,7 @@ class RestoreManager(): # TODO Cleaning app hooks else: self.targets.set_result("apps", app_instance_name, "Success") + uo.success() finally: # Cleaning temporary scripts directory shutil.rmtree(tmp_folder_for_app_restore, ignore_errors=True) diff --git a/src/yunohost/service.py b/src/yunohost/service.py index cc65fe237..d90965d3e 100644 --- a/src/yunohost/service.py +++ b/src/yunohost/service.py @@ -274,7 +274,8 @@ def service_log(name, number=50): return result -def service_regen_conf(names=[], with_diff=False, force=False, dry_run=False, +@is_unit_operation('names:service', auto=False) +def service_regen_conf(uo, names=[], with_diff=False, force=False, dry_run=False, list_pending=False): """ Regenerate the configuration file(s) for a service @@ -289,6 +290,8 @@ def service_regen_conf(names=[], with_diff=False, force=False, dry_run=False, """ result = {} + if not dry_run: + uo.start() # Return the list of pending conf if list_pending: pending_conf = _get_pending_conf(names) @@ -482,6 +485,8 @@ def service_regen_conf(names=[], with_diff=False, force=False, dry_run=False, return post_args + [regen_conf_files, ] hook_callback('conf_regen', names, pre_callback=_pre_call) + uo.success() + return result diff --git a/src/yunohost/tools.py b/src/yunohost/tools.py index eefe2d28d..8ffeaecf4 100644 --- a/src/yunohost/tools.py +++ b/src/yunohost/tools.py @@ -834,20 +834,31 @@ def tools_migrations_migrate(target=None, skip=False): # effectively run selected migrations for migration in migrations: + + # Start register change on system + uo= UnitOperation('tools_migrations_migrate_' + mode) + uo.start() + if not skip: logger.warn(m18n.n('migrations_show_currently_running_migration', **migration)) try: if mode == "forward": - migration["module"].MyMigration().migrate() + m = migration["module"].MyMigration() + m.uo = uo + m.migrate() elif mode == "backward": - migration["module"].MyMigration().backward() + m = migration["module"].MyMigration() + m.uo = uo + m.backward() else: # can't happen raise Exception("Illegal state for migration: '%s', should be either 'forward' or 'backward'" % mode) except Exception as e: # migration failed, let's stop here but still update state because # we managed to run the previous ones - logger.error(m18n.n('migrations_migration_has_failed', exception=e, **migration), exc_info=1) + msg = m18n.n('migrations_migration_has_failed', exception=e, **migration) + logger.error(msg, exc_info=1) + uo.error(msg) break else: # if skip @@ -859,6 +870,8 @@ def tools_migrations_migrate(target=None, skip=False): "name": migration["name"], } + uo.success() + # special case where we want to go back from the start if target == 0: state["last_run_migration"] = None