#!/usr/bin/python # -*- coding: utf-8 -*- # # Copyright: (c) 2016, Roman Belyakovsky # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type DOCUMENTATION = ''' --- module: interfaces_file short_description: Tweak settings in /etc/network/interfaces files extends_documentation_fragment: files description: - Manage (add, remove, change) individual interface options in an interfaces-style file without having to manage the file as a whole with, say, M(ansible.builtin.template) or M(ansible.builtin.assemble). Interface has to be presented in a file. - Read information about interfaces from interfaces-styled files options: dest: type: path description: - Path to the interfaces file default: /etc/network/interfaces iface: type: str description: - Name of the interface, required for value changes or option remove address_family: type: str description: - Address family of the interface, useful if same interface name is used for both inet and inet6 option: type: str description: - Name of the option, required for value changes or option remove value: type: str description: - If I(option) is not presented for the I(interface) and I(state) is C(present) option will be added. If I(option) already exists and is not C(pre-up), C(up), C(post-up) or C(down), it's value will be updated. C(pre-up), C(up), C(post-up) and C(down) options can't be updated, only adding new options, removing existing ones or cleaning the whole option set are supported backup: description: - Create a backup file including the timestamp information so you can get the original file back if you somehow clobbered it incorrectly. type: bool default: 'no' state: type: str description: - If set to C(absent) the option or section will be removed if present instead of created. default: "present" choices: [ "present", "absent" ] notes: - If option is defined multiple times last one will be updated but all will be deleted in case of an absent state requirements: [] author: "Roman Belyakovsky (@hryamzik)" ''' RETURN = ''' dest: description: destination file/path returned: success type: str sample: "/etc/network/interfaces" ifaces: description: interfaces dictionary returned: success type: complex contains: ifaces: description: interface dictionary returned: success type: dict contains: eth0: description: Name of the interface returned: success type: dict contains: address_family: description: interface address family returned: success type: str sample: "inet" method: description: interface method returned: success type: str sample: "manual" mtu: description: other options, all values returned as strings returned: success type: str sample: "1500" pre-up: description: list of C(pre-up) scripts returned: success type: list sample: - "route add -net 10.10.10.0/24 gw 10.10.10.1 dev eth1" - "route add -net 10.10.11.0/24 gw 10.10.11.1 dev eth2" up: description: list of C(up) scripts returned: success type: list sample: - "route add -net 10.10.10.0/24 gw 10.10.10.1 dev eth1" - "route add -net 10.10.11.0/24 gw 10.10.11.1 dev eth2" post-up: description: list of C(post-up) scripts returned: success type: list sample: - "route add -net 10.10.10.0/24 gw 10.10.10.1 dev eth1" - "route add -net 10.10.11.0/24 gw 10.10.11.1 dev eth2" down: description: list of C(down) scripts returned: success type: list sample: - "route del -net 10.10.10.0/24 gw 10.10.10.1 dev eth1" - "route del -net 10.10.11.0/24 gw 10.10.11.1 dev eth2" ... ''' EXAMPLES = ''' - name: Set eth1 mtu configuration value to 8000 community.general.interfaces_file: dest: /etc/network/interfaces.d/eth1.cfg iface: eth1 option: mtu value: 8000 backup: yes state: present register: eth1_cfg ''' import os import re import tempfile from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.common.text.converters import to_bytes def line_dict(line): return {'line': line, 'line_type': 'unknown'} def make_option_dict(line, iface, option, value, address_family): return {'line': line, 'iface': iface, 'option': option, 'value': value, 'line_type': 'option', 'address_family': address_family} def get_option_value(line): patt = re.compile(r'^\s+(?P