#!/usr/bin/python # -*- coding: utf-8 -*- # Copyright (c) 2021, Alexei Znamensky (@russoz) <russoz@gmail.com> # Copyright (c) 2013, Matthias Vogelgesang <matthias.vogelgesang@gmail.com> # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later from __future__ import absolute_import, division, print_function __metaclass__ = type DOCUMENTATION = ''' --- module: kernel_blacklist author: - Matthias Vogelgesang (@matze) short_description: Blacklist kernel modules description: - Add or remove kernel modules from blacklist. options: name: type: str description: - Name of kernel module to black- or whitelist. required: true state: type: str description: - Whether the module should be present in the blacklist or absent. choices: [ absent, present ] default: present blacklist_file: type: str description: - If specified, use this blacklist file instead of C(/etc/modprobe.d/blacklist-ansible.conf). default: /etc/modprobe.d/blacklist-ansible.conf ''' EXAMPLES = ''' - name: Blacklist the nouveau driver module community.general.kernel_blacklist: name: nouveau state: present ''' import os import re import tempfile from ansible_collections.community.general.plugins.module_utils.module_helper import StateModuleHelper class Blacklist(StateModuleHelper): output_params = ('name', 'state') module = dict( argument_spec=dict( name=dict(type='str', required=True), state=dict(type='str', default='present', choices=['absent', 'present']), blacklist_file=dict(type='str', default='/etc/modprobe.d/blacklist-ansible.conf'), ), supports_check_mode=True, ) def __init_module__(self): self.pattern = re.compile(r'^blacklist\s+{0}$'.format(re.escape(self.vars.name))) self.vars.filename = self.vars.blacklist_file self.vars.set('file_exists', os.path.exists(self.vars.filename), output=False, change=True) if not self.vars.file_exists: with open(self.vars.filename, 'a'): pass self.vars.file_exists = True self.vars.set('lines', [], change=True, diff=True) else: with open(self.vars.filename) as fd: self.vars.set('lines', [x.rstrip() for x in fd.readlines()], change=True, diff=True) self.vars.set('is_blacklisted', self._is_module_blocked(), change=True) def _is_module_blocked(self): for line in self.vars.lines: stripped = line.strip() if stripped.startswith('#'): continue if self.pattern.match(stripped): return True return False def state_absent(self): if not self.vars.is_blacklisted: return self.vars.is_blacklisted = False self.vars.lines = [line for line in self.vars.lines if not self.pattern.match(line.strip())] def state_present(self): if self.vars.is_blacklisted: return self.vars.is_blacklisted = True self.vars.lines = self.vars.lines + ['blacklist %s' % self.vars.name] def __quit_module__(self): if self.has_changed() and not self.module.check_mode: dummy, tmpfile = tempfile.mkstemp() try: os.remove(tmpfile) self.module.preserved_copy(self.vars.filename, tmpfile) # ensure right perms/ownership with open(tmpfile, 'w') as fd: fd.writelines(["{0}\n".format(x) for x in self.vars.lines]) self.module.atomic_move(tmpfile, self.vars.filename) finally: if os.path.exists(tmpfile): os.remove(tmpfile) def main(): Blacklist.execute() if __name__ == '__main__': main()