1#!/usr/local/bin/python3.8 2# -*- coding: utf-8 -*- 3 4# Copyright: (c) 2017, Joris Weijters <joris.weijters@gmail.com> 5# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 7from __future__ import absolute_import, division, print_function 8__metaclass__ = type 9 10DOCUMENTATION = r''' 11--- 12author: 13- Joris Weijters (@molekuul) 14module: aix_inittab 15short_description: Manages the inittab on AIX 16description: 17 - Manages the inittab on AIX. 18options: 19 name: 20 description: 21 - Name of the inittab entry. 22 type: str 23 required: yes 24 aliases: [ service ] 25 runlevel: 26 description: 27 - Runlevel of the entry. 28 type: str 29 required: yes 30 action: 31 description: 32 - Action what the init has to do with this entry. 33 type: str 34 choices: 35 - boot 36 - bootwait 37 - hold 38 - initdefault 39 - 'off' 40 - once 41 - ondemand 42 - powerfail 43 - powerwait 44 - respawn 45 - sysinit 46 - wait 47 command: 48 description: 49 - What command has to run. 50 type: str 51 required: yes 52 insertafter: 53 description: 54 - After which inittabline should the new entry inserted. 55 type: str 56 state: 57 description: 58 - Whether the entry should be present or absent in the inittab file. 59 type: str 60 choices: [ absent, present ] 61 default: present 62notes: 63 - The changes are persistent across reboots. 64 - You need root rights to read or adjust the inittab with the C(lsitab), C(chitab), C(mkitab) or C(rmitab) commands. 65 - Tested on AIX 7.1. 66requirements: 67- itertools 68''' 69 70EXAMPLES = ''' 71# Add service startmyservice to the inittab, directly after service existingservice. 72- name: Add startmyservice to inittab 73 community.general.aix_inittab: 74 name: startmyservice 75 runlevel: 4 76 action: once 77 command: echo hello 78 insertafter: existingservice 79 state: present 80 become: yes 81 82# Change inittab entry startmyservice to runlevel "2" and processaction "wait". 83- name: Change startmyservice to inittab 84 community.general.aix_inittab: 85 name: startmyservice 86 runlevel: 2 87 action: wait 88 command: echo hello 89 state: present 90 become: yes 91 92- name: Remove startmyservice from inittab 93 community.general.aix_inittab: 94 name: startmyservice 95 runlevel: 2 96 action: wait 97 command: echo hello 98 state: absent 99 become: yes 100''' 101 102RETURN = ''' 103name: 104 description: Name of the adjusted inittab entry 105 returned: always 106 type: str 107 sample: startmyservice 108msg: 109 description: Action done with the inittab entry 110 returned: changed 111 type: str 112 sample: changed inittab entry startmyservice 113changed: 114 description: Whether the inittab changed or not 115 returned: always 116 type: bool 117 sample: true 118''' 119 120# Import necessary libraries 121try: 122 # python 2 123 from itertools import izip 124except ImportError: 125 izip = zip 126 127from ansible.module_utils.basic import AnsibleModule 128 129# end import modules 130# start defining the functions 131 132 133def check_current_entry(module): 134 # Check if entry exists, if not return False in exists in return dict, 135 # if true return True and the entry in return dict 136 existsdict = {'exist': False} 137 lsitab = module.get_bin_path('lsitab') 138 (rc, out, err) = module.run_command([lsitab, module.params['name']]) 139 if rc == 0: 140 keys = ('name', 'runlevel', 'action', 'command') 141 values = out.split(":") 142 # strip non readable characters as \n 143 values = map(lambda s: s.strip(), values) 144 existsdict = dict(izip(keys, values)) 145 existsdict.update({'exist': True}) 146 return existsdict 147 148 149def main(): 150 # initialize 151 module = AnsibleModule( 152 argument_spec=dict( 153 name=dict(type='str', required=True, aliases=['service']), 154 runlevel=dict(type='str', required=True), 155 action=dict(type='str', choices=[ 156 'boot', 157 'bootwait', 158 'hold', 159 'initdefault', 160 'off', 161 'once', 162 'ondemand', 163 'powerfail', 164 'powerwait', 165 'respawn', 166 'sysinit', 167 'wait', 168 ]), 169 command=dict(type='str', required=True), 170 insertafter=dict(type='str'), 171 state=dict(type='str', default='present', choices=['absent', 'present']), 172 ), 173 supports_check_mode=True, 174 ) 175 176 result = { 177 'name': module.params['name'], 178 'changed': False, 179 'msg': "" 180 } 181 182 # Find commandline strings 183 mkitab = module.get_bin_path('mkitab') 184 rmitab = module.get_bin_path('rmitab') 185 chitab = module.get_bin_path('chitab') 186 rc = 0 187 188 # check if the new entry exists 189 current_entry = check_current_entry(module) 190 191 # if action is install or change, 192 if module.params['state'] == 'present': 193 194 # create new entry string 195 new_entry = module.params['name'] + ":" + module.params['runlevel'] + \ 196 ":" + module.params['action'] + ":" + module.params['command'] 197 198 # If current entry exists or fields are different(if the entry does not 199 # exists, then the entry wil be created 200 if (not current_entry['exist']) or ( 201 module.params['runlevel'] != current_entry['runlevel'] or 202 module.params['action'] != current_entry['action'] or 203 module.params['command'] != current_entry['command']): 204 205 # If the entry does exist then change the entry 206 if current_entry['exist']: 207 if not module.check_mode: 208 (rc, out, err) = module.run_command([chitab, new_entry]) 209 if rc != 0: 210 module.fail_json( 211 msg="could not change inittab", rc=rc, err=err) 212 result['msg'] = "changed inittab entry" + " " + current_entry['name'] 213 result['changed'] = True 214 215 # If the entry does not exist create the entry 216 elif not current_entry['exist']: 217 if module.params['insertafter']: 218 if not module.check_mode: 219 (rc, out, err) = module.run_command( 220 [mkitab, '-i', module.params['insertafter'], new_entry]) 221 else: 222 if not module.check_mode: 223 (rc, out, err) = module.run_command( 224 [mkitab, new_entry]) 225 226 if rc != 0: 227 module.fail_json(msg="could not adjust inittab", rc=rc, err=err) 228 result['msg'] = "add inittab entry" + " " + module.params['name'] 229 result['changed'] = True 230 231 elif module.params['state'] == 'absent': 232 # If the action is remove and the entry exists then remove the entry 233 if current_entry['exist']: 234 if not module.check_mode: 235 (rc, out, err) = module.run_command( 236 [rmitab, module.params['name']]) 237 if rc != 0: 238 module.fail_json( 239 msg="could not remove entry from inittab)", rc=rc, err=err) 240 result['msg'] = "removed inittab entry" + " " + current_entry['name'] 241 result['changed'] = True 242 243 module.exit_json(**result) 244 245 246if __name__ == '__main__': 247 main() 248