251 Zeilen
8.0 KiB
Python
251 Zeilen
8.0 KiB
Python
#!/usr/bin/python3
|
|
import pathlib
|
|
from typing import List, Union, Optional
|
|
|
|
try:
|
|
from ansible_module.module_utils.generic import SYSTEMD_NETWORK_CONFIG, Types, modspec, systemdbool
|
|
from ansible_module.module_utils.module import SystemdUnitModule
|
|
except ImportError:
|
|
from ansible_collections.sebastian.base.plugins.module_utils.generic import SYSTEMD_NETWORK_CONFIG, Types, modspec, systemdbool
|
|
from ansible_collections.sebastian.base.plugins.module_utils.module import SystemdUnitModule
|
|
|
|
|
|
class Module(SystemdUnitModule): # type: ignore
|
|
"""Sets up the systemd network unit"""
|
|
|
|
name = "network"
|
|
module_spec = modspec(
|
|
argument_spec=dict(
|
|
mac=Types.str(help="The MAC-Address of the device. An ! before the value matches anything but this value."),
|
|
device=Types.str(help="The name of the network device. An ! before the value matches anything but this value."),
|
|
virtualization=Types.str(help="The virtualization type. An ! before the value matches anything but this value."),
|
|
name=Types.str(required=True, help="name of the unit"),
|
|
dot=Types.bool(help="if DNS-over-TLS should be required or disabled. If it is unset, it will used if the server supports it"),
|
|
dnssec=Types.bool(
|
|
help="if the Domainqueries should require DNSSEC or not.\nIf its missing, domains that have DNSSEC enabled will be validated, all others it will be assumed to be okay."
|
|
),
|
|
dns=Types.list(elements=str, help="List of DNS-Servers"),
|
|
domain=Types.list(elements=str, help="List of domains that are on this device"),
|
|
defaultdns=Types.bool(
|
|
help="If the DNS-Server(s) on this device should be used for all domains that are not set on other devices"
|
|
),
|
|
address=Types.list(elements=str, required=True, help="IP-Addresses of this networkdevice"),
|
|
route=Types.list(
|
|
elements=str,
|
|
help="Routes of networks that can be reached with this device",
|
|
),
|
|
masquerade=Types.str(
|
|
help="how the packets are modified to look like the come from the computer itself.",
|
|
choices=("true", "false", "both", "ipv4", "ipv6", "no"),
|
|
),
|
|
),
|
|
required_if=(("defaultdns", True, ("dns",), False),),
|
|
required_one_of=(("mac", "device", "virtualization"),),
|
|
)
|
|
|
|
def prepare(self):
|
|
self.unitfile = SYSTEMD_NETWORK_CONFIG.joinpath(self.get("name")).with_suffix(".network")
|
|
self.__unit = None
|
|
|
|
def unit(self) -> str:
|
|
if self.__unit is None:
|
|
self.__unit = self._unit(
|
|
self.match(),
|
|
self.network(),
|
|
self.addresses(),
|
|
self.routes(),
|
|
)
|
|
return self.__unit
|
|
|
|
def match(self) -> Optional[str]:
|
|
matches = self.map_param(
|
|
mac="MACAddress",
|
|
device="Name",
|
|
virtualization="Virtualization",
|
|
)
|
|
if len(matches) == 0:
|
|
return None
|
|
return "[Match]\n" + "".join(matches)
|
|
|
|
def network(self) -> Optional[str]:
|
|
options = []
|
|
if self.get("description", None) is None:
|
|
options.append("Description={}".format(self.get("description")))
|
|
server: str
|
|
for server in self.get("dns", []):
|
|
options.append(f"DNS={server}")
|
|
options.append("DNSDefaultRoute={}".format(self.get("defaultdns", False)))
|
|
if self.get("domain", False):
|
|
options.append("Domains={}".format(" ".join(self.get("domain"))))
|
|
options.append("DNSOverTLS={}".format(systemdbool(self.get("dot", "opportunistic"))))
|
|
options.append("DNSSEC={}".format(systemdbool(self.get("dnssec", "allow-downgrade"))))
|
|
if self.get("masquerade", None) is not None:
|
|
masquerade: str = self.get("masquerade")
|
|
if masquerade == "true":
|
|
masquerade = "both"
|
|
elif masquerade == "false":
|
|
masquerade = "no"
|
|
options.append(f"IPMasquerade={masquerade}")
|
|
if len(options) == 0:
|
|
return None
|
|
return "[Network]\n" + "".join(options)
|
|
|
|
def addresses(self) -> str:
|
|
output = []
|
|
for address in self.get("address"):
|
|
output.append(f"[Address]\nAddress={address}\n")
|
|
return "\n".join(output)
|
|
|
|
def routes(self) -> Optional[str]:
|
|
output = []
|
|
routes: list[str] = self.get("route", [])
|
|
for gw in routes:
|
|
output.append(f"[Route]\nGateway={gw}\nGatewayOnLink=yes\nQuickAck=yes\n")
|
|
if len(output) == 0:
|
|
return None
|
|
return "\n".join(output)
|
|
|
|
|
|
DOCUMENTATION = """---
|
|
description:
|
|
- Sets up the systemd network unit
|
|
module: network
|
|
options:
|
|
address:
|
|
description:
|
|
- IP-Addresses of this networkdevice
|
|
elements: str
|
|
required: true
|
|
type: list
|
|
after:
|
|
default: []
|
|
description:
|
|
- list of units that this unit wants to be started after this unit
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
before:
|
|
default: []
|
|
description:
|
|
- list of units that this unit needs to be started before this unit.
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
defaultdns:
|
|
description:
|
|
- If the DNS-Server(s) on this device should be used for all domains that are
|
|
not set on other devices
|
|
required: false
|
|
type: bool
|
|
description:
|
|
description:
|
|
- An description for programs that access systemd
|
|
required: false
|
|
type: str
|
|
device:
|
|
description:
|
|
- The name of the network device. An ! before the value matches anything but this
|
|
value.
|
|
required: false
|
|
type: str
|
|
dns:
|
|
default: []
|
|
description:
|
|
- List of DNS-Servers
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
dnssec:
|
|
description:
|
|
- if the Domainqueries should require DNSSEC or not.
|
|
- If its missing, domains that have DNSSEC enabled will be validated, all others
|
|
it will be assumed to be okay.
|
|
required: false
|
|
type: bool
|
|
documentation:
|
|
default: []
|
|
description:
|
|
- Paths where documentation can be found
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
domain:
|
|
default: []
|
|
description:
|
|
- List of domains that are on this device
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
dot:
|
|
description:
|
|
- if DNS-over-TLS should be required or disabled. If it is unset, it will used
|
|
if the server supports it
|
|
required: false
|
|
type: bool
|
|
mac:
|
|
description:
|
|
- The MAC-Address of the device. An ! before the value matches anything but this
|
|
value.
|
|
required: false
|
|
type: str
|
|
masquerade:
|
|
choices:
|
|
- 'true'
|
|
- 'false'
|
|
- both
|
|
- ipv4
|
|
- ipv6
|
|
- 'no'
|
|
description:
|
|
- how the packets are modified to look like the come from the computer itself.
|
|
required: false
|
|
type: str
|
|
name:
|
|
description:
|
|
- name of the unit
|
|
required: true
|
|
type: str
|
|
partof:
|
|
default: []
|
|
description:
|
|
- list of units that this unit is part of.
|
|
- If the restart this unit does it too, but if this restarts it does not affect
|
|
the other units.
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
requires:
|
|
default: []
|
|
description:
|
|
- list of units that this unit requires. If it fails or can't be started this
|
|
unit fails. without before/after this is started at the same time
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
route:
|
|
default: []
|
|
description:
|
|
- Routes of networks that can be reached with this device
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
virtualization:
|
|
description:
|
|
- The virtualization type. An ! before the value matches anything but this value.
|
|
required: false
|
|
type: str
|
|
wants:
|
|
default: []
|
|
description:
|
|
- list of units that this unit wants. If it fails or can't be started it does
|
|
not affect this unit
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
short_description: Sets up the systemd network unit
|
|
"""
|
|
|
|
|
|
if __name__ == "__main__":
|
|
Module()()
|