#!/usr/bin/python # -*- coding: utf-8 -*- # (c) 2016, Andrew Gaffney # # This file is part of Ansible # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ansible is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . ANSIBLE_METADATA = {'status': ['preview'], 'supported_by': 'committer', 'version': '1.0'} DOCUMENTATION = ''' module: openwrt_init author: - "Andrew Gaffney (@agaffney)" version_added: "2.3" short_description: Manage services on OpenWrt. description: - Controls OpenWrt services on remote hosts. options: name: required: true description: - Name of the service. aliases: ['service'] state: required: false default: null choices: [ 'started', 'stopped', 'restarted', 'reloaded' ] description: - C(started)/C(stopped) are idempotent actions that will not run commands unless necessary. C(restarted) will always bounce the service. C(reloaded) will always reload. enabled: required: false choices: [ "yes", "no" ] default: null description: - Whether the service should start on boot. B(At least one of state and enabled are required.) pattern: required: false description: - If the service does not respond to the 'running' command, name a substring to look for as would be found in the output of the I(ps) command as a stand-in for a 'running' result. If the string is found, the service will be assumed to be running. notes: - One option other than name is required. requirements: - An OpenWrt system ''' EXAMPLES = ''' # Example action to start service httpd, if not running - openwrt_init: state: started name: httpd # Example action to stop service cron, if running - openwrt_init: name: cron state: stopped # Example action to reload service httpd, in all cases - openwrt_init: name: httpd state: reloaded # Example action to enable service httpd - openwrt_init: name: httpd enabled: yes ''' RETURN = ''' ''' import os import glob from ansible.module_utils.basic import AnsibleModule from ansible.module_utils._text import to_bytes, to_native module = None init_script = None # =============================== # Check if service is enabled def is_enabled(): (rc, out, err) = module.run_command("%s enabled" % init_script) if rc == 0: return True return False # =========================================== # Main control flow def main(): global module, init_script # init module = AnsibleModule( argument_spec = dict( name = dict(required=True, type='str', aliases=['service']), state = dict(choices=['started', 'stopped', 'restarted', 'reloaded'], type='str'), enabled = dict(type='bool'), pattern = dict(required=False, default=None), ), supports_check_mode=True, required_one_of=[['state', 'enabled']], ) # initialize service = module.params['name'] init_script = '/etc/init.d/' + service rc = 0 out = err = '' result = { 'name': service, 'changed': False, } # check if service exists if not os.path.exists(init_script): module.fail_json(msg='service %s does not exist' % service) # Enable/disable service startup at boot if requested if module.params['enabled'] is not None: # do we need to enable the service? enabled = is_enabled() # default to current state result['enabled'] = enabled # Change enable/disable if needed if enabled != module.params['enabled']: result['changed'] = True if module.params['enabled']: action = 'enable' else: action = 'disable' if not module.check_mode: (rc, out, err) = module.run_command("%s %s" % (init_script, action)) # openwrt init scripts can return a non-zero exit code on a successful 'enable' # command if the init script doesn't contain a STOP value, so we ignore the exit # code and explicitly check if the service is now in the desired state if is_enabled() != module.params['enabled']: module.fail_json(msg="Unable to %s service %s: %s" % (action, service, err)) result['enabled'] = not enabled if module.params['state'] is not None: running = False # check if service is currently running if module.params['pattern']: # Find ps binary psbin = module.get_bin_path('ps', True) # this should be busybox ps, so we only want/need to the 'w' option (rc, psout, pserr) = module.run_command('%s w' % psbin) # If rc is 0, set running as appropriate if rc == 0: lines = psout.split("\n") for line in lines: if module.params['pattern'] in line and not "pattern=" in line: # so as to not confuse ./hacking/test-module running = True break else: (rc, out, err) = module.run_command("%s running" % init_script) if rc == 0: running = True # default to desired state result['state'] = module.params['state'] # determine action, if any action = None if module.params['state'] == 'started': if not running: action = 'start' result['changed'] = True elif module.params['state'] == 'stopped': if running: action = 'stop' result['changed'] = True else: action = module.params['state'][:-2] # remove 'ed' from restarted/reloaded result['state'] = 'started' result['changed'] = True if action: if not module.check_mode: (rc, out, err) = module.run_command("%s %s" % (init_script, action)) if rc != 0: module.fail_json(msg="Unable to %s service %s: %s" % (action, service, err)) module.exit_json(**result) if __name__ == '__main__': main()