#!/usr/bin/python # -*- coding: utf-8 -*- # (c) 2016, Andrew Gaffney # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} 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: description: - Name of the service. required: true aliases: ['service'] state: 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. choices: [ 'started', 'stopped', 'restarted', 'reloaded' ] enabled: description: - Whether the service should start on boot. B(At least one of state and enabled are required.) type: bool pattern: 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 (with python) ''' 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 "pattern=" not 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()