From 74d5d84ada50609c60008d3160492c1f4a29d72d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Mon, 20 May 2019 11:59:39 +0100 Subject: [PATCH] Switch firewalld state to use change_interface firewalld.present state allows to bind interface to given zone. However if the interface is already bound to some other zone, call- ing `add_interface` will not change rebind the interface but report error. Option `change_interface` however can rebind the interface from one zone to another. This PR adds `firewalld.change_interface` call to firewalld module and updates `firewalld.present` state to use this call. --- salt/modules/firewalld.py | 100 ++++++++++++++++++++++---------------- salt/states/firewalld.py | 93 +++++++++++++++++------------------ 2 files changed, 104 insertions(+), 89 deletions(-) diff --git a/salt/modules/firewalld.py b/salt/modules/firewalld.py index ca35568c3f..12808cb038 100644 --- a/salt/modules/firewalld.py +++ b/salt/modules/firewalld.py @@ -1,19 +1,14 @@ -# -*- coding: utf-8 -*- """ Support for firewalld. .. versionadded:: 2015.2.0 """ -# Import Python Libs -from __future__ import absolute_import, print_function, unicode_literals import logging import re import salt.utils.path - -# Import Salt Libs from salt.exceptions import CommandExecutionError log = logging.getLogger(__name__) @@ -36,7 +31,7 @@ def __firewall_cmd(cmd): """ Return the firewall-cmd location """ - firewall_cmd = "{0} {1}".format(salt.utils.path.which("firewall-cmd"), cmd) + firewall_cmd = "{} {}".format(salt.utils.path.which("firewall-cmd"), cmd) out = __salt__["cmd.run_all"](firewall_cmd) if out["retcode"] != 0: @@ -44,7 +39,7 @@ def __firewall_cmd(cmd): msg = out["stdout"] else: msg = out["stderr"] - raise CommandExecutionError("firewall-cmd failed: {0}".format(msg)) + raise CommandExecutionError("firewall-cmd failed: {}".format(msg)) return out["stdout"] @@ -53,7 +48,7 @@ def __mgmt(name, _type, action): Perform zone management """ # It's permanent because the 4 concerned functions need the permanent option, it's wrong without - cmd = "--{0}-{1}={2} --permanent".format(action, _type, name) + cmd = "--{}-{}={} --permanent".format(action, _type, name) return __firewall_cmd(cmd) @@ -250,7 +245,7 @@ def set_default_zone(zone): salt '*' firewalld.set_default_zone damian """ - return __firewall_cmd("--set-default-zone={0}".format(zone)) + return __firewall_cmd("--set-default-zone={}".format(zone)) def new_service(name, restart=True): @@ -327,7 +322,7 @@ def list_all(zone=None, permanent=True): id_ = "" if zone: - cmd = "--zone={0} --list-all".format(zone) + cmd = "--zone={} --list-all".format(zone) else: cmd = "--list-all" @@ -372,7 +367,7 @@ def list_services(zone=None, permanent=True): salt '*' firewalld.list_services my_zone """ if zone: - cmd = "--zone={0} --list-services".format(zone) + cmd = "--zone={} --list-services".format(zone) else: cmd = "--list-services" @@ -399,9 +394,9 @@ def add_service(service, zone=None, permanent=True): salt '*' firewalld.add_service ssh my_zone """ if zone: - cmd = "--zone={0} --add-service={1}".format(zone, service) + cmd = "--zone={} --add-service={}".format(zone, service) else: - cmd = "--add-service={0}".format(service) + cmd = "--add-service={}".format(service) if permanent: cmd += " --permanent" @@ -427,9 +422,9 @@ def remove_service(service, zone=None, permanent=True): salt '*' firewalld.remove_service ssh dmz """ if zone: - cmd = "--zone={0} --remove-service={1}".format(zone, service) + cmd = "--zone={} --remove-service={}".format(zone, service) else: - cmd = "--remove-service={0}".format(service) + cmd = "--remove-service={}".format(service) if permanent: cmd += " --permanent" @@ -452,7 +447,7 @@ def add_service_port(service, port): if service not in get_services(permanent=True): raise CommandExecutionError("The service does not exist.") - cmd = "--permanent --service={0} --add-port={1}".format(service, port) + cmd = "--permanent --service={} --add-port={}".format(service, port) return __firewall_cmd(cmd) @@ -471,7 +466,7 @@ def remove_service_port(service, port): if service not in get_services(permanent=True): raise CommandExecutionError("The service does not exist.") - cmd = "--permanent --service={0} --remove-port={1}".format(service, port) + cmd = "--permanent --service={} --remove-port={}".format(service, port) return __firewall_cmd(cmd) @@ -487,7 +482,7 @@ def get_service_ports(service): salt '*' firewalld.get_service_ports zone """ - cmd = "--permanent --service={0} --get-ports".format(service) + cmd = "--permanent --service={} --get-ports".format(service) return __firewall_cmd(cmd).split() @@ -503,7 +498,7 @@ def add_service_protocol(service, protocol): salt '*' firewalld.add_service_protocol zone ssh """ - cmd = "--permanent --service={0} --add-protocol={1}".format(service, protocol) + cmd = "--permanent --service={} --add-protocol={}".format(service, protocol) return __firewall_cmd(cmd) @@ -519,7 +514,7 @@ def remove_service_protocol(service, protocol): salt '*' firewalld.remove_service_protocol zone ssh """ - cmd = "--permanent --service={0} --remove-protocol={1}".format(service, protocol) + cmd = "--permanent --service={} --remove-protocol={}".format(service, protocol) return __firewall_cmd(cmd) @@ -535,7 +530,7 @@ def get_service_protocols(service): salt '*' firewalld.get_service_protocols zone """ - cmd = "--permanent --service={0} --get-protocols".format(service) + cmd = "--permanent --service={} --get-protocols".format(service) return __firewall_cmd(cmd).split() @@ -578,7 +573,7 @@ def add_masquerade(zone=None, permanent=True): salt '*' firewalld.add_masquerade dmz """ if zone: - cmd = "--zone={0} --add-masquerade".format(zone) + cmd = "--zone={} --add-masquerade".format(zone) else: cmd = "--add-masquerade" @@ -608,7 +603,7 @@ def remove_masquerade(zone=None, permanent=True): salt '*' firewalld.remove_masquerade dmz """ if zone: - cmd = "--zone={0} --remove-masquerade".format(zone) + cmd = "--zone={} --remove-masquerade".format(zone) else: cmd = "--remove-masquerade" @@ -637,7 +632,7 @@ def add_port(zone, port, permanent=True, force_masquerade=False): if force_masquerade and not get_masquerade(zone): add_masquerade(zone) - cmd = "--zone={0} --add-port={1}".format(zone, port) + cmd = "--zone={} --add-port={}".format(zone, port) if permanent: cmd += " --permanent" @@ -657,7 +652,7 @@ def remove_port(zone, port, permanent=True): salt '*' firewalld.remove_port internal 443/tcp """ - cmd = "--zone={0} --remove-port={1}".format(zone, port) + cmd = "--zone={} --remove-port={}".format(zone, port) if permanent: cmd += " --permanent" @@ -677,7 +672,7 @@ def list_ports(zone, permanent=True): salt '*' firewalld.list_ports """ - cmd = "--zone={0} --list-ports".format(zone) + cmd = "--zone={} --list-ports".format(zone) if permanent: cmd += " --permanent" @@ -706,7 +701,7 @@ def add_port_fwd( if force_masquerade and not get_masquerade(zone): add_masquerade(zone) - cmd = "--zone={0} --add-forward-port=port={1}:proto={2}:toport={3}:toaddr={4}".format( + cmd = "--zone={} --add-forward-port=port={}:proto={}:toport={}:toaddr={}".format( zone, src, proto, dest, dstaddr ) @@ -728,7 +723,7 @@ def remove_port_fwd(zone, src, dest, proto="tcp", dstaddr="", permanent=True): salt '*' firewalld.remove_port_fwd public 80 443 tcp """ - cmd = "--zone={0} --remove-forward-port=port={1}:proto={2}:toport={3}:toaddr={4}".format( + cmd = "--zone={} --remove-forward-port=port={}:proto={}:toport={}:toaddr={}".format( zone, src, proto, dest, dstaddr ) @@ -752,7 +747,7 @@ def list_port_fwd(zone, permanent=True): """ ret = [] - cmd = "--zone={0} --list-forward-ports".format(zone) + cmd = "--zone={} --list-forward-ports".format(zone) if permanent: cmd += " --permanent" @@ -792,7 +787,7 @@ def block_icmp(zone, icmp, permanent=True): log.info("ICMP block already exists") return "success" - cmd = "--zone={0} --add-icmp-block={1}".format(zone, icmp) + cmd = "--zone={} --add-icmp-block={}".format(zone, icmp) if permanent: cmd += " --permanent" @@ -820,7 +815,7 @@ def allow_icmp(zone, icmp, permanent=True): log.info("ICMP Type is already permitted") return "success" - cmd = "--zone={0} --remove-icmp-block={1}".format(zone, icmp) + cmd = "--zone={} --remove-icmp-block={}".format(zone, icmp) if permanent: cmd += " --permanent" @@ -840,7 +835,7 @@ def list_icmp_block(zone, permanent=True): salt '*' firewlld.list_icmp_block zone """ - cmd = "--zone={0} --list-icmp-blocks".format(zone) + cmd = "--zone={} --list-icmp-blocks".format(zone) if permanent: cmd += " --permanent" @@ -875,7 +870,7 @@ def get_interfaces(zone, permanent=True): salt '*' firewalld.get_interfaces zone """ - cmd = "--zone={0} --list-interfaces".format(zone) + cmd = "--zone={} --list-interfaces".format(zone) if permanent: cmd += " --permanent" @@ -898,7 +893,7 @@ def add_interface(zone, interface, permanent=True): if interface in get_interfaces(zone, permanent): log.info("Interface is already bound to zone.") - cmd = "--zone={0} --add-interface={1}".format(zone, interface) + cmd = "--zone={} --add-interface={}".format(zone, interface) if permanent: cmd += " --permanent" @@ -921,7 +916,30 @@ def remove_interface(zone, interface, permanent=True): if interface not in get_interfaces(zone, permanent): log.info("Interface is not bound to zone.") - cmd = "--zone={0} --remove-interface={1}".format(zone, interface) + cmd = "--zone={} --remove-interface={}".format(zone, interface) + + if permanent: + cmd += " --permanent" + + return __firewall_cmd(cmd) + + +def change_interface(zone, interface, permanent=True): + """ + Change zone the interface bound to + + .. versionadded:: 2019.?.? + + CLI Example: + + .. code-block:: bash + + salt '*' firewalld.change_interface zone eth0 + """ + if interface in get_interfaces(zone, permanent): + log.info("Interface is already bound to zone.") + + cmd = "--zone={} --change-interface={}".format(zone, interface) if permanent: cmd += " --permanent" @@ -941,7 +959,7 @@ def get_sources(zone, permanent=True): salt '*' firewalld.get_sources zone """ - cmd = "--zone={0} --list-sources".format(zone) + cmd = "--zone={} --list-sources".format(zone) if permanent: cmd += " --permanent" @@ -964,7 +982,7 @@ def add_source(zone, source, permanent=True): if source in get_sources(zone, permanent): log.info("Source is already bound to zone.") - cmd = "--zone={0} --add-source={1}".format(zone, source) + cmd = "--zone={} --add-source={}".format(zone, source) if permanent: cmd += " --permanent" @@ -987,7 +1005,7 @@ def remove_source(zone, source, permanent=True): if source not in get_sources(zone, permanent): log.info("Source is not bound to zone.") - cmd = "--zone={0} --remove-source={1}".format(zone, source) + cmd = "--zone={} --remove-source={}".format(zone, source) if permanent: cmd += " --permanent" @@ -1007,7 +1025,7 @@ def get_rich_rules(zone, permanent=True): salt '*' firewalld.get_rich_rules zone """ - cmd = "--zone={0} --list-rich-rules".format(zone) + cmd = "--zone={} --list-rich-rules".format(zone) if permanent: cmd += " --permanent" @@ -1027,7 +1045,7 @@ def add_rich_rule(zone, rule, permanent=True): salt '*' firewalld.add_rich_rule zone 'rule' """ - cmd = "--zone={0} --add-rich-rule='{1}'".format(zone, rule) + cmd = "--zone={} --add-rich-rule='{}'".format(zone, rule) if permanent: cmd += " --permanent" @@ -1047,7 +1065,7 @@ def remove_rich_rule(zone, rule, permanent=True): salt '*' firewalld.remove_rich_rule zone 'rule' """ - cmd = "--zone={0} --remove-rich-rule='{1}'".format(zone, rule) + cmd = "--zone={} --remove-rich-rule='{}'".format(zone, rule) if permanent: cmd += " --permanent" diff --git a/salt/states/firewalld.py b/salt/states/firewalld.py index 4114e99f43..425defcfb1 100644 --- a/salt/states/firewalld.py +++ b/salt/states/firewalld.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Management of firewalld @@ -76,21 +75,17 @@ would allow access to the salt master from the 10.0.0.0/8 subnet: - 10.0.0.0/8 """ -# Import Python Libs -from __future__ import absolute_import, print_function, unicode_literals import logging import salt.utils.path - -# Import Salt Libs from salt.exceptions import CommandExecutionError from salt.output import nested log = logging.getLogger(__name__) -class ForwardingMapping(object): +class ForwardingMapping: """ Represents a port forwarding statement mapping a local port to a remote port for a specific protocol (TCP or UDP) @@ -282,7 +277,7 @@ def service(name, ports=None, protocols=None): try: _current_ports = __salt__["firewalld.get_service_ports"](name) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret new_ports = set(ports) - set(_current_ports) @@ -293,7 +288,7 @@ def service(name, ports=None, protocols=None): try: __salt__["firewalld.add_service_port"](name, port) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret for port in old_ports: @@ -301,7 +296,7 @@ def service(name, ports=None, protocols=None): try: __salt__["firewalld.remove_service_port"](name, port) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if new_ports or old_ports: @@ -312,7 +307,7 @@ def service(name, ports=None, protocols=None): try: _current_protocols = __salt__["firewalld.get_service_protocols"](name) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret new_protocols = set(protocols) - set(_current_protocols) @@ -323,7 +318,7 @@ def service(name, ports=None, protocols=None): try: __salt__["firewalld.add_service_protocol"](name, protocol) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret for protocol in old_protocols: @@ -331,7 +326,7 @@ def service(name, ports=None, protocols=None): try: __salt__["firewalld.remove_service_protocol"](name, protocol) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if new_protocols or old_protocols: @@ -344,15 +339,15 @@ def service(name, ports=None, protocols=None): ret["result"] = True if ret["changes"] == {}: - ret["comment"] = "'{0}' is already in the desired state.".format(name) + ret["comment"] = "'{}' is already in the desired state.".format(name) return ret if __opts__["test"]: ret["result"] = None - ret["comment"] = "Configuration for '{0}' will change.".format(name) + ret["comment"] = "Configuration for '{}' will change.".format(name) return ret - ret["comment"] = "'{0}' was configured.".format(name) + ret["comment"] = "'{}' was configured.".format(name) return ret @@ -385,7 +380,7 @@ def _present( try: zones = __salt__["firewalld.get_zones"](permanent=True) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if name not in zones: @@ -393,7 +388,7 @@ def _present( try: __salt__["firewalld.new_zone"](name) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret ret["changes"].update({name: {"old": zones, "new": name}}) @@ -408,14 +403,14 @@ def _present( name, permanent=True ) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if block_icmp: try: _valid_icmp_types = __salt__["firewalld.get_icmp_types"](permanent=True) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret # log errors for invalid ICMP types in block_icmp input @@ -431,7 +426,7 @@ def _present( name, icmp_type, permanent=True ) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if prune_block_icmp: @@ -446,7 +441,7 @@ def _present( name, icmp_type, permanent=True ) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if new_icmp_types or old_icmp_types: @@ -464,21 +459,21 @@ def _present( try: default_zone = __salt__["firewalld.default_zone"]() except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if name != default_zone: if not __opts__["test"]: try: __salt__["firewalld.set_default_zone"](name) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret ret["changes"].update({"default": {"old": default_zone, "new": name}}) try: masquerade_ret = __salt__["firewalld.get_masquerade"](name, permanent=True) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if masquerade and not masquerade_ret: @@ -486,7 +481,7 @@ def _present( try: __salt__["firewalld.add_masquerade"](name, permanent=True) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret ret["changes"].update( {"masquerade": {"old": "", "new": "Masquerading successfully set."}} @@ -496,7 +491,7 @@ def _present( try: __salt__["firewalld.remove_masquerade"](name, permanent=True) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret ret["changes"].update( {"masquerade": {"old": "", "new": "Masquerading successfully " "disabled."}} @@ -507,7 +502,7 @@ def _present( try: _current_ports = __salt__["firewalld.list_ports"](name, permanent=True) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret new_ports = set(ports) - set(_current_ports) @@ -520,7 +515,7 @@ def _present( name, port, permanent=True, force_masquerade=False ) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if prune_ports: @@ -530,7 +525,7 @@ def _present( try: __salt__["firewalld.remove_port"](name, port, permanent=True) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if new_ports or old_ports: @@ -547,7 +542,7 @@ def _present( name, permanent=True ) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret port_fwd = [_parse_forward(fwd) for fwd in port_fwd] @@ -577,7 +572,7 @@ def _present( force_masquerade=False, ) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if prune_port_fwd: @@ -594,7 +589,7 @@ def _present( permanent=True, ) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if new_port_fwd or old_port_fwd: @@ -618,7 +613,7 @@ def _present( name, permanent=True ) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret new_services = set(services) - set(_current_services) @@ -629,7 +624,7 @@ def _present( try: __salt__["firewalld.add_service"](new_service, name, permanent=True) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if prune_services: @@ -641,7 +636,7 @@ def _present( old_service, name, permanent=True ) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if new_services or old_services: @@ -660,7 +655,7 @@ def _present( name, permanent=True ) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret new_interfaces = set(interfaces) - set(_current_interfaces) @@ -669,9 +664,11 @@ def _present( for interface in new_interfaces: if not __opts__["test"]: try: - __salt__["firewalld.add_interface"](name, interface, permanent=True) + __salt__["firewalld.change_interface"]( + name, interface, permanent=True + ) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if prune_interfaces: @@ -683,7 +680,7 @@ def _present( name, interface, permanent=True ) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if new_interfaces or old_interfaces: @@ -700,7 +697,7 @@ def _present( try: _current_sources = __salt__["firewalld.get_sources"](name, permanent=True) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret new_sources = set(sources) - set(_current_sources) @@ -711,7 +708,7 @@ def _present( try: __salt__["firewalld.add_source"](name, source, permanent=True) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if prune_sources: @@ -723,7 +720,7 @@ def _present( name, source, permanent=True ) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if new_sources or old_sources: @@ -742,7 +739,7 @@ def _present( name, permanent=True ) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret new_rich_rules = set(rich_rules) - set(_current_rich_rules) @@ -753,7 +750,7 @@ def _present( try: __salt__["firewalld.add_rich_rule"](name, rich_rule, permanent=True) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if prune_rich_rules: @@ -765,7 +762,7 @@ def _present( name, rich_rule, permanent=True ) except CommandExecutionError as err: - ret["comment"] = "Error: {0}".format(err) + ret["comment"] = "Error: {}".format(err) return ret if new_rich_rules or old_rich_rules: @@ -780,7 +777,7 @@ def _present( # No changes if ret["changes"] == {}: ret["result"] = True - ret["comment"] = "'{0}' is already in the desired state.".format(name) + ret["comment"] = "'{}' is already in the desired state.".format(name) return ret # test=True and changes predicted @@ -789,7 +786,7 @@ def _present( # build comment string nested.__opts__ = __opts__ comment = [] - comment.append("Configuration for '{0}' will change:".format(name)) + comment.append("Configuration for '{}' will change:".format(name)) comment.append(nested.output(ret["changes"]).rstrip()) ret["comment"] = "\n".join(comment) ret["changes"] = {} @@ -797,5 +794,5 @@ def _present( # Changes were made successfully ret["result"] = True - ret["comment"] = "'{0}' was configured.".format(name) + ret["comment"] = "'{}' was configured.".format(name) return ret -- 2.29.2