PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/states/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : //proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/states/network.py |
""" Configuration of network interfaces =================================== The network module is used to create and manage network settings, interfaces can be set as either managed or ignored. By default all interfaces are ignored unless specified. .. note:: RedHat-based systems (RHEL, CentOS, Scientific, etc.) have been supported since version 2014.1.0. Debian-based systems (Debian, Ubuntu, etc.) have been supported since version 2017.7.0. The following options are not supported: ipaddr_start, and ipaddr_end. Other platforms are not yet supported. .. note:: On Debian-based systems, networking configuration can be specified in `/etc/network/interfaces` or via included files such as (by default) `/etc/network/interfaces.d/*`. This can be problematic for configuration management. It is recommended to use either `file.managed` *or* `network.managed`. If using ``network.managed``, it can be useful to ensure ``interfaces.d/`` is empty. This can be done using the following state .. code-block:: yaml /etc/network/interfaces.d: file.directory: - clean: True Configuring Global Network Settings ----------------------------------- Use the :py:func:`network.system <salt.states.network.system>` state to set global network settings: .. code-block:: yaml system: network.system: - enabled: True - hostname: server1.example.com - gateway: 192.168.0.1 - gatewaydev: eth0 - nozeroconf: True - nisdomain: example.com - require_reboot: True - apply_hostname: True .. note:: The use of ``apply_hostname`` above will apply changes to the hostname immediately. .. versionchanged:: 2015.5.0 ``apply_hostname`` added retain_settings *************** .. versionadded:: 2016.11.0 Use `retain_settings` to retain current network settings that are not otherwise specified in the state. Particularly useful if only setting the hostname. Default behavior is to delete unspecified network settings. .. code-block:: yaml system: network.system: - hostname: server2.example.com - apply_hostname: True - retain_settings: True Configuring Network Routes -------------------------- Use the :py:func:`network.routes <salt.states.network.routes>` state to set network routes. .. code-block:: yaml routes: network.routes: - name: eth0 - routes: - name: secure_network ipaddr: 10.2.0.0 netmask: 255.255.255.0 gateway: 10.1.0.3 - name: HQ_network ipaddr: 10.100.0.0 netmask: 255.255.0.0 gateway: 10.1.0.10 Managing Network Interfaces --------------------------- The :py:func:`network.managed <salt.states.network.managed>` state is used to configure network interfaces. Here are several examples: Ethernet Interface ****************** .. code-block:: yaml eth0: network.managed: - enabled: True - type: eth - proto: static - ipaddr: 10.1.0.7 - netmask: 255.255.255.0 - gateway: 10.1.0.1 - enable_ipv6: true - ipv6proto: static - ipv6addrs: - 2001:db8:dead:beef::3/64 - 2001:db8:dead:beef::7/64 - ipv6gateway: 2001:db8:dead:beef::1 - ipv6netmask: 64 - dns: - 8.8.8.8 - 8.8.4.4 - channels: rx: 4 tx: 4 other: 4 combined: 4 Ranged Interfaces (RHEL/CentOS Only) ************************************ .. versionadded:: 2015.8.0 Ranged interfaces can be created by including the word ``range`` in the interface name. .. important:: The interface type must be ``eth``. .. code-block:: yaml eth0-range0: network.managed: - type: eth - ipaddr_start: 192.168.1.1 - ipaddr_end: 192.168.1.10 - clonenum_start: 10 - mtu: 9000 bond0-range0: network.managed: - type: eth - ipaddr_start: 192.168.1.1 - ipaddr_end: 192.168.1.10 - clonenum_start: 10 - mtu: 9000 eth1.0-range0: network.managed: - type: eth - ipaddr_start: 192.168.1.1 - ipaddr_end: 192.168.1.10 - clonenum_start: 10 - vlan: True - mtu: 9000 bond0.1-range0: network.managed: - type: eth - ipaddr_start: 192.168.1.1 - ipaddr_end: 192.168.1.10 - clonenum_start: 10 - vlan: True - mtu: 9000 Bond Interfaces *************** To configure a bond, you must do the following: - Configure the bond slaves with a ``type`` of ``slave``, and a ``master`` option set to the name of the bond interface. - Configure the bond interface with a ``type`` of ``bond``, and a ``slaves`` option defining the bond slaves for the bond interface. .. code-block:: yaml eth2: network.managed: - enabled: True - type: slave - master: bond0 eth3: network.managed: - enabled: True - type: slave - master: bond0 bond0: network.managed: - type: bond - ipaddr: 10.1.0.1 - netmask: 255.255.255.0 - mode: gre - proto: static - dns: - 8.8.8.8 - 8.8.4.4 - enabled: False - slaves: eth2 eth3 - require: - network: eth2 - network: eth3 - miimon: 100 - arp_interval: 250 - downdelay: 200 - lacp_rate: fast - max_bonds: 1 - updelay: 0 - use_carrier: on - hashing-algorithm: layer2 - mtu: 9000 - autoneg: on - speed: 1000 - duplex: full - rx: on - tx: off - sg: on - tso: off - ufo: off - gso: off - gro: off - lro: off VLANs ***** Set ``type`` to ``vlan`` to configure a VLANs. These VLANs are configured on the bond interface defined above. .. code-block:: yaml bond0.2: network.managed: - type: vlan - ipaddr: 10.1.0.2 - use: - network: bond0 - require: - network: bond0 bond0.3: network.managed: - type: vlan - ipaddr: 10.1.0.3 - use: - network: bond0 - require: - network: bond0 bond0.10: network.managed: - type: vlan - ipaddr: 10.1.0.4 - use: - network: bond0 - require: - network: bond0 bond0.12: network.managed: - type: vlan - ipaddr: 10.1.0.5 - use: - network: bond0 - require: - network: bond0 Bridge Interfaces ***************** .. code-block:: yaml eth4: network.managed: - enabled: True - type: eth - proto: dhcp - bridge: br0 br0: network.managed: - enabled: True - type: bridge - proto: dhcp - bridge: br0 - delay: 0 - ports: eth4 - bypassfirewall: True - use: - network: eth4 - require: - network: eth4 .. note:: When managing bridged interfaces on a Debian/Ubuntu based system, the ``ports`` argument is required. RedHat-based systems will ignore the argument. Network Teaming (RHEL/CentOS 7 and later) ***************************************** .. versionadded:: 3002 - Configure the members of the team interface with a ``type`` of ``teamport``, and a ``team_master`` option set to the name of the bond interface. - ``master`` also works, but will be ignored if both ``team_master`` and ``master`` are present. - If applicable, include a ``team_port_config`` option. This should be formatted as a dictionary. Keep in mind that due to a quirk of PyYAML, dictionaries nested under a list item must be double-indented (see example below for interface ``eth5``). - Configure the team interface with a ``type`` of ``team``. The team configuration should be passed via the ``team_config`` option. As with ``team_port_config``, the dictionary should be double-indented. .. code-block:: yaml eth5: network.managed: - type: teamport - team_master: team0 - team_port_config: prio: 100 eth6: network.managed: - type: teamport - team_master: team0 team0: network.managed: - type: team - ipaddr: 172.24.90.42 - netmask: 255.255.255.128 - enable_ipv6: True - ipv6addr: 'fee1:dead:beef:af43::' - team_config: runner: hwaddr_policy: by_active name: activebackup link_watch: name: ethtool .. note:: While ``teamd`` must be installed to manage a team interface, it is not required to configure a separate :py:func:`pkg.installed <salt.states.pkg.installed>` state for it, as it will be silently installed if needed. Configuring the Loopback Interface ********************************** Use :py:func:`network.managed <salt.states.network.managed>` with a ``type`` of ``eth`` and a ``proto`` of ``loopback``. .. code-block:: yaml lo: network.managed: - name: lo - type: eth - proto: loopback - onboot: yes - userctl: no - ipv6_autoconf: no - enable_ipv6: true Other Useful Options -------------------- noifupdown ********** The ``noifupdown`` option, if set to ``True``, will keep Salt from restart the interface if changes are made, requiring them to be restarted manually. Here are a couple examples: .. code-block:: yaml eth7: network.managed: - enabled: True - type: eth # Automatic IP/DNS - proto: dhcp - noifupdown: True eth8: network.managed: - type: eth - noifupdown: True # IPv4 - proto: static - ipaddr: 192.168.4.9 - netmask: 255.255.255.0 - gateway: 192.168.4.1 - enable_ipv6: True # IPv6 - ipv6proto: static - ipv6addr: 2001:db8:dead:c0::3 - ipv6netmask: 64 - ipv6gateway: 2001:db8:dead:c0::1 # override shared; makes those options v4-only - ipv6ttl: 15 # Shared - mtu: 1480 - ttl: 18 - dns: - 8.8.8.8 - 8.8.4.4 """ import difflib import logging import salt.loader import salt.utils.network import salt.utils.platform # Set up logging log = logging.getLogger(__name__) def __virtual__(): """ Confine this module to non-Windows systems with the required execution module available. """ if salt.utils.platform.is_windows(): return (False, "Only supported on non-Windows OSs") if "ip.get_interface" in __salt__: return True return (False, "ip module could not be loaded") def managed(name, enabled=True, **kwargs): """ Ensure that the named interface is configured properly. name The name of the interface to manage type : eth Type of interface and configuration .. versionchanged:: 3002 enabled Designates the state of this interface. """ # For this function we are purposefully overwriting a bif # to enhance the user experience. This does not look like # it will cause a problem. Just giving a heads up in case # it does create a problem. ret = { "name": name, "changes": {}, "result": True, "comment": f"Interface {name} is up to date.", } if "test" not in kwargs: kwargs["test"] = __opts__.get("test", False) # set ranged status apply_ranged_setting = False # Pull interface type out of kwargs iface_type = str(kwargs.pop("type", "eth")) if "addr" in kwargs: hwaddr = kwargs.pop("addr") msg = "'addr' is not a valid argument name, " if "hwaddr" not in kwargs: msg += "its value has been assigned to 'hwaddr' instead." kwargs["hwaddr"] = hwaddr else: msg += "it has been ignored in favor of 'hwaddr'." msg += " Update your SLS file to get rid of this warning." ret.setdefault("warnings", []).append(msg) # Build interface try: old = __salt__["ip.get_interface"](name) new = __salt__["ip.build_interface"](name, iface_type, enabled, **kwargs) if kwargs["test"]: if old == new: pass if not old and new: ret["result"] = None ret["comment"] = f"Interface {name} is set to be added." elif old != new: diff = difflib.unified_diff(old, new, lineterm="") ret["result"] = None ret["comment"] = "Interface {} is set to be updated:\n{}".format( name, "\n".join(diff) ) else: if not old and new: ret["comment"] = f"Interface {name} added." ret["changes"]["interface"] = "Added network interface." apply_ranged_setting = True elif old != new: diff = difflib.unified_diff(old, new, lineterm="") ret["comment"] = f"Interface {name} updated." ret["changes"]["interface"] = "\n".join(diff) apply_ranged_setting = True except AttributeError as error: ret["result"] = False ret["comment"] = str(error) return ret # Debian based system can have a type of source # in the interfaces file, we don't ifup or ifdown it if iface_type == "source": return ret # Setup up bond modprobe script if required if iface_type == "bond" and "ip.get_bond" in __salt__: try: old = __salt__["ip.get_bond"](name) new = __salt__["ip.build_bond"](name, **kwargs) if kwargs["test"]: if not old and new: ret["result"] = None ret["comment"] = "Bond interface {} is set to be added.".format( name ) elif old != new: diff = difflib.unified_diff(old, new, lineterm="") ret["result"] = None ret["comment"] = ( "Bond interface {} is set to be updated:\n{}".format( name, "\n".join(diff) ) ) else: if not old and new: ret["comment"] = f"Bond interface {name} added." ret["changes"]["bond"] = f"Added bond {name}." apply_ranged_setting = True elif old != new: diff = difflib.unified_diff(old, new, lineterm="") ret["comment"] = f"Bond interface {name} updated." ret["changes"]["bond"] = "\n".join(diff) apply_ranged_setting = True except AttributeError as error: # TODO Add a way of reversing the interface changes. ret["result"] = False ret["comment"] = str(error) return ret if kwargs["test"]: return ret # For Redhat/Centos ranged network if "range" in name: if apply_ranged_setting: try: ret["result"] = __salt__["service.restart"]("network") ret["comment"] = "network restarted for change of ranged interfaces" return ret except Exception as error: # pylint: disable=broad-except ret["result"] = False ret["comment"] = str(error) return ret ret["result"] = True ret["comment"] = "no change, passing it" return ret # Bring up/shutdown interface try: # Get Interface current status interfaces = salt.utils.network.interfaces() interface_status = False if name in interfaces: interface_status = interfaces[name].get("up") else: for iface in interfaces: if "secondary" in interfaces[iface]: for second in interfaces[iface]["secondary"]: if second.get("label", "") == name: interface_status = True if iface == "lo": if "inet" in interfaces[iface]: inet_data = interfaces[iface]["inet"] if len(inet_data) > 1: for data in inet_data: if data.get("label", "") == name: interface_status = True if "inet6" in interfaces[iface]: inet6_data = interfaces[iface]["inet6"] if len(inet6_data) > 1: for data in inet6_data: if data.get("label", "") == name: interface_status = True if enabled: if "noifupdown" not in kwargs: if interface_status: if ret["changes"]: # Interface should restart to validate if it's up __salt__["ip.down"](name, iface_type) __salt__["ip.up"](name, iface_type) ret["changes"][ "status" ] = f"Interface {name} restart to validate" else: __salt__["ip.up"](name, iface_type) ret["changes"]["status"] = f"Interface {name} is up" else: if "noifupdown" not in kwargs: if interface_status: __salt__["ip.down"](name, iface_type) ret["changes"]["status"] = f"Interface {name} down" except Exception as error: # pylint: disable=broad-except ret["result"] = False ret["comment"] = str(error) return ret # Try to enslave bonding interfaces after master was created if iface_type == "bond" and "noifupdown" not in kwargs: if "slaves" in kwargs and kwargs["slaves"]: # Check that there are new slaves for this master present_slaves = __salt__["cmd.run"]( ["cat", f"/sys/class/net/{name}/bonding/slaves"] ).split() if isinstance(kwargs["slaves"], list): desired_slaves = kwargs["slaves"] else: desired_slaves = kwargs["slaves"].split() missing_slaves = set(desired_slaves) - set(present_slaves) # Enslave only slaves missing in master if missing_slaves: if __grains__["os_family"] != "Suse": ifenslave_path = __salt__["cmd.run"](["which", "ifenslave"]).strip() if ifenslave_path: log.info( "Adding slaves '%s' to the master %s", " ".join(missing_slaves), name, ) cmd = [ifenslave_path, name] + list(missing_slaves) __salt__["cmd.run"](cmd, python_shell=False) else: log.error("Command 'ifenslave' not found") ret["changes"]["enslave"] = ( "Added slaves '{}' to master '{}'".format( " ".join(missing_slaves), name ) ) else: log.info( "All slaves '%s' are already added to the master %s" ", no actions required", " ".join(missing_slaves), name, ) if enabled and interface_status: # Interface was restarted, return return ret # Make sure that the network grains reflect any changes made here __salt__["saltutil.refresh_grains"]() return ret def routes(name, **kwargs): """ Manage network interface static routes. name Interface name to apply the route to. kwargs Named routes """ ret = { "name": name, "changes": {}, "result": True, "comment": f"Interface {name} routes are up to date.", } apply_routes = False if "test" not in kwargs: kwargs["test"] = __opts__.get("test", False) # Build interface routes try: old = __salt__["ip.get_routes"](name) new = __salt__["ip.build_routes"](name, **kwargs) if kwargs["test"]: if old == new: return ret if not old and new: ret["result"] = None ret["comment"] = f"Interface {name} routes are set to be added." return ret elif old != new: diff = difflib.unified_diff(old, new, lineterm="") ret["result"] = None ret["comment"] = ( "Interface {} routes are set to be updated:\n{}".format( name, "\n".join(diff) ) ) return ret if not old and new: apply_routes = True ret["comment"] = f"Interface {name} routes added." ret["changes"]["network_routes"] = f"Added interface {name} routes." elif old != new: diff = difflib.unified_diff(old, new, lineterm="") apply_routes = True ret["comment"] = f"Interface {name} routes updated." ret["changes"]["network_routes"] = "\n".join(diff) except AttributeError as error: ret["result"] = False ret["comment"] = str(error) return ret # Apply interface routes if apply_routes: try: __salt__["ip.apply_network_settings"](**kwargs) except AttributeError as error: ret["result"] = False ret["comment"] = str(error) return ret return ret def system(name, **kwargs): """ Ensure that global network settings are configured properly. name Custom name to represent this configuration change. kwargs The global parameters for the system. """ ret = { "name": name, "changes": {}, "result": True, "comment": "Global network settings are up to date.", } apply_net_settings = False kwargs["test"] = __opts__["test"] # Build global network settings try: old = __salt__["ip.get_network_settings"]() new = __salt__["ip.build_network_settings"](**kwargs) if __opts__["test"]: if old == new: return ret if not old and new: ret["result"] = None ret["comment"] = "Global network settings are set to be added." return ret elif old != new: diff = difflib.unified_diff(old, new, lineterm="") ret["result"] = None ret["comment"] = ( "Global network settings are set to be updated:\n{}".format( "\n".join(diff) ) ) return ret if not old and new: apply_net_settings = True ret["changes"]["network_settings"] = "Added global network settings." elif old != new: diff = difflib.unified_diff(old, new, lineterm="") apply_net_settings = True ret["changes"]["network_settings"] = "\n".join(diff) except AttributeError as error: ret["result"] = False ret["comment"] = str(error) return ret except KeyError as error: ret["result"] = False ret["comment"] = str(error) return ret # Apply global network settings if apply_net_settings: try: __salt__["ip.apply_network_settings"](**kwargs) except AttributeError as error: ret["result"] = False ret["comment"] = str(error) return ret return ret