예제 #1
0
def main():
    argument_spec = rax_argument_spec()
    argument_spec.update(
        dict(state=dict(default='present', choices=['present', 'absent']),
             label=dict(required=True),
             entity_id=dict(required=True),
             check_id=dict(required=True),
             notification_plan_id=dict(required=True),
             criteria=dict(),
             disabled=dict(type='bool', default=False),
             metadata=dict(type='dict')))

    module = AnsibleModule(argument_spec=argument_spec,
                           required_together=rax_required_together())

    if not HAS_PYRAX:
        module.fail_json(msg='pyrax is required for this module')

    state = module.params.get('state')
    label = module.params.get('label')
    entity_id = module.params.get('entity_id')
    check_id = module.params.get('check_id')
    notification_plan_id = module.params.get('notification_plan_id')
    criteria = module.params.get('criteria')
    disabled = module.boolean(module.params.get('disabled'))
    metadata = module.params.get('metadata')

    setup_rax_module(module, pyrax)

    alarm(module, state, label, entity_id, check_id, notification_plan_id,
          criteria, disabled, metadata)
def main():
    argument_spec = rax_argument_spec()
    argument_spec.update(
        dict(loadbalancer=dict(required=True),
             state=dict(default='present', choices=['present', 'absent']),
             enabled=dict(type='bool', default=True),
             private_key=dict(),
             certificate=dict(),
             intermediate_certificate=dict(),
             secure_port=dict(type='int', default=443),
             secure_traffic_only=dict(type='bool', default=False),
             https_redirect=dict(type='bool'),
             wait=dict(type='bool', default=False),
             wait_timeout=dict(type='int', default=300)))

    module = AnsibleModule(
        argument_spec=argument_spec,
        required_together=rax_required_together(),
    )

    if not HAS_PYRAX:
        module.fail_json(msg='pyrax is required for this module.')

    loadbalancer = module.params.get('loadbalancer')
    state = module.params.get('state')
    enabled = module.boolean(module.params.get('enabled'))
    private_key = module.params.get('private_key')
    certificate = module.params.get('certificate')
    intermediate_certificate = module.params.get('intermediate_certificate')
    secure_port = module.params.get('secure_port')
    secure_traffic_only = module.boolean(
        module.params.get('secure_traffic_only'))
    https_redirect = module.boolean(module.params.get('https_redirect'))
    wait = module.boolean(module.params.get('wait'))
    wait_timeout = module.params.get('wait_timeout')

    setup_rax_module(module, pyrax)

    cloud_load_balancer_ssl(module, loadbalancer, state, enabled, private_key,
                            certificate, intermediate_certificate, secure_port,
                            secure_traffic_only, https_redirect, wait,
                            wait_timeout)
예제 #3
0
def main():
    arg_spec = dict(
        name=dict(default=None, required=False, aliases=['pkg']),
        from_path=dict(default=None, required=False, type='path'),
        notest=dict(default=False, type='bool'),
        locallib=dict(default=None, required=False, type='path'),
        mirror=dict(default=None, required=False),
        mirror_only=dict(default=False, type='bool'),
        installdeps=dict(default=False, type='bool'),
        system_lib=dict(default=False, type='bool', aliases=['use_sudo']),
        version=dict(default=None, required=False),
        executable=dict(required=False, type='path'),
    )

    module = AnsibleModule(
        argument_spec=arg_spec,
        required_one_of=[['name', 'from_path']],
    )

    cpanm = _get_cpanm_path(module)
    name = module.params['name']
    from_path = module.params['from_path']
    notest = module.boolean(module.params.get('notest', False))
    locallib = module.params['locallib']
    mirror = module.params['mirror']
    mirror_only = module.params['mirror_only']
    installdeps = module.params['installdeps']
    use_sudo = module.params['system_lib']
    version = module.params['version']

    changed = False

    installed = _is_package_installed(module, name, locallib, cpanm, version)

    if not installed:
        cmd = _build_cmd_line(name, from_path, notest, locallib, mirror,
                              mirror_only, installdeps, cpanm, use_sudo)

        rc_cpanm, out_cpanm, err_cpanm = module.run_command(cmd,
                                                            check_rc=False)

        if rc_cpanm != 0:
            module.fail_json(msg=err_cpanm, cmd=cmd)

        if (err_cpanm.find('is up to date') == -1
                and out_cpanm.find('is up to date') == -1):
            changed = True

    module.exit_json(changed=changed, binary=cpanm, name=name)
예제 #4
0
def main():
    argument_spec = rax_argument_spec()
    argument_spec.update(
        dict(entity_id=dict(required=True),
             label=dict(required=True),
             check_type=dict(required=True),
             monitoring_zones_poll=dict(),
             target_hostname=dict(),
             target_alias=dict(),
             details=dict(type='dict', default={}),
             disabled=dict(type='bool', default=False),
             metadata=dict(type='dict', default={}),
             period=dict(type='int'),
             timeout=dict(type='int'),
             state=dict(default='present', choices=['present', 'absent'])))

    module = AnsibleModule(argument_spec=argument_spec,
                           required_together=rax_required_together())

    if not HAS_PYRAX:
        module.fail_json(msg='pyrax is required for this module')

    entity_id = module.params.get('entity_id')
    label = module.params.get('label')
    check_type = module.params.get('check_type')
    monitoring_zones_poll = module.params.get('monitoring_zones_poll')
    target_hostname = module.params.get('target_hostname')
    target_alias = module.params.get('target_alias')
    details = module.params.get('details')
    disabled = module.boolean(module.params.get('disabled'))
    metadata = module.params.get('metadata')
    period = module.params.get('period')
    timeout = module.params.get('timeout')

    state = module.params.get('state')

    setup_rax_module(module, pyrax)

    cloud_check(module, state, entity_id, label, check_type,
                monitoring_zones_poll, target_hostname, target_alias, details,
                disabled, metadata, period, timeout)
예제 #5
0
def main():
    # MAIN

    global module
    module = AnsibleModule(argument_spec=dict(
        name=dict(type='str', required=True, aliases=['volume']),
        state=dict(type='str',
                   required=True,
                   choices=['absent', 'started', 'stopped', 'present']),
        cluster=dict(type='list'),
        host=dict(type='str'),
        stripes=dict(type='int'),
        replicas=dict(type='int'),
        arbiters=dict(type='int'),
        disperses=dict(type='int'),
        redundancies=dict(type='int'),
        transport=dict(type='str',
                       default='tcp',
                       choices=['tcp', 'rdma', 'tcp,rdma']),
        bricks=dict(type='str', aliases=['brick']),
        start_on_create=dict(type='bool', default=True),
        rebalance=dict(type='bool', default=False),
        options=dict(type='dict', default={}),
        quota=dict(type='str'),
        directory=dict(type='str'),
        force=dict(type='bool', default=False),
    ), )

    global glusterbin
    glusterbin = module.get_bin_path('gluster', True)

    changed = False

    action = module.params['state']
    volume_name = module.params['name']
    cluster = module.params['cluster']
    brick_paths = module.params['bricks']
    stripes = module.params['stripes']
    replicas = module.params['replicas']
    arbiters = module.params['arbiters']
    disperses = module.params['disperses']
    redundancies = module.params['redundancies']
    transport = module.params['transport']
    myhostname = module.params['host']
    start_on_create = module.boolean(module.params['start_on_create'])
    rebalance = module.boolean(module.params['rebalance'])
    force = module.boolean(module.params['force'])

    if not myhostname:
        myhostname = socket.gethostname()

    # Clean up if last element is empty. Consider that yml can look like this:
    #   cluster="{% for host in groups['glusterfs'] %}{{ hostvars[host]['private_ip'] }},{% endfor %}"
    if cluster is not None and len(cluster) > 1 and cluster[-1] == '':
        cluster = cluster[0:-1]

    if cluster is None:
        cluster = []

    if brick_paths is not None and "," in brick_paths:
        brick_paths = brick_paths.split(",")
    else:
        brick_paths = [brick_paths]

    options = module.params['options']
    quota = module.params['quota']
    directory = module.params['directory']

    # get current state info
    peers = get_peers()
    volumes = get_volumes()
    quotas = {}
    if volume_name in volumes and volumes[volume_name]['quota'] and volumes[
            volume_name]['status'].lower() == 'started':
        quotas = get_quotas(volume_name, True)

    # do the work!
    if action == 'absent':
        if volume_name in volumes:
            if volumes[volume_name]['status'].lower() != 'stopped':
                stop_volume(volume_name)
            run_gluster(['volume', 'delete', volume_name])
            changed = True

    if action == 'present':
        probe_all_peers(cluster, peers, myhostname)

        # create if it doesn't exist
        if volume_name not in volumes:
            create_volume(volume_name, stripes, replicas, arbiters, disperses,
                          redundancies, transport, cluster, brick_paths, force)
            volumes = get_volumes()
            changed = True

        if volume_name in volumes:
            if volumes[volume_name]['status'].lower(
            ) != 'started' and start_on_create:
                start_volume(volume_name)
                changed = True

            # switch bricks
            new_bricks = []
            removed_bricks = []
            all_bricks = []
            bricks_in_volume = volumes[volume_name]['bricks']

            for node in cluster:
                for brick_path in brick_paths:
                    brick = '%s:%s' % (node, brick_path)
                    all_bricks.append(brick)
                    if brick not in bricks_in_volume:
                        new_bricks.append(brick)

            if not new_bricks and len(all_bricks) > 0 and \
               len(all_bricks) < len(bricks_in_volume):
                for brick in bricks_in_volume:
                    if brick not in all_bricks:
                        removed_bricks.append(brick)

            if new_bricks:
                add_bricks(volume_name, new_bricks, stripes, replicas, force)
                changed = True

            if removed_bricks:
                if replicas and int(replicas) < int(
                        volumes[volume_name]['replicas']):
                    reduce_config(volume_name, removed_bricks, str(replicas),
                                  force)
                else:
                    remove_bricks(volume_name, removed_bricks, force)
                changed = True

            # handle quotas
            if quota:
                if not volumes[volume_name]['quota']:
                    enable_quota(volume_name)
                quotas = get_quotas(volume_name, False)
                if directory not in quotas or quotas[directory] != quota:
                    set_quota(volume_name, directory, quota)
                    changed = True

            # set options
            for option in options.keys():
                if option not in volumes[volume_name]['options'] or volumes[
                        volume_name]['options'][option] != options[option]:
                    set_volume_option(volume_name, option, options[option])
                    changed = True

        else:
            module.fail_json(msg='failed to create volume %s' % volume_name)

    if action != 'absent' and volume_name not in volumes:
        module.fail_json(msg='volume not found %s' % volume_name)

    if action == 'started':
        if volumes[volume_name]['status'].lower() != 'started':
            start_volume(volume_name)
            changed = True

    if action == 'stopped':
        if volumes[volume_name]['status'].lower() != 'stopped':
            stop_volume(volume_name)
            changed = True

    if changed:
        volumes = get_volumes()
        if rebalance:
            do_rebalance(volume_name)

    facts = {}
    facts['glusterfs'] = {'peers': peers, 'volumes': volumes, 'quotas': quotas}

    module.exit_json(changed=changed, ansible_facts=facts)
def main():

    module = AnsibleModule(argument_spec=dict(
        name=dict(required=True),
        state=dict(required=False,
                   choices=['present', 'absent'],
                   default='present'),
        type=dict(required=True),
        autostart=dict(required=False, type='bool', default=False),
        extra_info=dict(required=False, default=""),
        port_open=dict(required=False, type='bool', default=False),
        login_name=dict(required=True),
        login_password=dict(required=True, no_log=True),
        machine=dict(required=False, default=None),
    ),
                           supports_check_mode=True)
    app_name = module.params['name']
    app_type = module.params['type']
    app_state = module.params['state']

    if module.params['machine']:
        session_id, account = webfaction.login(module.params['login_name'],
                                               module.params['login_password'],
                                               module.params['machine'])
    else:
        session_id, account = webfaction.login(module.params['login_name'],
                                               module.params['login_password'])

    app_list = webfaction.list_apps(session_id)
    app_map = dict([(i['name'], i) for i in app_list])
    existing_app = app_map.get(app_name)

    result = {}

    # Here's where the real stuff happens

    if app_state == 'present':

        # Does an app with this name already exist?
        if existing_app:
            if existing_app['type'] != app_type:
                module.fail_json(
                    msg=
                    "App already exists with different type. Please fix by hand."
                )

            # If it exists with the right type, we don't change it
            # Should check other parameters.
            module.exit_json(
                changed=False,
                result=existing_app,
            )

        if not module.check_mode:
            # If this isn't a dry run, create the app
            result.update(
                webfaction.create_app(
                    session_id, app_name, app_type,
                    module.boolean(module.params['autostart']),
                    module.params['extra_info'],
                    module.boolean(module.params['port_open'])))

    elif app_state == 'absent':

        # If the app's already not there, nothing changed.
        if not existing_app:
            module.exit_json(changed=False, )

        if not module.check_mode:
            # If this isn't a dry run, delete the app
            result.update(webfaction.delete_app(session_id, app_name))

    else:
        module.fail_json(msg="Unknown state specified: {0}".format(app_state))

    module.exit_json(changed=True, result=result)
예제 #7
0
def main():
    command_keys = ['state', 'default', 'rule', 'logging']

    module = AnsibleModule(
        argument_spec=dict(
            state=dict(type='str',
                       choices=['enabled', 'disabled', 'reloaded', 'reset']),
            default=dict(type='str',
                         aliases=['policy'],
                         choices=['allow', 'deny', 'reject']),
            logging=dict(
                type='str',
                choices=['full', 'high', 'low', 'medium', 'off', 'on']),
            direction=dict(
                type='str',
                choices=['in', 'incoming', 'out', 'outgoing', 'routed']),
            delete=dict(type='bool', default=False),
            route=dict(type='bool', default=False),
            insert=dict(type='int'),
            insert_relative_to=dict(choices=[
                'zero', 'first-ipv4', 'last-ipv4', 'first-ipv6', 'last-ipv6'
            ],
                                    default='zero'),
            rule=dict(type='str', choices=['allow', 'deny', 'limit',
                                           'reject']),
            interface=dict(type='str', aliases=['if']),
            interface_in=dict(type='str', aliases=['if_in']),
            interface_out=dict(type='str', aliases=['if_out']),
            log=dict(type='bool', default=False),
            from_ip=dict(type='str', default='any', aliases=['from', 'src']),
            from_port=dict(type='str'),
            to_ip=dict(type='str', default='any', aliases=['dest', 'to']),
            to_port=dict(type='str', aliases=['port']),
            proto=dict(type='str',
                       aliases=['protocol'],
                       choices=[
                           'ah', 'any', 'esp', 'ipv6', 'tcp', 'udp', 'gre',
                           'igmp'
                       ]),
            name=dict(type='str', aliases=['app']),
            comment=dict(type='str'),
        ),
        supports_check_mode=True,
        mutually_exclusive=[
            ['name', 'proto', 'logging'],
            # Mutual exclusivity with `interface` implied by `required_by`.
            ['direction', 'interface_in'],
            ['direction', 'interface_out'],
        ],
        required_one_of=([command_keys]),
        required_by=dict(interface=('direction', ), ),
    )

    cmds = []

    ipv4_regexp = compile_ipv4_regexp()
    ipv6_regexp = compile_ipv6_regexp()

    def filter_line_that_not_start_with(pattern, content):
        return ''.join([
            line for line in content.splitlines(True)
            if line.startswith(pattern)
        ])

    def filter_line_that_contains(pattern, content):
        return [line for line in content.splitlines(True) if pattern in line]

    def filter_line_that_not_contains(pattern, content):
        return ''.join([
            line for line in content.splitlines(True)
            if not line.contains(pattern)
        ])

    def filter_line_that_match_func(match_func, content):
        return ''.join([
            line for line in content.splitlines(True)
            if match_func(line) is not None
        ])

    def filter_line_that_contains_ipv4(content):
        return filter_line_that_match_func(ipv4_regexp.search, content)

    def filter_line_that_contains_ipv6(content):
        return filter_line_that_match_func(ipv6_regexp.search, content)

    def is_starting_by_ipv4(ip):
        return ipv4_regexp.match(ip) is not None

    def is_starting_by_ipv6(ip):
        return ipv6_regexp.match(ip) is not None

    def execute(cmd, ignore_error=False):
        cmd = ' '.join(map(itemgetter(-1), filter(itemgetter(0), cmd)))

        cmds.append(cmd)
        (rc, out, err) = module.run_command(cmd, environ_update={"LANG": "C"})

        if rc != 0 and not ignore_error:
            module.fail_json(msg=err or out, commands=cmds)

        return out

    def get_current_rules():
        user_rules_files = [
            "/lib/ufw/user.rules", "/lib/ufw/user6.rules",
            "/etc/ufw/user.rules", "/etc/ufw/user6.rules",
            "/var/lib/ufw/user.rules", "/var/lib/ufw/user6.rules"
        ]

        cmd = [[grep_bin], ["-h"], ["'^### tuple'"]]

        cmd.extend([[f] for f in user_rules_files])
        return execute(cmd, ignore_error=True)

    def ufw_version():
        """
        Returns the major and minor version of ufw installed on the system.
        """
        out = execute([[ufw_bin], ["--version"]])

        lines = [x for x in out.split('\n') if x.strip() != '']
        if len(lines) == 0:
            module.fail_json(msg="Failed to get ufw version.", rc=0, out=out)

        matches = re.search(r'^ufw.+(\d+)\.(\d+)(?:\.(\d+))?.*$', lines[0])
        if matches is None:
            module.fail_json(msg="Failed to get ufw version.", rc=0, out=out)

        # Convert version to numbers
        major = int(matches.group(1))
        minor = int(matches.group(2))
        rev = 0
        if matches.group(3) is not None:
            rev = int(matches.group(3))

        return major, minor, rev

    params = module.params

    commands = dict((key, params[key]) for key in command_keys if params[key])

    # Ensure ufw is available
    ufw_bin = module.get_bin_path('ufw', True)
    grep_bin = module.get_bin_path('grep', True)

    # Save the pre state and rules in order to recognize changes
    pre_state = execute([[ufw_bin], ['status verbose']])
    pre_rules = get_current_rules()

    changed = False

    # Execute filter
    for (command, value) in commands.items():

        cmd = [[ufw_bin], [module.check_mode, '--dry-run']]

        if command == 'state':
            states = {
                'enabled': 'enable',
                'disabled': 'disable',
                'reloaded': 'reload',
                'reset': 'reset'
            }

            if value in ['reloaded', 'reset']:
                changed = True

            if module.check_mode:
                # "active" would also match "inactive", hence the space
                ufw_enabled = pre_state.find(" active") != -1
                if (value == 'disabled'
                        and ufw_enabled) or (value == 'enabled'
                                             and not ufw_enabled):
                    changed = True
            else:
                execute(cmd + [['-f'], [states[value]]])

        elif command == 'logging':
            extract = re.search(r'Logging: (on|off)(?: \(([a-z]+)\))?',
                                pre_state)
            if extract:
                current_level = extract.group(2)
                current_on_off_value = extract.group(1)
                if value != "off":
                    if current_on_off_value == "off":
                        changed = True
                    elif value != "on" and value != current_level:
                        changed = True
                elif current_on_off_value != "off":
                    changed = True
            else:
                changed = True

            if not module.check_mode:
                execute(cmd + [[command], [value]])

        elif command == 'default':
            if params['direction'] not in [
                    'outgoing', 'incoming', 'routed', None
            ]:
                module.fail_json(
                    msg=
                    'For default, direction must be one of "outgoing", "incoming" and "routed", or direction must not be specified.'
                )
            if module.check_mode:
                regexp = r'Default: (deny|allow|reject) \(incoming\), (deny|allow|reject) \(outgoing\), (deny|allow|reject|disabled) \(routed\)'
                extract = re.search(regexp, pre_state)
                if extract is not None:
                    current_default_values = {}
                    current_default_values["incoming"] = extract.group(1)
                    current_default_values["outgoing"] = extract.group(2)
                    current_default_values["routed"] = extract.group(3)
                    v = current_default_values[params['direction']
                                               or 'incoming']
                    if v not in (value, 'disabled'):
                        changed = True
                else:
                    changed = True
            else:
                execute(cmd + [[command], [value], [params['direction']]])

        elif command == 'rule':
            if params['direction'] not in ['in', 'out', None]:
                module.fail_json(
                    msg=
                    'For rules, direction must be one of "in" and "out", or direction must not be specified.'
                )
            if not params['route'] and params['interface_in'] and params[
                    'interface_out']:
                module.fail_json(msg='Only route rules can combine '
                                 'interface_in and interface_out')
            # Rules are constructed according to the long format
            #
            # ufw [--dry-run] [route] [delete] [insert NUM] allow|deny|reject|limit [in|out on INTERFACE] [log|log-all] \
            #     [from ADDRESS [port PORT]] [to ADDRESS [port PORT]] \
            #     [proto protocol] [app application] [comment COMMENT]
            cmd.append([module.boolean(params['route']), 'route'])
            cmd.append([module.boolean(params['delete']), 'delete'])
            if params['insert'] is not None:
                relative_to_cmd = params['insert_relative_to']
                if relative_to_cmd == 'zero':
                    insert_to = params['insert']
                else:
                    (dummy, numbered_state, dummy) = module.run_command(
                        [ufw_bin, 'status', 'numbered'])
                    numbered_line_re = re.compile(R'^\[ *([0-9]+)\] ')
                    lines = [(numbered_line_re.match(line), '(v6)' in line)
                             for line in numbered_state.splitlines()]
                    lines = [(int(matcher.group(1)), ipv6)
                             for (matcher, ipv6) in lines if matcher]
                    last_number = max([no for (no,
                                               ipv6) in lines]) if lines else 0
                    has_ipv4 = any([not ipv6 for (no, ipv6) in lines])
                    has_ipv6 = any([ipv6 for (no, ipv6) in lines])
                    if relative_to_cmd == 'first-ipv4':
                        relative_to = 1
                    elif relative_to_cmd == 'last-ipv4':
                        relative_to = max(
                            [no for (no, ipv6) in lines
                             if not ipv6]) if has_ipv4 else 1
                    elif relative_to_cmd == 'first-ipv6':
                        relative_to = max(
                            [no for (no, ipv6) in lines
                             if not ipv6]) + 1 if has_ipv4 else 1
                    elif relative_to_cmd == 'last-ipv6':
                        relative_to = last_number if has_ipv6 else last_number + 1
                    insert_to = params['insert'] + relative_to
                    if insert_to > last_number:
                        # ufw does not like it when the insert number is larger than the
                        # maximal rule number for IPv4/IPv6.
                        insert_to = None
                cmd.append([insert_to is not None, "insert %s" % insert_to])
            cmd.append([value])
            cmd.append([params['direction'], "%s" % params['direction']])
            cmd.append([params['interface'], "on %s" % params['interface']])
            cmd.append(
                [params['interface_in'],
                 "in on %s" % params['interface_in']])
            cmd.append([
                params['interface_out'],
                "out on %s" % params['interface_out']
            ])
            cmd.append([module.boolean(params['log']), 'log'])

            for (key, template) in [('from_ip', "from %s"),
                                    ('from_port', "port %s"),
                                    ('to_ip', "to %s"), ('to_port', "port %s"),
                                    ('proto', "proto %s"),
                                    ('name', "app '%s'")]:
                value = params[key]
                cmd.append([value, template % (value)])

            ufw_major, ufw_minor, dummy = ufw_version()
            # comment is supported only in ufw version after 0.35
            if (ufw_major == 0 and ufw_minor >= 35) or ufw_major > 0:
                cmd.append(
                    [params['comment'],
                     "comment '%s'" % params['comment']])

            rules_dry = execute(cmd)

            if module.check_mode:

                nb_skipping_line = len(
                    filter_line_that_contains("Skipping", rules_dry))

                if not (nb_skipping_line > 0 and nb_skipping_line == len(
                        rules_dry.splitlines(True))):

                    rules_dry = filter_line_that_not_start_with(
                        "### tuple", rules_dry)
                    # ufw dry-run doesn't send all rules so have to compare ipv4 or ipv6 rules
                    if is_starting_by_ipv4(
                            params['from_ip']) or is_starting_by_ipv4(
                                params['to_ip']):
                        if filter_line_that_contains_ipv4(
                                pre_rules) != filter_line_that_contains_ipv4(
                                    rules_dry):
                            changed = True
                    elif is_starting_by_ipv6(
                            params['from_ip']) or is_starting_by_ipv6(
                                params['to_ip']):
                        if filter_line_that_contains_ipv6(
                                pre_rules) != filter_line_that_contains_ipv6(
                                    rules_dry):
                            changed = True
                    elif pre_rules != rules_dry:
                        changed = True

    # Get the new state
    if module.check_mode:
        return module.exit_json(changed=changed, commands=cmds)
    else:
        post_state = execute([[ufw_bin], ['status'], ['verbose']])
        if not changed:
            post_rules = get_current_rules()
            changed = (pre_state != post_state) or (pre_rules != post_rules)
        return module.exit_json(changed=changed,
                                commands=cmds,
                                msg=post_state.rstrip())
예제 #8
0
def main():
    module = AnsibleModule(
        argument_spec=dict(
            login_user=dict(type='str'),
            login_password=dict(type='str', no_log=True),
            login_host=dict(type='str', default='localhost'),
            login_port=dict(type='int', default=3306),
            login_unix_socket=dict(type='str'),
            user=dict(type='str', required=True, aliases=['name']),
            password=dict(type='str', no_log=True),
            encrypted=dict(type='bool', default=False),
            host=dict(type='str', default='localhost'),
            host_all=dict(type="bool", default=False),
            state=dict(type='str',
                       default='present',
                       choices=['absent', 'present']),
            priv=dict(type='str'),
            append_privs=dict(type='bool', default=False),
            check_implicit_admin=dict(type='bool', default=False),
            update_password=dict(type='str',
                                 default='always',
                                 choices=['always', 'on_create']),
            connect_timeout=dict(type='int', default=30),
            config_file=dict(type='path', default='~/.my.cnf'),
            sql_log_bin=dict(type='bool', default=True),
            client_cert=dict(type='path', aliases=['ssl_cert']),
            client_key=dict(type='path', aliases=['ssl_key']),
            ca_cert=dict(type='path', aliases=['ssl_ca']),
            plugin=dict(default=None, type='str'),
            plugin_hash_string=dict(default=None, type='str'),
            plugin_auth_string=dict(default=None, type='str'),
        ),
        supports_check_mode=True,
    )
    login_user = module.params["login_user"]
    login_password = module.params["login_password"]
    user = module.params["user"]
    password = module.params["password"]
    encrypted = module.boolean(module.params["encrypted"])
    host = module.params["host"].lower()
    host_all = module.params["host_all"]
    state = module.params["state"]
    priv = module.params["priv"]
    check_implicit_admin = module.params['check_implicit_admin']
    connect_timeout = module.params['connect_timeout']
    config_file = module.params['config_file']
    append_privs = module.boolean(module.params["append_privs"])
    update_password = module.params['update_password']
    ssl_cert = module.params["client_cert"]
    ssl_key = module.params["client_key"]
    ssl_ca = module.params["ca_cert"]
    db = ''
    sql_log_bin = module.params["sql_log_bin"]
    plugin = module.params["plugin"]
    plugin_hash_string = module.params["plugin_hash_string"]
    plugin_auth_string = module.params["plugin_auth_string"]

    if mysql_driver is None:
        module.fail_json(msg=mysql_driver_fail_msg)

    cursor = None
    try:
        if check_implicit_admin:
            try:
                cursor, db_conn = mysql_connect(
                    module,
                    'root',
                    '',
                    config_file,
                    ssl_cert,
                    ssl_key,
                    ssl_ca,
                    db,
                    connect_timeout=connect_timeout)
            except Exception:
                pass

        if not cursor:
            cursor, db_conn = mysql_connect(module,
                                            login_user,
                                            login_password,
                                            config_file,
                                            ssl_cert,
                                            ssl_key,
                                            ssl_ca,
                                            db,
                                            connect_timeout=connect_timeout)
    except Exception as e:
        module.fail_json(
            msg=
            "unable to connect to database, check login_user and login_password are correct or %s has the credentials. "
            "Exception message: %s" % (config_file, to_native(e)))

    if not sql_log_bin:
        cursor.execute("SET SQL_LOG_BIN=0;")

    if priv is not None:
        try:
            mode = get_mode(cursor)
        except Exception as e:
            module.fail_json(msg=to_native(e))
        try:
            priv = privileges_unpack(priv, mode)
        except Exception as e:
            module.fail_json(msg="invalid privileges string: %s" %
                             to_native(e))

    if state == "present":
        if user_exists(cursor, user, host, host_all):
            try:
                if update_password == 'always':
                    changed, msg = user_mod(cursor, user, host, host_all,
                                            password, encrypted, plugin,
                                            plugin_hash_string,
                                            plugin_auth_string, priv,
                                            append_privs, module)
                else:
                    changed, msg = user_mod(cursor, user, host, host_all, None,
                                            encrypted, plugin,
                                            plugin_hash_string,
                                            plugin_auth_string, priv,
                                            append_privs, module)

            except (SQLParseError, InvalidPrivsError, mysql_driver.Error) as e:
                module.fail_json(msg=to_native(e))
        else:
            if host_all:
                module.fail_json(
                    msg="host_all parameter cannot be used when adding a user")
            try:
                changed = user_add(cursor, user, host, host_all, password,
                                   encrypted, plugin, plugin_hash_string,
                                   plugin_auth_string, priv, module.check_mode)
                if changed:
                    msg = "User added"

            except (SQLParseError, InvalidPrivsError, mysql_driver.Error) as e:
                module.fail_json(msg=to_native(e))
    elif state == "absent":
        if user_exists(cursor, user, host, host_all):
            changed = user_delete(cursor, user, host, host_all,
                                  module.check_mode)
            msg = "User deleted"
        else:
            changed = False
            msg = "User doesn't exist"
    module.exit_json(changed=changed, user=user, msg=msg)
예제 #9
0
def main():
    command_allowed_param_map = dict(
        cleanup=(),
        createcachetable=(
            'cache_table',
            'database',
        ),
        flush=('database', ),
        loaddata=(
            'database',
            'fixtures',
        ),
        syncdb=('database', ),
        test=(
            'failfast',
            'testrunner',
            'liveserver',
            'apps',
        ),
        validate=(),
        migrate=(
            'apps',
            'skip',
            'merge',
            'database',
        ),
        collectstatic=(
            'clear',
            'link',
        ),
    )

    command_required_param_map = dict(loaddata=('fixtures', ), )

    # forces --noinput on every command that needs it
    noinput_commands = (
        'flush',
        'syncdb',
        'migrate',
        'test',
        'collectstatic',
    )

    # These params are allowed for certain commands only
    specific_params = ('apps', 'clear', 'database', 'failfast', 'fixtures',
                       'liveserver', 'testrunner')

    # These params are automatically added to the command if present
    general_params = (
        'settings',
        'pythonpath',
        'database',
    )
    specific_boolean_params = ('clear', 'failfast', 'skip', 'merge', 'link')
    end_of_command_params = ('apps', 'cache_table', 'fixtures')

    module = AnsibleModule(argument_spec=dict(
        command=dict(default=None, required=True),
        app_path=dict(default=None, required=True, type='path'),
        settings=dict(default=None, required=False),
        pythonpath=dict(default=None, required=False, aliases=['python_path']),
        virtualenv=dict(default=None,
                        required=False,
                        type='path',
                        aliases=['virtual_env']),
        apps=dict(default=None, required=False),
        cache_table=dict(default=None, required=False),
        clear=dict(default=None, required=False, type='bool'),
        database=dict(default=None, required=False),
        failfast=dict(default='no',
                      required=False,
                      type='bool',
                      aliases=['fail_fast']),
        fixtures=dict(default=None, required=False),
        liveserver=dict(default=None, required=False, aliases=['live_server']),
        testrunner=dict(default=None, required=False, aliases=['test_runner']),
        skip=dict(default=None, required=False, type='bool'),
        merge=dict(default=None, required=False, type='bool'),
        link=dict(default=None, required=False, type='bool'),
    ), )

    command = module.params['command']
    app_path = module.params['app_path']
    virtualenv = module.params['virtualenv']

    for param in specific_params:
        value = module.params[param]
        if param in specific_boolean_params:
            value = module.boolean(value)
        if value and param not in command_allowed_param_map[command]:
            module.fail_json(msg='%s param is incompatible with command=%s' %
                             (param, command))

    for param in command_required_param_map.get(command, ()):
        if not module.params[param]:
            module.fail_json(msg='%s param is required for command=%s' %
                             (param, command))

    _ensure_virtualenv(module)

    cmd = "./manage.py %s" % (command, )

    if command in noinput_commands:
        cmd = '%s --noinput' % cmd

    for param in general_params:
        if module.params[param]:
            cmd = '%s --%s=%s' % (cmd, param, module.params[param])

    for param in specific_boolean_params:
        if module.boolean(module.params[param]):
            cmd = '%s --%s' % (cmd, param)

    # these params always get tacked on the end of the command
    for param in end_of_command_params:
        if module.params[param]:
            cmd = '%s %s' % (cmd, module.params[param])

    rc, out, err = module.run_command(cmd, cwd=app_path)
    if rc != 0:
        if command == 'createcachetable' and 'table' in err and 'already exists' in err:
            out = 'Already exists.'
        else:
            if "Unknown command:" in err:
                _fail(module, cmd, err, "Unknown django command: %s" % command)
            _fail(module,
                  cmd,
                  out,
                  err,
                  path=os.environ["PATH"],
                  syspath=sys.path)

    changed = False

    lines = out.split('\n')
    filt = globals().get(command + "_filter_output", None)
    if filt:
        filtered_output = list(filter(filt, lines))
        if len(filtered_output):
            changed = True

    module.exit_json(changed=changed,
                     out=out,
                     cmd=cmd,
                     app_path=app_path,
                     virtualenv=virtualenv,
                     settings=module.params['settings'],
                     pythonpath=module.params['pythonpath'])
예제 #10
0
def main():
    """Main function"""

    module = AnsibleModule(argument_spec=dict(
        state=dict(default='present',
                   choices=['present', 'absent'],
                   type='str'),
        record=dict(required=True, aliases=['name'], type='str'),
        zone=dict(type='str'),
        zone_id=dict(type='str'),
        type=dict(required=True, choices=SUPPORTED_RECORD_TYPES, type='str'),
        record_data=dict(aliases=['value'], type='list'),
        ttl=dict(default=300, type='int'),
        overwrite=dict(default=False, type='bool'),
        service_account_email=dict(type='str'),
        pem_file=dict(type='path'),
        credentials_file=dict(type='path'),
        project_id=dict(type='str')),
                           required_if=[('state', 'present', ['record_data']),
                                        ('overwrite', False, ['record_data'])],
                           required_one_of=[['zone', 'zone_id']],
                           supports_check_mode=True)

    _sanity_check(module)

    record_name = module.params['record']
    record_type = module.params['type']
    state = module.params['state']
    ttl = module.params['ttl']
    zone_name = module.params['zone']
    zone_id = module.params['zone_id']

    json_output = dict(state=state,
                       record=record_name,
                       zone=zone_name,
                       zone_id=zone_id,
                       type=record_type,
                       record_data=module.params['record_data'],
                       ttl=ttl,
                       overwrite=module.boolean(module.params['overwrite']))

    # Google Cloud DNS wants the trailing dot on all DNS names.
    if zone_name is not None and zone_name[-1] != '.':
        zone_name = zone_name + '.'
    if record_name[-1] != '.':
        record_name = record_name + '.'

    # Build a connection object that we can use to connect with Google Cloud
    # DNS.
    gcdns = gcdns_connect(module, provider=PROVIDER)

    # We need to check that the zone we're creating a record for actually
    # exists.
    zone = _get_zone(gcdns, zone_name, zone_id)
    if zone is None and zone_name is not None:
        module.fail_json(msg='zone name was not found: %s' % zone_name,
                         changed=False)
    elif zone is None and zone_id is not None:
        module.fail_json(msg='zone id was not found: %s' % zone_id,
                         changed=False)

    # Populate the returns with the actual zone information.
    json_output['zone'] = zone.domain
    json_output['zone_id'] = zone.id

    # We also need to check if the record we want to create or remove actually
    # exists.
    try:
        record = _get_record(gcdns, zone, record_type, record_name)
    except InvalidRequestError:
        # We gave Google Cloud DNS an invalid DNS record name.
        module.fail_json(msg='record name is invalid: %s' % record_name,
                         changed=False)

    _additional_sanity_checks(module, zone)

    diff = dict()

    # Build the 'before' diff
    if record is None:
        diff['before'] = ''
        diff['before_header'] = '<absent>'
    else:
        diff['before'] = dict(record=record.data['name'],
                              type=record.data['type'],
                              record_data=record.data['rrdatas'],
                              ttl=record.data['ttl'])
        diff['before_header'] = "%s:%s" % (record_type, record_name)

    # Create, remove, or modify the record.
    if state == 'present':
        diff['after'] = dict(record=record_name,
                             type=record_type,
                             record_data=module.params['record_data'],
                             ttl=ttl)
        diff['after_header'] = "%s:%s" % (record_type, record_name)

        changed = create_record(module, gcdns, zone, record)

    elif state == 'absent':
        diff['after'] = ''
        diff['after_header'] = '<absent>'

        changed = remove_record(module, gcdns, record)

    module.exit_json(changed=changed, diff=diff, **json_output)
예제 #11
0
def main():

    module = AnsibleModule(
        argument_spec=dict(
            name=dict(required=True),
            state=dict(required=False, choices=['present', 'absent'], default='present'),
            # You can specify an IP address or hostname.
            host=dict(required=True),
            https=dict(required=False, type='bool', default=False),
            subdomains=dict(required=False, type='list', default=[]),
            site_apps=dict(required=False, type='list', default=[]),
            login_name=dict(required=True),
            login_password=dict(required=True, no_log=True),
        ),
        supports_check_mode=True
    )
    site_name = module.params['name']
    site_state = module.params['state']
    site_host = module.params['host']
    site_ip = socket.gethostbyname(site_host)

    session_id, account = webfaction.login(
        module.params['login_name'],
        module.params['login_password']
    )

    site_list = webfaction.list_websites(session_id)
    site_map = dict([(i['name'], i) for i in site_list])
    existing_site = site_map.get(site_name)

    result = {}

    # Here's where the real stuff happens

    if site_state == 'present':

        # Does a site with this name already exist?
        if existing_site:

            # If yes, but it's on a different IP address, then fail.
            # If we wanted to allow relocation, we could add a 'relocate=true' option
            # which would get the existing IP address, delete the site there, and create it
            # at the new address.  A bit dangerous, perhaps, so for now we'll require manual
            # deletion if it's on another host.

            if existing_site['ip'] != site_ip:
                module.fail_json(msg="Website already exists with a different IP address. Please fix by hand.")

            # If it's on this host and the key parameters are the same, nothing needs to be done.

            if (existing_site['https'] == module.boolean(module.params['https'])) and \
               (set(existing_site['subdomains']) == set(module.params['subdomains'])) and \
               (dict(existing_site['website_apps']) == dict(module.params['site_apps'])):
                module.exit_json(
                    changed=False
                )

        positional_args = [
            session_id, site_name, site_ip,
            module.boolean(module.params['https']),
            module.params['subdomains'],
        ]
        for a in module.params['site_apps']:
            positional_args.append((a[0], a[1]))

        if not module.check_mode:
            # If this isn't a dry run, create or modify the site
            result.update(
                webfaction.create_website(
                    *positional_args
                ) if not existing_site else webfaction.update_website(
                    *positional_args
                )
            )

    elif site_state == 'absent':

        # If the site's already not there, nothing changed.
        if not existing_site:
            module.exit_json(
                changed=False,
            )

        if not module.check_mode:
            # If this isn't a dry run, delete the site
            result.update(
                webfaction.delete_website(session_id, site_name, site_ip)
            )

    else:
        module.fail_json(msg="Unknown state specified: {0}".format(site_state))

    module.exit_json(
        changed=True,
        result=result
    )
예제 #12
0
def main():
    module = AnsibleModule(
        argument_spec=dict(
            vg=dict(type='str', required=True),
            lv=dict(type='str'),
            size=dict(type='str'),
            opts=dict(type='str'),
            state=dict(type='str',
                       default='present',
                       choices=['absent', 'present']),
            force=dict(type='bool', default=False),
            shrink=dict(type='bool', default=True),
            active=dict(type='bool', default=True),
            snapshot=dict(type='str'),
            pvs=dict(type='str'),
            resizefs=dict(type='bool', default=False),
            thinpool=dict(type='str'),
        ),
        supports_check_mode=True,
        required_one_of=(['lv', 'thinpool'], ),
    )

    module.run_command_environ_update = LVOL_ENV_VARS

    # Determine if the "--yes" option should be used
    version_found = get_lvm_version(module)
    if version_found is None:
        module.fail_json(msg="Failed to get LVM version number")
    version_yesopt = mkversion(2, 2, 99)  # First LVM with the "--yes" option
    if version_found >= version_yesopt:
        yesopt = "--yes"
    else:
        yesopt = ""

    vg = module.params['vg']
    lv = module.params['lv']
    size = module.params['size']
    opts = module.params['opts']
    state = module.params['state']
    force = module.boolean(module.params['force'])
    shrink = module.boolean(module.params['shrink'])
    active = module.boolean(module.params['active'])
    resizefs = module.boolean(module.params['resizefs'])
    thinpool = module.params['thinpool']
    size_opt = 'L'
    size_unit = 'm'
    snapshot = module.params['snapshot']
    pvs = module.params['pvs']

    if pvs is None:
        pvs = ""
    else:
        pvs = pvs.replace(",", " ")

    if opts is None:
        opts = ""

    # Add --test option when running in check-mode
    if module.check_mode:
        test_opt = ' --test'
    else:
        test_opt = ''

    if size:
        # LVCREATE(8) -l --extents option with percentage
        if '%' in size:
            size_parts = size.split('%', 1)
            size_percent = int(size_parts[0])
            if size_percent > 100:
                module.fail_json(
                    msg="Size percentage cannot be larger than 100%")
            size_whole = size_parts[1]
            if size_whole == 'ORIGIN':
                module.fail_json(msg="Snapshot Volumes are not supported")
            elif size_whole not in ['VG', 'PVS', 'FREE']:
                module.fail_json(
                    msg="Specify extents as a percentage of VG|PVS|FREE")
            size_opt = 'l'
            size_unit = ''

        if '%' not in size:
            # LVCREATE(8) -L --size option unit
            if size[-1].lower() in 'bskmgtpe':
                size_unit = size[-1].lower()
                size = size[0:-1]

            try:
                float(size)
                if not size[0].isdigit():
                    raise ValueError()
            except ValueError:
                module.fail_json(msg="Bad size specification of '%s'" % size)

    # when no unit, megabytes by default
    if size_opt == 'l':
        unit = 'm'
    else:
        unit = size_unit

    # Get information on volume group requested
    vgs_cmd = module.get_bin_path("vgs", required=True)
    rc, current_vgs, err = module.run_command(
        "%s --noheadings --nosuffix -o vg_name,size,free,vg_extent_size --units %s --separator ';' %s"
        % (vgs_cmd, unit, vg))

    if rc != 0:
        if state == 'absent':
            module.exit_json(changed=False,
                             stdout="Volume group %s does not exist." % vg)
        else:
            module.fail_json(msg="Volume group %s does not exist." % vg,
                             rc=rc,
                             err=err)

    vgs = parse_vgs(current_vgs)
    this_vg = vgs[0]

    # Get information on logical volume requested
    lvs_cmd = module.get_bin_path("lvs", required=True)
    rc, current_lvs, err = module.run_command(
        "%s -a --noheadings --nosuffix -o lv_name,size,lv_attr --units %s --separator ';' %s"
        % (lvs_cmd, unit, vg))

    if rc != 0:
        if state == 'absent':
            module.exit_json(changed=False,
                             stdout="Volume group %s does not exist." % vg)
        else:
            module.fail_json(msg="Volume group %s does not exist." % vg,
                             rc=rc,
                             err=err)

    changed = False

    lvs = parse_lvs(current_lvs)

    if snapshot:
        # Check snapshot pre-conditions
        for test_lv in lvs:
            if test_lv['name'] == lv or test_lv['name'] == thinpool:
                if not test_lv['thinpool'] and not thinpool:
                    break
                else:
                    module.fail_json(
                        msg="Snapshots of thin pool LVs are not supported.")
        else:
            module.fail_json(
                msg="Snapshot origin LV %s does not exist in volume group %s."
                % (lv, vg))
        check_lv = snapshot

    elif thinpool:
        if lv:
            # Check thin volume pre-conditions
            for test_lv in lvs:
                if test_lv['name'] == thinpool:
                    break
            else:
                module.fail_json(
                    msg="Thin pool LV %s does not exist in volume group %s." %
                    (thinpool, vg))
            check_lv = lv
        else:
            check_lv = thinpool
    else:
        check_lv = lv

    for test_lv in lvs:
        if test_lv['name'] in (check_lv, check_lv.rsplit('/', 1)[-1]):
            this_lv = test_lv
            break
    else:
        this_lv = None

    msg = ''
    if this_lv is None:
        if state == 'present':
            # Require size argument except for snapshot of thin volumes
            if (lv or thinpool) and not size:
                for test_lv in lvs:
                    if test_lv['name'] == lv and test_lv[
                            'thinvol'] and snapshot:
                        break
                else:
                    module.fail_json(msg="No size given.")

            # create LV
            lvcreate_cmd = module.get_bin_path("lvcreate", required=True)
            if snapshot is not None:
                if size:
                    cmd = "%s %s %s -%s %s%s -s -n %s %s %s/%s" % (
                        lvcreate_cmd, test_opt, yesopt, size_opt, size,
                        size_unit, snapshot, opts, vg, lv)
                else:
                    cmd = "%s %s %s -s -n %s %s %s/%s" % (
                        lvcreate_cmd, test_opt, yesopt, snapshot, opts, vg, lv)
            elif thinpool and lv:
                if size_opt == 'l':
                    module.fail_json(
                        changed=False,
                        msg="Thin volume sizing with percentage not supported."
                    )
                size_opt = 'V'
                cmd = "%s %s -n %s -%s %s%s %s -T %s/%s" % (
                    lvcreate_cmd, yesopt, lv, size_opt, size, size_unit, opts,
                    vg, thinpool)
            elif thinpool and not lv:
                cmd = "%s %s -%s %s%s %s -T %s/%s" % (
                    lvcreate_cmd, yesopt, size_opt, size, size_unit, opts, vg,
                    thinpool)
            else:
                cmd = "%s %s %s -n %s -%s %s%s %s %s %s" % (
                    lvcreate_cmd, test_opt, yesopt, lv, size_opt, size,
                    size_unit, opts, vg, pvs)
            rc, _, err = module.run_command(cmd)
            if rc == 0:
                changed = True
            else:
                module.fail_json(msg="Creating logical volume '%s' failed" %
                                 lv,
                                 rc=rc,
                                 err=err)
    else:
        if state == 'absent':
            # remove LV
            if not force:
                module.fail_json(
                    msg=
                    "Sorry, no removal of logical volume %s without force=yes."
                    % (this_lv['name']))
            lvremove_cmd = module.get_bin_path("lvremove", required=True)
            rc, _, err = module.run_command(
                "%s %s --force %s/%s" %
                (lvremove_cmd, test_opt, vg, this_lv['name']))
            if rc == 0:
                module.exit_json(changed=True)
            else:
                module.fail_json(msg="Failed to remove logical volume %s" %
                                 (lv),
                                 rc=rc,
                                 err=err)

        elif not size:
            pass

        elif size_opt == 'l':
            # Resize LV based on % value
            tool = None
            size_free = this_vg['free']
            if size_whole == 'VG' or size_whole == 'PVS':
                size_requested = size_percent * this_vg['size'] / 100
            else:  # size_whole == 'FREE':
                size_requested = size_percent * this_vg['free'] / 100
            if '+' in size:
                size_requested += this_lv['size']
            if this_lv['size'] < size_requested:
                if (size_free > 0) and (('+' not in size) or
                                        (size_free >=
                                         (size_requested - this_lv['size']))):
                    tool = module.get_bin_path("lvextend", required=True)
                else:
                    module.fail_json(
                        msg=
                        "Logical Volume %s could not be extended. Not enough free space left (%s%s required / %s%s available)"
                        % (this_lv['name'], (size_requested - this_lv['size']),
                           unit, size_free, unit))
            elif shrink and this_lv['size'] > size_requested + this_vg[
                    'ext_size']:  # more than an extent too large
                if size_requested == 0:
                    module.fail_json(
                        msg="Sorry, no shrinking of %s to 0 permitted." %
                        (this_lv['name']))
                elif not force:
                    module.fail_json(
                        msg="Sorry, no shrinking of %s without force=yes" %
                        (this_lv['name']))
                else:
                    tool = module.get_bin_path("lvreduce", required=True)
                    tool = '%s %s' % (tool, '--force')

            if tool:
                if resizefs:
                    tool = '%s %s' % (tool, '--resizefs')
                cmd = "%s %s -%s %s%s %s/%s %s" % (tool, test_opt, size_opt,
                                                   size, size_unit, vg,
                                                   this_lv['name'], pvs)
                rc, out, err = module.run_command(cmd)
                if "Reached maximum COW size" in out:
                    module.fail_json(msg="Unable to resize %s to %s%s" %
                                     (lv, size, size_unit),
                                     rc=rc,
                                     err=err,
                                     out=out)
                elif rc == 0:
                    changed = True
                    msg = "Volume %s resized to %s%s" % (this_lv['name'],
                                                         size_requested, unit)
                elif "matches existing size" in err:
                    module.exit_json(changed=False,
                                     vg=vg,
                                     lv=this_lv['name'],
                                     size=this_lv['size'])
                elif "not larger than existing size" in err:
                    module.exit_json(
                        changed=False,
                        vg=vg,
                        lv=this_lv['name'],
                        size=this_lv['size'],
                        msg="Original size is larger than requested size",
                        err=err)
                else:
                    module.fail_json(msg="Unable to resize %s to %s%s" %
                                     (lv, size, size_unit),
                                     rc=rc,
                                     err=err)

        else:
            # resize LV based on absolute values
            tool = None
            if float(size) > this_lv['size']:
                tool = module.get_bin_path("lvextend", required=True)
            elif shrink and float(size) < this_lv['size']:
                if float(size) == 0:
                    module.fail_json(
                        msg="Sorry, no shrinking of %s to 0 permitted." %
                        (this_lv['name']))
                if not force:
                    module.fail_json(
                        msg="Sorry, no shrinking of %s without force=yes." %
                        (this_lv['name']))
                else:
                    tool = module.get_bin_path("lvreduce", required=True)
                    tool = '%s %s' % (tool, '--force')

            if tool:
                if resizefs:
                    tool = '%s %s' % (tool, '--resizefs')
                cmd = "%s %s -%s %s%s %s/%s %s" % (tool, test_opt, size_opt,
                                                   size, size_unit, vg,
                                                   this_lv['name'], pvs)
                rc, out, err = module.run_command(cmd)
                if "Reached maximum COW size" in out:
                    module.fail_json(msg="Unable to resize %s to %s%s" %
                                     (lv, size, size_unit),
                                     rc=rc,
                                     err=err,
                                     out=out)
                elif rc == 0:
                    changed = True
                elif "matches existing size" in err:
                    module.exit_json(changed=False,
                                     vg=vg,
                                     lv=this_lv['name'],
                                     size=this_lv['size'])
                elif "not larger than existing size" in err:
                    module.exit_json(
                        changed=False,
                        vg=vg,
                        lv=this_lv['name'],
                        size=this_lv['size'],
                        msg="Original size is larger than requested size",
                        err=err)
                else:
                    module.fail_json(msg="Unable to resize %s to %s%s" %
                                     (lv, size, size_unit),
                                     rc=rc,
                                     err=err)

    if this_lv is not None:
        if active:
            lvchange_cmd = module.get_bin_path("lvchange", required=True)
            rc, _, err = module.run_command(
                "%s -ay %s/%s" % (lvchange_cmd, vg, this_lv['name']))
            if rc == 0:
                module.exit_json(changed=((not this_lv['active']) or changed),
                                 vg=vg,
                                 lv=this_lv['name'],
                                 size=this_lv['size'])
            else:
                module.fail_json(msg="Failed to activate logical volume %s" %
                                 (lv),
                                 rc=rc,
                                 err=err)
        else:
            lvchange_cmd = module.get_bin_path("lvchange", required=True)
            rc, _, err = module.run_command(
                "%s -an %s/%s" % (lvchange_cmd, vg, this_lv['name']))
            if rc == 0:
                module.exit_json(changed=(this_lv['active'] or changed),
                                 vg=vg,
                                 lv=this_lv['name'],
                                 size=this_lv['size'])
            else:
                module.fail_json(msg="Failed to deactivate logical volume %s" %
                                 (lv),
                                 rc=rc,
                                 err=err)

    module.exit_json(changed=changed, msg=msg)
def main():
    module = AnsibleModule(
        argument_spec=dict(
            path=dict(type='path', required=True, aliases=['dest', 'destfile', 'name']),
            state=dict(type='str', default='present', choices=['absent', 'present']),
            marker=dict(type='str', default='# {mark} ANSIBLE MANAGED BLOCK'),
            block=dict(type='str', default='', aliases=['content']),
            insertafter=dict(type='str'),
            insertbefore=dict(type='str'),
            create=dict(type='bool', default=False),
            backup=dict(type='bool', default=False),
            validate=dict(type='str'),
            marker_begin=dict(type='str', default='BEGIN'),
            marker_end=dict(type='str', default='END'),
        ),
        mutually_exclusive=[['insertbefore', 'insertafter']],
        add_file_common_args=True,
        supports_check_mode=True
    )

    params = module.params
    path = params['path']

    if os.path.isdir(path):
        module.fail_json(rc=256,
                         msg='Path %s is a directory !' % path)

    path_exists = os.path.exists(path)
    if not path_exists:
        if not module.boolean(params['create']):
            module.fail_json(rc=257,
                             msg='Path %s does not exist !' % path)
        destpath = os.path.dirname(path)
        if not os.path.exists(destpath) and not module.check_mode:
            try:
                os.makedirs(destpath)
            except Exception as e:
                module.fail_json(msg='Error creating %s Error code: %s Error description: %s' % (destpath, e[0], e[1]))
        original = None
        lines = []
    else:
        f = open(path, 'rb')
        original = f.read()
        f.close()
        lines = original.splitlines()

    diff = {'before': '',
            'after': '',
            'before_header': '%s (content)' % path,
            'after_header': '%s (content)' % path}

    if module._diff and original:
        diff['before'] = original

    insertbefore = params['insertbefore']
    insertafter = params['insertafter']
    block = to_bytes(params['block'])
    marker = to_bytes(params['marker'])
    present = params['state'] == 'present'

    if not present and not path_exists:
        module.exit_json(changed=False, msg="File %s not present" % path)

    if insertbefore is None and insertafter is None:
        insertafter = 'EOF'

    if insertafter not in (None, 'EOF'):
        insertre = re.compile(to_bytes(insertafter, errors='surrogate_or_strict'))
    elif insertbefore not in (None, 'BOF'):
        insertre = re.compile(to_bytes(insertbefore, errors='surrogate_or_strict'))
    else:
        insertre = None

    marker0 = re.sub(b(r'{mark}'), b(params['marker_begin']), marker)
    marker1 = re.sub(b(r'{mark}'), b(params['marker_end']), marker)
    if present and block:
        # Escape sequences like '\n' need to be handled in Ansible 1.x
        if module.ansible_version.startswith('1.'):
            block = re.sub('', block, '')
        blocklines = [marker0] + block.splitlines() + [marker1]
    else:
        blocklines = []

    n0 = n1 = None
    for i, line in enumerate(lines):
        if line == marker0:
            n0 = i
        if line == marker1:
            n1 = i

    if None in (n0, n1):
        n0 = None
        if insertre is not None:
            for i, line in enumerate(lines):
                if insertre.search(line):
                    n0 = i
            if n0 is None:
                n0 = len(lines)
            elif insertafter is not None:
                n0 += 1
        elif insertbefore is not None:
            n0 = 0  # insertbefore=BOF
        else:
            n0 = len(lines)  # insertafter=EOF
    elif n0 < n1:
        lines[n0:n1 + 1] = []
    else:
        lines[n1:n0 + 1] = []
        n0 = n1

    lines[n0:n0] = blocklines

    if lines:
        result = b('\n').join(lines)
        if original is None or original.endswith(b('\n')):
            result += b('\n')
    else:
        result = b''

    if module._diff:
        diff['after'] = result

    if original == result:
        msg = ''
        changed = False
    elif original is None:
        msg = 'File created'
        changed = True
    elif not blocklines:
        msg = 'Block removed'
        changed = True
    else:
        msg = 'Block inserted'
        changed = True

    if changed and not module.check_mode:
        if module.boolean(params['backup']) and path_exists:
            module.backup_local(path)
        # We should always follow symlinks so that we change the real file
        real_path = os.path.realpath(params['path'])
        write_changes(module, result, real_path)

    if module.check_mode and not path_exists:
        module.exit_json(changed=changed, msg=msg, diff=diff)

    attr_diff = {}
    msg, changed = check_file_attrs(module, changed, msg, attr_diff)

    attr_diff['before_header'] = '%s (file attributes)' % path
    attr_diff['after_header'] = '%s (file attributes)' % path

    difflist = [diff, attr_diff]
    module.exit_json(changed=changed, msg=msg, diff=difflist)