Ejemplo n.º 1
0
def get_unit_properties(unit, systemctl, module):
    is_initd = sysv_exists(unit)
    is_systemd = False
    properties = None

    # check service data, cannot error out on rc as it changes across versions, assume not found
    (rc, out, err) = module.run_command("%s show '%s'" % (systemctl, unit))

    if request_was_ignored(out) or request_was_ignored(err):
        # fallback list-unit-files as show does not work on some systems (chroot)
        # not used as primary as it skips some services (like those using init.d) and requires .service/etc notation
        (rc, out, err) = module.run_command("%s list-unit-files '%s'" % (systemctl, unit))
        if rc == 0:
            is_systemd = True

    elif rc == 0:
        # load return of systemctl show into dictionary for easy access and return
        if out:
            properties = parse_systemctl_show(to_native(out).split('\n'))

            is_systemd = 'LoadState' in properties and properties['LoadState'] != 'not-found'

            # Check for loading error
            if is_systemd and 'LoadError' in properties:
                module.fail_json(msg="Error loading unit file '%s': %s" % (unit, properties['LoadError']))
    else:
        # Check for systemctl command
        module.run_command(systemctl, check_rc=True)

    return is_systemd, is_initd, properties
Ejemplo n.º 2
0
def call_systemd(module, unit):
    # Vars
    rc=0
    found=False
    result = dict(
        name=unit,
        changed=False,
        status=dict()
    )
    is_initd = sysv_exists(unit)
    is_systemd = False
    # Launch systemctl command
    systemctl = module.get_bin_path('systemctl', True)
    (rc, out, err) = module.run_command("%s show '%s'" % (systemctl, unit))
    if request_was_ignored(out) or request_was_ignored(err):
        # fallback list-unit-files as show does not work on some systems (chroot)
        # not used as primary as it skips some services (like those using init.d) and requires .service/etc notation
        (rc, out, err) = module.run_command("%s list-unit-files '%s'" % (systemctl, unit))
        if rc == 0:
            is_systemd = True
    elif rc == 0:
        # load return of systemctl show into dictionary for easy access and return
        if out:
            result['status'] = parse_systemctl_show(to_native(out).split('\n'))
            is_systemd = 'LoadState' in result['status'] and result['status']['LoadState'] != 'not-found'
            # Check for loading error
            if is_systemd and 'LoadError' in result['status']:
                module.fail_json(msg="Error loading unit file '%s': %s" % (unit, result['status']['LoadError']))
    else:
        # Check for systemctl command
        module.run_command(systemctl, check_rc=True)
    # Does service exist?
    found = is_systemd or is_initd
    if is_initd and not is_systemd:
        module.warn('The service (%s) is actually an init script but the system is managed by systemd' % unit)
    return found, result
Ejemplo n.º 3
0
def main():
    # initialize
    module = AnsibleModule(
        argument_spec=dict(
            name=dict(type='str', aliases=['service', 'unit']),
            state=dict(type='str',
                       choices=['reloaded', 'restarted', 'started',
                                'stopped']),
            enabled=dict(type='bool'),
            force=dict(type='bool'),
            masked=dict(type='bool'),
            daemon_reload=dict(type='bool',
                               default=False,
                               aliases=['daemon-reload']),
            daemon_reexec=dict(type='bool',
                               default=False,
                               aliases=['daemon-reexec']),
            user=dict(type='bool'),
            scope=dict(type='str', choices=['system', 'user', 'global']),
            no_block=dict(type='bool', default=False),
        ),
        supports_check_mode=True,
        required_one_of=[[
            'state', 'enabled', 'masked', 'daemon_reload', 'daemon_reexec'
        ]],
        required_by=dict(
            state=('name', ),
            enabled=('name', ),
            masked=('name', ),
        ),
        mutually_exclusive=[['scope', 'user']],
    )

    unit = module.params['name']
    if unit is not None:
        for globpattern in (r"*", r"?", r"["):
            if globpattern in unit:
                module.fail_json(
                    msg=
                    "This module does not currently support using glob patterns, found '%s' in service name: %s"
                    % (globpattern, unit))

    systemctl = module.get_bin_path('systemctl', True)

    if os.getenv('XDG_RUNTIME_DIR') is None:
        os.environ['XDG_RUNTIME_DIR'] = '/run/user/%s' % os.geteuid()
    ''' Set CLI options depending on params '''
    if module.params['user'] is not None:
        # handle user deprecation, mutually exclusive with scope
        module.deprecate("The 'user' option is being replaced by 'scope'",
                         version='2.11')
        if module.params['user']:
            module.params['scope'] = 'user'
        else:
            module.params['scope'] = 'system'

    # if scope is 'system' or None, we can ignore as there is no extra switch.
    # The other choices match the corresponding switch
    if module.params['scope'] not in (None, 'system'):
        systemctl += " --%s" % module.params['scope']

    if module.params['no_block']:
        systemctl += " --no-block"

    if module.params['force']:
        systemctl += " --force"

    rc = 0
    out = err = ''
    result = dict(
        name=unit,
        changed=False,
        status=dict(),
    )

    # Run daemon-reload first, if requested
    if module.params['daemon_reload'] and not module.check_mode:
        (rc, out, err) = module.run_command("%s daemon-reload" % (systemctl))
        if rc != 0:
            module.fail_json(msg='failure %d during daemon-reload: %s' %
                             (rc, err))

    # Run daemon-reexec
    if module.params['daemon_reexec'] and not module.check_mode:
        (rc, out, err) = module.run_command("%s daemon-reexec" % (systemctl))
        if rc != 0:
            module.fail_json(msg='failure %d during daemon-reexec: %s' %
                             (rc, err))

    if unit:
        found = False
        is_initd = sysv_exists(unit)
        is_systemd = False

        # check service data, cannot error out on rc as it changes across versions, assume not found
        (rc, out, err) = module.run_command("%s show '%s'" % (systemctl, unit))

        if request_was_ignored(out) or request_was_ignored(err):
            # fallback list-unit-files as show does not work on some systems (chroot)
            # not used as primary as it skips some services (like those using init.d) and requires .service/etc notation
            (rc, out, err) = module.run_command("%s list-unit-files '%s'" %
                                                (systemctl, unit))
            if rc == 0:
                is_systemd = True

        elif rc == 0:
            # load return of systemctl show into dictionary for easy access and return
            if out:
                result['status'] = parse_systemctl_show(
                    to_native(out).split('\n'))

                is_systemd = 'LoadState' in result[
                    'status'] and result['status']['LoadState'] != 'not-found'

                is_masked = 'LoadState' in result['status'] and result[
                    'status']['LoadState'] == 'masked'

                # Check for loading error
                if is_systemd and not is_masked and 'LoadError' in result[
                        'status']:
                    module.fail_json(msg="Error loading unit file '%s': %s" %
                                     (unit, result['status']['LoadError']))
        else:
            # Check for systemctl command
            module.run_command(systemctl, check_rc=True)

        # Does service exist?
        found = is_systemd or is_initd
        if is_initd and not is_systemd:
            module.warn(
                'The service (%s) is actually an init script but the system is managed by systemd'
                % unit)

        # mask/unmask the service, if requested, can operate on services before they are installed
        if module.params['masked'] is not None:
            # state is not masked unless systemd affirms otherwise
            masked = ('LoadState' in result['status']
                      and result['status']['LoadState'] == 'masked')

            if masked != module.params['masked']:
                result['changed'] = True
                if module.params['masked']:
                    action = 'mask'
                else:
                    action = 'unmask'

                if not module.check_mode:
                    (rc, out, err) = module.run_command(
                        "%s %s '%s'" % (systemctl, action, unit))
                    if rc != 0:
                        # some versions of system CAN mask/unmask non existing services, we only fail on missing if they don't
                        fail_if_missing(module, found, unit, msg='host')

        # Enable/disable service startup at boot if requested
        if module.params['enabled'] is not None:

            if module.params['enabled']:
                action = 'enable'
            else:
                action = 'disable'

            fail_if_missing(module, found, unit, msg='host')

            # do we need to enable the service?
            enabled = False
            (rc, out, err) = module.run_command("%s is-enabled '%s'" %
                                                (systemctl, unit))

            # check systemctl result or if it is a init script
            if rc == 0:
                enabled = True
            elif rc == 1:
                # if not a user or global user service and both init script and unit file exist stdout should have enabled/disabled, otherwise use rc entries
                if module.params['scope'] in (None, 'system') and \
                        not module.params['user'] and \
                        is_initd and \
                        not out.strip().endswith('disabled') and \
                        sysv_is_enabled(unit):
                    enabled = True

            # default to current state
            result['enabled'] = enabled

            # Change enable/disable if needed
            if enabled != module.params['enabled']:
                result['changed'] = True
                if not module.check_mode:
                    (rc, out, err) = module.run_command(
                        "%s %s '%s'" % (systemctl, action, unit))
                    if rc != 0:
                        module.fail_json(msg="Unable to %s service %s: %s" %
                                         (action, unit, out + err))

                result['enabled'] = not enabled

        # set service state if requested
        if module.params['state'] is not None:
            fail_if_missing(module, found, unit, msg="host")

            # default to desired state
            result['state'] = module.params['state']

            # What is current service state?
            if 'ActiveState' in result['status']:
                action = None
                if module.params['state'] == 'started':
                    if not is_running_service(result['status']):
                        action = 'start'
                elif module.params['state'] == 'stopped':
                    if is_running_service(
                            result['status']) or is_deactivating_service(
                                result['status']):
                        action = 'stop'
                else:
                    if not is_running_service(result['status']):
                        action = 'start'
                    else:
                        action = module.params[
                            'state'][:
                                     -2]  # remove 'ed' from restarted/reloaded
                    result['state'] = 'started'

                if action:
                    result['changed'] = True
                    if not module.check_mode:
                        (rc, out, err) = module.run_command(
                            "%s %s '%s'" % (systemctl, action, unit))
                        if rc != 0:
                            module.fail_json(
                                msg="Unable to %s service %s: %s" %
                                (action, unit, err))
            # check for chroot
            elif is_chroot(module):
                module.warn(
                    "Target is a chroot. This can lead to false positives or prevent the init system tools from working."
                )
            else:
                # this should not happen?
                module.fail_json(msg="Service is in unknown state",
                                 status=result['status'])

    module.exit_json(**result)
Ejemplo n.º 4
0
def main():
    # initialize
    module = AnsibleModule(
        argument_spec = dict(
            name = dict(required=True, type='str', aliases=['unit', 'service']),
            state = dict(choices=[ 'started', 'stopped', 'restarted', 'reloaded'], type='str'),
            enabled = dict(type='bool'),
            masked = dict(type='bool'),
            daemon_reload = dict(type='bool', default=False, aliases=['daemon-reload']),
            user = dict(type='bool', default=False),
            no_block = dict(type='bool', default=False),
        ),
        supports_check_mode=True,
        required_one_of=[['state', 'enabled', 'masked', 'daemon_reload']],
        )

    systemctl = module.get_bin_path('systemctl', True)
    if module.params['user']:
        systemctl = systemctl + " --user"
    if module.params['no_block']:
        systemctl = systemctl + " --no-block"
    unit = module.params['name']
    rc = 0
    out = err = ''
    result = {
        'name':  unit,
        'changed': False,
        'status': {},
    }

    # Run daemon-reload first, if requested
    if module.params['daemon_reload']:
        (rc, out, err) = module.run_command("%s daemon-reload" % (systemctl))
        if rc != 0:
            module.fail_json(msg='failure %d during daemon-reload: %s' % (rc, err))

    found = False
    is_initd = sysv_exists(unit)
    is_systemd = False

    # check service data, cannot error out on rc as it changes across versions, assume not found
    (rc, out, err) = module.run_command("%s show '%s'" % (systemctl, unit))

    if out.find('ignoring request') != -1:
        # fallback list-unit-files as show does not work on some systems (chroot)
        # not used as primary as it skips some services (like those using init.d) and requires .service/etc notation
        (rc, out, err) = module.run_command("%s list-unit-files '%s'" % (systemctl, unit))
        if rc == 0:
            is_systemd = True

    elif rc == 0:
        # load return of systemctl show into dictionary for easy access and return
        multival = []
        if out:
            k = None
            for line in to_native(out).split('\n'): # systemd can have multiline values delimited with {}
                if line.strip():
                    if k is None:
                        if '=' in line:
                            k,v = line.split('=', 1)
                            if v.lstrip().startswith('{'):
                                if not v.rstrip().endswith('}'):
                                    multival.append(line)
                                    continue
                            result['status'][k] = v.strip()
                            k = None
                    else:
                        if line.rstrip().endswith('}'):
                            result['status'][k] = '\n'.join(multival).strip()
                            multival = []
                            k = None
                        else:
                            multival.append(line)

            is_systemd = 'LoadState' in result['status'] and result['status']['LoadState'] != 'not-found'

            # Check for loading error
            if is_systemd and 'LoadError' in result['status']:
                module.fail_json(msg="Error loading unit file '%s': %s" % (unit, result['status']['LoadError']))

    # Does service exist?
    found = is_systemd or is_initd
    if is_initd and not is_systemd:
        module.warn('The service (%s) is actually an init script but the system is managed by systemd' % unit)

    # mask/unmask the service, if requested, can operate on services before they are installed
    if module.params['masked'] is not None:
        # state is not masked unless systemd affirms otherwise
        masked = ('LoadState' in result['status'] and result['status']['LoadState'] == 'masked')

        if masked != module.params['masked']:
            result['changed'] = True
            if module.params['masked']:
                action = 'mask'
            else:
                action = 'unmask'

            if not module.check_mode:
                (rc, out, err) = module.run_command("%s %s '%s'" % (systemctl, action, unit))
                if rc != 0:
                    # some versions of system CAN mask/unmask non existing services, we only fail on missing if they don't
                    fail_if_missing(module, found, unit, msg='host')


    # Enable/disable service startup at boot if requested
    if module.params['enabled'] is not None:

        if module.params['enabled']:
            action = 'enable'
        else:
            action = 'disable'

        fail_if_missing(module, found, unit, msg='host')

        # do we need to enable the service?
        enabled = False
        (rc, out, err) = module.run_command("%s is-enabled '%s'" % (systemctl, unit))

        # check systemctl result or if it is a init script
        if rc == 0:
            enabled = True
        elif rc == 1:
            # if not a user service and both init script and unit file exist stdout should have enabled/disabled, otherwise use rc entries
            if not module.params['user'] and \
               is_initd and \
               (not out.strip().endswith('disabled') or sysv_is_enabled(unit)):

                enabled = True

        # default to current state
        result['enabled'] = enabled

        # Change enable/disable if needed
        if enabled != module.params['enabled']:
            result['changed'] = True
            if not module.check_mode:
                (rc, out, err) = module.run_command("%s %s '%s'" % (systemctl, action, unit))
                if rc != 0:
                    module.fail_json(msg="Unable to %s service %s: %s" % (action, unit, out + err))

            result['enabled'] = not enabled

    # set service state if requested
    if module.params['state'] is not None:
        fail_if_missing(module, found, unit, msg="host")

        # default to desired state
        result['state'] = module.params['state']

        # What is current service state?
        if 'ActiveState' in result['status']:
            action = None
            if module.params['state'] == 'started':
                if not is_running_service(result['status']):
                    action = 'start'
            elif module.params['state'] == 'stopped':
                if is_running_service(result['status']):
                    action = 'stop'
            else:
                if not is_running_service(result['status']):
                    action = 'start'
                else:
                    action = module.params['state'][:-2] # remove 'ed' from restarted/reloaded
                result['state'] = 'started'

            if action:
                result['changed'] = True
                if not module.check_mode:
                    (rc, out, err) = module.run_command("%s %s '%s'" % (systemctl, action, unit))
                    if rc != 0:
                        module.fail_json(msg="Unable to %s service %s: %s" % (action, unit, err))
        else:
            # this should not happen?
            module.fail_json(msg="Service is in unknown state", status=result['status'])


    module.exit_json(**result)
Ejemplo n.º 5
0
def main():
    # initialize
    module = AnsibleModule(
        argument_spec=dict(
            name=dict(type='str', aliases=['service', 'unit']),
            properties=dict(type='dict'),
        ),
        supports_check_mode=True,
        required_one_of=[['properties']],
    )

    systemctl = module.get_bin_path('systemctl', True)

    unit = module.params['name']
    rc = 0
    out = err = ''
    result = dict(
        name=unit,
        changed=False,
        status=dict(),
    )

    for requires in ('properties'):
        if module.params[requires] is not None and unit is None:
            module.fail_json(msg="name is also required when specifying %s" % requires)

    if unit:
        found = False
        is_initd = sysv_exists(unit)
        is_systemd = False

        # check service data, cannot error out on rc as it changes across versions, assume not found
        (rc, out, err) = module.run_command("%s show '%s'" % (systemctl, unit))

        if request_was_ignored(out) or request_was_ignored(err):
            # fallback list-unit-files as show does not work on some systems (chroot)
            # not used as primary as it skips some services (like those using init.d) and requires .service/etc notation
            (rc, out, err) = module.run_command("%s list-unit-files '%s'" % (systemctl, unit))
            if rc == 0:
                is_systemd = True

        elif rc == 0:
            # load return of systemctl show into dictionary for easy access and return
            if out:
                result['status'] = parse_systemctl_show(to_native(out).split('\n'))

                is_systemd = 'LoadState' in result['status'] and result['status']['LoadState'] != 'not-found'

                is_masked = 'LoadState' in result['status'] and result['status']['LoadState'] == 'masked'

                # Check for loading error
                if is_systemd and not is_masked and 'LoadError' in result['status']:
                    module.fail_json(msg="Error loading unit file '%s': %s" % (unit, result['status']['LoadError']))
        else:
            # Check for systemctl command
            module.run_command(systemctl, check_rc=True)

        # Does service exist?
        found = is_systemd or is_initd
        if is_initd and not is_systemd:
            module.warn('The service (%s) is actually an init script but the system is managed by systemd' % unit)

        # set service properties if requested and this is not an initd service.  Should be done before starting the service.
        if module.params['properties'] is not None and not is_initd:
            fail_if_missing(module, found, unit, msg="host")

            # loop through all of the properties we want to set
            prop_list = module.params['properties']
            prop_action = ""
            for prop in prop_list.keys():
                # convert the output to a str as that is what result['status'][prop] will be when we compare later
                prop_val = str(convert_property_suffix(prop_list[prop]))

                # the property name must already be in the output from `systemctl show`
                if prop in result['status'] and prop_val != result['status'][prop]:
                    prop_action += (" %s=%s" % (prop, prop_val))

            # Modify all items
            if prop_action and not module.check_mode:
                result['changed'] = True
                (rc, out, err) = module.run_command("%s set-property %s %s" % (systemctl, unit, prop_action))
                if rc != 0:
                    module.fail_json(msg="Unable to set-property service %s - %s: %s" % (unit, prop_action, err))
                else:
                    # In the case where we have updated properties we need to pull the full list again
                    # so that the result[status] reflects the new values
                    (rc, out, err) = module.run_command("%s show '%s'" % (systemctl, unit))

                    if rc == 0:
                        # load return of systemctl show into dictionary for easy access and return
                        if out:
                            result['status'] = parse_systemctl_show(to_native(out).split('\n'))

    module.exit_json(**result)
Ejemplo n.º 6
0
def main():
    # initialize
    module = AnsibleModule(
        argument_spec=dict(
            name=dict(type='str', aliases=['service', 'unit']),
            state=dict(type='str',
                       choices=[
                           'tried-restarting',
                           'reloaded-or-restarted',
                           'tried-reloading-or-restarting',
                           'reloaded',
                           'restarted',
                           'started',
                           'stopped',
                       ]),
            enabled=dict(type='bool'),
            force=dict(type='bool'),
            masked=dict(type='bool'),
            daemon_reload=dict(type='bool',
                               default=False,
                               aliases=['daemon-reload']),
            user=dict(type='bool', default=False),
            no_block=dict(type='bool', default=False),
        ),
        supports_check_mode=True,
        required_one_of=[['state', 'enabled', 'masked', 'daemon_reload']],
    )

    systemctl = module.get_bin_path('systemctl', True)
    if module.params['user']:
        systemctl = systemctl + " --user"
    if module.params['no_block']:
        systemctl = systemctl + " --no-block"
    if module.params['force']:
        systemctl = systemctl + " --force"
    unit = module.params['name']
    rc = 0
    out = err = ''
    result = dict(
        name=unit,
        changed=False,
        status=dict(),
    )

    for requires in ('state', 'enabled', 'masked'):
        if module.params[requires] is not None and unit is None:
            module.fail_json(msg="name is also required when specifying %s" %
                             requires)

    # Run daemon-reload first, if requested
    if module.params['daemon_reload'] and not module.check_mode:
        (rc, out, err) = module.run_command("%s daemon-reload" % (systemctl))
        if rc != 0:
            module.fail_json(msg='failure %d during daemon-reload: %s' %
                             (rc, err))

    if unit:
        found = False
        is_initd = sysv_exists(unit)
        is_systemd = False

        # check service data, cannot error out on rc as it changes across versions, assume not found
        (rc, out, err) = module.run_command("%s show '%s'" % (systemctl, unit))

        if request_was_ignored(out) or request_was_ignored(err):
            # fallback list-unit-files as show does not work on some systems (chroot)
            # not used as primary as it skips some services (like those using init.d) and requires .service/etc notation
            (rc, out, err) = module.run_command("%s list-unit-files '%s'" %
                                                (systemctl, unit))
            if rc == 0:
                is_systemd = True

        elif rc == 0:
            # load return of systemctl show into dictionary for easy access and return
            if out:
                result['status'] = parse_systemctl_show(
                    to_native(out).split('\n'))

                is_systemd = 'LoadState' in result[
                    'status'] and result['status']['LoadState'] != 'not-found'

                # Check for loading error
                if is_systemd and 'LoadError' in result['status']:
                    module.fail_json(msg="Error loading unit file '%s': %s" %
                                     (unit, result['status']['LoadError']))
        else:
            # Check for systemctl command
            module.run_command(systemctl, check_rc=True)

        # Does service exist?
        found = is_systemd or is_initd
        if is_initd and not is_systemd:
            module.warn(
                'The service (%s) is actually an init script but the system is managed by systemd'
                % unit)

        # mask/unmask the service, if requested, can operate on services before they are installed
        if module.params['masked'] is not None:
            # state is not masked unless systemd affirms otherwise
            masked = ('LoadState' in result['status']
                      and result['status']['LoadState'] == 'masked')

            if masked != module.params['masked']:
                result['changed'] = True
                if module.params['masked']:
                    action = 'mask'
                else:
                    action = 'unmask'

                if not module.check_mode:
                    (rc, out, err) = module.run_command(
                        "%s %s '%s'" % (systemctl, action, unit))
                    if rc != 0:
                        # some versions of system CAN mask/unmask non existing services, we only fail on missing if they don't
                        fail_if_missing(module, found, unit, msg='host')

        # Enable/disable service startup at boot if requested
        if module.params['enabled'] is not None:

            if module.params['enabled']:
                action = 'enable'
            else:
                action = 'disable'

            fail_if_missing(module, found, unit, msg='host')

            # do we need to enable the service?
            enabled = False
            (rc, out, err) = module.run_command("%s is-enabled '%s'" %
                                                (systemctl, unit))

            # check systemctl result or if it is a init script
            if rc == 0:
                enabled = True
            elif rc == 1:
                # if not a user service and both init script and unit file exist stdout should have enabled/disabled, otherwise use rc entries
                if not module.params['user'] and \
                        is_initd and \
                        (not out.strip().endswith('disabled') or sysv_is_enabled(unit)):
                    enabled = True

            # default to current state
            result['enabled'] = enabled

            # Change enable/disable if needed
            if enabled != module.params['enabled']:
                result['changed'] = True
                if not module.check_mode:
                    (rc, out, err) = module.run_command(
                        "%s %s '%s'" % (systemctl, action, unit))
                    if rc != 0:
                        module.fail_json(msg="Unable to %s service %s: %s" %
                                         (action, unit, out + err))

                result['enabled'] = not enabled

        # set service state if requested
        if module.params['state'] is not None:
            fail_if_missing(module, found, unit, msg="host")

            # default to desired state
            result['state'] = module.params['state']

            # What is current service state?
            if 'ActiveState' in result['status']:
                is_service_running = is_running_service(result['status'])
                action = get_action_from_state(
                    requested_state=module.params['state'],
                    current_state=is_service_running,
                    # Fall back to start if not running:
                    fallback_action=DO_NOTHING
                    if is_service_running else 'start',
                )
                if module.params['state'] not in ('started', 'stopped'):
                    result['state'] = 'started'

                supported_features = detect_systemd_features(module, systemctl)
                actor = convert_action_to_actor(action, supported_features)

                if actor is not DO_NOTHING:
                    result['changed'] = True
                    if action == 'reload' and not unit_supports_reload(
                            module, systemctl, unit):
                        module.warn(
                            'The service (%s) does not support '
                            '`reload` action and it is likely to fail. '
                            'you may try `reloaded-or-restarted`, '
                            '`tried-reloading-or-restarting` or anything else '
                            'which suits your needs better. '
                            'If you maintain this unit, you might want to '
                            'implement ExecReload there first.' % unit)
                    if not module.check_mode:
                        actor(module, systemctl, unit)
            else:
                # this should not happen?
                module.fail_json(msg="Service is in unknown state",
                                 status=result['status'])

    module.exit_json(**result)
Ejemplo n.º 7
0
def main():

    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'),
            sleep=dict(type='int', default=1),
            pattern=dict(type='str'),
            arguments=dict(type='str', aliases=['args']),
            runlevels=dict(type='list'),
            daemonize=dict(type='bool', default=False),
        ),
        supports_check_mode=True,
        required_one_of=[['state', 'enabled']],
    )

    name = module.params['name']
    action = module.params['state']
    enabled = module.params['enabled']
    runlevels = module.params['runlevels']
    pattern = module.params['pattern']
    sleep_for = module.params['sleep']
    rc = 0
    out = err = ''
    result = {'name': name, 'changed': False, 'status': {}}

    # ensure service exists, get script name
    fail_if_missing(module, sysv_exists(name), name)
    script = get_sysv_script(name)

    # locate binaries for service management
    paths = ['/sbin', '/usr/sbin', '/bin', '/usr/bin']
    binaries = ['chkconfig', 'update-rc.d', 'insserv', 'service']

    # Keeps track of the service status for various runlevels because we can
    # operate on multiple runlevels at once
    runlevel_status = {}

    location = {}
    for binary in binaries:
        location[binary] = module.get_bin_path(binary, opt_dirs=paths)

    # figure out enable status
    if runlevels:
        for rl in runlevels:
            runlevel_status.setdefault(rl, {})
            runlevel_status[rl]["enabled"] = sysv_is_enabled(name, runlevel=rl)
    else:
        runlevel_status["enabled"] = sysv_is_enabled(name)

    # figure out started status, everyone does it different!
    is_started = False

    # user knows other methods fail and supplied pattern
    if pattern:
        is_started = get_ps(module, pattern)
    else:
        worked = False
        if location.get('service'):
            # standard tool that has been 'destandarized' by reimplementation in other OS/distros
            cmd = '%s %s status' % (location['service'], name)
        elif script:
            # maybe script implements status (not LSB)
            cmd = '%s status' % script
        else:
            module.fail_json(msg="Unable to determine service status")

        (rc, out, err) = module.run_command(cmd)
        if not rc == -1:
            # special case
            if name == 'iptables' and "ACCEPT" in out:
                worked = True
                is_started = True

            # check output messages, messy but sadly more reliable than rc
            if not worked and out.count('\n') <= 1:

                cleanout = out.lower().replace(name.lower(), '')

                for stopped in [
                        'stop', 'is dead ', 'dead but ',
                        'could not access pid file', 'inactive'
                ]:
                    if stopped in cleanout:
                        worked = True
                        break

                if not worked:
                    for started_status in ['run', 'start', 'active']:
                        if started_status in cleanout and "not " not in cleanout:
                            is_started = True
                            worked = True
                            break

            # hope rc is not lying to us, use often used 'bad' returns
            if not worked and rc in [1, 2, 3, 4, 69]:
                worked = True

        if not worked:
            # hail mary
            if rc == 0:
                worked = True
            # ps for luck, can only assure positive match
            elif get_ps(module, name):
                is_started = True
                worked = True
                module.warn(
                    "Used ps output to match service name and determine it is up, this is very unreliable"
                )

    if not worked:
        module.warn(
            "Unable to determine if service is up, assuming it is down")

    ###########################################################################
    # BEGIN: Enable/Disable
    result['status'].setdefault('enabled', {})
    result['status']['enabled']['changed'] = False
    result['status']['enabled']['rc'] = None
    result['status']['enabled']['stdout'] = None
    result['status']['enabled']['stderr'] = None
    if runlevels:
        result['status']['enabled']['runlevels'] = runlevels
        for rl in runlevels:
            if enabled != runlevel_status[rl]["enabled"]:
                result['changed'] = True
                result['status']['enabled']['changed'] = True

        if not module.check_mode and result['changed']:
            # Perform enable/disable here
            if enabled:
                if location.get('update-rc.d'):
                    (rc, out, err) = module.run_command(
                        "%s %s enable %s" %
                        (location['update-rc.d'], name, ' '.join(runlevels)))
                elif location.get('chkconfig'):
                    (rc, out, err) = module.run_command(
                        "%s --level %s %s on" %
                        (location['chkconfig'], ''.join(runlevels), name))
            else:
                if location.get('update-rc.d'):
                    (rc, out, err) = module.run_command(
                        "%s %s disable %s" %
                        (location['update-rc.d'], name, ' '.join(runlevels)))
                elif location.get('chkconfig'):
                    (rc, out, err) = module.run_command(
                        "%s --level %s %s off" %
                        (location['chkconfig'], ''.join(runlevels), name))
    else:
        if enabled is not None and enabled != runlevel_status["enabled"]:
            result['changed'] = True
            result['status']['enabled']['changed'] = True

        if not module.check_mode and result['changed']:
            # Perform enable/disable here
            if enabled:
                if location.get('update-rc.d'):
                    (rc, out, err) = module.run_command(
                        "%s %s enable" % (location['update-rc.d'], name))
                elif location.get('chkconfig'):
                    (rc, out, err) = module.run_command(
                        "%s %s on" % (location['chkconfig'], name))
            else:
                if location.get('update-rc.d'):
                    (rc, out, err) = module.run_command(
                        "%s %s disable" % (location['update-rc.d'], name))
                elif location.get('chkconfig'):
                    (rc, out, err) = module.run_command(
                        "%s %s off" % (location['chkconfig'], name))

    # Assigned above, might be useful is something goes sideways
    if not module.check_mode and result['status']['enabled']['changed']:
        result['status']['enabled']['rc'] = rc
        result['status']['enabled']['stdout'] = out
        result['status']['enabled']['stderr'] = err
        rc, out, err = None, None, None

        if "illegal runlevel specified" in result['status']['enabled'][
                'stderr']:
            module.fail_json(
                msg=
                "Illegal runlevel specified for enable operation on service %s"
                % name,
                **result)
    # END: Enable/Disable
    ###########################################################################

    ###########################################################################
    # BEGIN: state
    result['status'].setdefault(module.params['state'], {})
    result['status'][module.params['state']]['changed'] = False
    result['status'][module.params['state']]['rc'] = None
    result['status'][module.params['state']]['stdout'] = None
    result['status'][module.params['state']]['stderr'] = None
    if action:
        action = re.sub(r'p?ed$', '', action.lower())

        def runme(doit):

            args = module.params['arguments']
            cmd = "%s %s %s" % (script, doit, "" if args is None else args)

            # how to run
            if module.params['daemonize']:
                (rc, out, err) = daemonize(cmd)
            else:
                (rc, out, err) = module.run_command(cmd)
            # FIXME: ERRORS

            if rc != 0:
                module.fail_json(msg="Failed to %s service: %s" %
                                 (action, name))

            return (rc, out, err)

        if action == 'restart':
            result['changed'] = True
            result['status'][module.params['state']]['changed'] = True
            if not module.check_mode:

                # cannot rely on existing 'restart' in init script
                for dothis in ['stop', 'start']:
                    (rc, out, err) = runme(dothis)
                    if sleep_for:
                        sleep(sleep_for)

        elif is_started != (action == 'start'):
            result['changed'] = True
            result['status'][module.params['state']]['changed'] = True
            if not module.check_mode:
                rc, out, err = runme(action)

        elif is_started == (action == 'stop'):
            result['changed'] = True
            result['status'][module.params['state']]['changed'] = True
            if not module.check_mode:
                rc, out, err = runme(action)

        if not module.check_mode and result['status'][
                module.params['state']]['changed']:
            result['status'][module.params['state']]['rc'] = rc
            result['status'][module.params['state']]['stdout'] = out
            result['status'][module.params['state']]['stderr'] = err
            rc, out, err = None, None, None
    # END: state
    ###########################################################################

    module.exit_json(**result)
Ejemplo n.º 8
0
def main():
    # initialize
    module = AnsibleModule(
        argument_spec=dict(
            name=dict(type='str', aliases=['service', 'unit']),
            state=dict(type='str', choices=['reloaded', 'restarted', 'started', 'stopped']),
            enabled=dict(type='bool'),
            force=dict(type='bool'),
            masked=dict(type='bool'),
            daemon_reload=dict(type='bool', default=False, aliases=['daemon-reload']),
            user=dict(type='bool', default=False),
            no_block=dict(type='bool', default=False),
        ),
        supports_check_mode=True,
        required_one_of=[['state', 'enabled', 'masked', 'daemon_reload']],
    )

    systemctl = module.get_bin_path('systemctl', True)
    if module.params['user']:
        systemctl = systemctl + " --user"
    if module.params['no_block']:
        systemctl = systemctl + " --no-block"
    if module.params['force']:
        systemctl = systemctl + " --force"
    unit = module.params['name']
    rc = 0
    out = err = ''
    result = dict(
        name=unit,
        changed=False,
        status=dict(),
    )

    for requires in ('state', 'enabled', 'masked'):
        if module.params[requires] is not None and unit is None:
            module.fail_json(msg="name is also required when specifying %s" % requires)

    # Run daemon-reload first, if requested
    if module.params['daemon_reload'] and not module.check_mode:
        (rc, out, err) = module.run_command("%s daemon-reload" % (systemctl))
        if rc != 0:
            module.fail_json(msg='failure %d during daemon-reload: %s' % (rc, err))

    if unit:
        found = False
        is_initd = sysv_exists(unit)
        is_systemd = False

        # check service data, cannot error out on rc as it changes across versions, assume not found
        (rc, out, err) = module.run_command("%s show '%s'" % (systemctl, unit))

        if request_was_ignored(out) or request_was_ignored(err):
            # fallback list-unit-files as show does not work on some systems (chroot)
            # not used as primary as it skips some services (like those using init.d) and requires .service/etc notation
            (rc, out, err) = module.run_command("%s list-unit-files '%s'" % (systemctl, unit))
            if rc == 0:
                is_systemd = True

        elif rc == 0:
            # load return of systemctl show into dictionary for easy access and return
            if out:
                result['status'] = parse_systemctl_show(to_native(out).split('\n'))

                is_systemd = 'LoadState' in result['status'] and result['status']['LoadState'] != 'not-found'

                # Check for loading error
                if is_systemd and 'LoadError' in result['status']:
                    module.fail_json(msg="Error loading unit file '%s': %s" % (unit, result['status']['LoadError']))
        else:
            # Check for systemctl command
            module.run_command(systemctl, check_rc=True)

        # Does service exist?
        found = is_systemd or is_initd
        if is_initd and not is_systemd:
            module.warn('The service (%s) is actually an init script but the system is managed by systemd' % unit)

        # mask/unmask the service, if requested, can operate on services before they are installed
        if module.params['masked'] is not None:
            # state is not masked unless systemd affirms otherwise
            masked = ('LoadState' in result['status'] and result['status']['LoadState'] == 'masked')

            if masked != module.params['masked']:
                result['changed'] = True
                if module.params['masked']:
                    action = 'mask'
                else:
                    action = 'unmask'

                if not module.check_mode:
                    (rc, out, err) = module.run_command("%s %s '%s'" % (systemctl, action, unit))
                    if rc != 0:
                        # some versions of system CAN mask/unmask non existing services, we only fail on missing if they don't
                        fail_if_missing(module, found, unit, msg='host')

        # Enable/disable service startup at boot if requested
        if module.params['enabled'] is not None:

            if module.params['enabled']:
                action = 'enable'
            else:
                action = 'disable'

            fail_if_missing(module, found, unit, msg='host')

            # do we need to enable the service?
            enabled = False
            (rc, out, err) = module.run_command("%s is-enabled '%s'" % (systemctl, unit))

            # check systemctl result or if it is a init script
            if rc == 0:
                enabled = True
            elif rc == 1:
                # if not a user service and both init script and unit file exist stdout should have enabled/disabled, otherwise use rc entries
                if not module.params['user'] and \
                        is_initd and \
                        (not out.strip().endswith('disabled') or sysv_is_enabled(unit)):
                    enabled = True

            # default to current state
            result['enabled'] = enabled

            # Change enable/disable if needed
            if enabled != module.params['enabled']:
                result['changed'] = True
                if not module.check_mode:
                    (rc, out, err) = module.run_command("%s %s '%s'" % (systemctl, action, unit))
                    if rc != 0:
                        module.fail_json(msg="Unable to %s service %s: %s" % (action, unit, out + err))

                result['enabled'] = not enabled

        # set service state if requested
        if module.params['state'] is not None:
            fail_if_missing(module, found, unit, msg="host")

            # default to desired state
            result['state'] = module.params['state']

            # What is current service state?
            if 'ActiveState' in result['status']:
                action = None
                if module.params['state'] == 'started':
                    if not is_running_service(result['status']):
                        action = 'start'
                elif module.params['state'] == 'stopped':
                    if is_running_service(result['status']):
                        action = 'stop'
                else:
                    if not is_running_service(result['status']):
                        action = 'start'
                    else:
                        action = module.params['state'][:-2]  # remove 'ed' from restarted/reloaded
                    result['state'] = 'started'

                if action:
                    result['changed'] = True
                    if not module.check_mode:
                        (rc, out, err) = module.run_command("%s %s '%s'" % (systemctl, action, unit))
                        if rc != 0:
                            module.fail_json(msg="Unable to %s service %s: %s" % (action, unit, err))
            else:
                # this should not happen?
                module.fail_json(msg="Service is in unknown state", status=result['status'])

    module.exit_json(**result)
Ejemplo n.º 9
0
def main():
    # initialize
    module = AnsibleModule(
        argument_spec=dict(
            name=dict(required=True, type="str", aliases=["unit", "service"]),
            state=dict(choices=["started", "stopped", "restarted", "reloaded"], type="str"),
            enabled=dict(type="bool"),
            masked=dict(type="bool"),
            daemon_reload=dict(type="bool", default=False, aliases=["daemon-reload"]),
            user=dict(type="bool", default=False),
        ),
        supports_check_mode=True,
        required_one_of=[["state", "enabled", "masked", "daemon_reload"]],
    )

    systemctl = module.get_bin_path("systemctl")
    if module.params["user"]:
        systemctl = systemctl + " --user"
    unit = module.params["name"]
    rc = 0
    out = err = ""
    result = {"name": unit, "changed": False, "status": {}, "warnings": []}

    # Run daemon-reload first, if requested
    if module.params["daemon_reload"]:
        (rc, out, err) = module.run_command("%s daemon-reload" % (systemctl))
        if rc != 0:
            module.fail_json(msg="failure %d during daemon-reload: %s" % (rc, err))

    found = False
    is_initd = sysv_exists(unit)
    is_systemd = False

    # check service data, cannot error out on rc as it changes across versions, assume not found
    (rc, out, err) = module.run_command("%s show '%s'" % (systemctl, unit))
    if rc == 0:
        # load return of systemctl show into dictionary for easy access and return
        multival = []
        if out:
            k = None
            for line in to_native(out).split("\n"):  # systemd can have multiline values delimited with {}
                if line.strip():
                    if k is None:
                        if "=" in line:
                            k, v = line.split("=", 1)
                            if v.lstrip().startswith("{"):
                                if not v.rstrip().endswith("}"):
                                    multival.append(line)
                                    continue
                            result["status"][k] = v.strip()
                            k = None
                    else:
                        if line.rstrip().endswith("}"):
                            result["status"][k] = "\n".join(multival).strip()
                            multival = []
                            k = None
                        else:
                            multival.append(line)

            is_systemd = "LoadState" in result["status"] and result["status"]["LoadState"] != "not-found"

            # Check for loading error
            if is_systemd and "LoadError" in result["status"]:
                module.fail_json(msg="Error loading unit file '%s': %s" % (unit, result["status"]["LoadError"]))

    # Does service exist?
    found = is_systemd or is_initd
    if is_initd and not is_systemd:
        result["warnings"].append(
            "The service (%s) is actually an init script but the system is managed by systemd" % unit
        )

    # mask/unmask the service, if requested, can operate on services before they are installed
    if module.params["masked"] is not None:
        # state is not masked unless systemd affirms otherwise
        masked = "LoadState" in result["status"] and result["status"]["LoadState"] == "masked"

        if masked != module.params["masked"]:
            result["changed"] = True
            if module.params["masked"]:
                action = "mask"
            else:
                action = "unmask"

            if not module.check_mode:
                (rc, out, err) = module.run_command("%s %s '%s'" % (systemctl, action, unit))
                if rc != 0:
                    # some versions of system CAN mask/unmask non existing services, we only fail on missing if they don't
                    fail_if_missing(module, found, unit, msg="host")

    # Enable/disable service startup at boot if requested
    if module.params["enabled"] is not None:

        if module.params["enabled"]:
            action = "enable"
        else:
            action = "disable"

        fail_if_missing(module, found, unit, msg="host")

        # do we need to enable the service?
        enabled = False
        (rc, out, err) = module.run_command("%s is-enabled '%s'" % (systemctl, unit))

        # check systemctl result or if it is a init script
        if rc == 0:
            enabled = True
        elif rc == 1:
            # if both init script and unit file exist stdout should have enabled/disabled, otherwise use rc entries
            if is_initd and (not out.startswith("disabled") or sysv_is_enabled(unit)):
                enabled = True

        # default to current state
        result["enabled"] = enabled

        # Change enable/disable if needed
        if enabled != module.params["enabled"]:
            result["changed"] = True
            if not module.check_mode:
                (rc, out, err) = module.run_command("%s %s '%s'" % (systemctl, action, unit))
                if rc != 0:
                    module.fail_json(msg="Unable to %s service %s: %s" % (action, unit, out + err))

            result["enabled"] = not enabled

    # set service state if requested
    if module.params["state"] is not None:
        fail_if_missing(module, found, unit, msg="host")

        # default to desired state
        result["state"] = module.params["state"]

        # What is current service state?
        if "ActiveState" in result["status"]:
            action = None
            if module.params["state"] == "started":
                if result["status"]["ActiveState"] != "active":
                    action = "start"
            elif module.params["state"] == "stopped":
                if result["status"]["ActiveState"] == "active":
                    action = "stop"
            else:
                if result["status"]["ActiveState"] != "active":
                    action = "start"
                else:
                    action = module.params["state"][:-2]  # remove 'ed' from restarted/reloaded
                result["state"] = "started"

            if action:
                result["changed"] = True
                if not module.check_mode:
                    (rc, out, err) = module.run_command("%s %s '%s'" % (systemctl, action, unit))
                    if rc != 0:
                        module.fail_json(msg="Unable to %s service %s: %s" % (action, unit, err))
        else:
            # this should not happen?
            module.fail_json(msg="Service is in unknown state", status=result["status"])

    module.exit_json(**result)