コード例 #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)
コード例 #2
0
ファイル: getent.py プロジェクト: katiestar99/ansible
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)
コード例 #3
0
ファイル: assemble.py プロジェクト: katiestar99/ansible
def main():

    module = AssibleModule(
        # not checking because of daisy chain to file module
        argument_spec=dict(
            src=dict(type='path', required=True),
            delimiter=dict(type='str'),
            dest=dict(type='path', required=True),
            backup=dict(type='bool', default=False),
            remote_src=dict(type='bool', default=True),
            regexp=dict(type='str'),
            ignore_hidden=dict(type='bool', default=False),
            validate=dict(type='str'),
        ),
        add_file_common_args=True,
    )

    changed = False
    path_hash = None
    dest_hash = None
    src = module.params['src']
    dest = module.params['dest']
    backup = module.params['backup']
    delimiter = module.params['delimiter']
    regexp = module.params['regexp']
    compiled_regexp = None
    ignore_hidden = module.params['ignore_hidden']
    validate = module.params.get('validate', None)

    result = dict(src=src, dest=dest)
    if not os.path.exists(src):
        module.fail_json(msg="Source (%s) does not exist" % src)

    if not os.path.isdir(src):
        module.fail_json(msg="Source (%s) is not a directory" % src)

    if regexp is not None:
        try:
            compiled_regexp = re.compile(regexp)
        except re.error as e:
            module.fail_json(msg="Invalid Regexp (%s) in \"%s\"" %
                             (to_native(e), regexp))

    if validate and "%s" not in validate:
        module.fail_json(msg="validate must contain %%s: %s" % validate)

    path = assemble_from_fragments(src, delimiter, compiled_regexp,
                                   ignore_hidden, module.tmpdir)
    path_hash = module.sha1(path)
    result['checksum'] = path_hash

    # Backwards compat.  This won't return data if FIPS mode is active
    try:
        pathmd5 = module.md5(path)
    except ValueError:
        pathmd5 = None
    result['md5sum'] = pathmd5

    if os.path.exists(dest):
        dest_hash = module.sha1(dest)

    if path_hash != dest_hash:
        if validate:
            (rc, out, err) = module.run_command(validate % path)
            result['validation'] = dict(rc=rc, stdout=out, stderr=err)
            if rc != 0:
                cleanup(path)
                module.fail_json(msg="failed to validate: rc:%s error:%s" %
                                 (rc, err))
        if backup and dest_hash is not None:
            result['backup_file'] = module.backup_local(dest)

        module.atomic_move(path,
                           dest,
                           unsafe_writes=module.params['unsafe_writes'])
        changed = True

    cleanup(path, result)

    # handle file permissions
    file_args = module.load_file_common_arguments(module.params)
    result['changed'] = module.set_fs_attributes_if_different(
        file_args, changed)

    # Mission complete
    result['msg'] = "OK"
    module.exit_json(**result)
コード例 #4
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)
コード例 #5
0
def main():
    state_map = dict(
        present=['install'],
        absent=['uninstall', '-y'],
        latest=['install', '-U'],
        forcereinstall=['install', '-U', '--force-reinstall'],
    )

    module = AssibleModule(
        argument_spec=dict(
            state=dict(type='str', default='present', choices=state_map.keys()),
            name=dict(type='list', elements='str'),
            version=dict(type='str'),
            requirements=dict(type='str'),
            virtualenv=dict(type='path'),
            virtualenv_site_packages=dict(type='bool', default=False),
            virtualenv_command=dict(type='path', default='virtualenv'),
            virtualenv_python=dict(type='str'),
            extra_args=dict(type='str'),
            editable=dict(type='bool', default=False),
            chdir=dict(type='path'),
            executable=dict(type='path'),
            umask=dict(type='str'),
        ),
        required_one_of=[['name', 'requirements']],
        mutually_exclusive=[['name', 'requirements'], ['executable', 'virtualenv']],
        supports_check_mode=True,
    )

    if not HAS_SETUPTOOLS:
        module.fail_json(msg=missing_required_lib("setuptools"),
                         exception=SETUPTOOLS_IMP_ERR)

    state = module.params['state']
    name = module.params['name']
    version = module.params['version']
    requirements = module.params['requirements']
    extra_args = module.params['extra_args']
    chdir = module.params['chdir']
    umask = module.params['umask']
    env = module.params['virtualenv']

    venv_created = False
    if env and chdir:
        env = os.path.join(chdir, env)

    if umask and not isinstance(umask, int):
        try:
            umask = int(umask, 8)
        except Exception:
            module.fail_json(msg="umask must be an octal integer",
                             details=to_native(sys.exc_info()[1]))

    old_umask = None
    if umask is not None:
        old_umask = os.umask(umask)
    try:
        if state == 'latest' and version is not None:
            module.fail_json(msg='version is incompatible with state=latest')

        if chdir is None:
            # this is done to avoid permissions issues with privilege escalation and virtualenvs
            chdir = tempfile.gettempdir()

        err = ''
        out = ''

        if env:
            if not os.path.exists(os.path.join(env, 'bin', 'activate')):
                venv_created = True
                out, err = setup_virtualenv(module, env, chdir, out, err)

        pip = _get_pip(module, env, module.params['executable'])

        cmd = [pip] + state_map[state]

        # If there's a virtualenv we want things we install to be able to use other
        # installations that exist as binaries within this virtualenv. Example: we
        # install cython and then gevent -- gevent needs to use the cython binary,
        # not just a python package that will be found by calling the right python.
        # So if there's a virtualenv, we add that bin/ to the beginning of the PATH
        # in run_command by setting path_prefix here.
        path_prefix = None
        if env:
            path_prefix = "/".join(pip.split('/')[:-1])

        # Automatically apply -e option to extra_args when source is a VCS url. VCS
        # includes those beginning with svn+, git+, hg+ or bzr+
        has_vcs = False
        if name:
            for pkg in name:
                if pkg and _is_vcs_url(pkg):
                    has_vcs = True
                    break

            # convert raw input package names to Package instances
            packages = [Package(pkg) for pkg in _recover_package_name(name)]
            # check invalid combination of arguments
            if version is not None:
                if len(packages) > 1:
                    module.fail_json(
                        msg="'version' argument is ambiguous when installing multiple package distributions. "
                            "Please specify version restrictions next to each package in 'name' argument."
                    )
                if packages[0].has_version_specifier:
                    module.fail_json(
                        msg="The 'version' argument conflicts with any version specifier provided along with a package name. "
                            "Please keep the version specifier, but remove the 'version' argument."
                    )
                # if the version specifier is provided by version, append that into the package
                packages[0] = Package(to_native(packages[0]), version)

        if module.params['editable']:
            args_list = []  # used if extra_args is not used at all
            if extra_args:
                args_list = extra_args.split(' ')
            if '-e' not in args_list:
                args_list.append('-e')
                # Ok, we will reconstruct the option string
                extra_args = ' '.join(args_list)

        if extra_args:
            cmd.extend(shlex.split(extra_args))

        if name:
            cmd.extend(to_native(p) for p in packages)
        elif requirements:
            cmd.extend(['-r', requirements])
        else:
            module.exit_json(
                changed=False,
                warnings=["No valid name or requirements file found."],
            )

        if module.check_mode:
            if extra_args or requirements or state == 'latest' or not name:
                module.exit_json(changed=True)

            pkg_cmd, out_pip, err_pip = _get_packages(module, pip, chdir)

            out += out_pip
            err += err_pip

            changed = False
            if name:
                pkg_list = [p for p in out.split('\n') if not p.startswith('You are using') and not p.startswith('You should consider') and p]

                if pkg_cmd.endswith(' freeze') and ('pip' in name or 'setuptools' in name):
                    # Older versions of pip (pre-1.3) do not have pip list.
                    # pip freeze does not list setuptools or pip in its output
                    # So we need to get those via a specialcase
                    for pkg in ('setuptools', 'pip'):
                        if pkg in name:
                            formatted_dep = _get_package_info(module, pkg, env)
                            if formatted_dep is not None:
                                pkg_list.append(formatted_dep)
                                out += '%s\n' % formatted_dep

                for package in packages:
                    is_present = _is_present(module, package, pkg_list, pkg_cmd)
                    if (state == 'present' and not is_present) or (state == 'absent' and is_present):
                        changed = True
                        break
            module.exit_json(changed=changed, cmd=pkg_cmd, stdout=out, stderr=err)

        out_freeze_before = None
        if requirements or has_vcs:
            _, out_freeze_before, _ = _get_packages(module, pip, chdir)

        rc, out_pip, err_pip = module.run_command(cmd, path_prefix=path_prefix, cwd=chdir)
        out += out_pip
        err += err_pip
        if rc == 1 and state == 'absent' and \
           ('not installed' in out_pip or 'not installed' in err_pip):
            pass  # rc is 1 when attempting to uninstall non-installed package
        elif rc != 0:
            _fail(module, cmd, out, err)

        if state == 'absent':
            changed = 'Successfully uninstalled' in out_pip
        else:
            if out_freeze_before is None:
                changed = 'Successfully installed' in out_pip
            else:
                _, out_freeze_after, _ = _get_packages(module, pip, chdir)
                changed = out_freeze_before != out_freeze_after

        changed = changed or venv_created

        module.exit_json(changed=changed, cmd=cmd, name=name, version=version,
                         state=state, requirements=requirements, virtualenv=env,
                         stdout=out, stderr=err)
    finally:
        if old_umask is not None:
            os.umask(old_umask)
コード例 #6
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)
コード例 #7
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)
コード例 #8
0
ファイル: command.py プロジェクト: katiestar99/ansible
def main():

    # the command module is the one assible module that does not take key=value args
    # hence don't copy this one if you are looking to build others!
    module = AssibleModule(
        argument_spec=dict(
            _raw_params=dict(),
            _uses_shell=dict(type='bool', default=False),
            argv=dict(type='list', elements='str'),
            chdir=dict(type='path'),
            executable=dict(),
            creates=dict(type='path'),
            removes=dict(type='path'),
            # The default for this really comes from the action plugin
            warn=dict(type='bool', default=False, removed_in_version='2.14', removed_from_collection='assible.builtin'),
            stdin=dict(required=False),
            stdin_add_newline=dict(type='bool', default=True),
            strip_empty_ends=dict(type='bool', default=True),
        ),
        supports_check_mode=True,
    )
    shell = module.params['_uses_shell']
    chdir = module.params['chdir']
    executable = module.params['executable']
    args = module.params['_raw_params']
    argv = module.params['argv']
    creates = module.params['creates']
    removes = module.params['removes']
    warn = module.params['warn']
    stdin = module.params['stdin']
    stdin_add_newline = module.params['stdin_add_newline']
    strip = module.params['strip_empty_ends']

    if not shell and executable:
        module.warn("As of Assible 2.4, the parameter 'executable' is no longer supported with the 'command' module. Not using '%s'." % executable)
        executable = None

    if (not args or args.strip() == '') and not argv:
        module.fail_json(rc=256, msg="no command given")

    if args and argv:
        module.fail_json(rc=256, msg="only command or argv can be given, not both")

    if not shell and args:
        args = shlex.split(args)

    args = args or argv

    # All args must be strings
    if is_iterable(args, include_strings=False):
        args = [to_native(arg, errors='surrogate_or_strict', nonstring='simplerepr') for arg in args]

    if chdir:
        try:
            chdir = to_bytes(os.path.abspath(chdir), errors='surrogate_or_strict')
        except ValueError as e:
            module.fail_json(msg='Unable to use supplied chdir: %s' % to_text(e))

        try:
            os.chdir(chdir)
        except (IOError, OSError) as e:
            module.fail_json(msg='Unable to change directory before execution: %s' % to_text(e))

    if creates:
        # do not run the command if the line contains creates=filename
        # and the filename already exists.  This allows idempotence
        # of command executions.
        if glob.glob(creates):
            module.exit_json(
                cmd=args,
                stdout="skipped, since %s exists" % creates,
                changed=False,
                rc=0
            )

    if removes:
        # do not run the command if the line contains removes=filename
        # and the filename does not exist.  This allows idempotence
        # of command executions.
        if not glob.glob(removes):
            module.exit_json(
                cmd=args,
                stdout="skipped, since %s does not exist" % removes,
                changed=False,
                rc=0
            )

    if warn:
        check_command(module, args)

    startd = datetime.datetime.now()

    if not module.check_mode:
        rc, out, err = module.run_command(args, executable=executable, use_unsafe_shell=shell, encoding=None, data=stdin, binary_data=(not stdin_add_newline))
    elif creates or removes:
        rc = 0
        out = err = b'Command would have run if not in check mode'
    else:
        module.exit_json(msg="skipped, running in check mode", skipped=True)

    endd = datetime.datetime.now()
    delta = endd - startd

    if strip:
        out = out.rstrip(b"\r\n")
        err = err.rstrip(b"\r\n")

    result = dict(
        cmd=args,
        stdout=out,
        stderr=err,
        rc=rc,
        start=str(startd),
        end=str(endd),
        delta=str(delta),
        changed=True,
    )

    if rc != 0:
        module.fail_json(msg='non-zero return code', **result)

    module.exit_json(**result)
コード例 #9
0
def main():

    global module

    module = AssibleModule(
        # not checking because of daisy chain to file module
        argument_spec=dict(
            src=dict(type='path'),
            _original_basename=dict(
                type='str'
            ),  # used to handle 'dest is a directory' via template, a slight hack
            content=dict(type='str', no_log=True),
            dest=dict(type='path', required=True),
            backup=dict(type='bool', default=False),
            force=dict(type='bool', default=True, aliases=['thirsty']),
            validate=dict(type='str'),
            directory_mode=dict(type='raw'),
            remote_src=dict(type='bool'),
            local_follow=dict(type='bool'),
            checksum=dict(type='str'),
            follow=dict(type='bool', default=False),
        ),
        add_file_common_args=True,
        supports_check_mode=True,
    )

    if module.params.get('thirsty'):
        module.deprecate(
            'The alias "thirsty" has been deprecated and will be removed, use "force" instead',
            version='2.13',
            collection_name='assible.builtin')

    src = module.params['src']
    b_src = to_bytes(src, errors='surrogate_or_strict')
    dest = module.params['dest']
    # Make sure we always have a directory component for later processing
    if os.path.sep not in dest:
        dest = '.{0}{1}'.format(os.path.sep, dest)
    b_dest = to_bytes(dest, errors='surrogate_or_strict')
    backup = module.params['backup']
    force = module.params['force']
    _original_basename = module.params.get('_original_basename', None)
    validate = module.params.get('validate', None)
    follow = module.params['follow']
    local_follow = module.params['local_follow']
    mode = module.params['mode']
    owner = module.params['owner']
    group = module.params['group']
    remote_src = module.params['remote_src']
    checksum = module.params['checksum']

    if not os.path.exists(b_src):
        module.fail_json(msg="Source %s not found" % (src))
    if not os.access(b_src, os.R_OK):
        module.fail_json(msg="Source %s not readable" % (src))

    # Preserve is usually handled in the action plugin but mode + remote_src has to be done on the
    # remote host
    if module.params['mode'] == 'preserve':
        module.params['mode'] = '0%03o' % stat.S_IMODE(os.stat(b_src).st_mode)
    mode = module.params['mode']

    checksum_dest = None

    if os.path.isfile(src):
        checksum_src = module.sha1(src)
    else:
        checksum_src = None

    # Backwards compat only.  This will be None in FIPS mode
    try:
        if os.path.isfile(src):
            md5sum_src = module.md5(src)
        else:
            md5sum_src = None
    except ValueError:
        md5sum_src = None

    changed = False

    if checksum and checksum_src != checksum:
        module.fail_json(
            msg=
            'Copied file does not match the expected checksum. Transfer failed.',
            checksum=checksum_src,
            expected_checksum=checksum)

    # Special handling for recursive copy - create intermediate dirs
    if dest.endswith(os.sep):
        if _original_basename:
            dest = os.path.join(dest, _original_basename)
        b_dest = to_bytes(dest, errors='surrogate_or_strict')
        dirname = os.path.dirname(dest)
        b_dirname = to_bytes(dirname, errors='surrogate_or_strict')
        if not os.path.exists(b_dirname):
            try:
                (pre_existing_dir,
                 new_directory_list) = split_pre_existing_dir(dirname)
            except AssibleModuleError as e:
                e.result['msg'] += ' Could not copy to {0}'.format(dest)
                module.fail_json(**e.results)

            os.makedirs(b_dirname)
            directory_args = module.load_file_common_arguments(module.params)
            directory_mode = module.params["directory_mode"]
            if directory_mode is not None:
                directory_args['mode'] = directory_mode
            else:
                directory_args['mode'] = None
            adjust_recursive_directory_permissions(pre_existing_dir,
                                                   new_directory_list, module,
                                                   directory_args, changed)

    if os.path.isdir(b_dest):
        basename = os.path.basename(src)
        if _original_basename:
            basename = _original_basename
        dest = os.path.join(dest, basename)
        b_dest = to_bytes(dest, errors='surrogate_or_strict')

    if os.path.exists(b_dest):
        if os.path.islink(b_dest) and follow:
            b_dest = os.path.realpath(b_dest)
            dest = to_native(b_dest, errors='surrogate_or_strict')
        if not force:
            module.exit_json(msg="file already exists",
                             src=src,
                             dest=dest,
                             changed=False)
        if os.access(b_dest, os.R_OK) and os.path.isfile(b_dest):
            checksum_dest = module.sha1(dest)
    else:
        if not os.path.exists(os.path.dirname(b_dest)):
            try:
                # os.path.exists() can return false in some
                # circumstances where the directory does not have
                # the execute bit for the current user set, in
                # which case the stat() call will raise an OSError
                os.stat(os.path.dirname(b_dest))
            except OSError as e:
                if "permission denied" in to_native(e).lower():
                    module.fail_json(
                        msg="Destination directory %s is not accessible" %
                        (os.path.dirname(dest)))
            module.fail_json(msg="Destination directory %s does not exist" %
                             (os.path.dirname(dest)))

    if not os.access(os.path.dirname(b_dest),
                     os.W_OK) and not module.params['unsafe_writes']:
        module.fail_json(msg="Destination %s not writable" %
                         (os.path.dirname(dest)))

    backup_file = None
    if checksum_src != checksum_dest or os.path.islink(b_dest):
        if not module.check_mode:
            try:
                if backup:
                    if os.path.exists(b_dest):
                        backup_file = module.backup_local(dest)
                # allow for conversion from symlink.
                if os.path.islink(b_dest):
                    os.unlink(b_dest)
                    open(b_dest, 'w').close()
                if validate:
                    # if we have a mode, make sure we set it on the temporary
                    # file source as some validations may require it
                    if mode is not None:
                        module.set_mode_if_different(src, mode, False)
                    if owner is not None:
                        module.set_owner_if_different(src, owner, False)
                    if group is not None:
                        module.set_group_if_different(src, group, False)
                    if "%s" not in validate:
                        module.fail_json(msg="validate must contain %%s: %s" %
                                         (validate))
                    (rc, out, err) = module.run_command(validate % src)
                    if rc != 0:
                        module.fail_json(msg="failed to validate",
                                         exit_status=rc,
                                         stdout=out,
                                         stderr=err)
                b_mysrc = b_src
                if remote_src and os.path.isfile(b_src):
                    _, b_mysrc = tempfile.mkstemp(dir=os.path.dirname(b_dest))

                    shutil.copyfile(b_src, b_mysrc)
                    try:
                        shutil.copystat(b_src, b_mysrc)
                    except OSError as err:
                        if err.errno == errno.ENOSYS and mode == "preserve":
                            module.warn("Unable to copy stats {0}".format(
                                to_native(b_src)))
                        else:
                            raise

                # might be needed below
                if PY3 and hasattr(os, 'listxattr'):
                    try:
                        src_has_acls = 'system.posix_acl_access' in os.listxattr(
                            src)
                    except Exception as e:
                        # assume unwanted ACLs by default
                        src_has_acls = True

                module.atomic_move(
                    b_mysrc,
                    dest,
                    unsafe_writes=module.params['unsafe_writes'])

                if PY3 and hasattr(os, 'listxattr') and platform.system(
                ) == 'Linux' and not remote_src:
                    # atomic_move used above to copy src into dest might, in some cases,
                    # use shutil.copy2 which in turn uses shutil.copystat.
                    # Since Python 3.3, shutil.copystat copies file extended attributes:
                    # https://docs.python.org/3/library/shutil.html#shutil.copystat
                    # os.listxattr (along with others) was added to handle the operation.

                    # This means that on Python 3 we are copying the extended attributes which includes
                    # the ACLs on some systems - further limited to Linux as the documentation above claims
                    # that the extended attributes are copied only on Linux. Also, os.listxattr is only
                    # available on Linux.

                    # If not remote_src, then the file was copied from the controller. In that
                    # case, any filesystem ACLs are artifacts of the copy rather than preservation
                    # of existing attributes. Get rid of them:

                    if src_has_acls:
                        # FIXME If dest has any default ACLs, there are not applied to src now because
                        # they were overridden by copystat. Should/can we do anything about this?
                        # 'system.posix_acl_default' in os.listxattr(os.path.dirname(b_dest))

                        try:
                            clear_facls(dest)
                        except ValueError as e:
                            if 'setfacl' in to_native(e):
                                # No setfacl so we're okay.  The controller couldn't have set a facl
                                # without the setfacl command
                                pass
                            else:
                                raise
                        except RuntimeError as e:
                            # setfacl failed.
                            if 'Operation not supported' in to_native(e):
                                # The file system does not support ACLs.
                                pass
                            else:
                                raise

            except (IOError, OSError):
                module.fail_json(msg="failed to copy: %s to %s" % (src, dest),
                                 traceback=traceback.format_exc())
        changed = True
    else:
        changed = False

    # If neither have checksums, both src and dest are directories.
    if checksum_src is None and checksum_dest is None:
        if remote_src and os.path.isdir(module.params['src']):
            b_src = to_bytes(module.params['src'],
                             errors='surrogate_or_strict')
            b_dest = to_bytes(module.params['dest'],
                              errors='surrogate_or_strict')

            if src.endswith(os.path.sep) and os.path.isdir(
                    module.params['dest']):
                diff_files_changed = copy_diff_files(b_src, b_dest, module)
                left_only_changed = copy_left_only(b_src, b_dest, module)
                common_dirs_changed = copy_common_dirs(b_src, b_dest, module)
                owner_group_changed = chown_recursive(b_dest, module)
                if diff_files_changed or left_only_changed or common_dirs_changed or owner_group_changed:
                    changed = True

            if src.endswith(
                    os.path.sep) and not os.path.exists(module.params['dest']):
                b_basename = to_bytes(os.path.basename(src),
                                      errors='surrogate_or_strict')
                b_dest = to_bytes(os.path.join(b_dest, b_basename),
                                  errors='surrogate_or_strict')
                b_src = to_bytes(os.path.join(module.params['src'], ""),
                                 errors='surrogate_or_strict')
                if not module.check_mode:
                    shutil.copytree(b_src, b_dest, symlinks=not (local_follow))
                chown_recursive(dest, module)
                changed = True

            if not src.endswith(os.path.sep) and os.path.isdir(
                    module.params['dest']):
                b_basename = to_bytes(os.path.basename(src),
                                      errors='surrogate_or_strict')
                b_dest = to_bytes(os.path.join(b_dest, b_basename),
                                  errors='surrogate_or_strict')
                b_src = to_bytes(os.path.join(module.params['src'], ""),
                                 errors='surrogate_or_strict')
                if not module.check_mode and not os.path.exists(b_dest):
                    shutil.copytree(b_src, b_dest, symlinks=not (local_follow))
                    changed = True
                    chown_recursive(dest, module)
                if module.check_mode and not os.path.exists(b_dest):
                    changed = True
                if os.path.exists(b_dest):
                    diff_files_changed = copy_diff_files(b_src, b_dest, module)
                    left_only_changed = copy_left_only(b_src, b_dest, module)
                    common_dirs_changed = copy_common_dirs(
                        b_src, b_dest, module)
                    owner_group_changed = chown_recursive(b_dest, module)
                    if diff_files_changed or left_only_changed or common_dirs_changed or owner_group_changed:
                        changed = True

            if not src.endswith(os.path.sep) and not os.path.exists(
                    module.params['dest']):
                b_basename = to_bytes(os.path.basename(module.params['src']),
                                      errors='surrogate_or_strict')
                b_dest = to_bytes(os.path.join(b_dest, b_basename),
                                  errors='surrogate_or_strict')
                if not module.check_mode and not os.path.exists(b_dest):
                    os.makedirs(b_dest)
                    b_src = to_bytes(os.path.join(module.params['src'], ""),
                                     errors='surrogate_or_strict')
                    diff_files_changed = copy_diff_files(b_src, b_dest, module)
                    left_only_changed = copy_left_only(b_src, b_dest, module)
                    common_dirs_changed = copy_common_dirs(
                        b_src, b_dest, module)
                    owner_group_changed = chown_recursive(b_dest, module)
                    if diff_files_changed or left_only_changed or common_dirs_changed or owner_group_changed:
                        changed = True
                if module.check_mode and not os.path.exists(b_dest):
                    changed = True

    res_args = dict(dest=dest,
                    src=src,
                    md5sum=md5sum_src,
                    checksum=checksum_src,
                    changed=changed)
    if backup_file:
        res_args['backup_file'] = backup_file

    if not module.check_mode:
        file_args = module.load_file_common_arguments(module.params, path=dest)
        res_args['changed'] = module.set_fs_attributes_if_different(
            file_args, res_args['changed'])

    module.exit_json(**res_args)
コード例 #10
0
ファイル: apt.py プロジェクト: katiestar99/ansible
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)
コード例 #11
0
def run_module():
    module_args = dict(
        server=dict(type='str', required=True),
        token=dict(type='str'),
        collections=dict(
            type='list',
            elements='dict',
            required=True,
            options=dict(
                namespace=dict(type='str', required=True),
                name=dict(type='str', required=True),
                version=dict(type='str', default='1.0.0'),
                dependencies=dict(type='dict', default={}),
                use_symlink=dict(type='bool', default=False),
            ),
        ),
    )

    module = AssibleModule(argument_spec=module_args,
                           supports_check_mode=False)

    result = dict(changed=True, results=[])

    for idx, collection in enumerate(module.params['collections']):
        collection_dir = os.path.join(
            module.tmpdir,
            "%s-%s-%s" % (collection['namespace'], collection['name'],
                          collection['version']))
        b_collection_dir = to_bytes(collection_dir,
                                    errors='surrogate_or_strict')
        os.mkdir(b_collection_dir)

        with open(os.path.join(b_collection_dir, b'README.md'),
                  mode='wb') as fd:
            fd.write(b"Collection readme")

        galaxy_meta = {
            'namespace': collection['namespace'],
            'name': collection['name'],
            'version': collection['version'],
            'readme': 'README.md',
            'authors': ['Collection author <*****@*****.**'],
            'dependencies': collection['dependencies'],
            'license': ['GPL-3.0-or-later'],
        }
        with open(os.path.join(b_collection_dir, b'galaxy.yml'),
                  mode='wb') as fd:
            fd.write(
                to_bytes(yaml.safe_dump(galaxy_meta),
                         errors='surrogate_or_strict'))

        with tempfile.NamedTemporaryFile(mode='wb') as temp_fd:
            temp_fd.write(b"data")

            if collection['use_symlink']:
                os.mkdir(os.path.join(b_collection_dir, b'docs'))
                os.mkdir(os.path.join(b_collection_dir, b'plugins'))
                b_target_file = b'RE\xc3\x85DM\xc3\x88.md'
                with open(os.path.join(b_collection_dir, b_target_file),
                          mode='wb') as fd:
                    fd.write(b'data')

                os.symlink(
                    b_target_file,
                    os.path.join(b_collection_dir, b_target_file + b'-link'))
                os.symlink(
                    temp_fd.name,
                    os.path.join(b_collection_dir,
                                 b_target_file + b'-outside-link'))
                os.symlink(
                    os.path.join(b'..', b_target_file),
                    os.path.join(b_collection_dir, b'docs', b_target_file))
                os.symlink(
                    os.path.join(b_collection_dir, b_target_file),
                    os.path.join(b_collection_dir, b'plugins', b_target_file))
                os.symlink(b'docs', os.path.join(b_collection_dir,
                                                 b'docs-link'))

            release_filename = '%s-%s-%s.tar.gz' % (collection['namespace'],
                                                    collection['name'],
                                                    collection['version'])
            collection_path = os.path.join(collection_dir, release_filename)
            rc, stdout, stderr = module.run_command(
                ['assible-galaxy', 'collection', 'build'], cwd=collection_dir)
            result['results'].append(
                {'build': {
                    'rc': rc,
                    'stdout': stdout,
                    'stderr': stderr,
                }})

        # To save on time, skip the import wait until the last collection is being uploaded.
        publish_args = [
            'assible-galaxy', 'collection', 'publish', collection_path,
            '--server', module.params['server']
        ]
        if module.params['token']:
            publish_args.extend(['--token', module.params['token']])
        if idx != (len(module.params['collections']) - 1):
            publish_args.append('--no-wait')
        rc, stdout, stderr = module.run_command(publish_args)
        result['results'][-1]['publish'] = {
            'rc': rc,
            'stdout': stdout,
            'stderr': stderr,
        }

    failed = bool(
        sum(r['build']['rc'] + r['publish']['rc'] for r in result['results']))

    module.exit_json(failed=failed, **result)
コード例 #12
0
ファイル: stat.py プロジェクト: katiestar99/ansible
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)