Example #1
0
def main():
    module = AssibleModule(
        argument_spec=dict(
            name=dict(required=True),
            selection=dict(choices=['install', 'hold', 'deinstall', 'purge'],
                           required=True)),
        supports_check_mode=True,
    )

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

    name = module.params['name']
    selection = module.params['selection']

    # Get current settings.
    rc, out, err = module.run_command([dpkg, '--get-selections', name],
                                      check_rc=True)
    if not out:
        current = 'not present'
    else:
        current = out.split()[1]

    changed = current != selection

    if module.check_mode or not changed:
        module.exit_json(changed=changed, before=current, after=selection)

    module.run_command([dpkg, '--set-selections'],
                       data="%s %s" % (name, selection),
                       check_rc=True)
    module.exit_json(changed=changed, before=current, after=selection)
Example #2
0
def main():
    module = AssibleModule(
        argument_spec=dict(
            database=dict(type='str', required=True),
            key=dict(type='str'),
            service=dict(type='str'),
            split=dict(type='str'),
            fail_key=dict(type='bool', default=True),
        ),
        supports_check_mode=True,
    )

    colon = ['passwd', 'shadow', 'group', 'gshadow']

    database = module.params['database']
    key = module.params.get('key')
    split = module.params.get('split')
    service = module.params.get('service')
    fail_key = module.params.get('fail_key')

    getent_bin = module.get_bin_path('getent', True)

    if key is not None:
        cmd = [getent_bin, database, key]
    else:
        cmd = [getent_bin, database]

    if service is not None:
        cmd.extend(['-s', service])

    if split is None and database in colon:
        split = ':'

    try:
        rc, out, err = module.run_command(cmd)
    except Exception as e:
        module.fail_json(msg=to_native(e), exception=traceback.format_exc())

    msg = "Unexpected failure!"
    dbtree = 'getent_%s' % database
    results = {dbtree: {}}

    if rc == 0:
        for line in out.splitlines():
            record = line.split(split)
            results[dbtree][record[0]] = record[1:]

        module.exit_json(assible_facts=results)

    elif rc == 1:
        msg = "Missing arguments, or database unknown."
    elif rc == 2:
        msg = "One or more supplied key could not be found in the database."
        if not fail_key:
            results[dbtree][key] = None
            module.exit_json(assible_facts=results, msg=msg)
    elif rc == 3:
        msg = "Enumeration not supported on this database."

    module.fail_json(msg=msg)
Example #3
0
def main():
    module = AssibleModule(
        argument_spec=dict(
            state=dict(default="present", choices=["present", "latest", "absent"], required=False),
            name=dict(aliases=["pkg"], required=True, type='list'),
            cached=dict(default=False, type='bool'),
            annotation=dict(default="", required=False),
            pkgsite=dict(default="", required=False),
            rootdir=dict(default="", required=False, type='path'),
            chroot=dict(default="", required=False, type='path'),
            jail=dict(default="", required=False, type='str'),
            autoremove=dict(default=False, type='bool')),
        supports_check_mode=True,
        mutually_exclusive=[["rootdir", "chroot", "jail"]])

    pkgng_path = module.get_bin_path('pkg', True)

    p = module.params

    pkgs = p["name"]

    changed = False
    msgs = []
    dir_arg = ""

    if p["rootdir"] != "":
        old_pkgng = pkgng_older_than(module, pkgng_path, [1, 5, 0])
        if old_pkgng:
            module.fail_json(msg="To use option 'rootdir' pkg version must be 1.5 or greater")
        else:
            dir_arg = "--rootdir %s" % (p["rootdir"])

    if p["chroot"] != "":
        dir_arg = '--chroot %s' % (p["chroot"])

    if p["jail"] != "":
        dir_arg = '--jail %s' % (p["jail"])

    if p["state"] in ("present", "latest"):
        _changed, _msg = install_packages(module, pkgng_path, pkgs, p["cached"], p["pkgsite"], dir_arg, p["state"])
        changed = changed or _changed
        msgs.append(_msg)

    elif p["state"] == "absent":
        _changed, _msg = remove_packages(module, pkgng_path, pkgs, dir_arg)
        changed = changed or _changed
        msgs.append(_msg)

    if p["autoremove"]:
        _changed, _msg = autoremove_packages(module, pkgng_path, dir_arg)
        changed = changed or _changed
        msgs.append(_msg)

    if p["annotation"]:
        _changed, _msg = annotate_packages(module, pkgng_path, pkgs, p["annotation"], dir_arg)
        changed = changed or _changed
        msgs.append(_msg)

    module.exit_json(changed=changed, msg=", ".join(msgs))
Example #4
0
 def test_sanity_check(self):
     basic._load_params = lambda: {}
     # Module used internally to execute ssh-keygen system executable
     module = AssibleModule(argument_spec={})
     host = '10.0.0.1'
     key = '%s ssh-rsa ASDF foo@bar' % (host, )
     keygen = module.get_bin_path('ssh-keygen')
     sanity_check(module, host, key, keygen)
Example #5
0
def main():
    module = AssibleModule(
        supports_check_mode=True,
        argument_spec=dict(
            table=dict(type='str',
                       default='filter',
                       choices=['filter', 'nat', 'mangle', 'raw', 'security']),
            state=dict(type='str',
                       default='present',
                       choices=['absent', 'present']),
            action=dict(type='str',
                        default='append',
                        choices=['append', 'insert']),
            ip_version=dict(type='str',
                            default='ipv4',
                            choices=['ipv4', 'ipv6']),
            chain=dict(type='str'),
            rule_num=dict(type='str'),
            protocol=dict(type='str'),
            wait=dict(type='str'),
            source=dict(type='str'),
            to_source=dict(type='str'),
            destination=dict(type='str'),
            to_destination=dict(type='str'),
            match=dict(type='list', elements='str', default=[]),
            tcp_flags=dict(type='dict',
                           options=dict(flags=dict(type='list',
                                                   elements='str'),
                                        flags_set=dict(type='list',
                                                       elements='str'))),
            jump=dict(type='str'),
            gateway=dict(type='str'),
            log_prefix=dict(type='str'),
            log_level=dict(
                type='str',
                choices=[
                    '0', '1', '2', '3', '4', '5', '6', '7', 'emerg', 'alert',
                    'crit', 'error', 'warning', 'notice', 'info', 'debug'
                ],
                default=None,
            ),
            goto=dict(type='str'),
            in_interface=dict(type='str'),
            out_interface=dict(type='str'),
            fragment=dict(type='str'),
            set_counters=dict(type='str'),
            source_port=dict(type='str'),
            destination_port=dict(type='str'),
            to_ports=dict(type='str'),
            set_dscp_mark=dict(type='str'),
            set_dscp_mark_class=dict(type='str'),
            comment=dict(type='str'),
            ctstate=dict(type='list', elements='str', default=[]),
            src_range=dict(type='str'),
            dst_range=dict(type='str'),
            limit=dict(type='str'),
            limit_burst=dict(type='str'),
            uid_owner=dict(type='str'),
            gid_owner=dict(type='str'),
            reject_with=dict(type='str'),
            icmp_type=dict(type='str'),
            syn=dict(type='str',
                     default='ignore',
                     choices=['ignore', 'match', 'negate']),
            flush=dict(type='bool', default=False),
            policy=dict(type='str',
                        choices=['ACCEPT', 'DROP', 'QUEUE', 'RETURN']),
        ),
        mutually_exclusive=(
            ['set_dscp_mark', 'set_dscp_mark_class'],
            ['flush', 'policy'],
        ),
        required_if=[
            ['jump', 'TEE', ['gateway']],
            ['jump', 'tee', ['gateway']],
        ])
    args = dict(
        changed=False,
        failed=False,
        ip_version=module.params['ip_version'],
        table=module.params['table'],
        chain=module.params['chain'],
        flush=module.params['flush'],
        rule=' '.join(construct_rule(module.params)),
        state=module.params['state'],
    )

    ip_version = module.params['ip_version']
    iptables_path = module.get_bin_path(BINS[ip_version], True)

    # Check if chain option is required
    if args['flush'] is False and args['chain'] is None:
        module.fail_json(
            msg="Either chain or flush parameter must be specified.")

    if module.params.get('log_prefix', None) or module.params.get(
            'log_level', None):
        if module.params['jump'] is None:
            module.params['jump'] = 'LOG'
        elif module.params['jump'] != 'LOG':
            module.fail_json(
                msg="Logging options can only be used with the LOG jump target."
            )

    # Check if wait option is supported
    iptables_version = LooseVersion(get_iptables_version(
        iptables_path, module))

    if iptables_version >= LooseVersion(IPTABLES_WAIT_SUPPORT_ADDED):
        if iptables_version < LooseVersion(
                IPTABLES_WAIT_WITH_SECONDS_SUPPORT_ADDED):
            module.params['wait'] = ''
    else:
        module.params['wait'] = None

    # Flush the table
    if args['flush'] is True:
        args['changed'] = True
        if not module.check_mode:
            flush_table(iptables_path, module, module.params)

    # Set the policy
    elif module.params['policy']:
        current_policy = get_chain_policy(iptables_path, module, module.params)
        if not current_policy:
            module.fail_json(msg='Can\'t detect current policy')

        changed = current_policy != module.params['policy']
        args['changed'] = changed
        if changed and not module.check_mode:
            set_chain_policy(iptables_path, module, module.params)

    else:
        insert = (module.params['action'] == 'insert')
        rule_is_present = check_present(iptables_path, module, module.params)
        should_be_present = (args['state'] == 'present')

        # Check if target is up to date
        args['changed'] = (rule_is_present != should_be_present)
        if args['changed'] is False:
            # Target is already up to date
            module.exit_json(**args)

        # Check only; don't modify
        if not module.check_mode:
            if should_be_present:
                if insert:
                    insert_rule(iptables_path, module, module.params)
                else:
                    append_rule(iptables_path, module, module.params)
            else:
                remove_rule(iptables_path, module, module.params)

    module.exit_json(**args)
Example #6
0
def main():
    module = AssibleModule(
        argument_spec=dict(
            vg=dict(type='str', required=True),
            pvs=dict(type='list'),
            pesize=dict(type='str', default='4'),
            pv_options=dict(type='str', default=''),
            vg_options=dict(type='str', default=''),
            state=dict(type='str',
                       default='present',
                       choices=['absent', 'present']),
            force=dict(type='bool', default=False),
        ),
        supports_check_mode=True,
    )

    vg = module.params['vg']
    state = module.params['state']
    force = module.boolean(module.params['force'])
    pesize = module.params['pesize']
    pvoptions = module.params['pv_options'].split()
    vgoptions = module.params['vg_options'].split()

    dev_list = []
    if module.params['pvs']:
        dev_list = list(module.params['pvs'])
    elif state == 'present':
        module.fail_json(msg="No physical volumes given.")

    # LVM always uses real paths not symlinks so replace symlinks with actual path
    for idx, dev in enumerate(dev_list):
        dev_list[idx] = os.path.realpath(dev)

    if state == 'present':
        # check given devices
        for test_dev in dev_list:
            if not os.path.exists(test_dev):
                module.fail_json(msg="Device %s not found." % test_dev)

        # get pv list
        pvs_cmd = module.get_bin_path('pvs', True)
        if dev_list:
            pvs_filter_pv_name = ' || '.join(
                'pv_name = {0}'.format(x)
                for x in itertools.chain(dev_list, module.params['pvs']))
            pvs_filter_vg_name = 'vg_name = {0}'.format(vg)
            pvs_filter = "--select '{0} || {1}' ".format(
                pvs_filter_pv_name, pvs_filter_vg_name)
        else:
            pvs_filter = ''
        rc, current_pvs, err = module.run_command(
            "%s --noheadings -o pv_name,vg_name --separator ';' %s" %
            (pvs_cmd, pvs_filter))
        if rc != 0:
            module.fail_json(msg="Failed executing pvs command.",
                             rc=rc,
                             err=err)

        # check pv for devices
        pvs = parse_pvs(module, current_pvs)
        used_pvs = [
            pv for pv in pvs
            if pv['name'] in dev_list and pv['vg_name'] and pv['vg_name'] != vg
        ]
        if used_pvs:
            module.fail_json(msg="Device %s is already in %s volume group." %
                             (used_pvs[0]['name'], used_pvs[0]['vg_name']))

    vgs_cmd = module.get_bin_path('vgs', True)
    rc, current_vgs, err = module.run_command(
        "%s --noheadings -o vg_name,pv_count,lv_count --separator ';'" %
        vgs_cmd)

    if rc != 0:
        module.fail_json(msg="Failed executing vgs command.", rc=rc, err=err)

    changed = False

    vgs = parse_vgs(current_vgs)

    for test_vg in vgs:
        if test_vg['name'] == vg:
            this_vg = test_vg
            break
    else:
        this_vg = None

    if this_vg is None:
        if state == 'present':
            # create VG
            if module.check_mode:
                changed = True
            else:
                # create PV
                pvcreate_cmd = module.get_bin_path('pvcreate', True)
                for current_dev in dev_list:
                    rc, _, err = module.run_command(
                        [pvcreate_cmd] + pvoptions +
                        ['-f', str(current_dev)])
                    if rc == 0:
                        changed = True
                    else:
                        module.fail_json(
                            msg="Creating physical volume '%s' failed" %
                            current_dev,
                            rc=rc,
                            err=err)
                vgcreate_cmd = module.get_bin_path('vgcreate')
                rc, _, err = module.run_command([vgcreate_cmd] + vgoptions +
                                                ['-s', pesize, vg] + dev_list)
                if rc == 0:
                    changed = True
                else:
                    module.fail_json(msg="Creating volume group '%s' failed" %
                                     vg,
                                     rc=rc,
                                     err=err)
    else:
        if state == 'absent':
            if module.check_mode:
                module.exit_json(changed=True)
            else:
                if this_vg['lv_count'] == 0 or force:
                    # remove VG
                    vgremove_cmd = module.get_bin_path('vgremove', True)
                    rc, _, err = module.run_command("%s --force %s" %
                                                    (vgremove_cmd, vg))
                    if rc == 0:
                        module.exit_json(changed=True)
                    else:
                        module.fail_json(
                            msg="Failed to remove volume group %s" % (vg),
                            rc=rc,
                            err=err)
                else:
                    module.fail_json(
                        msg=
                        "Refuse to remove non-empty volume group %s without force=yes"
                        % (vg))

        # resize VG
        current_devs = [
            os.path.realpath(pv['name']) for pv in pvs if pv['vg_name'] == vg
        ]
        devs_to_remove = list(set(current_devs) - set(dev_list))
        devs_to_add = list(set(dev_list) - set(current_devs))

        if devs_to_add or devs_to_remove:
            if module.check_mode:
                changed = True
            else:
                if devs_to_add:
                    devs_to_add_string = ' '.join(devs_to_add)
                    # create PV
                    pvcreate_cmd = module.get_bin_path('pvcreate', True)
                    for current_dev in devs_to_add:
                        rc, _, err = module.run_command(
                            [pvcreate_cmd] + pvoptions +
                            ['-f', str(current_dev)])
                        if rc == 0:
                            changed = True
                        else:
                            module.fail_json(
                                msg="Creating physical volume '%s' failed" %
                                current_dev,
                                rc=rc,
                                err=err)
                    # add PV to our VG
                    vgextend_cmd = module.get_bin_path('vgextend', True)
                    rc, _, err = module.run_command(
                        "%s %s %s" % (vgextend_cmd, vg, devs_to_add_string))
                    if rc == 0:
                        changed = True
                    else:
                        module.fail_json(msg="Unable to extend %s by %s." %
                                         (vg, devs_to_add_string),
                                         rc=rc,
                                         err=err)

                # remove some PV from our VG
                if devs_to_remove:
                    devs_to_remove_string = ' '.join(devs_to_remove)
                    vgreduce_cmd = module.get_bin_path('vgreduce', True)
                    rc, _, err = module.run_command(
                        "%s --force %s %s" %
                        (vgreduce_cmd, vg, devs_to_remove_string))
                    if rc == 0:
                        changed = True
                    else:
                        module.fail_json(msg="Unable to reduce %s by %s." %
                                         (vg, devs_to_remove_string),
                                         rc=rc,
                                         err=err)

    module.exit_json(changed=changed)
Example #7
0
def main():

    module = AssibleModule(
        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', elements='str'),
            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
    worked = False

    # user knows other methods fail and supplied pattern
    if pattern:
        worked = is_started = get_ps(module, pattern)
    else:
        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:
                is_started = True
                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 defaults" % (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(module, 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), rc=rc, stdout=out, stderr=err)

            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)
Example #8
0
def main():
    # initialize
    module = AssibleModule(
        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']),
            scope=dict(type='str',
                       default='system',
                       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', ),
        ),
    )

    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 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'] != '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 rc == 0 and not (request_was_ignored(out)
                            or request_was_ignored(err)):
            # 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:
            # list taken from man systemctl(1) for systemd 244
            valid_enabled_states = [
                "enabled", "enabled-runtime", "linked", "linked-runtime",
                "masked", "masked-runtime", "static", "indirect", "disabled",
                "generated", "transient"
            ]

            (rc, out, err) = module.run_command("%s is-enabled '%s'" %
                                                (systemctl, unit))
            if out.strip() in valid_enabled_states:
                is_systemd = True
            else:
                # 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
                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
            (rc, out, err) = module.run_command("%s is-enabled '%s'" %
                                                (systemctl, unit))
            masked = out.strip() == "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'] == 'system' 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) or os.environ.get('SYSTEMD_OFFLINE') == '1':
                module.warn(
                    "Target is a chroot or systemd is offline. 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)
Example #9
0
def main():
    module = AssibleModule(
        argument_spec=dict(
            dest=dict(type='path'),
            repo=dict(type='str', required=True, aliases=['name', 'repository']),
            revision=dict(type='str', default='HEAD', aliases=['rev', 'version']),
            force=dict(type='bool', default=False),
            username=dict(type='str'),
            password=dict(type='str', no_log=True),
            executable=dict(type='path'),
            export=dict(type='bool', default=False),
            checkout=dict(type='bool', default=True),
            update=dict(type='bool', default=True),
            switch=dict(type='bool', default=True),
            in_place=dict(type='bool', default=False),
            validate_certs=dict(type='bool', default=False),
        ),
        supports_check_mode=True,
    )

    dest = module.params['dest']
    repo = module.params['repo']
    revision = module.params['revision']
    force = module.params['force']
    username = module.params['username']
    password = module.params['password']
    svn_path = module.params['executable'] or module.get_bin_path('svn', True)
    export = module.params['export']
    switch = module.params['switch']
    checkout = module.params['checkout']
    update = module.params['update']
    in_place = module.params['in_place']
    validate_certs = module.params['validate_certs']

    # We screenscrape a huge amount of svn commands so use C locale anytime we
    # call run_command()
    module.run_command_environ_update = dict(LANG='C', LC_MESSAGES='C')

    if not dest and (checkout or update or export):
        module.fail_json(msg="the destination directory must be specified unless checkout=no, update=no, and export=no")

    svn = Subversion(module, dest, repo, revision, username, password, svn_path, validate_certs)

    if not export and not update and not checkout:
        module.exit_json(changed=False, after=svn.get_remote_revision())
    if export or not os.path.exists(dest):
        before = None
        local_mods = False
        if module.check_mode:
            module.exit_json(changed=True)
        elif not export and not checkout:
            module.exit_json(changed=False)
        if not export and checkout:
            svn.checkout()
            files_changed = True
        else:
            svn.export(force=force)
            files_changed = True
    elif svn.is_svn_repo():
        # Order matters. Need to get local mods before switch to avoid false
        # positives. Need to switch before revert to ensure we are reverting to
        # correct repo.
        if not update:
            module.exit_json(changed=False)
        if module.check_mode:
            if svn.has_local_mods() and not force:
                module.fail_json(msg="ERROR: modified files exist in the repository.")
            check, before, after = svn.needs_update()
            module.exit_json(changed=check, before=before, after=after)
        files_changed = False
        before = svn.get_revision()
        local_mods = svn.has_local_mods()
        if switch:
            files_changed = svn.switch() or files_changed
        if local_mods:
            if force:
                files_changed = svn.revert() or files_changed
            else:
                module.fail_json(msg="ERROR: modified files exist in the repository.")
        files_changed = svn.update() or files_changed
    elif in_place:
        before = None
        svn.checkout(force=True)
        files_changed = True
        local_mods = svn.has_local_mods()
        if local_mods and force:
            svn.revert()
    else:
        module.fail_json(msg="ERROR: %s folder already exists, but its not a subversion repository." % (dest,))

    if export:
        module.exit_json(changed=True)
    else:
        after = svn.get_revision()
        changed = files_changed or local_mods
        module.exit_json(changed=changed, before=before, after=after)
Example #10
0
def main():
    module = AssibleModule(
        argument_spec=dict(
            state=dict(
                type='str',
                default='present',
                choices=['absent', 'build-dep', 'fixed', 'latest', 'present']),
            update_cache=dict(type='bool', aliases=['update-cache']),
            update_cache_retries=dict(type='int', default=5),
            update_cache_retry_max_delay=dict(type='int', default=12),
            cache_valid_time=dict(type='int', default=0),
            purge=dict(type='bool', default=False),
            package=dict(type='list', elements='str', aliases=['pkg', 'name']),
            deb=dict(type='path'),
            default_release=dict(type='str', aliases=['default-release']),
            install_recommends=dict(type='bool',
                                    aliases=['install-recommends']),
            force=dict(type='bool', default=False),
            upgrade=dict(type='str',
                         choices=['dist', 'full', 'no', 'safe', 'yes'],
                         default='no'),
            dpkg_options=dict(type='str', default=DPKG_OPTIONS),
            autoremove=dict(type='bool', default=False),
            autoclean=dict(type='bool', default=False),
            fail_on_autoremove=dict(type='bool', default=False),
            policy_rc_d=dict(type='int', default=None),
            only_upgrade=dict(type='bool', default=False),
            force_apt_get=dict(type='bool', default=False),
            allow_unauthenticated=dict(type='bool',
                                       default=False,
                                       aliases=['allow-unauthenticated']),
        ),
        mutually_exclusive=[['deb', 'package', 'upgrade']],
        required_one_of=[[
            'autoremove', 'deb', 'package', 'update_cache', 'upgrade'
        ]],
        supports_check_mode=True,
    )

    module.run_command_environ_update = APT_ENV_VARS

    if not HAS_PYTHON_APT:
        if module.check_mode:
            module.fail_json(
                msg="%s must be installed to use check mode. "
                "If run normally this module can auto-install it." %
                PYTHON_APT)
        try:
            # We skip cache update in auto install the dependency if the
            # user explicitly declared it with update_cache=no.
            if module.params.get('update_cache') is False:
                module.warn(
                    "Auto-installing missing dependency without updating cache: %s"
                    % PYTHON_APT)
            else:
                module.warn(
                    "Updating cache and auto-installing missing dependency: %s"
                    % PYTHON_APT)
                module.run_command(['apt-get', 'update'], check_rc=True)

            module.run_command([
                'apt-get', 'install', '--no-install-recommends', PYTHON_APT,
                '-y', '-q'
            ],
                               check_rc=True)
            global apt, apt_pkg
            import apt
            import apt.debfile
            import apt_pkg
        except ImportError:
            module.fail_json(
                msg="Could not import python modules: apt, apt_pkg. "
                "Please install %s package." % PYTHON_APT)

    global APTITUDE_CMD
    APTITUDE_CMD = module.get_bin_path("aptitude", False)
    global APT_GET_CMD
    APT_GET_CMD = module.get_bin_path("apt-get")

    p = module.params

    if p['upgrade'] == 'no':
        p['upgrade'] = None

    use_apt_get = p['force_apt_get']

    if not use_apt_get and not APTITUDE_CMD:
        use_apt_get = True

    updated_cache = False
    updated_cache_time = 0
    install_recommends = p['install_recommends']
    allow_unauthenticated = p['allow_unauthenticated']
    dpkg_options = expand_dpkg_options(p['dpkg_options'])
    autoremove = p['autoremove']
    fail_on_autoremove = p['fail_on_autoremove']
    autoclean = p['autoclean']

    # Get the cache object
    cache = get_cache(module)

    try:
        if p['default_release']:
            try:
                apt_pkg.config['APT::Default-Release'] = p['default_release']
            except AttributeError:
                apt_pkg.Config['APT::Default-Release'] = p['default_release']
            # reopen cache w/ modified config
            cache.open(progress=None)

        mtimestamp, updated_cache_time = get_updated_cache_time()
        # Cache valid time is default 0, which will update the cache if
        #  needed and `update_cache` was set to true
        updated_cache = False
        if p['update_cache'] or p['cache_valid_time']:
            now = datetime.datetime.now()
            tdelta = datetime.timedelta(seconds=p['cache_valid_time'])
            if not mtimestamp + tdelta >= now:
                # Retry to update the cache with exponential backoff
                err = ''
                update_cache_retries = module.params.get(
                    'update_cache_retries')
                update_cache_retry_max_delay = module.params.get(
                    'update_cache_retry_max_delay')
                randomize = random.randint(0, 1000) / 1000.0

                for retry in range(update_cache_retries):
                    try:
                        cache.update()
                        break
                    except apt.cache.FetchFailedException as e:
                        err = to_native(e)

                    # Use exponential backoff plus a little bit of randomness
                    delay = 2**retry + randomize
                    if delay > update_cache_retry_max_delay:
                        delay = update_cache_retry_max_delay + randomize
                    time.sleep(delay)
                else:
                    module.fail_json(msg='Failed to update apt cache: %s' %
                                     (err if err else 'unknown reason'))

                cache.open(progress=None)
                mtimestamp, post_cache_update_time = get_updated_cache_time()
                if updated_cache_time != post_cache_update_time:
                    updated_cache = True
                updated_cache_time = post_cache_update_time

            # If there is nothing else to do exit. This will set state as
            #  changed based on if the cache was updated.
            if not p['package'] and not p['upgrade'] and not p['deb']:
                module.exit_json(changed=updated_cache,
                                 cache_updated=updated_cache,
                                 cache_update_time=updated_cache_time)

        force_yes = p['force']

        if p['upgrade']:
            upgrade(module, p['upgrade'], force_yes, p['default_release'],
                    use_apt_get, dpkg_options, autoremove, fail_on_autoremove,
                    allow_unauthenticated)

        if p['deb']:
            if p['state'] != 'present':
                module.fail_json(msg="deb only supports state=present")
            if '://' in p['deb']:
                p['deb'] = fetch_file(module, p['deb'])
            install_deb(module,
                        p['deb'],
                        cache,
                        install_recommends=install_recommends,
                        allow_unauthenticated=allow_unauthenticated,
                        force=force_yes,
                        fail_on_autoremove=fail_on_autoremove,
                        dpkg_options=p['dpkg_options'])

        unfiltered_packages = p['package'] or ()
        packages = [
            package.strip() for package in unfiltered_packages
            if package != '*'
        ]
        all_installed = '*' in unfiltered_packages
        latest = p['state'] == 'latest'

        if latest and all_installed:
            if packages:
                module.fail_json(
                    msg=
                    'unable to install additional packages when upgrading all installed packages'
                )
            upgrade(module, 'yes', force_yes, p['default_release'],
                    use_apt_get, dpkg_options, autoremove, fail_on_autoremove,
                    allow_unauthenticated)

        if packages:
            for package in packages:
                if package.count('=') > 1:
                    module.fail_json(msg="invalid package spec: %s" % package)
                if latest and '=' in package:
                    module.fail_json(
                        msg='version number inconsistent with state=latest: %s'
                        % package)

        if not packages:
            if autoclean:
                cleanup(module,
                        p['purge'],
                        force=force_yes,
                        operation='autoclean',
                        dpkg_options=dpkg_options)
            if autoremove:
                cleanup(module,
                        p['purge'],
                        force=force_yes,
                        operation='autoremove',
                        dpkg_options=dpkg_options)

        if p['state'] in ('latest', 'present', 'build-dep', 'fixed'):
            state_upgrade = False
            state_builddep = False
            state_fixed = False
            if p['state'] == 'latest':
                state_upgrade = True
            if p['state'] == 'build-dep':
                state_builddep = True
            if p['state'] == 'fixed':
                state_fixed = True

            success, retvals = install(
                module,
                packages,
                cache,
                upgrade=state_upgrade,
                default_release=p['default_release'],
                install_recommends=install_recommends,
                force=force_yes,
                dpkg_options=dpkg_options,
                build_dep=state_builddep,
                fixed=state_fixed,
                autoremove=autoremove,
                fail_on_autoremove=fail_on_autoremove,
                only_upgrade=p['only_upgrade'],
                allow_unauthenticated=allow_unauthenticated)

            # Store if the cache has been updated
            retvals['cache_updated'] = updated_cache
            # Store when the update time was last
            retvals['cache_update_time'] = updated_cache_time

            if success:
                module.exit_json(**retvals)
            else:
                module.fail_json(**retvals)
        elif p['state'] == 'absent':
            remove(module,
                   packages,
                   cache,
                   p['purge'],
                   force=force_yes,
                   dpkg_options=dpkg_options,
                   autoremove=autoremove)

    except apt.cache.LockFailedException as lockFailedException:
        module.fail_json(msg="Failed to lock apt for exclusive operation: %s" %
                         lockFailedException)
    except apt.cache.FetchFailedException as fetchFailedException:
        module.fail_json(msg="Could not fetch updated apt files: %s" %
                         fetchFailedException)
Example #11
0
def main():
    module = AssibleModule(
        argument_spec=dict(
            path=dict(type='path', required=True, aliases=['dest', 'name']),
            follow=dict(type='bool', default=False),
            get_md5=dict(type='bool', default=False),
            get_checksum=dict(type='bool', default=True),
            get_mime=dict(type='bool',
                          default=True,
                          aliases=['mime', 'mime_type', 'mime-type']),
            get_attributes=dict(type='bool',
                                default=True,
                                aliases=['attr', 'attributes']),
            checksum_algorithm=dict(type='str',
                                    default='sha1',
                                    choices=[
                                        'md5', 'sha1', 'sha224', 'sha256',
                                        'sha384', 'sha512'
                                    ],
                                    aliases=['checksum', 'checksum_algo']),
        ),
        supports_check_mode=True,
    )

    path = module.params.get('path')
    b_path = to_bytes(path, errors='surrogate_or_strict')
    follow = module.params.get('follow')
    get_mime = module.params.get('get_mime')
    get_attr = module.params.get('get_attributes')
    get_checksum = module.params.get('get_checksum')
    checksum_algorithm = module.params.get('checksum_algorithm')

    # NOTE: undocumented option since 2.9 to be removed at a later date if possible (3.0+)
    # no real reason for keeping other than fear we may break older content.
    get_md5 = module.params.get('get_md5')

    # main stat data
    try:
        if follow:
            st = os.stat(b_path)
        else:
            st = os.lstat(b_path)
    except OSError as e:
        if e.errno == errno.ENOENT:
            output = {'exists': False}
            module.exit_json(changed=False, stat=output)

        module.fail_json(msg=e.strerror)

    # process base results
    output = format_output(module, path, st)

    # resolved permissions
    for perm in [('readable', os.R_OK), ('writeable', os.W_OK),
                 ('executable', os.X_OK)]:
        output[perm[0]] = os.access(b_path, perm[1])

    # symlink info
    if output.get('islnk'):
        output['lnk_source'] = os.path.realpath(b_path)
        output['lnk_target'] = os.readlink(b_path)

    try:  # user data
        pw = pwd.getpwuid(st.st_uid)
        output['pw_name'] = pw.pw_name
    except (TypeError, KeyError):
        pass

    try:  # group data
        grp_info = grp.getgrgid(st.st_gid)
        output['gr_name'] = grp_info.gr_name
    except (KeyError, ValueError, OverflowError):
        pass

    # checksums
    if output.get('isreg') and output.get('readable'):

        # NOTE: see above about get_md5
        if get_md5:
            # Will fail on FIPS-140 compliant systems
            try:
                output['md5'] = module.md5(b_path)
            except ValueError:
                output['md5'] = None

        if get_checksum:
            output['checksum'] = module.digest_from_file(
                b_path, checksum_algorithm)

    # try to get mime data if requested
    if get_mime:
        output['mimetype'] = output['charset'] = 'unknown'
        mimecmd = module.get_bin_path('file')
        if mimecmd:
            mimecmd = [mimecmd, '--mime-type', '--mime-encoding', b_path]
            try:
                rc, out, err = module.run_command(mimecmd)
                if rc == 0:
                    mimetype, charset = out.rsplit(':', 1)[1].split(';')
                    output['mimetype'] = mimetype.strip()
                    output['charset'] = charset.split('=')[1].strip()
            except Exception:
                pass

    # try to get attr data
    if get_attr:
        output['version'] = None
        output['attributes'] = []
        output['attr_flags'] = ''
        out = module.get_file_attributes(b_path)
        for x in ('version', 'attributes', 'attr_flags'):
            if x in out:
                output[x] = out[x]

    module.exit_json(changed=False, stat=output)