diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8d953e0..eeeb696 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,10 +1,18 @@ ===================================== -sebastian.systemd 0.3.2 Release Notes +sebastian.systemd 0.3.3 Release Notes ===================================== .. contents:: Topics +v0.3.3 +====== + +Changelog +--------- + +added netdev module + v0.3.2 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 115e125..4b786ca 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -48,3 +48,7 @@ releases: changes: release_date: "2023-07-15" release_summary: "added virtualization and negative matches to link and network" + 0.3.3: + changes: + release_date: "2023-07-16" + release_summary: "added netdev module" diff --git a/plugins/module_utils/generic.py b/plugins/module_utils/generic.py index 20fbe06..494d74f 100644 --- a/plugins/module_utils/generic.py +++ b/plugins/module_utils/generic.py @@ -123,3 +123,11 @@ def format_condition(key: str, value: str) -> str: value = value[1:] key = "!" + key return f"{key}={value}\n" + + +def joindict(*items: dict) -> dict: + odict = dict() + for item in items: + for key, value in item.items(): + odict[key] = value + return odict diff --git a/plugins/modules/netdev.py b/plugins/modules/netdev.py new file mode 100644 index 0000000..5bc38f0 --- /dev/null +++ b/plugins/modules/netdev.py @@ -0,0 +1,201 @@ +#!/usr/bin/python3 +import pathlib +from typing import List, Optional + +try: + from ansible_collections.sebastian.systemd.plugins.module_utils.generic import ( + SYSTEMD_NETWORK_CONFIG, + Types, + joindict, + modspec, + systemdbool, + ) + from ansible_collections.sebastian.systemd.plugins.module_utils.module import SystemdUnitModule +except ImportError: + from plugins.module_utils.generic import SYSTEMD_NETWORK_CONFIG, Types, joindict, modspec, systemdbool + from plugins.module_utils.module import SystemdUnitModule + + +kinds = ( + "bond", + "bridge", + "dummy", + "wireguard", + "vlan", +) + +matchspec = dict( + host=Types.str(help="hostname of the host that is matched against"), + virtualization=Types.str("Virtualization that is checked against"), + kernelcmd=Types.str(help="checks an kernel commandline argument"), +) + +netdevspec = dict( + description=Types.str(help="Description of the device"), + name=Types.str(required=True, help="name of the device"), + kind=Types.str(required=True, help="type of the device", choices=kinds), +) + +bridgespec = dict( + stp=Types.bool(help="enable the stp protocol"), + priority=Types.int(help="Priority of the bridge"), +) + +bondspec = dict( + mode=Types.str( + help="bonding policy", + choices=("balance-rr", "active-backup", "balance-xor", "broadcast", "802.3ad", "balance-tlb", "balance-alb"), + ), + minlinks=Types.int(help="Specifies the minimum number of links that must be active before asserting carrier."), +) + +wireguardspec = dict( + privatekey=Types.str(help="private key of this side of the tunnel"), + privatekeyfile=Types.path(help="Path of the private key on the host."), + port=Types.raw(help="Port that wireguard uses to listen for packets. the value 'auto' means that the port is automatically decided."), +) + + +class Module(SystemdUnitModule): + """Creates an netdev unit that creates an virtual devices""" + + name = "netdev" + module_spec = modspec(argument_spec=joindict(bondspec, bridgespec, matchspec, netdevspec)) + _common_args = dict( + supports_check_mode=True, + add_file_common_args=True, + ) + + def prepare(self): + self.__unit = None + self.unitfile = SYSTEMD_NETWORK_CONFIG.joinpath(self.get("name")).with_suffix(".netdev") + + def unit(self): + if self.__unit is None: + kind = self.get("kind") + parts = [self.match(), self.netdev()] + if kind != "dummy": + parts.append(getattr(self, kind)()) + self.__unit = "\n".join(parts) + return self.__unit + + def match(self) -> str: + options = self.map_param( + host="Host", + kernelcmd="KernelCommandLine", + virtualization="Virtualization", + ) + return "[Match]\n" + "".join(options) + + def netdev(self) -> str: + options = self.map_param( + description="Description", + name="Name", + kind="Kind", + ) + return "[Netdev]\n" + "".join(options) + + def bond(self) -> str: + return "[Bond]\n" + "".join( + self.map_param( + mode="Mode", + minlinks="MinLinks", + ) + ) + + def bridge(self) -> str: + return "[Bridge]\n" + "".join( + self.map_param( + stp="STP", + priority="Priority", + ) + ) + + def wireguard(self) -> str: + port = self.get("port", False) + if port not in (False, "auto") and (port < 1 or port > 65535): + raise ValueError("Port must be between 0 and 65536") + return "[Wireguard]\n" + "".join( + self.map_param( + privatekey="PrivateKey", + privatekeyfile="PrivateKeyFile", + port="ListenPort", + ) + ) + + def vlan(self) -> str: + return "" + + +DOCUMENTATION = """--- +description: +- Creates an netdev unit that creates an virtual devices +module: netdev +options: + description: + description: + - Description of the device + required: false + type: str + host: + description: + - hostname of the host that is matched against + required: false + type: str + kernelcmd: + description: + - checks an kernel commandline argument + required: false + type: str + kind: + choices: + - bond + - bridge + - dummy + - wireguard + - vlan + description: + - type of the device + required: true + type: str + minlinks: + description: + - Specifies the minimum number of links that must be active before asserting carrier. + required: false + type: int + mode: + choices: + - balance-rr + - active-backup + - balance-xor + - broadcast + - 802.3ad + - balance-tlb + - balance-alb + description: + - bonding policy + required: false + type: str + name: + description: + - name of the device + required: true + type: str + priority: + description: + - Priority of the bridge + required: false + type: int + stp: + description: + - enable the stp protocol + required: false + type: bool + virtualization: + required: true + type: str +short_description: Creates an netdev unit that creates an virtual devices +""" + +if __name__ == "__main__": + Module()()