diff --git a/locales/en.json b/locales/en.json index 8528c2576..34517a036 100644 --- a/locales/en.json +++ b/locales/en.json @@ -377,6 +377,21 @@ "port_available": "Port {port:d} is available", "port_unavailable": "Port {port:d} is not available", "recommend_to_add_first_user": "The post-install is finished but YunoHost needs at least one user to work correctly, you should add one using 'yunohost user create' or the admin interface.", + "regenconf_file_backed_up": "The configuration file '{conf}' has been backed up to '{backup}'", + "regenconf_file_copy_failed": "Unable to copy the new configuration file '{new}' to '{conf}'", + "regenconf_file_kept_back": "The configuration file '{conf}' is expected to be deleted by regen-conf (category {category}) but has been kept back.", + "regenconf_file_manually_modified": "The configuration file '{conf}' has been manually modified and will not be updated", + "regenconf_file_manually_removed": "The configuration file '{conf}' has been manually removed and will not be created", + "regenconf_file_remove_failed": "Unable to remove the configuration file '{conf}'", + "regenconf_file_removed": "The configuration file '{conf}' has been removed", + "regenconf_file_updated": "The configuration file '{conf}' has been updated", + "regenconf_now_managed_by_yunohost": "The configuration file '{conf}' is now managed by YunoHost (category {category}).", + "regenconf_up_to_date": "The configuration is already up-to-date for category '{category}'", + "regenconf_updated": "The configuration has been updated for category '{category}'", + "regenconf_would_be_updated": "The configuration would have been updated for category '{category}'", + "regenconf_dry_pending_applying": "Checking pending configuration which would have been applied for category '{category}'…", + "regenconf_failed": "Unable to regenerate the configuration for category(s): {categories}", + "regenconf_pending_applying": "Applying pending configuration for category '{category}'…", "restore_action_required": "You must specify something to restore", "restore_already_installed_app": "An app is already installed with the id '{app:s}'", "restore_app_failed": "Unable to restore the app '{app:s}'", @@ -405,18 +420,6 @@ "service_already_started": "Service '{service:s}' has already been started", "service_already_stopped": "Service '{service:s}' has already been stopped", "service_cmd_exec_failed": "Unable to execute command '{command:s}'", - "service_conf_file_backed_up": "The configuration file '{conf}' has been backed up to '{backup}'", - "service_conf_file_copy_failed": "Unable to copy the new configuration file '{new}' to '{conf}'", - "service_conf_file_kept_back": "The configuration file '{conf}' is expected to be deleted by service {service} but has been kept back.", - "service_conf_file_manually_modified": "The configuration file '{conf}' has been manually modified and will not be updated", - "service_conf_file_manually_removed": "The configuration file '{conf}' has been manually removed and will not be created", - "service_conf_file_remove_failed": "Unable to remove the configuration file '{conf}'", - "service_conf_file_removed": "The configuration file '{conf}' has been removed", - "service_conf_file_updated": "The configuration file '{conf}' has been updated", - "service_conf_now_managed_by_yunohost": "The configuration file '{conf}' is now managed by YunoHost.", - "service_conf_up_to_date": "The configuration is already up-to-date for service '{service}'", - "service_conf_updated": "The configuration has been updated for service '{service}'", - "service_conf_would_be_updated": "The configuration would have been updated for service '{service}'", "service_description_avahi-daemon": "allows to reach your server using yunohost.local on your local network", "service_description_dnsmasq": "handles domain name resolution (DNS)", "service_description_dovecot": "allows e-mail client to access/fetch email (via IMAP and POP3)", @@ -440,9 +443,6 @@ "service_enable_failed": "Unable to enable service '{service:s}'\n\nRecent service logs:{logs:s}", "service_enabled": "The service '{service:s}' has been enabled", "service_no_log": "No log to display for service '{service:s}'", - "service_regenconf_dry_pending_applying": "Checking pending configuration which would have been applied for service '{service}'…", - "service_regenconf_failed": "Unable to regenerate the configuration for service(s): {services}", - "service_regenconf_pending_applying": "Applying pending configuration for service '{service}'…", "service_remove_failed": "Unable to remove service '{service:s}'", "service_removed": "The service '{service:s}' has been removed", "service_reload_failed": "Unable to reload service '{service:s}'\n\nRecent service logs:{logs:s}", diff --git a/src/yunohost/regenconf.py b/src/yunohost/regenconf.py index 0330db508..4104e2491 100644 --- a/src/yunohost/regenconf.py +++ b/src/yunohost/regenconf.py @@ -43,14 +43,16 @@ PENDING_CONF_DIR = os.path.join(BASE_CONF_PATH, 'pending') logger = log.getActionLogger('yunohost.regenconf') +# FIXME : those ain't just services anymore ... what are we supposed to do with this ... +# FIXME : check for all reference of 'service' close to operation_logger stuff @is_unit_operation([('names', 'service')]) def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run=False, list_pending=False): """ - Regenerate the configuration file(s) for a service + Regenerate the configuration file(s) Keyword argument: - names -- Services name to regenerate configuration of + names -- Categories to regenerate configuration of with_diff -- Show differences in case of configuration changes force -- Override all manual modifications in configuration files dry_run -- Show what would have been regenerated @@ -66,10 +68,10 @@ def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run if not with_diff: return pending_conf - for service, conf_files in pending_conf.items(): + for category, conf_files in pending_conf.items(): for system_path, pending_path in conf_files.items(): - pending_conf[service][system_path] = { + pending_conf[category][system_path] = { 'pending_conf': pending_path, 'diff': _get_files_diff( system_path, pending_path, True), @@ -103,12 +105,12 @@ def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run pre_args = ['pre', ] + common_args 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, 0o755, True, uid='root') + # create the pending conf directory for the category + category_pending_path = os.path.join(PENDING_CONF_DIR, name) + filesystem.mkdir(category_pending_path, 0o755, True, uid='root') # return the arguments to pass to the script - return pre_args + [service_pending_path, ] + return pre_args + [category_pending_path, ] # Don't regen SSH if not specifically specified if not names: @@ -118,29 +120,29 @@ def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run pre_result = hook_callback('conf_regen', names, pre_callback=_pre_call) - # Update the services name + # Update the categorys name names = pre_result['succeed'].keys() if not names: - raise YunohostError('service_regenconf_failed', - services=', '.join(pre_result['failed'])) + raise YunohostError('regenconf_failed', + categories=', '.join(pre_result['failed'])) # Set the processing method _regen = _process_regen_conf if not dry_run else lambda *a, **k: True operation_logger.related_to = [] - # Iterate over services and process pending conf - for service, conf_files in _get_pending_conf(names).items(): + # Iterate over categorys and process pending conf + for category, conf_files in _get_pending_conf(names).items(): if not dry_run: - operation_logger.related_to.append(('service', service)) + operation_logger.related_to.append(('service', category)) logger.debug(m18n.n( - 'service_regenconf_pending_applying' if not dry_run else - 'service_regenconf_dry_pending_applying', - service=service)) + 'regenconf_pending_applying' if not dry_run else + 'regenconf_dry_pending_applying', + category=category)) - conf_hashes = _get_conf_hashes(service) + conf_hashes = _get_conf_hashes(category) succeed_regen = {} failed_regen = {} @@ -179,7 +181,7 @@ def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run system_path, pending_path, save=False) else: logger.info(m18n.n( - 'service_conf_file_manually_removed', + 'regenconf_file_manually_removed', conf=system_path)) conf_status = 'removed' @@ -195,16 +197,16 @@ def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run # we assume that it is safe to regen it, since the file is backuped # anyway (by default in _regen), as long as we warn the user # appropriately. - logger.info(m18n.n('service_conf_now_managed_by_yunohost', - conf=system_path)) + logger.info(m18n.n('regenconf_now_managed_by_yunohost', + conf=system_path, category=category)) regenerated = _regen(system_path, pending_path) conf_status = 'new' elif force: regenerated = _regen(system_path) conf_status = 'force-removed' else: - logger.info(m18n.n('service_conf_file_kept_back', - conf=system_path, service=service)) + logger.info(m18n.n('regenconf_file_kept_back', + conf=system_path, category=category)) conf_status = 'unmanaged' # -> system conf has not been manually modified @@ -231,7 +233,7 @@ def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run conf_status = 'force-updated' else: logger.warning(m18n.n( - 'service_conf_file_manually_modified', + 'regenconf_file_manually_modified', conf=system_path)) conf_status = 'modified' @@ -247,21 +249,21 @@ def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run else: failed_regen[system_path] = conf_result - # Check for service conf changes + # Check for category conf changes if not succeed_regen and not failed_regen: - logger.debug(m18n.n('service_conf_up_to_date', service=service)) + logger.debug(m18n.n('regenconf_up_to_date', category=category)) continue elif not failed_regen: logger.success(m18n.n( - 'service_conf_updated' if not dry_run else - 'service_conf_would_be_updated', - service=service)) + 'regenconf_updated' if not dry_run else + 'regenconf_would_be_updated', + category=category)) if succeed_regen and not dry_run: - _update_conf_hashes(service, conf_hashes) + _update_conf_hashes(category, conf_hashes) - # Append the service results - result[service] = { + # Append the category results + result[category] = { 'applied': succeed_regen, 'pending': failed_regen } @@ -274,7 +276,7 @@ def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run post_args = ['post', ] + common_args def _pre_call(name, priority, path, args): - # append coma-separated applied changes for the service + # append coma-separated applied changes for the category if name in result and result[name]['applied']: regen_conf_files = ','.join(result[name]['applied'].keys()) else: @@ -379,14 +381,14 @@ def _calculate_hash(path): return None -def _get_pending_conf(services=[]): - """Get pending configuration for service(s) +def _get_pending_conf(categories=[]): + """Get pending configuration for categories - Iterate over the pending configuration directory for given service(s) - or + Iterate over the pending configuration directory for given categories - or all if empty - and look for files inside. Each file is considered as a pending configuration file and therefore must be in the same directory tree than the system file that it replaces. - The result is returned as a dict of services with pending configuration as + The result is returned as a dict of categories with pending configuration as key and a dict of `system_conf_path` => `pending_conf_path` as value. """ @@ -395,63 +397,63 @@ def _get_pending_conf(services=[]): if not os.path.isdir(PENDING_CONF_DIR): return result - if not services: - services = os.listdir(PENDING_CONF_DIR) + if not categories: + categories = os.listdir(PENDING_CONF_DIR) - for name in services: - service_pending_path = os.path.join(PENDING_CONF_DIR, name) + for name in categories: + category_pending_path = os.path.join(PENDING_CONF_DIR, name) - if not os.path.isdir(service_pending_path): + if not os.path.isdir(category_pending_path): continue - path_index = len(service_pending_path) - service_conf = {} + path_index = len(category_pending_path) + category_conf = {} - for root, dirs, files in os.walk(service_pending_path): + for root, dirs, files in os.walk(category_pending_path): for filename in files: pending_path = os.path.join(root, filename) - service_conf[pending_path[path_index:]] = pending_path + category_conf[pending_path[path_index:]] = pending_path - if service_conf: - result[name] = service_conf + if category_conf: + result[name] = category_conf else: # remove empty directory - shutil.rmtree(service_pending_path, ignore_errors=True) + shutil.rmtree(category_pending_path, ignore_errors=True) return result -def _get_conf_hashes(service): - """Get the registered conf hashes for a service""" +def _get_conf_hashes(category): + """Get the registered conf hashes for a category""" - services = _get_services() + categories = _get_categories() - if service not in services: - logger.debug("Service %s is not in services.yml yet.", service) + if category not in categories: + logger.debug("category %s is not in categories.yml yet.", category) return {} - elif services[service] is None or 'conffiles' not in services[service]: - logger.debug("No configuration files for service %s.", service) + elif categories[category] is None or 'conffiles' not in categories[category]: + logger.debug("No configuration files for category %s.", category) return {} else: - return services[service]['conffiles'] + return categories[category]['conffiles'] -def _update_conf_hashes(service, hashes): - """Update the registered conf hashes for a service""" +def _update_conf_hashes(category, hashes): + """Update the registered conf hashes for a category""" logger.debug("updating conf hashes for '%s' with: %s", - service, hashes) - services = _get_services() - service_conf = services.get(service, {}) + category, hashes) + categories = _get_categories() + category_conf = categories.get(category, {}) - # Handle the case where services[service] is set to null in the yaml - if service_conf is None: - service_conf = {} + # Handle the case where categories[category] is set to null in the yaml + if category_conf is None: + category_conf = {} - service_conf['conffiles'] = hashes - services[service] = service_conf - _save_services(services) + category_conf['conffiles'] = hashes + categories[category] = category_conf + _save_categories(categories) def _process_regen_conf(system_conf, new_conf=None, save=True): @@ -471,13 +473,13 @@ def _process_regen_conf(system_conf, new_conf=None, save=True): filesystem.mkdir(backup_dir, 0o755, True) shutil.copy2(system_conf, backup_path) - logger.debug(m18n.n('service_conf_file_backed_up', + logger.debug(m18n.n('regenconf_file_backed_up', conf=system_conf, backup=backup_path)) try: if not new_conf: os.remove(system_conf) - logger.debug(m18n.n('service_conf_file_removed', + logger.debug(m18n.n('regenconf_file_removed', conf=system_conf)) else: system_dir = os.path.dirname(system_conf) @@ -486,12 +488,12 @@ def _process_regen_conf(system_conf, new_conf=None, save=True): filesystem.mkdir(system_dir, 0o755, True) shutil.copyfile(new_conf, system_conf) - logger.debug(m18n.n('service_conf_file_updated', + logger.debug(m18n.n('regenconf_file_updated', conf=system_conf)) except Exception as e: logger.warning("Exception while trying to regenerate conf '%s': %s", system_conf, e, exc_info=1) if not new_conf and os.path.exists(system_conf): - logger.warning(m18n.n('service_conf_file_remove_failed', + logger.warning(m18n.n('regenconf_file_remove_failed', conf=system_conf), exc_info=1) return False @@ -506,7 +508,7 @@ def _process_regen_conf(system_conf, new_conf=None, save=True): copy_succeed = False finally: if not copy_succeed: - logger.warning(m18n.n('service_conf_file_copy_failed', + logger.warning(m18n.n('regenconf_file_copy_failed', conf=system_conf, new=new_conf), exc_info=1) return False @@ -518,9 +520,9 @@ def manually_modified_files(): # We do this to have --quiet, i.e. don't throw a whole bunch of logs # just to fetch this... - # Might be able to optimize this by looking at what service_regenconf does + # Might be able to optimize this by looking at what the regen conf does # and only do the part that checks file hashes... - cmd = "yunohost service regen-conf --dry-run --output-as json --quiet" + cmd = "yunohost tools regen-conf --dry-run --output-as json --quiet" j = json.loads(subprocess.check_output(cmd.split())) # j is something like :