def _tools_migrations_run_before_app_restore(backup_version, app_id): all_migrations = _get_migrations_list() current_version = version.parse( ynh_packages_version()["yunohost"]["version"]) backup_version = version.parse(backup_version) if backup_version == current_version: return for migration in all_migrations: if (hasattr(migration, "introduced_in_version") and version.parse(migration.introduced_in_version) > backup_version and hasattr(migration, "run_before_app_restore")): try: logger.info( m18n.n("migrations_running_forward", id=migration.id)) migration.run_before_app_restore(app_id) except Exception as e: msg = m18n.n("migrations_migration_has_failed", exception=e, id=migration.id) logger.error(msg, exc_info=1) raise
def disclaimer(self): # Avoid having a super long disclaimer + uncessary check if we ain't # on stretch / yunohost 3.x anymore # NB : we do both check to cover situations where the upgrade crashed # in the middle and debian version could be >= 10.x but yunohost package # would still be in 3.x... if not self.debian_major_version() == 9 \ and not self.yunohost_major_version() == 3: return None # Get list of problematic apps ? I.e. not official or community+working problematic_apps = unstable_apps() problematic_apps = "".join( ["\n - " + app for app in problematic_apps]) # Manually modified files ? (c.f. yunohost service regen-conf) modified_files = manually_modified_files() modified_files = "".join(["\n - " + f for f in modified_files]) message = m18n.n("migration_0015_general_warning") message = "N.B.: This migration has been tested by the community over the last few months but has only been declared stable recently. If your server hosts critical services and if you are not too confident with debugging possible issues, we recommend you to wait a little bit more while we gather more feedback and polish things up. If on the other hand you are relatively confident with debugging small issues that may arise, you are encouraged to run this migration ;)! You can read about remaining known issues and feedback from the community here: https://forum.yunohost.org/t/12195\n\n" + message if problematic_apps: message += "\n\n" + m18n.n( "migration_0015_problematic_apps_warning", problematic_apps=problematic_apps) if modified_files: message += "\n\n" + m18n.n("migration_0015_modified_files", manually_modified_files=modified_files) return message
def user_permission_reset(operation_logger, permission, sync_perm=True): """ Reset a given permission to just 'all_users' Keyword argument: permission -- Name of the permission (e.g. mail or nextcloud or wordpress.editors) """ # By default, manipulate main permission if "." not in permission: permission = permission + ".main" # Fetch existing permission existing_permission = user_permission_info(permission) if existing_permission["allowed"] == ["all_users"]: logger.warning(m18n.n("permission_already_up_to_date")) return # Update permission with default (all_users) operation_logger.related_to.append(("app", permission.split(".")[0])) operation_logger.start() new_permission = _update_ldap_group_permission(permission=permission, allowed="all_users", sync_perm=sync_perm) logger.debug(m18n.n("permission_updated", permission=permission)) return new_permission
def add_new_ldap_attributes(self): from yunohost.utils.ldap import _get_ldap_interface from yunohost.regenconf import regen_conf, BACKUP_CONF_DIR # Check if the migration can be processed ldap_regen_conf_status = regen_conf(names=["slapd"], dry_run=True) # By this we check if the have been customized if ldap_regen_conf_status and ldap_regen_conf_status["slapd"][ "pending"]: logger.warning( m18n.n( "migration_0019_slapd_config_will_be_overwritten", conf_backup_folder=BACKUP_CONF_DIR, )) # Update LDAP schema restart slapd logger.info(m18n.n("migration_0011_update_LDAP_schema")) regen_conf(names=["slapd"], force=True) logger.info(m18n.n("migration_0019_add_new_attributes_in_ldap")) ldap = _get_ldap_interface() permission_list = user_permission_list(full=True)["permissions"] for permission in permission_list: system_perms = { "mail": "E-mail", "xmpp": "XMPP", "ssh": "SSH", "sftp": "STFP", } if permission.split(".")[0] in system_perms: update = { "authHeader": ["FALSE"], "label": [system_perms[permission.split(".")[0]]], "showTile": ["FALSE"], "isProtected": ["TRUE"], } else: app, subperm_name = permission.split(".") if permission.endswith(".main"): update = { "authHeader": ["TRUE"], "label": [ app ], # Note that this is later re-changed during the call to migrate_legacy_permission_settings() if a 'label' setting exists "showTile": ["TRUE"], "isProtected": ["FALSE"], } else: update = { "authHeader": ["TRUE"], "label": [subperm_name.title()], "showTile": ["FALSE"], "isProtected": ["TRUE"], } ldap.update("cn=%s,ou=permission" % permission, update)
def tools_adminpw(new_password, check_strength=True): """ Change admin password Keyword argument: new_password """ from yunohost.user import _hash_user_password from yunohost.utils.password import assert_password_is_strong_enough import spwd if check_strength: assert_password_is_strong_enough("admin", new_password) # UNIX seems to not like password longer than 127 chars ... # e.g. SSH login gets broken (or even 'su admin' when entering the password) if len(new_password) >= 127: raise YunohostValidationError("admin_password_too_long") new_hash = _hash_user_password(new_password) from yunohost.utils.ldap import _get_ldap_interface ldap = _get_ldap_interface() try: ldap.update( "cn=admin", { "userPassword": [new_hash], }, ) except Exception: logger.error("unable to change admin password") raise YunohostError("admin_password_change_failed") else: # Write as root password try: hash_root = spwd.getspnam("root").sp_pwd with open("/etc/shadow", "r") as before_file: before = before_file.read() with open("/etc/shadow", "w") as after_file: after_file.write( before.replace("root:" + hash_root, "root:" + new_hash.replace("{CRYPT}", ""))) # An IOError may be thrown if for some reason we can't read/write /etc/passwd # A KeyError could also be thrown if 'root' is not in /etc/passwd in the first place (for example because no password defined ?) # (c.f. the line about getspnam) except (IOError, KeyError): logger.warning(m18n.n("root_password_desynchronized")) return logger.info(m18n.n("root_password_replaced_by_admin_password")) logger.success(m18n.n("admin_password_changed"))
def migrate_LDAP_db(): logger.info(m18n.n("migration_0011_update_LDAP_database")) from yunohost.utils.ldap import _get_ldap_interface ldap = _get_ldap_interface() ldap_map = read_yaml( '/usr/share/yunohost/yunohost-config/moulinette/ldap_scheme.yml') try: SetupGroupPermissions.remove_if_exists("ou=permission") SetupGroupPermissions.remove_if_exists('ou=groups') attr_dict = ldap_map['parents']['ou=permission'] ldap.add('ou=permission', attr_dict) attr_dict = ldap_map['parents']['ou=groups'] ldap.add('ou=groups', attr_dict) attr_dict = ldap_map['children']['cn=all_users,ou=groups'] ldap.add('cn=all_users,ou=groups', attr_dict) attr_dict = ldap_map['children']['cn=visitors,ou=groups'] ldap.add('cn=visitors,ou=groups', attr_dict) for rdn, attr_dict in ldap_map['depends_children'].items(): ldap.add(rdn, attr_dict) except Exception as e: raise YunohostError("migration_0011_LDAP_update_failed", error=e) logger.info(m18n.n("migration_0011_create_group")) # Create a group for each yunohost user user_list = ldap.search( 'ou=users,dc=yunohost,dc=org', '(&(objectclass=person)(!(uid=root))(!(uid=nobody)))', ['uid', 'uidNumber']) for user_info in user_list: username = user_info['uid'][0] ldap.update( 'uid=%s,ou=users' % username, { 'objectClass': [ 'mailAccount', 'inetOrgPerson', 'posixAccount', 'userPermissionYnh' ] }) user_group_create(username, gid=user_info['uidNumber'][0], primary_group=True, sync_perm=False) user_group_update(groupname='all_users', add=username, force=True, sync_perm=False)
def diagnosis_run(categories=[], force=False, except_if_never_ran_yet=False, email=False): if (email or except_if_never_ran_yet) and not os.path.exists(DIAGNOSIS_CACHE): return # Get all the categories all_categories = _list_diagnosis_categories() all_categories_names = [category for category, _ in all_categories] # Check the requested category makes sense if categories == []: categories = all_categories_names else: unknown_categories = [ c for c in categories if c not in all_categories_names ] if unknown_categories: raise YunohostValidationError( "diagnosis_unknown_categories", categories=", ".join(unknown_categories)) issues = [] # Call the hook ... diagnosed_categories = [] for category in categories: logger.debug("Running diagnosis for %s ..." % category) path = [p for n, p in all_categories if n == category][0] try: code, report = hook_exec(path, args={"force": force}, env=None) except Exception: import traceback logger.error( m18n.n( "diagnosis_failed_for_category", category=category, error="\n" + traceback.format_exc(), )) else: diagnosed_categories.append(category) if report != {}: issues.extend([ item for item in report["items"] if item["status"] in ["WARNING", "ERROR"] ]) if email: _email_diagnosis_issues() if issues and msettings.get("interface") == "cli": logger.warning(m18n.n("diagnosis_display_tip"))
def run(self): # FIXME : what do we really want to do here ... # Imho we should just force-regen the conf in all case, and maybe # just display a warning if we detect that the conf was manually modified # Backup LDAP and the apps settings before to do the migration logger.info(m18n.n("migration_0019_backup_before_migration")) try: backup_folder = "/home/yunohost.backup/premigration/" + time.strftime( "%Y%m%d-%H%M%S", time.gmtime()) os.makedirs(backup_folder, 0o750) os.system("systemctl stop slapd") os.system("cp -r --preserve /etc/ldap %s/ldap_config" % backup_folder) os.system("cp -r --preserve /var/lib/ldap %s/ldap_db" % backup_folder) os.system("cp -r --preserve /etc/yunohost/apps %s/apps_settings" % backup_folder) except Exception as e: raise YunohostError( "migration_0019_can_not_backup_before_migration", error=e) finally: os.system("systemctl start slapd") try: # Update LDAP database self.add_new_ldap_attributes() # Migrate old settings migrate_legacy_permission_settings() except Exception: logger.warn( m18n.n("migration_0019_migration_failed_trying_to_rollback")) os.system("systemctl stop slapd") os.system( "rm -r /etc/ldap/slapd.d" ) # To be sure that we don't keep some part of the old config os.system("cp -r --preserve %s/ldap_config/. /etc/ldap/" % backup_folder) os.system("cp -r --preserve %s/ldap_db/. /var/lib/ldap/" % backup_folder) os.system( "cp -r --preserve %s/apps_settings/. /etc/yunohost/apps/" % backup_folder) os.system("systemctl start slapd") os.system("rm -r " + backup_folder) logger.info(m18n.n("migration_0019_rollback_success")) raise else: os.system("rm -r " + backup_folder)
def _run_service_command(action, service): """ Run services management command (start, stop, enable, disable, restart, reload) Keyword argument: action -- Action to perform service -- Service name """ services = _get_services() if service not in services.keys(): raise YunohostError('service_unknown', service=service) possible_actions = ['start', 'stop', 'restart', 'reload', 'reload-or-restart', 'enable', 'disable'] if action not in possible_actions: raise ValueError("Unknown action '%s', available actions are: %s" % (action, ", ".join(possible_actions))) cmd = 'systemctl %s %s' % (action, service) need_lock = services[service].get('need_lock', False) \ and action in ['start', 'stop', 'restart', 'reload', 'reload-or-restart'] if action in ["enable", "disable"]: cmd += " --quiet" try: # Launch the command logger.debug("Running '%s'" % cmd) p = subprocess.Popen(cmd.split(), stderr=subprocess.STDOUT) # If this command needs a lock (because the service uses yunohost # commands inside), find the PID and add a lock for it if need_lock: PID = _give_lock(action, service, p) # Wait for the command to complete p.communicate() if p.returncode != 0: logger.warning(m18n.n('service_cmd_exec_failed', command=cmd)) return False except Exception as e: logger.warning(m18n.n("unexpected_error", error=str(e))) return False finally: # Remove the lock if one was given if need_lock and PID != 0: _remove_lock(PID) return True
def tools_reboot(operation_logger, force=False): reboot = force if not reboot: try: # Ask confirmation for restoring i = msignals.prompt(m18n.n('server_reboot_confirm', answers='y/N')) except NotImplemented: pass else: if i.lower() == 'y' or i.lower() == 'yes': reboot = True if reboot: operation_logger.start() logger.warn(m18n.n('server_reboot')) subprocess.check_call(['systemctl', 'reboot'])
def tools_reboot(operation_logger, force=False): reboot = force if not reboot: try: # Ask confirmation for restoring i = msignals.prompt(m18n.n("server_reboot_confirm", answers="y/N")) except NotImplemented: pass else: if i.lower() == "y" or i.lower() == "yes": reboot = True if reboot: operation_logger.start() logger.warn(m18n.n("server_reboot")) subprocess.check_call(["systemctl", "reboot"])
def firewall_allow( protocol, port, ipv4_only=False, ipv6_only=False, no_upnp=False, no_reload=False ): """ Allow connections on a port Keyword arguments: protocol -- Protocol type to allow (TCP/UDP/Both) port -- Port or range of ports to open ipv4_only -- Only add a rule for IPv4 connections ipv6_only -- Only add a rule for IPv6 connections no_upnp -- Do not add forwarding of this port with UPnP no_reload -- Do not reload firewall rules """ firewall = firewall_list(raw=True) # Validate port if not isinstance(port, int) and ":" not in port: port = int(port) # Validate protocols protocols = ["TCP", "UDP"] if protocol != "Both" and protocol in protocols: protocols = [ protocol, ] # Validate IP versions ipvs = ["ipv4", "ipv6"] if ipv4_only and not ipv6_only: ipvs = [ "ipv4", ] elif ipv6_only and not ipv4_only: ipvs = [ "ipv6", ] for p in protocols: # Iterate over IP versions to add port for i in ipvs: if port not in firewall[i][p]: firewall[i][p].append(port) else: ipv = "IPv%s" % i[3] logger.warning(m18n.n("port_already_opened", port=port, ip_version=ipv)) # Add port forwarding with UPnP if not no_upnp and port not in firewall["uPnP"][p]: firewall["uPnP"][p].append(port) if ( p + "_TO_CLOSE" in firewall["uPnP"] and port in firewall["uPnP"][p + "_TO_CLOSE"] ): firewall["uPnP"][p + "_TO_CLOSE"].remove(port) # Update and reload firewall _update_firewall_file(firewall) if not no_reload: return firewall_reload()
def __call__(self, arguments, arg_name, arg_value): pattern, message = (arguments[0], arguments[1]) # Use temporarly utf-8 encoded value try: v = str(arg_value, "utf-8") except Exception: v = arg_value if v and not re.match(pattern, v or "", re.UNICODE): logger.warning( "argument value '%s' for '%s' doesn't match pattern '%s'", v, arg_name, pattern, ) # Attempt to retrieve message translation msg = m18n.n(message) if msg == message: msg = m18n.g(message) raise MoulinetteValidationError( "invalid_argument", argument=arg_name, error=msg ) return arg_value
def settings_reset_all(): """ Reset all settings to their default value Keyword argument: yes -- Yes I'm sure I want to do that """ settings = _get_settings() # For now on, we backup the previous settings in case of but we don't have # any mecanism to take advantage of those backups. It could be a nice # addition but we'll see if this is a common need. # Another solution would be to use etckeeper and integrate those # modification inside of it and take advantage of its git history old_settings_backup_path = ( SETTINGS_PATH_OTHER_LOCATION % datetime.utcnow().strftime("%F_%X") ) _save_settings(settings, location=old_settings_backup_path) for value in settings.values(): value["value"] = value["default"] _save_settings(settings) return { "old_settings_backup_path": old_settings_backup_path, "message": m18n.n( "global_settings_reset_success", path=old_settings_backup_path ), }
def _set_hostname(hostname, pretty_hostname=None): """ Change the machine hostname using hostnamectl """ if not pretty_hostname: pretty_hostname = "(YunoHost/%s)" % hostname # First clear nsswitch cache for hosts to make sure hostname is resolved... subprocess.call(["nscd", "-i", "hosts"]) # Then call hostnamectl commands = [ "hostnamectl --static set-hostname".split() + [hostname], "hostnamectl --transient set-hostname".split() + [hostname], "hostnamectl --pretty set-hostname".split() + [pretty_hostname], ] for command in commands: p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) out, _ = p.communicate() if p.returncode != 0: logger.warning(command) logger.warning(out) logger.error(m18n.n("domain_hostname_failed")) else: logger.debug(out)
def run(self): if not self.package_is_installed("postgresql-9.6"): logger.warning( m18n.n("migration_0017_postgresql_96_not_installed")) return if not self.package_is_installed("postgresql-11"): raise YunohostError("migration_0017_postgresql_11_not_installed") # Make sure there's a 9.6 cluster try: self.runcmd("pg_lsclusters | grep -q '^9.6 '") except Exception: logger.warning( "It looks like there's not active 9.6 cluster, so probably don't need to run this migration" ) return if not space_used_by_directory( "/var/lib/postgresql/9.6") > free_space_in_directory( "/var/lib/postgresql"): raise YunohostError("migration_0017_not_enough_space", path="/var/lib/postgresql/") self.runcmd("systemctl stop postgresql") self.runcmd( "LC_ALL=C pg_dropcluster --stop 11 main || true" ) # We do not trigger an exception if the command fails because that probably means cluster 11 doesn't exists, which is fine because it's created during the pg_upgradecluster) self.runcmd("LC_ALL=C pg_upgradecluster -m upgrade 9.6 main") self.runcmd("LC_ALL=C pg_dropcluster --stop 9.6 main") self.runcmd("systemctl start postgresql")
def _name_self_CA(): ca_conf = os.path.join(SSL_DIR, "openssl.ca.cnf") if not os.path.exists(ca_conf): logger.warning(m18n.n("certmanager_self_ca_conf_file_not_found", file=ca_conf)) return "" with open(ca_conf) as f: lines = f.readlines() for line in lines: if line.startswith("commonName_default"): return line.split()[2] logger.warning(m18n.n("certmanager_unable_to_parse_self_CA_name", file=ca_conf)) return ""
def func(self): # Backup LDAP before the migration logger.info(m18n.n("migration_ldap_backup_before_migration")) try: backup_folder = "/home/yunohost.backup/premigration/" + time.strftime( "%Y%m%d-%H%M%S", time.gmtime()) os.makedirs(backup_folder, 0o750) os.system("systemctl stop slapd") os.system( f"cp -r --preserve /etc/ldap {backup_folder}/ldap_config") os.system( f"cp -r --preserve /var/lib/ldap {backup_folder}/ldap_db") os.system( f"cp -r --preserve /etc/yunohost/apps {backup_folder}/apps_settings" ) except Exception as e: raise YunohostError( "migration_ldap_can_not_backup_before_migration", error=str(e)) finally: os.system("systemctl start slapd") try: run(self, backup_folder) except Exception: logger.warning( m18n.n( "migration_ldap_migration_failed_trying_to_rollback")) os.system("systemctl stop slapd") # To be sure that we don't keep some part of the old config os.system("rm -r /etc/ldap/slapd.d") os.system( f"cp -r --preserve {backup_folder}/ldap_config/. /etc/ldap/" ) os.system( f"cp -r --preserve {backup_folder}/ldap_db/. /var/lib/ldap/" ) os.system( f"cp -r --preserve {backup_folder}/apps_settings/. /etc/yunohost/apps/" ) os.system("systemctl start slapd") os.system(f"rm -r {backup_folder}") logger.info(m18n.n("migration_ldap_rollback_success")) raise else: os.system(f"rm -r {backup_folder}")
def tools_shutdown(operation_logger, force=False): shutdown = force if not shutdown: try: # Ask confirmation for server shutdown i = msignals.prompt( m18n.n("server_shutdown_confirm", answers="y/N")) except NotImplemented: pass else: if i.lower() == "y" or i.lower() == "yes": shutdown = True if shutdown: operation_logger.start() logger.warn(m18n.n("server_shutdown")) subprocess.check_call(["systemctl", "poweroff"])
def service_stop(names): """ Stop one or more services Keyword argument: name -- Services name to stop """ if isinstance(names, str): names = [names] for name in names: if _run_service_command('stop', name): logger.success(m18n.n('service_stopped', service=name)) else: if service_status(name)['status'] != 'inactive': raise YunohostError('service_stop_failed', service=name, logs=_get_journalctl_logs(name)) logger.debug(m18n.n('service_already_stopped', service=name))
def tools_shutdown(operation_logger, force=False): shutdown = force if not shutdown: try: # Ask confirmation for server shutdown i = msignals.prompt( m18n.n('server_shutdown_confirm', answers='y/N')) except NotImplemented: pass else: if i.lower() == 'y' or i.lower() == 'yes': shutdown = True if shutdown: operation_logger.start() logger.warn(m18n.n('server_shutdown')) subprocess.check_call(['systemctl', 'poweroff'])
def close(self, error=None): """ Close properly the unit operation """ # When the error happen's in the is_unit_operation try/except, # we want to inject the log ref in the exception, such that it may be # transmitted to the webadmin which can then redirect to the appropriate # log page if isinstance(error, Exception) and not isinstance( error, YunohostValidationError): error.log_ref = self.name if self.ended_at is not None or self.started_at is None: return if error is not None and not isinstance(error, str): error = str(error) self.ended_at = datetime.utcnow() self._error = error self._success = error is None if self.logger is not None: self.logger.removeHandler(self.file_handler) self.file_handler.close() is_api = msettings.get("interface") == "api" desc = _get_description_from_name(self.name) if error is None: if is_api: msg = m18n.n("log_link_to_log", name=self.name, desc=desc) else: msg = m18n.n("log_help_to_get_log", name=self.name, desc=desc) logger.debug(msg) else: if is_api: msg = ("<strong>" + m18n.n( "log_link_to_failed_log", name=self.name, desc=desc) + "</strong>") else: msg = m18n.n("log_help_to_get_failed_log", name=self.name, desc=desc) logger.info(msg) self.flush() return msg
def __call__(self, message, arg_name, arg_value): if arg_value: return arg_value try: # Ask for the password return Moulinette.prompt(m18n.n(message), True, True) except NotImplementedError: return arg_value
def run(self, *args): from yunohost.utils.ldap import _get_ldap_interface ldap = _get_ldap_interface() existing_perms_raw = ldap.search( "ou=permission,dc=yunohost,dc=org", "(objectclass=permissionYnh)", ["cn"] ) existing_perms = [perm["cn"][0] for perm in existing_perms_raw] # Add SSH and SFTP permissions ldap_map = read_yaml( "/usr/share/yunohost/yunohost-config/moulinette/ldap_scheme.yml" ) if "sftp.main" not in existing_perms: ldap.add( "cn=sftp.main,ou=permission", ldap_map["depends_children"]["cn=sftp.main,ou=permission"], ) if "ssh.main" not in existing_perms: ldap.add( "cn=ssh.main,ou=permission", ldap_map["depends_children"]["cn=ssh.main,ou=permission"], ) # Add a bash terminal to each users users = ldap.search( "ou=users,dc=yunohost,dc=org", filter="(loginShell=*)", attrs=["dn", "uid", "loginShell"], ) for user in users: if user["loginShell"][0] == "/bin/false": dn = user["dn"][0].replace(",dc=yunohost,dc=org", "") ldap.update(dn, {"loginShell": ["/bin/bash"]}) else: user_permission_update( "ssh.main", add=user["uid"][0], sync_perm=False ) permission_sync_to_user() # Somehow this is needed otherwise the PAM thing doesn't forget about the # old loginShell value ? subprocess.call(["nscd", "-i", "passwd"]) if ( "/etc/ssh/sshd_config" in manually_modified_files() and os.system( "grep -q '^ *AllowGroups\\|^ *AllowUsers' /etc/ssh/sshd_config" ) != 0 ): logger.error(m18n.n("diagnosis_sshd_config_insecure"))
def _tools_migrations_run_before_app_restore(backup_version, app_id): all_migrations = _get_migrations_list() for migration in all_migrations: if hasattr(migration, "introduced_in_version") \ and version.parse(migration.introduced_in_version) > version.parse(backup_version) \ and hasattr(migration, "run_before_app_restore"): try: logger.info( m18n.n("migrations_running_forward", id=migration.id)) migration.run_before_app_restore(app_id) except Exception as e: msg = m18n.n("migrations_migration_has_failed", exception=e, id=migration.id) logger.error(msg, exc_info=1) raise
def dyndns_installcron(): """ Install IP update cron """ with open("/etc/cron.d/yunohost-dyndns", "w+") as f: f.write("*/2 * * * * root yunohost dyndns update >> /dev/null\n") logger.success(m18n.n("dyndns_cron_installed"))
def __init__(self, key, raw_msg=False, log_ref=None, *args, **kwargs): self.key = key # Saving the key is useful for unit testing self.kwargs = kwargs # Saving the key is useful for unit testing self.log_ref = log_ref if raw_msg: msg = key else: msg = m18n.n(key, *args, **kwargs) super(YunohostError, self).__init__(msg, raw_msg=True)
def __del__(self): """ Try to close the unit operation, if it's missing. The missing of the message below could help to see an electrical shortage. """ if self.ended_at is not None or self.started_at is None: return else: self.error(m18n.n("log_operation_unit_unclosed_properly"))
def dyndns_installcron(): """ Install IP update cron """ with open('/etc/cron.d/yunohost-dyndns', 'w+') as f: f.write('*/2 * * * * root yunohost dyndns update >> /dev/null\n') logger.success(m18n.n('dyndns_cron_installed'))
def firewall_disallow(protocol, port, ipv4_only=False, ipv6_only=False, upnp_only=False, no_reload=False): """ Disallow connections on a port Keyword arguments: protocol -- Protocol type to disallow (TCP/UDP/Both) port -- Port or range of ports to close ipv4_only -- Only remove the rule for IPv4 connections ipv6_only -- Only remove the rule for IPv6 connections upnp_only -- Only remove forwarding of this port with UPnP no_reload -- Do not reload firewall rules """ firewall = firewall_list(raw=True) # Validate port if not isinstance(port, int) and ':' not in port: port = int(port) # Validate protocols protocols = ['TCP', 'UDP'] if protocol != 'Both' and protocol in protocols: protocols = [protocol, ] # Validate IP versions and UPnP ipvs = ['ipv4', 'ipv6'] upnp = True if ipv4_only and ipv6_only: upnp = True # automatically disallow UPnP elif ipv4_only: ipvs = ['ipv4', ] upnp = upnp_only elif ipv6_only: ipvs = ['ipv6', ] upnp = upnp_only elif upnp_only: ipvs = [] for p in protocols: # Iterate over IP versions to remove port for i in ipvs: if port in firewall[i][p]: firewall[i][p].remove(port) else: ipv = "IPv%s" % i[3] logger.warning(m18n.n('port_already_closed', port=port, ip_version=ipv)) # Remove port forwarding with UPnP if upnp and port in firewall['uPnP'][p]: firewall['uPnP'][p].remove(port) # Update and reload firewall _update_firewall_file(firewall) if not no_reload: return firewall_reload()