#!/usr/bin/python3 import pathlib from typing import List, Optional try: from ansible.module_utils.generic import SYSTEMD_SERVICE_CONFIG as SYSTEMD_PATH from ansible.module_utils.generic import Types from ansible.module_utils.module import SystemdUnitModule except ImportError: from generic import SYSTEMD_SERVICE_CONFIG as SYSTEMD_PATH from generic import Types from module import SystemdUnitModule SYSTEMD_PATH = pathlib.Path("/etc/systemd/system") OPTION_MAPPING = dict( required_by="RequiredBy", wanted_by="WantedBy", ) class Module(SystemdUnitModule): """Creates an systemd mount""" name = "systemd_mount" module_spec = dict( argument_spec=dict( fs=Types.str( required=True, help="The filesystem that is used for the mount" ), where=Types.path( required=True, help="The Path where the filesystem is mounted to" ), what=Types.str( required=True, help="The device or an string that will be mounted" ), state=Types.str( choices=("present", "absent"), default="present", help="the state the mount is", ), options=Types.list(elements=str, help="The options for the mount"), description=Types.str( help="An description for programs that access systemd" ), required_by=Types.list( elements=str, help="systemd units that require this mount" ), wanted_by=Types.list( elements=str, help="systemd units that want the mount, but not explicitly require it. Commonly used for target if not service explicitly require it.", ), ), ) def prepare(self): self.mountdir = pathlib.Path(self.params["where"]) self.unitfile = SYSTEMD_PATH.joinpath( self.mountdir.relative_to("/").as_posix().replace("/", "-") ).with_suffix(".mount") self.__unit = None def unit(self) -> str: if self.__unit is None: self.__unit = "\n".join( ( self.header(), self.mount(), self.install(), ) ) return self.__unit def header(self) -> str: return "[Unit]\nDescription={}\n".format( self.get("description", "Mount for {}".format(self.get("where"))) ) def mount(self) -> str: output = "[Mount]\n" output += "Where={}\n".format(self.get("where")) output += "What={}\n".format(self.get("what")) output += "Type={}\n".format(self.get("fs")) if self.get("options", False): output += "Options={}\n".format(",".join(self.get("options"))) return output def install(self) -> str: output = "[Install]\n" for argument, key in OPTION_MAPPING.items(): if self.get(argument, False): for unit in self.get(argument): output += "{}={}\n".format(key, unit) return output def post(self): if not self.changed: return systemctl = self.module.get_bin_path("systemctl", required=True) self.module.run_command([systemctl, "daemon-reload"], check_rc=True) (rc, _, _) = self.module.run_command( [systemctl, "is-enabled", self.unitfile.name], check_rc=False ) if rc == 0: self.module.run_command( [systemctl, "restart", self.unitfile.name], check_rc=True ) DOCUMENTATION = """--- description: - Creates an systemd mount module: systemd_mount options: description: description: - An description for programs that access systemd required: false type: str fs: description: - The filesystem that is used for the mount required: true type: str options: default: [] description: - The options for the mount elements: str required: false type: list required_by: default: [] description: - systemd units that require this mount elements: str required: false type: list state: choices: - present - absent default: present description: - the state the mount is required: false type: str wanted_by: default: [] description: - systemd units that want the mount, but not explicitly require it. Commonly used for target if not service explicitly require it. elements: str required: false type: list what: description: - The device or an string that will be mounted required: true type: str where: description: - The Path where the filesystem is mounted to required: true type: path short_description: Creates an systemd mount """ if __name__ == "__main__": Module()()