def main():
    argument_spec = ovirt_facts_full_argument_spec(
        pattern=dict(default='', required=False),
    )
    module = AnsibleModule(argument_spec)

    if module._name == 'ovirt_clusters_facts':
        module.deprecate("The 'ovirt_clusters_facts' module is being renamed 'ovirt_cluster_facts'", version=2.8)

    check_sdk(module)

    try:
        auth = module.params.pop('auth')
        connection = create_connection(auth)
        clusters_service = connection.system_service().clusters_service()
        clusters = clusters_service.list(search=module.params['pattern'])
        module.exit_json(
            changed=False,
            ansible_facts=dict(
                ovirt_clusters=[
                    get_dict_of_struct(
                        struct=c,
                        connection=connection,
                        fetch_nested=module.params.get('fetch_nested'),
                        attributes=module.params.get('nested_attributes'),
                    ) for c in clusters
                ],
            ),
        )
    except Exception as e:
        module.fail_json(msg=str(e), exception=traceback.format_exc())
    finally:
        connection.close(logout=auth.get('token') is None)
Beispiel #2
0
def main():
    """ Main entry point for Ansible module execution
    """
    argument_spec = dict(
        hostname=dict(),
        vrf=dict(type='str', default='default'),
        domain_name=dict(),
        domain_search=dict(type='list'),

        name_servers=dict(type='list'),
        lookup_source=dict(),
        lookup_enabled=dict(type='bool', default=True),

        state=dict(choices=['present', 'absent'], default='present')
    )

    argument_spec.update(iosxr_argument_spec)

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)

    config_object = None
    if is_cliconf(module):
        module.deprecate(msg="cli support for 'iosxr_system' is deprecated. Use transport netconf instead",
                         version="4 releases from v2.5")
        config_object = CliConfiguration(module)
    elif is_netconf(module):
        config_object = NCConfiguration(module)

    result = None
    if config_object:
        result = config_object.run()
    module.exit_json(**result)
def main():
    """ main entry point for module execution
    """
    element_spec = dict(
        name=dict(type='str'),
        description=dict(type='str'),
        speed=dict(choices=['10', '100', '1000']),
        mtu=dict(),
        duplex=dict(choices=['full', 'half']),
        enabled=dict(default=True, type='bool'),
        active=dict(default='active', type='str', choices=['active', 'preconfigure']),
        tx_rate=dict(),
        rx_rate=dict(),
        delay=dict(default=10, type='int'),
        state=dict(default='present',
                   choices=['present', 'absent', 'up', 'down'])
    )

    aggregate_spec = deepcopy(element_spec)
    aggregate_spec['name'] = dict(required=True)

    # remove default in aggregate spec, to handle common arguments
    remove_default_spec(aggregate_spec)

    argument_spec = dict(
        aggregate=dict(type='list', elements='dict', options=aggregate_spec),
    )

    argument_spec.update(element_spec)
    argument_spec.update(iosxr_argument_spec)

    required_one_of = [['name', 'aggregate']]
    mutually_exclusive = [['name', 'aggregate']]

    module = AnsibleModule(argument_spec=argument_spec,
                           required_one_of=required_one_of,
                           mutually_exclusive=mutually_exclusive,
                           supports_check_mode=True)

    config_object = None
    if is_cliconf(module):
        module.deprecate("cli support for 'iosxr_interface' is deprecated. Use transport netconf instead",
                         version='4 releases from v2.5')
        config_object = CliConfiguration(module)
    elif is_netconf(module):
        if module.params['active'] == 'preconfigure':
            module.fail_json(msg="Physical interface pre-configuration is not supported with transport 'netconf'")
        config_object = NCConfiguration(module)

    result = {}
    if config_object:
        result = config_object.run()
    module.exit_json(**result)
def main():
    module = AnsibleModule(
        argument_spec={},
        supports_check_mode=True,
    )

    if module._name == 'ec2_facts':
        module.deprecate("The 'ec2_facts' module is being renamed 'ec2_metadata_facts'", version=2.7)

    ec2_metadata_facts = Ec2Metadata(module).run()
    ec2_metadata_facts_result = dict(changed=False, ansible_facts=ec2_metadata_facts)

    module.exit_json(**ec2_metadata_facts_result)
def main():
    argument_spec = ovirt_full_argument_spec(
        state=dict(
            choices=['present', 'absent'],
            default='present',
        ),
        name=dict(default=None, required=True),
        description=dict(default=None),
        local=dict(type='bool'),
        compatibility_version=dict(default=None),
        quota_mode=dict(choices=['disabled', 'audit', 'enabled']),
        comment=dict(default=None),
        mac_pool=dict(default=None),
        force=dict(default=None, type='bool'),
    )
    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
    )

    if module._name == 'ovirt_datacenters':
        module.deprecate("The 'ovirt_datacenters' module is being renamed 'ovirt_datacenter'", version=2.8)

    check_sdk(module)
    check_params(module)

    try:
        auth = module.params.pop('auth')
        connection = create_connection(auth)
        data_centers_service = connection.system_service().data_centers_service()
        clusters_module = DatacentersModule(
            connection=connection,
            module=module,
            service=data_centers_service,
        )

        state = module.params['state']
        if state == 'present':
            ret = clusters_module.create()
        elif state == 'absent':
            ret = clusters_module.remove(force=module.params['force'])

        module.exit_json(**ret)
    except Exception as e:
        module.fail_json(msg=str(e), exception=traceback.format_exc())
    finally:
        connection.close(logout=auth.get('token') is None)
Beispiel #6
0
def main():
    argument_spec = ovirt_full_argument_spec(
        state=dict(
            choices=['present', 'absent'],
            default='present',
        ),
        name=dict(required=True),
        authz_name=dict(required=True, aliases=['domain']),
        namespace=dict(default=None),
    )
    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
    )

    if module._name == 'ovirt_groups':
        module.deprecate("The 'ovirt_groups' module is being renamed 'ovirt_group'", version=2.8)

    check_sdk(module)
    check_params(module)

    try:
        auth = module.params.pop('auth')
        connection = create_connection(auth)
        groups_service = connection.system_service().groups_service()
        groups_module = GroupsModule(
            connection=connection,
            module=module,
            service=groups_service,
        )
        group = _group(connection, module)
        state = module.params['state']
        if state == 'present':
            ret = groups_module.create(entity=group)
        elif state == 'absent':
            ret = groups_module.remove(entity=group)

        module.exit_json(**ret)
    except Exception as e:
        module.fail_json(msg=str(e), exception=traceback.format_exc())
    finally:
        connection.close(logout=auth.get('token') is None)
def main():
    module = AnsibleModule(
        argument_spec=dict(
            path=dict(type='path', required=True),
            passphrase=dict(type='str', no_log=True),
            return_private_key_data=dict(type='bool', default=False),
            select_crypto_backend=dict(
                type='str',
                default='auto',
                choices=['auto', 'cryptography', 'pyopenssl']),
        ),
        supports_check_mode=True,
    )

    try:
        base_dir = os.path.dirname(module.params['path']) or '.'
        if not os.path.isdir(base_dir):
            module.fail_json(
                name=base_dir,
                msg=
                'The directory %s does not exist or the file is not a directory'
                % base_dir)

        backend = module.params['select_crypto_backend']
        if backend == 'auto':
            # Detect what backend we can use
            can_use_cryptography = CRYPTOGRAPHY_FOUND and CRYPTOGRAPHY_VERSION >= LooseVersion(
                MINIMAL_CRYPTOGRAPHY_VERSION)
            can_use_pyopenssl = PYOPENSSL_FOUND and PYOPENSSL_VERSION >= LooseVersion(
                MINIMAL_PYOPENSSL_VERSION)

            # If cryptography is available we'll use it
            if can_use_cryptography:
                backend = 'cryptography'
            elif can_use_pyopenssl:
                backend = 'pyopenssl'

            # Fail if no backend has been found
            if backend == 'auto':
                module.fail_json(
                    msg=("Can't detect any of the required Python libraries "
                         "cryptography (>= {0}) or PyOpenSSL (>= {1})"
                         ).format(MINIMAL_CRYPTOGRAPHY_VERSION,
                                  MINIMAL_PYOPENSSL_VERSION))

        if backend == 'pyopenssl':
            if not PYOPENSSL_FOUND:
                module.fail_json(msg=missing_required_lib(
                    'pyOpenSSL >= {0}'.format(MINIMAL_PYOPENSSL_VERSION)),
                                 exception=PYOPENSSL_IMP_ERR)
            module.deprecate(
                'The module is using the PyOpenSSL backend. This backend has been deprecated',
                version='2.13')
            privatekey = PrivateKeyInfoPyOpenSSL(module)
        elif backend == 'cryptography':
            if not CRYPTOGRAPHY_FOUND:
                module.fail_json(msg=missing_required_lib(
                    'cryptography >= {0}'.format(
                        MINIMAL_CRYPTOGRAPHY_VERSION)),
                                 exception=CRYPTOGRAPHY_IMP_ERR)
            privatekey = PrivateKeyInfoCryptography(module)

        result = privatekey.get_info()
        module.exit_json(**result)
    except crypto_utils.OpenSSLObjectError as exc:
        module.fail_json(msg=to_native(exc))
def main():
    argument_spec = ovirt_full_argument_spec(
        state=dict(
            choices=['present', 'absent'],
            default='present',
        ),
        name=dict(required=True),
        data_center=dict(required=True),
        description=dict(default=None),
        cluster_threshold=dict(default=None,
                               type='int',
                               aliases=['cluster_soft_limit']),
        cluster_grace=dict(default=None,
                           type='int',
                           aliases=['cluster_hard_limit']),
        storage_threshold=dict(default=None,
                               type='int',
                               aliases=['storage_soft_limit']),
        storage_grace=dict(default=None,
                           type='int',
                           aliases=['storage_hard_limit']),
        clusters=dict(default=[], type='list'),
        storages=dict(default=[], type='list'),
    )
    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
    )

    if module._name == 'ovirt_quotas':
        module.deprecate(
            "The 'ovirt_quotas' module is being renamed 'ovirt_quota'",
            version=2.8)

    check_sdk(module)

    try:
        auth = module.params.pop('auth')
        connection = create_connection(auth)
        datacenters_service = connection.system_service().data_centers_service(
        )
        dc_name = module.params['data_center']
        dc_id = getattr(search_by_name(datacenters_service, dc_name), 'id',
                        None)
        if dc_id is None:
            raise Exception("Datacenter '%s' was not found." % dc_name)

        quotas_service = datacenters_service.service(dc_id).quotas_service()
        quotas_module = QuotasModule(
            connection=connection,
            module=module,
            service=quotas_service,
        )

        state = module.params['state']
        if state == 'present':
            ret = quotas_module.create()

            # Manage cluster limits:
            cl_limit_service = quotas_service.service(
                ret['id']).quota_cluster_limits_service()
            for cluster in module.params.get('clusters'):
                cl_limit_service.add(limit=otypes.QuotaClusterLimit(
                    memory_limit=float(cluster.get('memory')),
                    vcpu_limit=cluster.get('cpu'),
                    cluster=search_by_name(
                        connection.system_service().clusters_service(),
                        cluster.get('name')),
                ), )

            # Manage storage limits:
            sd_limit_service = quotas_service.service(
                ret['id']).quota_storage_limits_service()
            for storage in module.params.get('storages'):
                sd_limit_service.add(limit=otypes.QuotaStorageLimit(
                    limit=storage.get('size'),
                    storage_domain=search_by_name(
                        connection.system_service().storage_domains_service(),
                        storage.get('name')),
                ))

        elif state == 'absent':
            ret = quotas_module.remove()

        module.exit_json(**ret)
    except Exception as e:
        module.fail_json(msg=str(e), exception=traceback.format_exc())
    finally:
        connection.close(logout=auth.get('token') is None)
Beispiel #9
0
def main():
    """ main entry point for module execution
    """
    backup_spec = dict(filename=dict(), dir_path=dict(type='path'))
    argument_spec = dict(
        content=dict(aliases=['xml']),
        target=dict(choices=['auto', 'candidate', 'running'],
                    default='auto',
                    aliases=['datastore']),
        source_datastore=dict(aliases=['source']),
        format=dict(choices=['xml', 'text'], default='xml'),
        lock=dict(choices=['never', 'always', 'if-supported'],
                  default='always'),
        default_operation=dict(choices=['merge', 'replace', 'none']),
        confirm=dict(type='int', default=0),
        confirm_commit=dict(type='bool', default=False),
        error_option=dict(choices=[
            'stop-on-error', 'continue-on-error', 'rollback-on-error'
        ],
                          default='stop-on-error'),
        backup=dict(type='bool', default=False),
        backup_options=dict(type='dict', options=backup_spec),
        save=dict(type='bool', default=False),
        delete=dict(type='bool', default=False),
        commit=dict(type='bool', default=True),
        validate=dict(type='bool', default=False),
        get_filter=dict(),
    )

    # deprecated options
    netconf_top_spec = {
        'src':
        dict(type='path', removed_in_version=2.11),
        'host':
        dict(removed_in_version=2.11),
        'port':
        dict(removed_in_version=2.11, type='int', default=830),
        'username':
        dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME']),
             removed_in_version=2.11,
             no_log=True),
        'password':
        dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']),
             removed_in_version=2.11,
             no_log=True),
        'ssh_keyfile':
        dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']),
             removed_in_version=2.11,
             type='path'),
        'hostkey_verify':
        dict(removed_in_version=2.11, type='bool', default=True),
        'look_for_keys':
        dict(removed_in_version=2.11, type='bool', default=True),
        'timeout':
        dict(removed_in_version=2.11, type='int', default=10),
    }
    argument_spec.update(netconf_top_spec)

    mutually_exclusive = [('content', 'src', 'source', 'delete',
                           'confirm_commit')]
    required_one_of = [('content', 'src', 'source', 'delete', 'confirm_commit')
                       ]

    module = AnsibleModule(argument_spec=argument_spec,
                           required_one_of=required_one_of,
                           mutually_exclusive=mutually_exclusive,
                           supports_check_mode=True)

    if module.params['src']:
        module.deprecate(
            msg=
            "argument 'src' has been deprecated. Use file lookup plugin instead to read file contents.",
            version="2.11")

    config = module.params['content'] or module.params['src']
    target = module.params['target']
    lock = module.params['lock']
    source = module.params['source_datastore']
    delete = module.params['delete']
    confirm_commit = module.params['confirm_commit']
    confirm = module.params['confirm']
    validate = module.params['validate']
    save = module.params['save']
    filter = module.params['get_filter']
    filter_type = get_filter_type(filter)

    conn = Connection(module._socket_path)
    capabilities = get_capabilities(module)
    operations = capabilities['device_operations']

    supports_commit = operations.get('supports_commit', False)
    supports_writable_running = operations.get('supports_writable_running',
                                               False)
    supports_startup = operations.get('supports_startup', False)

    # identify target datastore
    if target == 'candidate' and not supports_commit:
        module.fail_json(
            msg=':candidate is not supported by this netconf server')
    elif target == 'running' and not supports_writable_running:
        module.fail_json(
            msg=':writable-running is not supported by this netconf server')
    elif target == 'auto':
        if supports_commit:
            target = 'candidate'
        elif supports_writable_running:
            target = 'running'
        else:
            module.fail_json(
                msg=
                'neither :candidate nor :writable-running are supported by this netconf server'
            )

    # Netconf server capability validation against input options
    if save and not supports_startup:
        module.fail_json(
            msg=
            'cannot copy <%s/> to <startup/>, while :startup is not supported'
            % target)

    if confirm_commit and not operations.get('supports_confirm_commit', False):
        module.fail_json(
            msg='confirm commit is not supported by Netconf server')

    if (confirm > 0) and not operations.get('supports_confirm_commit', False):
        module.fail_json(
            msg=
            'confirm commit is not supported by this netconf server, given confirm timeout: %d'
            % confirm)

    if validate and not operations.get('supports_validate', False):
        module.fail_json(
            msg='validate is not supported by this netconf server')

    if filter_type == 'xpath' and not operations.get('supports_xpath', False):
        module.fail_json(
            msg=
            "filter value '%s' of type xpath is not supported on this device" %
            filter)

    filter_spec = (filter_type, filter) if filter_type else None

    if lock == 'never':
        execute_lock = False
    elif target in operations.get('lock_datastore', []):
        # lock is requested (always/if-support) and supported => lets do it
        execute_lock = True
    else:
        # lock is requested (always/if-supported) but not supported => issue warning
        module.warn(
            "lock operation on '%s' source is not supported on this device" %
            target)
        execute_lock = (lock == 'always')

    result = {
        'changed': False,
        'server_capabilities': capabilities.get('server_capabilities', [])
    }
    before = None
    after = None
    locked = False
    try:
        if module.params['backup']:
            response = get_config(module,
                                  target,
                                  filter_spec,
                                  lock=execute_lock)
            before = to_text(tostring(response),
                             errors='surrogate_then_replace').strip()
            result['__backup__'] = before.strip()
        if validate:
            conn.validate(target)
        if source:
            if not module.check_mode:
                conn.copy(source, target)
            result['changed'] = True
        elif delete:
            if not module.check_mode:
                conn.delete(target)
            result['changed'] = True
        elif confirm_commit:
            if not module.check_mode:
                conn.commit()
            result['changed'] = True
        elif config:
            if module.check_mode and not supports_commit:
                module.warn(
                    "check mode not supported as Netconf server doesn't support candidate capability"
                )
                result['changed'] = True
                module.exit_json(**result)

            if execute_lock:
                conn.lock(target=target)
                locked = True
            if before is None:
                before = to_text(conn.get_config(source=target,
                                                 filter=filter_spec),
                                 errors='surrogate_then_replace').strip()

            kwargs = {
                'config': config,
                'target': target,
                'default_operation': module.params['default_operation'],
                'error_option': module.params['error_option'],
                'format': module.params['format'],
            }

            conn.edit_config(**kwargs)

            if supports_commit and module.params['commit']:
                after = to_text(conn.get_config(source='candidate',
                                                filter=filter_spec),
                                errors='surrogate_then_replace').strip()
                if not module.check_mode:
                    confirm_timeout = confirm if confirm > 0 else None
                    confirmed_commit = True if confirm_timeout else False
                    conn.commit(confirmed=confirmed_commit,
                                timeout=confirm_timeout)
                else:
                    conn.discard_changes()

            if after is None:
                after = to_text(conn.get_config(source='running',
                                                filter=filter_spec),
                                errors='surrogate_then_replace').strip()

            sanitized_before = sanitize_xml(before)
            sanitized_after = sanitize_xml(after)
            if sanitized_before != sanitized_after:
                result['changed'] = True

            if result['changed']:
                if save and not module.check_mode:
                    conn.copy_config(target, 'startup')
                if module._diff:
                    result['diff'] = {
                        'before': sanitized_before,
                        'after': sanitized_after
                    }

    except ConnectionError as e:
        module.fail_json(
            msg=to_text(e, errors='surrogate_then_replace').strip())
    finally:
        if locked:
            conn.unlock(target=target)

    module.exit_json(**result)
Beispiel #10
0
def main():
    helper = get_connection(
        vsys=True,
        rulebase=True,
        with_classic_provider_spec=True,
        panorama_error='Panorama is not supported',
        argument_spec=dict(
            rule_type=dict(default='security', choices=['security', 'nat']),
            source_zone=dict(),
            source_ip=dict(required=True),
            source_port=dict(type='int'),
            source_user=dict(),
            to_interface=dict(),
            destination_zone=dict(),
            destination_ip=dict(required=True),
            destination_port=dict(required=True, type='int'),
            application=dict(),
            protocol=dict(required=True, type='int'),
            category=dict(),

            # TODO(gfreeman) - Remove this in the next role release.
            vsys_id=dict(),
        ),
    )

    module = AnsibleModule(
        argument_spec=helper.argument_spec,
        supports_check_mode=False,
        required_one_of=helper.required_one_of,
    )

    # TODO(gfreeman) - Remove this in the next role release.
    if not HAS_LIB:
        module.fail_json(msg='Missing xmltodict library')
    if module.params['vsys_id'] is not None:
        module.fail_json(msg='Param "vsys_id" is removed; use vsys')

    parent = helper.get_pandevice_parent(module)

    params = (
        ('application', 'application', [
            'security',
        ]),
        ('category', 'category', [
            'security',
        ]),
        ('destination_ip', 'destination', ['security', 'nat']),
        ('destination_port', 'destination-port', ['security', 'nat']),
        ('source_zone', 'from', ['security', 'nat']),
        ('protocol', 'protocol', ['security', 'nat']),
        ('source_ip', 'source', ['security', 'nat']),
        ('source_user', 'source-user', [
            'security',
        ]),
        ('destination_zone', 'to', ['security', 'nat']),
        ('to_interface', 'to-interface', [
            'nat',
        ]),
    )

    cmd = []
    rtype = module.params['rule_type']

    if rtype == 'security':
        cmd.append('test security-policy-match')
        listing = SecurityRule.refreshall(parent)
    else:
        cmd.append('test nat-policy-match')
        listing = NatRule.refreshall(parent)

    for ansible_param, cmd_param, rule_types in params:
        if rtype not in rule_types or module.params[ansible_param] is None:
            continue
        cmd.append('{0} "{1}"'.format(cmd_param, module.params[ansible_param]))

    # Submit the op command with the appropriate test string
    test_string = ' '.join(cmd)
    try:
        response = helper.device.op(cmd=test_string, vsys=parent.vsys)
    except PanDeviceError as e:
        module.fail_json(msg='Failed "{0}": {1}'.format(test_string, e))

    elm = response.find('./result/rules/entry')
    if elm is not None:
        try:
            rule_name = elm.attrib['name']
        except KeyError:
            rule_name = elm.text
    else:
        module.exit_json(msg='No matching {0} rule.'.format(rtype))

    for x in listing:
        if x.name != rule_name:
            continue
        module.deprecate(
            'The "stdout_lines" output is deprecated; use "rule" instead',
            '2.12')
        module.exit_json(
            stdout_lines=json.dumps(xmltodict.parse(x.element_str()),
                                    indent=2),
            msg='Rule matched',
            rule=x.about(),
        )

    module.fail_json(
        msg='Matched "{0}" with "{1}", but wasn\'t in rulebase'.format(
            rule_name, test_string))
Beispiel #11
0
def main():
    argument_spec = ovirt_full_argument_spec(
        state=dict(
            choices=['present', 'absent'],
            default='present',
        ),
        cluster=dict(default=None, required=True),
        name=dict(default=None, required=True),
        description=dict(default=None),
        vm_enforcing=dict(default=None, type='bool'),
        vm_rule=dict(default=None, choices=['positive', 'negative', 'disabled']),
        host_enforcing=dict(default=None, type='bool'),
        host_rule=dict(default=None, choices=['positive', 'negative']),
        vms=dict(default=None, type='list'),
        hosts=dict(default=None, type='list'),
    )
    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
    )

    if module._name == 'ovirt_affinity_groups':
        module.deprecate("The 'ovirt_affinity_groups' module is being renamed 'ovirt_affinity_group'", version=2.8)

    check_sdk(module)
    try:
        auth = module.params.pop('auth')
        connection = create_connection(auth)
        # Check if unsupported parameters were passed:
        supported_41 = ('host_enforcing', 'host_rule', 'hosts')
        if not check_support(
            version='4.1',
            connection=connection,
            module=module,
            params=supported_41,
        ):
            module.fail_json(
                msg='Following parameters are supported since 4.1: {params}'.format(
                    params=supported_41,
                )
            )
        clusters_service = connection.system_service().clusters_service()
        vms_service = connection.system_service().vms_service()
        hosts_service = connection.system_service().hosts_service()
        cluster_name = module.params['cluster']
        cluster = search_by_name(clusters_service, cluster_name)
        if cluster is None:
            raise Exception("Cluster '%s' was not found." % cluster_name)
        cluster_service = clusters_service.cluster_service(cluster.id)
        affinity_groups_service = cluster_service.affinity_groups_service()

        # Fetch VM ids which should be assigned to affinity group:
        vm_ids = sorted([
            get_id_by_name(vms_service, vm_name)
            for vm_name in module.params['vms']
        ]) if module.params['vms'] is not None else None
        # Fetch host ids which should be assigned to affinity group:
        host_ids = sorted([
            get_id_by_name(hosts_service, host_name)
            for host_name in module.params['hosts']
        ]) if module.params['hosts'] is not None else None

        affinity_groups_module = AffinityGroupsModule(
            connection=connection,
            module=module,
            service=affinity_groups_service,
            vm_ids=vm_ids,
            host_ids=host_ids,
        )

        state = module.params['state']
        if state == 'present':
            ret = affinity_groups_module.create()
        elif state == 'absent':
            ret = affinity_groups_module.remove()

        module.exit_json(**ret)
    except Exception as e:
        module.fail_json(msg=str(e), exception=traceback.format_exc())
    finally:
        connection.close(logout=auth.get('token') is None)
Beispiel #12
0
def main():
    argument_spec = ovirt_full_argument_spec(
        state=dict(
            choices=['present', 'absent', 'attached', 'detached', 'exported'],
            default='present'
        ),
        id=dict(default=None),
        name=dict(default=None, aliases=['alias']),
        description=dict(default=None),
        vm_name=dict(default=None),
        vm_id=dict(default=None),
        size=dict(default=None),
        interface=dict(default=None,),
        storage_domain=dict(default=None),
        storage_domains=dict(default=None, type='list'),
        profile=dict(default=None),
        quota_id=dict(default=None),
        format=dict(default='cow', choices=['raw', 'cow']),
        sparse=dict(default=None, type='bool'),
        bootable=dict(default=None, type='bool'),
        shareable=dict(default=None, type='bool'),
        logical_unit=dict(default=None, type='dict'),
        download_image_path=dict(default=None),
        upload_image_path=dict(default=None, aliases=['image_path']),
        force=dict(default=False, type='bool'),
        sparsify=dict(default=None, type='bool'),
        openstack_volume_type=dict(default=None),
        image_provider=dict(default=None),
    )
    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
    )

    if module._name == 'ovirt_disks':
        module.deprecate("The 'ovirt_disks' module is being renamed 'ovirt_disk'", version=2.8)

    check_sdk(module)
    check_params(module)

    try:
        disk = None
        state = module.params['state']
        auth = module.params.get('auth')
        connection = create_connection(auth)
        disks_service = connection.system_service().disks_service()
        disks_module = DisksModule(
            connection=connection,
            module=module,
            service=disks_service,
        )

        lun = module.params.get('logical_unit')
        if lun:
            disk = _search_by_lun(disks_service, lun.get('id'))

        ret = None
        # First take care of creating the VM, if needed:
        if state in ('present', 'detached', 'attached'):
            ret = disks_module.create(
                entity=disk,
                result_state=otypes.DiskStatus.OK if lun is None else None,
                fail_condition=lambda d: d.status == otypes.DiskStatus.ILLEGAL if lun is None else False,
            )
            is_new_disk = ret['changed']
            ret['changed'] = ret['changed'] or disks_module.update_storage_domains(ret['id'])
            # We need to pass ID to the module, so in case we want detach/attach disk
            # we have this ID specified to attach/detach method:
            module.params['id'] = ret['id'] if disk is None else disk.id

            # Upload disk image in case it's new disk or force parameter is passed:
            if module.params['upload_image_path'] and (is_new_disk or module.params['force']):
                uploaded = upload_disk_image(connection, module)
                ret['changed'] = ret['changed'] or uploaded
            # Download disk image in case it's file don't exist or force parameter is passed:
            if (
                module.params['download_image_path'] and (not os.path.isfile(module.params['download_image_path']) or module.params['force'])
            ):
                downloaded = download_disk_image(connection, module)
                ret['changed'] = ret['changed'] or downloaded

            # Disk sparsify, only if disk is of image type:
            disk = disks_service.disk_service(module.params['id']).get()
            if disk.storage_type == otypes.DiskStorageType.IMAGE:
                ret = disks_module.action(
                    action='sparsify',
                    action_condition=lambda d: module.params['sparsify'],
                    wait_condition=lambda d: d.status == otypes.DiskStatus.OK,
                )

        # Export disk as image to glance domain
        elif state == 'exported':
            disk = disks_module.search_entity()
            if disk is None:
                module.fail_json(
                    msg="Can not export given disk '%s', it doesn't exist" %
                        module.params.get('name') or module.params.get('id')
                )
            if disk.storage_type == otypes.DiskStorageType.IMAGE:
                ret = disks_module.action(
                    action='export',
                    action_condition=lambda d: module.params['image_provider'],
                    wait_condition=lambda d: d.status == otypes.DiskStatus.OK,
                    storage_domain=otypes.StorageDomain(name=module.params['image_provider']),
                )
        elif state == 'absent':
            ret = disks_module.remove()

        # If VM was passed attach/detach disks to/from the VM:
        if module.params.get('vm_id') is not None or module.params.get('vm_name') is not None and state != 'absent':
            vms_service = connection.system_service().vms_service()

            # If `vm_id` isn't specified, find VM by name:
            vm_id = module.params['vm_id']
            if vm_id is None:
                vm_id = getattr(search_by_name(vms_service, module.params['vm_name']), 'id', None)

            if vm_id is None:
                module.fail_json(
                    msg="VM don't exists, please create it first."
                )

            disk_attachments_service = vms_service.vm_service(vm_id).disk_attachments_service()
            disk_attachments_module = DiskAttachmentsModule(
                connection=connection,
                module=module,
                service=disk_attachments_service,
                changed=ret['changed'] if ret else False,
            )

            if state == 'present' or state == 'attached':
                ret = disk_attachments_module.create()
                if lun is None:
                    wait(
                        service=disk_attachments_service.service(ret['id']),
                        condition=lambda d: follow_link(connection, d.disk).status == otypes.DiskStatus.OK,
                        wait=module.params['wait'],
                        timeout=module.params['timeout'],
                    )
            elif state == 'detached':
                ret = disk_attachments_module.remove()

        module.exit_json(**ret)
    except Exception as e:
        module.fail_json(msg=str(e), exception=traceback.format_exc())
    finally:
        connection.close(logout=auth.get('token') is None)
Beispiel #13
0
def main():
    """ main entry point for module execution
    """
    element_spec = dict(
        name=dict(),

        configured_password=dict(no_log=True),
        update_password=dict(default='always', choices=['on_create', 'always']),

        public_key=dict(),
        public_key_contents=dict(),

        group=dict(aliases=['role']),
        groups=dict(type='list', elements='dict'),

        state=dict(default='present', choices=['present', 'absent'])
    )
    aggregate_spec = deepcopy(element_spec)
    aggregate_spec['name'] = dict(required=True)

    # remove default in aggregate spec, to handle common arguments
    remove_default_spec(aggregate_spec)

    mutually_exclusive = [('name', 'aggregate'), ('public_key', 'public_key_contents'), ('group', 'groups')]

    argument_spec = dict(
        aggregate=dict(type='list', elements='dict', options=aggregate_spec, aliases=['users', 'collection'],
                       mutually_exclusive=mutually_exclusive),
        purge=dict(type='bool', default=False)
    )

    argument_spec.update(element_spec)
    argument_spec.update(iosxr_argument_spec)

    module = AnsibleModule(argument_spec=argument_spec,
                           mutually_exclusive=mutually_exclusive,
                           supports_check_mode=True)

    if (module.params['public_key_contents'] or module.params['public_key']):
        if not HAS_B64:
            module.fail_json(
                msg='library base64 is required but does not appear to be '
                    'installed. It can be installed using `pip install base64`'
            )
        if not HAS_PARAMIKO:
            module.fail_json(
                msg='library paramiko is required but does not appear to be '
                    'installed. It can be installed using `pip install paramiko`'
            )

    result = {'changed': False, 'warnings': []}
    if module.params['password'] and not module.params['configured_password']:
        result['warnings'].append(
            'The "password" argument is used to authenticate the current connection. ' +
            'To set a user password use "configured_password" instead.'
        )

    config_object = None
    if is_cliconf(module):
        module.deprecate(msg="cli support for 'iosxr_user' is deprecated. Use transport netconf instead",
                         version="4 releases from v2.5")
        config_object = CliConfiguration(module, result)
    elif is_netconf(module):
        config_object = NCConfiguration(module, result)

    if config_object:
        result = config_object.run()

    if module.params['public_key_contents'] or module.params['public_key']:
        pubkey_object = PublicKeyManager(module, result)
        result = pubkey_object.run()

    module.exit_json(**result)
Beispiel #14
0
def main():
    module = AnsibleModule(
        argument_spec=dict(
            path=dict(required=True, type='path'),
            follow=dict(type='bool', default='no'),
            get_md5=dict(type='bool'),
            get_checksum=dict(type='bool', default='yes'),
            get_mime=dict(type='bool', default='yes', aliases=['mime', 'mime_type', 'mime-type']),
            get_attributes=dict(type='bool', default='yes', 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_md5 = module.params.get('get_md5')

    # get_md5 will be an undocumented option in 2.9 to be removed at a later
    # date if possible (3.0+)
    if get_md5:
        module.deprecate("get_md5 has been deprecated along with the md5 return value, use "
                         "get_checksum=True and checksum_algorithm=md5 instead", 2.9)
    else:
        get_md5 = False
    get_checksum = module.params.get('get_checksum')
    checksum_algorithm = module.params.get('checksum_algorithm')

    # 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:
        pass

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

    # checksums
    if output.get('isreg') and output.get('readable'):
        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, '-i', b_path]
            try:
                rc, out, err = module.run_command(mimecmd)
                if rc == 0:
                    mimetype, charset = out.split(':')[1].split(';')
                    output['mimetype'] = mimetype.strip()
                    output['charset'] = charset.split('=')[1].strip()
            except:
                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)
def main():

    module = AnsibleModule(
        argument_spec=dict(
            cluster=dict(default='localhost'),
            port=dict(default='5433'),
            db=dict(default=None),
            login_user=dict(default='dbadmin'),
            login_password=dict(default=None, no_log=True),
        ), supports_check_mode=True)
    is_old_facts = module._name in ('vertica_facts', 'community.general.vertica_facts')
    if is_old_facts:
        module.deprecate("The 'vertica_facts' module has been renamed to 'vertica_info', "
                         "and the renamed one no longer returns ansible_facts", version='2.13')

    if not pyodbc_found:
        module.fail_json(msg=missing_required_lib('pyodbc'), exception=PYODBC_IMP_ERR)

    db = ''
    if module.params['db']:
        db = module.params['db']

    try:
        dsn = (
            "Driver=Vertica;"
            "Server=%s;"
            "Port=%s;"
            "Database=%s;"
            "User=%s;"
            "Password=%s;"
            "ConnectionLoadBalance=%s"
        ) % (module.params['cluster'], module.params['port'], db,
             module.params['login_user'], module.params['login_password'], 'true')
        db_conn = pyodbc.connect(dsn, autocommit=True)
        cursor = db_conn.cursor()
    except Exception as e:
        module.fail_json(msg="Unable to connect to database: %s." % to_native(e), exception=traceback.format_exc())

    try:
        schema_facts = get_schema_facts(cursor)
        user_facts = get_user_facts(cursor)
        role_facts = get_role_facts(cursor)
        configuration_facts = get_configuration_facts(cursor)
        node_facts = get_node_facts(cursor)

        if is_old_facts:
            module.exit_json(changed=False,
                             ansible_facts={'vertica_schemas': schema_facts,
                                            'vertica_users': user_facts,
                                            'vertica_roles': role_facts,
                                            'vertica_configuration': configuration_facts,
                                            'vertica_nodes': node_facts})
        else:
            module.exit_json(changed=False,
                             vertica_schemas=schema_facts,
                             vertica_users=user_facts,
                             vertica_roles=role_facts,
                             vertica_configuration=configuration_facts,
                             vertica_nodes=node_facts)
    except NotSupportedError as e:
        module.fail_json(msg=to_native(e), exception=traceback.format_exc())
    except SystemExit:
        # avoid catching this on python 2.4
        raise
    except Exception as e:
        module.fail_json(msg=to_native(e), exception=traceback.format_exc())
Beispiel #16
0
def main():
    argument_spec = ovirt_info_full_argument_spec(
        name=dict(default=None),
        host=dict(default=None),
        vm=dict(default=None),
    )
    module = AnsibleModule(argument_spec)
    is_old_facts = module._name in ('ovirt_affinity_label_facts', 'community.general.ovirt_affinity_label_facts')
    if is_old_facts:
        module.deprecate("The 'ovirt_affinity_label_facts' module has been renamed to 'ovirt_affinity_label_info', "
                         "and the renamed one no longer returns ansible_facts",
                         version='3.0.0', collection_name='community.general')  # was Ansible 2.13

    check_sdk(module)

    try:
        auth = module.params.pop('auth')
        connection = create_connection(auth)
        affinity_labels_service = connection.system_service().affinity_labels_service()
        labels = []
        all_labels = affinity_labels_service.list()
        if module.params['name']:
            labels.extend([
                l for l in all_labels
                if fnmatch.fnmatch(l.name, module.params['name'])
            ])
        if module.params['host']:
            hosts_service = connection.system_service().hosts_service()
            if search_by_name(hosts_service, module.params['host']) is None:
                raise Exception("Host '%s' was not found." % module.params['host'])
            labels.extend([
                label
                for label in all_labels
                for host in connection.follow_link(label.hosts)
                if fnmatch.fnmatch(hosts_service.service(host.id).get().name, module.params['host'])
            ])
        if module.params['vm']:
            vms_service = connection.system_service().vms_service()
            if search_by_name(vms_service, module.params['vm']) is None:
                raise Exception("Vm '%s' was not found." % module.params['vm'])
            labels.extend([
                label
                for label in all_labels
                for vm in connection.follow_link(label.vms)
                if fnmatch.fnmatch(vms_service.service(vm.id).get().name, module.params['vm'])
            ])

        if not (module.params['vm'] or module.params['host'] or module.params['name']):
            labels = all_labels

        result = dict(
            ovirt_affinity_labels=[
                get_dict_of_struct(
                    struct=l,
                    connection=connection,
                    fetch_nested=module.params.get('fetch_nested'),
                    attributes=module.params.get('nested_attributes'),
                ) for l in labels
            ],
        )
        if is_old_facts:
            module.exit_json(changed=False, ansible_facts=result)
        else:
            module.exit_json(changed=False, **result)
    except Exception as e:
        module.fail_json(msg=str(e), exception=traceback.format_exc())
    finally:
        connection.close(logout=auth.get('token') is None)
Beispiel #17
0
def main():
    argument_spec = dict(ip_address=dict(required=True),
                         password=dict(no_log=True),
                         username=dict(default='admin'),
                         api_key=dict(no_log=True),
                         sag_match_filter=dict(type='list',
                                               elements='str',
                                               required=False),
                         sag_name=dict(required=True),
                         commit=dict(type='bool', default=False),
                         devicegroup=dict(default=None),
                         description=dict(default=None),
                         tags=dict(type='list', elements='str', default=[]),
                         operation=dict(type='str',
                                        required=True,
                                        choices=['add', 'list', 'delete']))
    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=False,
                           required_one_of=[['api_key', 'password']])

    module.deprecate(
        'This module has been deprecated; use panos_address_group',
        version='3.0.0',
        collection_name='paloaltonetworks.panos')

    if not HAS_LIB:
        module.fail_json(msg='pan-python is required for this module')

    ip_address = module.params["ip_address"]
    password = module.params["password"]
    username = module.params['username']
    api_key = module.params['api_key']
    operation = module.params['operation']

    ag_object = create_address_group_object(
        address_gp_name=module.params.get('sag_name', None),
        sag_match_filter=module.params.get('sag_match_filter', None),
        description=module.params.get('description', None),
        tag_name=module.params.get('tags', None))
    commit = module.params['commit']

    devicegroup = module.params['devicegroup']
    # Create the device with the appropriate pandevice type
    device = base.PanDevice.create_from_device(ip_address,
                                               username,
                                               password,
                                               api_key=api_key)

    # If Panorama, validate the devicegroup
    dev_group = None
    if devicegroup and isinstance(device, panorama.Panorama):
        dev_group = get_devicegroup(device, devicegroup)
        if dev_group:
            device.add(dev_group)
        else:
            module.fail_json(
                msg=
                '\'%s\' device group not found in Panorama. Is the name correct?'
                % devicegroup)

    if operation == 'add':
        result, exc = add_address_group(device, dev_group, ag_object)

        if result and commit:
            try:
                device.commit(sync=True)
            except Exception:
                exc = get_exception()
                module.fail_json(msg=exc.message)
    elif operation == 'list':
        result, exc = get_all_address_group(device)

        if not exc:
            module.exit_json(msg=result)
        else:
            module.fail_json(msg=exc.message)
    elif operation == 'delete':
        obj_name = module.params.get('sag_name', None)
        result, exc = delete_address_group(device, dev_group, obj_name)
        if not result and exc:
            module.fail_json(msg=exc.message)
        elif not result:
            module.fail_json(msg="Specified object not found.")
    else:
        module.fail_json(changed=False, msg="Unsupported option.")

    module.exit_json(changed=True, msg="Address Group Operation Completed.")
Beispiel #18
0
def main():
    argument_spec = ovirt_info_full_argument_spec(
        name=dict(default=None),
        host=dict(default=None),
        vm=dict(default=None),
    )
    module = AnsibleModule(argument_spec)
    check_sdk(module)
    if module.params['fetch_nested'] or module.params['nested_attributes']:
        module.deprecate(
            "The 'fetch_nested' and 'nested_attributes' are deprecated please use 'follow' parameter",
            version='2.0.0',
            collection_name='ovirt.ovirt'
        )

    try:
        auth = module.params.pop('auth')
        connection = create_connection(auth)
        affinity_labels_service = connection.system_service().affinity_labels_service()
        labels = []
        all_labels = affinity_labels_service.list()
        if module.params['name']:
            labels.extend([
                l for l in all_labels
                if fnmatch.fnmatch(l.name, module.params['name'])
            ])
        if module.params['host']:
            hosts_service = connection.system_service().hosts_service()
            if search_by_name(hosts_service, module.params['host']) is None:
                raise Exception("Host '%s' was not found." % module.params['host'])
            labels.extend([
                label
                for label in all_labels
                for host in connection.follow_link(label.hosts)
                if fnmatch.fnmatch(hosts_service.service(host.id).get().name, module.params['host'])
            ])
        if module.params['vm']:
            vms_service = connection.system_service().vms_service()
            if search_by_name(vms_service, module.params['vm']) is None:
                raise Exception("Vm '%s' was not found." % module.params['vm'])
            labels.extend([
                label
                for label in all_labels
                for vm in connection.follow_link(label.vms)
                if fnmatch.fnmatch(vms_service.service(vm.id).get().name, module.params['vm'])
            ])

        if not (module.params['vm'] or module.params['host'] or module.params['name']):
            labels = all_labels

        result = dict(
            ovirt_affinity_labels=[
                get_dict_of_struct(
                    struct=l,
                    connection=connection,
                    fetch_nested=module.params.get('fetch_nested'),
                    attributes=module.params.get('nested_attributes'),
                ) for l in labels
            ],
        )
        module.exit_json(changed=False, **result)
    except Exception as e:
        module.fail_json(msg=str(e), exception=traceback.format_exc())
    finally:
        connection.close(logout=auth.get('token') is None)
Beispiel #19
0
def main():

    module = AnsibleModule(
        argument_spec=dict(
            name=dict(type='str', required=True),
            state=dict(type='str', required=True, choices=['absent', 'present']),
            # No longer used. Deprecated and due for removal
            createparent=dict(type='bool', default=None),
            extra_zfs_properties=dict(type='dict', default={}),
        ),
        supports_check_mode=True,
        # Remove this in Ansible 2.9
        check_invalid_arguments=False,
    )

    state = module.params.pop('state')
    name = module.params.pop('name')

    # The following is deprecated.  Remove in Ansible 2.9
    # Get all valid zfs-properties
    properties = dict()
    for prop, value in module.params.items():
        # All freestyle params are zfs properties
        if prop not in module.argument_spec:
            if isinstance(value, bool):
                if value is True:
                    properties[prop] = 'on'
                else:
                    properties[prop] = 'off'
            else:
                properties[prop] = value

    if properties:
        module.deprecate('Passing zfs properties as arbitrary parameters to the zfs module is'
                         ' deprecated.  Send them as a dictionary in the extra_zfs_properties'
                         ' parameter instead.', version='2.9')
        # Merge, giving the module_params precedence
        for prop, value in module.params['extra_zfs_properties'].items():
            properties[prop] = value

        module.params['extras_zfs_properties'] = properties
    # End deprecated section

    # Reverse the boolification of zfs properties
    for prop, value in module.params['extra_zfs_properties'].items():
        if isinstance(value, bool):
            if value is True:
                module.params['extra_zfs_properties'][prop] = 'on'
            else:
                module.params['extra_zfs_properties'][prop] = 'off'
        else:
            module.params['extra_zfs_properties'][prop] = value

    result = dict(
        name=name,
        state=state,
    )

    zfs = Zfs(module, name, module.params['extra_zfs_properties'])

    if state == 'present':
        if zfs.exists():
            zfs.set_properties_if_changed()
        else:
            zfs.create()

    elif state == 'absent':
        if zfs.exists():
            zfs.destroy()

    result.update(zfs.properties)
    result['changed'] = zfs.changed
    module.exit_json(**result)
Beispiel #20
0
def main():
    module = AnsibleModule(
        argument_spec=dict(
            path=dict(type='path', aliases=['dest', 'file']),
            xmlstring=dict(type='str'),
            xpath=dict(type='str'),
            namespaces=dict(type='dict', default={}),
            state=dict(type='str',
                       default='present',
                       choices=['absent', 'present'],
                       aliases=['ensure']),
            value=dict(type='raw'),
            attribute=dict(type='raw'),
            add_children=dict(type='list'),
            set_children=dict(type='list'),
            count=dict(type='bool', default=False),
            print_match=dict(type='bool', default=False),
            pretty_print=dict(type='bool', default=False),
            content=dict(type='str', choices=['attribute', 'text']),
            input_type=dict(type='str',
                            default='yaml',
                            choices=['xml', 'yaml']),
            backup=dict(type='bool', default=False),
            strip_cdata_tags=dict(type='bool', default=False),
            insertbefore=dict(type='bool', default=False),
            insertafter=dict(type='bool', default=False),
        ),
        supports_check_mode=True,
        required_by=dict(
            add_children=['xpath'],
            # TODO: Reinstate this in Ansible v2.12 when we have deprecated the incorrect use below
            # attribute=['value'],
            content=['xpath'],
            set_children=['xpath'],
            value=['xpath'],
        ),
        required_if=[
            ['count', True, ['xpath']],
            ['print_match', True, ['xpath']],
            ['insertbefore', True, ['xpath']],
            ['insertafter', True, ['xpath']],
        ],
        required_one_of=[
            ['path', 'xmlstring'],
            [
                'add_children', 'content', 'count', 'pretty_print',
                'print_match', 'set_children', 'value'
            ],
        ],
        mutually_exclusive=[
            [
                'add_children', 'content', 'count', 'print_match',
                'set_children', 'value'
            ],
            ['path', 'xmlstring'],
            ['insertbefore', 'insertafter'],
        ],
    )

    xml_file = module.params['path']
    xml_string = module.params['xmlstring']
    xpath = module.params['xpath']
    namespaces = module.params['namespaces']
    state = module.params['state']
    value = json_dict_bytes_to_unicode(module.params['value'])
    attribute = module.params['attribute']
    set_children = json_dict_bytes_to_unicode(module.params['set_children'])
    add_children = json_dict_bytes_to_unicode(module.params['add_children'])
    pretty_print = module.params['pretty_print']
    content = module.params['content']
    input_type = module.params['input_type']
    print_match = module.params['print_match']
    count = module.params['count']
    backup = module.params['backup']
    strip_cdata_tags = module.params['strip_cdata_tags']
    insertbefore = module.params['insertbefore']
    insertafter = module.params['insertafter']

    # Check if we have lxml 2.3.0 or newer installed
    if not HAS_LXML:
        module.fail_json(msg=missing_required_lib("lxml"),
                         exception=LXML_IMP_ERR)
    elif LooseVersion('.'.join(
            to_native(f) for f in etree.LXML_VERSION)) < LooseVersion('2.3.0'):
        module.fail_json(
            msg=
            'The xml ansible module requires lxml 2.3.0 or newer installed on the managed machine'
        )
    elif LooseVersion('.'.join(
            to_native(f) for f in etree.LXML_VERSION)) < LooseVersion('3.0.0'):
        module.warn(
            'Using lxml version lower than 3.0.0 does not guarantee predictable element attribute order.'
        )

    # Report wrongly used attribute parameter when using content=attribute
    # TODO: Remove this in Ansible v2.12 (and reinstate strict parameter test above) and remove the integration test example
    if content == 'attribute' and attribute is not None:
        module.deprecate(
            "Parameter 'attribute=%s' is ignored when using 'content=attribute' only 'xpath' is used. Please remove entry."
            % attribute, 'ansible.builtin:2.12')

    # Check if the file exists
    if xml_string:
        infile = BytesIO(to_bytes(xml_string, errors='surrogate_or_strict'))
    elif os.path.isfile(xml_file):
        infile = open(xml_file, 'rb')
    else:
        module.fail_json(msg="The target XML source '%s' does not exist." %
                         xml_file)

    # Parse and evaluate xpath expression
    if xpath is not None:
        try:
            etree.XPath(xpath)
        except etree.XPathSyntaxError as e:
            module.fail_json(msg="Syntax error in xpath expression: %s (%s)" %
                             (xpath, e))
        except etree.XPathEvalError as e:
            module.fail_json(
                msg="Evaluation error in xpath expression: %s (%s)" %
                (xpath, e))

    # Try to parse in the target XML file
    try:
        parser = etree.XMLParser(remove_blank_text=pretty_print,
                                 strip_cdata=strip_cdata_tags)
        doc = etree.parse(infile, parser)
    except etree.XMLSyntaxError as e:
        module.fail_json(msg="Error while parsing document: %s (%s)" %
                         (xml_file or 'xml_string', e))

    # Ensure we have the original copy to compare
    global orig_doc
    orig_doc = copy.deepcopy(doc)

    if print_match:
        do_print_match(module, doc, xpath, namespaces)

    if count:
        count_nodes(module, doc, xpath, namespaces)

    if content == 'attribute':
        get_element_attr(module, doc, xpath, namespaces)
    elif content == 'text':
        get_element_text(module, doc, xpath, namespaces)

    # File exists:
    if state == 'absent':
        # - absent: delete xpath target
        delete_xpath_target(module, doc, xpath, namespaces)

    # - present: carry on

    # children && value both set?: should have already aborted by now
    # add_children && set_children both set?: should have already aborted by now

    # set_children set?
    if set_children:
        set_target_children(module, doc, xpath, namespaces, set_children,
                            input_type)

    # add_children set?
    if add_children:
        add_target_children(module, doc, xpath, namespaces, add_children,
                            input_type, insertbefore, insertafter)

    # No?: Carry on

    # Is the xpath target an attribute selector?
    if value is not None:
        set_target(module, doc, xpath, namespaces, attribute, value)

    # If an xpath was provided, we need to do something with the data
    if xpath is not None:
        ensure_xpath_exists(module, doc, xpath, namespaces)

    # Otherwise only reformat the xml data?
    if pretty_print:
        make_pretty(module, doc)

    module.fail_json(msg="Don't know what to do")
Beispiel #21
0
def main():
    module = AnsibleModule(
        argument_spec=dict(
            state=dict(type='str', default='present', choices=['absent', 'build-dep', 'installed', 'latest', 'present', 'removed', 'present']),
            update_cache=dict(type='bool', aliases=['update-cache']),
            cache_valid_time=dict(type='int', default=0),
            purge=dict(type='bool', default=False),
            package=dict(type='list', 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']),
            dpkg_options=dict(type='str', default=DPKG_OPTIONS),
            autoremove=dict(type='bool', default=False),
            autoclean=dict(type='bool', default=False),
            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:
            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 and p.get('upgrade', None) in ['full', 'safe', 'yes']:
        module.warn("Could not find aptitude. Using apt-get instead.")
        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']
    autoclean = p['autoclean']

    # Deal with deprecated aliases
    if p['state'] == 'installed':
        module.deprecate("State 'installed' is deprecated. Using state 'present' instead.", version="2.9")
        p['state'] = 'present'
    if p['state'] == 'removed':
        module.deprecate("State 'removed' is deprecated. Using state 'absent' instead.", version="2.9")
        p['state'] = 'absent'

    # 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 up to 3 times
                err = ''
                for retry in range(3):
                    try:
                        cache.update()
                        break
                    except apt.cache.FetchFailedException as e:
                        err = to_native(e)
                else:
                    module.fail_json(msg='Failed to update apt cache: %s' % err)
                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, allow_unauthenticated)

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

        unfiltered_packages = p['package'] or ()
        packages = [package 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, 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'):
            state_upgrade = False
            state_builddep = False
            if p['state'] == 'latest':
                state_upgrade = True
            if p['state'] == 'build-dep':
                state_builddep = 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,
                autoremove=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:
        module.fail_json(msg="Failed to lock apt for exclusive operation")
    except apt.cache.FetchFailedException:
        module.fail_json(msg="Could not fetch updated apt files")
Beispiel #22
0
def main():
    argument_spec = ec2_argument_spec()
    argument_spec.update(
        dict(bucket=dict(required=True),
             dest=dict(default=None, type='path'),
             encrypt=dict(default=True, type='bool'),
             expiry=dict(default=600, type='int', aliases=['expiration']),
             headers=dict(type='dict'),
             marker=dict(default=""),
             max_keys=dict(default=1000, type='int'),
             metadata=dict(type='dict'),
             mode=dict(choices=[
                 'get', 'put', 'delete', 'create', 'geturl', 'getstr',
                 'delobj', 'list'
             ],
                       required=True),
             object=dict(),
             permission=dict(type='list', default=['private']),
             version=dict(default=None),
             overwrite=dict(aliases=['force'], default='always'),
             prefix=dict(default=""),
             retries=dict(aliases=['retry'], type='int', default=0),
             s3_url=dict(aliases=['S3_URL']),
             rgw=dict(default='no', type='bool'),
             src=dict(),
             ignore_nonexistent_bucket=dict(default=False, type='bool')), )
    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[('mode', 'put', ('src', ))],
    )

    if module._name == 's3':
        module.deprecate("The 's3' module is being renamed 'aws_s3'",
                         version=2.7)

    if not HAS_BOTO3:
        module.fail_json(msg='boto3 and botocore required for this module')

    bucket = module.params.get('bucket')
    encrypt = module.params.get('encrypt')
    expiry = module.params.get('expiry')
    dest = module.params.get('dest', '')
    headers = module.params.get('headers')
    marker = module.params.get('marker')
    max_keys = module.params.get('max_keys')
    metadata = module.params.get('metadata')
    mode = module.params.get('mode')
    obj = module.params.get('object')
    version = module.params.get('version')
    overwrite = module.params.get('overwrite')
    prefix = module.params.get('prefix')
    retries = module.params.get('retries')
    s3_url = module.params.get('s3_url')
    rgw = module.params.get('rgw')
    src = module.params.get('src')
    ignore_nonexistent_bucket = module.params.get('ignore_nonexistent_bucket')

    object_canned_acl = [
        "private", "public-read", "public-read-write", "aws-exec-read",
        "authenticated-read", "bucket-owner-read", "bucket-owner-full-control"
    ]
    bucket_canned_acl = [
        "private", "public-read", "public-read-write", "authenticated-read"
    ]

    if overwrite not in ['always', 'never', 'different']:
        if module.boolean(overwrite):
            overwrite = 'always'
        else:
            overwrite = 'never'

    region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module,
                                                                  boto3=True)

    if region in ('us-east-1', '', None):
        # default to US Standard region
        location = 'us-east-1'
    else:
        # Boto uses symbolic names for locations but region strings will
        # actually work fine for everything except us-east-1 (US Standard)
        location = region

    if module.params.get('object'):
        obj = module.params['object']
        # If there is a top level object, do nothing - if the object starts with /
        # remove the leading character to maintain compatibility with Ansible versions < 2.4
        if obj.startswith('/'):
            obj = obj[1:]

    # Bucket deletion does not require obj.  Prevents ambiguity with delobj.
    if obj and mode == "delete":
        module.fail_json(msg='Parameter obj cannot be used with mode=delete')

    # allow eucarc environment variables to be used if ansible vars aren't set
    if not s3_url and 'S3_URL' in os.environ:
        s3_url = os.environ['S3_URL']

    # rgw requires an explicit url
    if rgw and not s3_url:
        module.fail_json(msg='rgw flavour requires s3_url')

    # Look at s3_url and tweak connection settings
    # if connecting to RGW, Walrus or fakes3
    if s3_url:
        for key in ['validate_certs', 'security_token', 'profile_name']:
            aws_connect_kwargs.pop(key, None)
    try:
        s3 = get_s3_connection(module, aws_connect_kwargs, location, rgw,
                               s3_url)
    except botocore.exceptions.ProfileNotFound as e:
        module.fail_json(msg=to_native(e))

    validate = not ignore_nonexistent_bucket

    # separate types of ACLs
    bucket_acl = [
        acl for acl in module.params.get('permission')
        if acl in bucket_canned_acl
    ]
    object_acl = [
        acl for acl in module.params.get('permission')
        if acl in object_canned_acl
    ]
    error_acl = [
        acl for acl in module.params.get('permission')
        if acl not in bucket_canned_acl and acl not in object_canned_acl
    ]
    if error_acl:
        module.fail_json(msg='Unknown permission specified: %s' % error_acl)

    # First, we check to see if the bucket exists, we get "bucket" returned.
    bucketrtn = bucket_check(module, s3, bucket, validate=validate)

    if validate and mode not in ('create', 'put', 'delete') and not bucketrtn:
        module.fail_json(msg="Source bucket cannot be found.")

    # If our mode is a GET operation (download), go through the procedure as appropriate ...
    if mode == 'get':
        # Next, we check to see if the key in the bucket exists. If it exists, it also returns key_matches md5sum check.
        keyrtn = key_check(module,
                           s3,
                           bucket,
                           obj,
                           version=version,
                           validate=validate)
        if keyrtn is False:
            if version:
                module.fail_json(
                    msg="Key %s with version id %s does not exist." %
                    (obj, version))
            else:
                module.fail_json(msg="Key %s does not exist." % obj)

        # If the destination path doesn't exist or overwrite is True, no need to do the md5um etag check, so just download.
        # Compare the remote MD5 sum of the object with the local dest md5sum, if it already exists.
        if path_check(dest):
            # Determine if the remote and local object are identical
            if keysum(module, s3, bucket, obj,
                      version=version) == module.md5(dest):
                sum_matches = True
                if overwrite == 'always':
                    download_s3file(module,
                                    s3,
                                    bucket,
                                    obj,
                                    dest,
                                    retries,
                                    version=version)
                else:
                    module.exit_json(
                        msg=
                        "Local and remote object are identical, ignoring. Use overwrite=always parameter to force.",
                        changed=False)
            else:
                sum_matches = False

                if overwrite in ('always', 'different'):
                    download_s3file(module,
                                    s3,
                                    bucket,
                                    obj,
                                    dest,
                                    retries,
                                    version=version)
                else:
                    module.exit_json(
                        msg=
                        "WARNING: Checksums do not match. Use overwrite parameter to force download."
                    )
        else:
            download_s3file(module,
                            s3,
                            bucket,
                            obj,
                            dest,
                            retries,
                            version=version)

    # if our mode is a PUT operation (upload), go through the procedure as appropriate ...
    if mode == 'put':

        # if putting an object in a bucket yet to be created, acls for the bucket and/or the object may be specified
        # these were separated into the variables bucket_acl and object_acl above

        # Lets check the src path.
        if not path_check(src):
            module.fail_json(msg="Local object for PUT does not exist")

        # Lets check to see if bucket exists to get ground truth.
        if bucketrtn:
            keyrtn = key_check(module,
                               s3,
                               bucket,
                               obj,
                               version=version,
                               validate=validate)

        # Lets check key state. Does it exist and if it does, compute the etag md5sum.
        if bucketrtn and keyrtn:
            # Compare the local and remote object
            if module.md5(src) == keysum(module, s3, bucket, obj):
                sum_matches = True
                if overwrite == 'always':
                    # only use valid object acls for the upload_s3file function
                    module.params['permission'] = object_acl
                    upload_s3file(module, s3, bucket, obj, src, expiry,
                                  metadata, encrypt, headers)
                else:
                    get_download_url(module,
                                     s3,
                                     bucket,
                                     obj,
                                     expiry,
                                     changed=False)
            else:
                sum_matches = False
                if overwrite in ('always', 'different'):
                    # only use valid object acls for the upload_s3file function
                    module.params['permission'] = object_acl
                    upload_s3file(module, s3, bucket, obj, src, expiry,
                                  metadata, encrypt, headers)
                else:
                    module.exit_json(
                        msg=
                        "WARNING: Checksums do not match. Use overwrite parameter to force upload."
                    )

        # If neither exist (based on bucket existence), we can create both.
        if not bucketrtn:
            # only use valid bucket acls for create_bucket function
            module.params['permission'] = bucket_acl
            create_bucket(module, s3, bucket, location)
            # only use valid object acls for the upload_s3file function
            module.params['permission'] = object_acl
            upload_s3file(module, s3, bucket, obj, src, expiry, metadata,
                          encrypt, headers)

        # If bucket exists but key doesn't, just upload.
        if bucketrtn and not keyrtn:
            # only use valid object acls for the upload_s3file function
            module.params['permission'] = object_acl
            upload_s3file(module, s3, bucket, obj, src, expiry, metadata,
                          encrypt, headers)

    # Delete an object from a bucket, not the entire bucket
    if mode == 'delobj':
        if obj is None:
            module.fail_json(msg="object parameter is required")
        if bucket:
            deletertn = delete_key(module, s3, bucket, obj)
            if deletertn is True:
                module.exit_json(msg="Object deleted from bucket %s." % bucket,
                                 changed=True)
        else:
            module.fail_json(msg="Bucket parameter is required.")

    # Delete an entire bucket, including all objects in the bucket
    if mode == 'delete':
        if bucket:
            deletertn = delete_bucket(module, s3, bucket)
            if deletertn is True:
                module.exit_json(
                    msg="Bucket %s and all keys have been deleted." % bucket,
                    changed=True)
        else:
            module.fail_json(msg="Bucket parameter is required.")

    # Support for listing a set of keys
    if mode == 'list':
        exists = bucket_check(module, s3, bucket)

        # If the bucket does not exist then bail out
        if not exists:
            module.fail_json(msg="Target bucket (%s) cannot be found" % bucket)

        list_keys(module, s3, bucket, prefix, marker, max_keys)

    # Need to research how to create directories without "populating" a key, so this should just do bucket creation for now.
    # WE SHOULD ENABLE SOME WAY OF CREATING AN EMPTY KEY TO CREATE "DIRECTORY" STRUCTURE, AWS CONSOLE DOES THIS.
    if mode == 'create':

        # if both creating a bucket and putting an object in it, acls for the bucket and/or the object may be specified
        # these were separated above into the variables bucket_acl and object_acl

        if bucket and not obj:
            if bucketrtn:
                module.exit_json(msg="Bucket already exists.", changed=False)
            else:
                # only use valid bucket acls when creating the bucket
                module.params['permission'] = bucket_acl
                module.exit_json(msg="Bucket created successfully",
                                 changed=create_bucket(module, s3, bucket,
                                                       location))
        if bucket and obj:
            if obj.endswith('/'):
                dirobj = obj
            else:
                dirobj = obj + "/"
            if bucketrtn:
                if key_check(module, s3, bucket, dirobj):
                    module.exit_json(
                        msg="Bucket %s and key %s already exists." %
                        (bucket, obj),
                        changed=False)
                else:
                    # setting valid object acls for the create_dirkey function
                    module.params['permission'] = object_acl
                    create_dirkey(module, s3, bucket, dirobj)
            else:
                # only use valid bucket acls for the create_bucket function
                module.params['permission'] = bucket_acl
                created = create_bucket(module, s3, bucket, location)
                # only use valid object acls for the create_dirkey function
                module.params['permission'] = object_acl
                create_dirkey(module, s3, bucket, dirobj)

    # Support for grabbing the time-expired URL for an object in S3/Walrus.
    if mode == 'geturl':
        if not bucket and not obj:
            module.fail_json(msg="Bucket and Object parameters must be set")

        keyrtn = key_check(module,
                           s3,
                           bucket,
                           obj,
                           version=version,
                           validate=validate)
        if keyrtn:
            get_download_url(module, s3, bucket, obj, expiry)
        else:
            module.fail_json(msg="Key %s does not exist." % obj)

    if mode == 'getstr':
        if bucket and obj:
            keyrtn = key_check(module,
                               s3,
                               bucket,
                               obj,
                               version=version,
                               validate=validate)
            if keyrtn:
                download_s3str(module, s3, bucket, obj, version=version)
            elif version is not None:
                module.fail_json(
                    msg="Key %s with version id %s does not exist." %
                    (obj, version))
            else:
                module.fail_json(msg="Key %s does not exist." % obj)

    module.exit_json(failed=False)
def main():
    argument_spec = ec2_argument_spec()
    argument_spec.update(dict(
        dhcp_options_id=dict(type='str', default=None),
        domain_name=dict(type='str', default=None),
        dns_servers=dict(type='list', default=None),
        ntp_servers=dict(type='list', default=None),
        netbios_name_servers=dict(type='list', default=None),
        netbios_node_type=dict(type='int', default=None),
        vpc_id=dict(type='str', default=None),
        delete_old=dict(type='bool', default=True),
        inherit_existing=dict(type='bool', default=False),
        tags=dict(type='dict', default=None, aliases=['resource_tags']),
        state=dict(type='str', default='present', choices=['present', 'absent'])
    )
    )

    module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
    if module._name == 'ec2_vpc_dhcp_options':
        module.deprecate("The 'ec2_vpc_dhcp_options' module has been renamed "
                         "'ec2_vpc_dhcp_option' (option is no longer plural)",
                         version=2.8)

    params = module.params
    found = False
    changed = False
    new_options = collections.defaultdict(lambda: None)

    if not HAS_BOTO:
        module.fail_json(msg='boto is required for this module')

    region, ec2_url, boto_params = get_aws_connection_info(module)
    connection = connect_to_aws(boto.vpc, region, **boto_params)

    existing_options = None

    # First check if we were given a dhcp_options_id
    if not params['dhcp_options_id']:
        # No, so create new_options from the parameters
        if params['dns_servers'] is not None:
            new_options['domain-name-servers'] = params['dns_servers']
        if params['netbios_name_servers'] is not None:
            new_options['netbios-name-servers'] = params['netbios_name_servers']
        if params['ntp_servers'] is not None:
            new_options['ntp-servers'] = params['ntp_servers']
        if params['domain_name'] is not None:
            # needs to be a list for comparison with boto objects later
            new_options['domain-name'] = [params['domain_name']]
        if params['netbios_node_type'] is not None:
            # needs to be a list for comparison with boto objects later
            new_options['netbios-node-type'] = [str(params['netbios_node_type'])]
        # If we were given a vpc_id then we need to look at the options on that
        if params['vpc_id']:
            existing_options = fetch_dhcp_options_for_vpc(connection, params['vpc_id'])
            # if we've been asked to inherit existing options, do that now
            if params['inherit_existing']:
                if existing_options:
                    for option in ['domain-name-servers', 'netbios-name-servers', 'ntp-servers', 'domain-name', 'netbios-node-type']:
                        if existing_options.options.get(option) and new_options[option] != [] and (not new_options[option] or [''] == new_options[option]):
                            new_options[option] = existing_options.options.get(option)

            # Do the vpc's dhcp options already match what we're asked for? if so we are done
            if existing_options and new_options == existing_options.options:
                module.exit_json(changed=changed, new_options=new_options, dhcp_options_id=existing_options.id)

        # If no vpc_id was given, or the options don't match then look for an existing set using tags
        found, dhcp_option = match_dhcp_options(connection, params['tags'], new_options)

    # Now let's cover the case where there are existing options that we were told about by id
    # If a dhcp_options_id was supplied we don't look at options inside, just set tags (if given)
    else:
        supplied_options = connection.get_all_dhcp_options(filters={'dhcp-options-id': params['dhcp_options_id']})
        if len(supplied_options) != 1:
            if params['state'] != 'absent':
                module.fail_json(msg=" a dhcp_options_id was supplied, but does not exist")
        else:
            found = True
            dhcp_option = supplied_options[0]
            if params['state'] != 'absent' and params['tags']:
                ensure_tags(module, connection, dhcp_option.id, params['tags'], False, module.check_mode)

    # Now we have the dhcp options set, let's do the necessary

    # if we found options we were asked to remove then try to do so
    if params['state'] == 'absent':
        if not module.check_mode:
            if found:
                changed = remove_dhcp_options_by_id(connection, dhcp_option.id)
        module.exit_json(changed=changed, new_options={})

    # otherwise if we haven't found the required options we have something to do
    elif not module.check_mode and not found:

        # create some dhcp options if we weren't able to use existing ones
        if not found:
            # Convert netbios-node-type and domain-name back to strings
            if new_options['netbios-node-type']:
                new_options['netbios-node-type'] = new_options['netbios-node-type'][0]
            if new_options['domain-name']:
                new_options['domain-name'] = new_options['domain-name'][0]

            # create the new dhcp options set requested
            dhcp_option = connection.create_dhcp_options(
                new_options['domain-name'],
                new_options['domain-name-servers'],
                new_options['ntp-servers'],
                new_options['netbios-name-servers'],
                new_options['netbios-node-type'])

            # wait for dhcp option to be accessible
            found_dhcp_opt = False
            start_time = time()
            try:
                found_dhcp_opt = retry_not_found(connection.get_all_dhcp_options, dhcp_options_ids=[dhcp_option.id])
            except EC2ResponseError as e:
                module.fail_json(msg="Failed to describe DHCP options", exception=traceback.format_exc)
            if not found_dhcp_opt:
                module.fail_json(msg="Failed to wait for {0} to be available.".format(dhcp_option.id))

            changed = True
            if params['tags']:
                ensure_tags(module, connection, dhcp_option.id, params['tags'], False, module.check_mode)

    # If we were given a vpc_id, then attach the options we now have to that before we finish
    if params['vpc_id'] and not module.check_mode:
        changed = True
        connection.associate_dhcp_options(dhcp_option.id, params['vpc_id'])
        # and remove old ones if that was requested
        if params['delete_old'] and existing_options:
            remove_dhcp_options_by_id(connection, existing_options.id)

    module.exit_json(changed=changed, new_options=new_options, dhcp_options_id=dhcp_option.id)
Beispiel #24
0
def main():

    global module

    module = AnsibleModule(
        # 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'),
        ),
        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')

    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 _original_basename and dest.endswith(os.sep):
        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 AnsibleModuleError 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 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

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

    module.exit_json(**res_args)
def main():
    argument_spec = dict(
        ip_address=dict(required=True),
        password=dict(required=True, no_log=True),
        username=dict(default='admin'),
        rule_name=dict(required=True),
        from_zone=dict(type='list', required=True),
        to_zone=dict(required=True),
        source=dict(type='list', default=["any"]),
        destination=dict(type='list', default=["any"]),
        service=dict(default="any"),
        snat_type=dict(),
        snat_address=dict(),
        snat_interface=dict(),
        snat_interface_address=dict(),
        snat_bidirectional=dict(default=False),
        dnat_address=dict(),
        dnat_port=dict(),
        override=dict(type='bool', default=False),
        commit=dict(type='bool', default=True)
    )
    module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False)

    if module._name == 'panos_nat_policy':
        module.deprecate("The 'panos_nat_policy' module is being renamed 'panos_nat_rule'", version=2.8)

    if not HAS_LIB:
        module.fail_json(msg='pan-python is required for this module')

    ip_address = module.params["ip_address"]
    password = module.params["password"]
    username = module.params['username']

    xapi = pan.xapi.PanXapi(
        hostname=ip_address,
        api_username=username,
        api_password=password
    )

    rule_name = module.params['rule_name']
    from_zone = module.params['from_zone']
    to_zone = module.params['to_zone']
    source = module.params['source']
    destination = module.params['destination']
    service = module.params['service']

    snat_type = module.params['snat_type']
    snat_address = module.params['snat_address']
    snat_interface = module.params['snat_interface']
    snat_interface_address = module.params['snat_interface_address']
    snat_bidirectional = module.params['snat_bidirectional']

    dnat_address = module.params['dnat_address']
    dnat_port = module.params['dnat_port']
    commit = module.params['commit']

    override = module.params["override"]
    if not override and nat_rule_exists(xapi, rule_name):
        module.exit_json(changed=False, msg="rule exists")

    try:
        changed = add_nat(
            xapi,
            module,
            rule_name,
            from_zone,
            to_zone,
            source,
            destination,
            service,
            dnatxml=dnat_xml(module, dnat_address, dnat_port),
            snatxml=snat_xml(module, snat_type, snat_address,
                             snat_interface, snat_interface_address,
                             snat_bidirectional)
        )

        if changed and commit:
            xapi.commit(cmd="<commit></commit>", sync=True, interval=1)

        module.exit_json(changed=changed, msg="okey dokey")

    except PanXapiError as exc:
        module.fail_json(msg=to_native(exc))
Beispiel #26
0
def main():
    helper = get_connection(
        vsys=True,
        device_group=True,
        rulebase=True,
        with_state=True,
        with_classic_provider_spec=True,
        error_on_shared=True,
        argument_spec=dict(
            rule_name=dict(required=True),
            source_zone=dict(type='list', default=['any']),
            source_ip=dict(type='list', default=["any"]),
            source_user=dict(type='list', default=['any']),
            hip_profiles=dict(type='list', default=['any']),
            destination_zone=dict(type='list', default=['any']),
            destination_ip=dict(type='list', default=["any"]),
            application=dict(type='list', default=['any']),
            service=dict(type='list', default=['application-default']),
            category=dict(type='list', default=['any']),
            action=dict(
                default='allow',
                choices=[
                    'allow', 'deny', 'drop', 'reset-client', 'reset-server',
                    'reset-both'
                ],
            ),
            log_setting=dict(),
            log_start=dict(type='bool', default=False),
            log_end=dict(type='bool', default=True),
            description=dict(),
            rule_type=dict(default='universal',
                           choices=['universal', 'intrazone', 'interzone']),
            tag_name=dict(type='list'),
            negate_source=dict(type='bool', default=False),
            negate_destination=dict(type='bool', default=False),
            disabled=dict(type='bool', default=False),
            schedule=dict(),
            icmp_unreachable=dict(type='bool'),
            disable_server_response_inspection=dict(type='bool',
                                                    default=False),
            group_profile=dict(),
            antivirus=dict(),
            spyware=dict(),
            vulnerability=dict(),
            url_filtering=dict(),
            file_blocking=dict(),
            wildfire_analysis=dict(),
            data_filtering=dict(),
            target=dict(type='list'),
            negate_target=dict(type='bool'),
            location=dict(choices=['top', 'bottom', 'before', 'after']),
            existing_rule=dict(),
            commit=dict(type='bool', default=True),

            # TODO(gfreeman) - remove this in the next role release.
            operation=dict(),

            # TODO(gfreeman) - remove this in the next role release.
            devicegroup=dict(),
        ),
    )
    module = AnsibleModule(
        argument_spec=helper.argument_spec,
        supports_check_mode=True,
        required_one_of=helper.required_one_of,
    )

    # TODO(gfreeman) - removed when operation is removed.
    if module.params['operation'] is not None:
        module.fail_json(
            msg='Param "operation" is removed; use "state" instead')

    # TODO(gfreeman) - remove when devicegroup is removed.
    if module.params['devicegroup'] is not None:
        module.deprecate(
            'Param "devicegroup" is deprecated; use "device_group"', '2.12')
        if module.params['device_group'] is not None:
            msg = [
                'Both "devicegroup" and "device_group" are specified',
                'Specify one or the other, not both.',
            ]
            module.fail_json(msg='. '.join(msg))
        module.params['device_group'] = module.params['devicegroup']

    # Verify imports, build pandevice object tree.
    parent = helper.get_pandevice_parent(module)

    # Set the SecurityRule object params.
    rule_spec = {
        'name':
        module.params['rule_name'],
        'fromzone':
        module.params['source_zone'],
        'tozone':
        module.params['destination_zone'],
        'source':
        module.params['source_ip'],
        'source_user':
        module.params['source_user'],
        'hip_profiles':
        module.params['hip_profiles'],
        'destination':
        module.params['destination_ip'],
        'application':
        module.params['application'],
        'service':
        module.params['service'],
        'category':
        module.params['category'],
        'action':
        module.params['action'],
        'log_setting':
        module.params['log_setting'],
        'log_start':
        module.params['log_start'],
        'log_end':
        module.params['log_end'],
        'description':
        module.params['description'],
        'type':
        module.params['rule_type'],
        'tag':
        module.params['tag_name'],
        'negate_source':
        module.params['negate_source'],
        'negate_destination':
        module.params['negate_destination'],
        'disabled':
        module.params['disabled'],
        'schedule':
        module.params['schedule'],
        'icmp_unreachable':
        module.params['icmp_unreachable'],
        'disable_server_response_inspection':
        module.params['disable_server_response_inspection'],
        'group':
        module.params['group_profile'],
        'virus':
        module.params['antivirus'],
        'spyware':
        module.params['spyware'],
        'vulnerability':
        module.params['vulnerability'],
        'url_filtering':
        module.params['url_filtering'],
        'file_blocking':
        module.params['file_blocking'],
        'wildfire_analysis':
        module.params['wildfire_analysis'],
        'data_filtering':
        module.params['data_filtering'],
        'target':
        module.params['target'],
        'negate_target':
        module.params['negate_target'],
    }

    # Other module info.
    location = module.params['location']
    existing_rule = module.params['existing_rule']
    commit = module.params['commit']

    # Retrieve the current rules.
    try:
        rules = SecurityRule.refreshall(parent, add=False)
    except PanDeviceError as e:
        module.fail_json(msg='Failed refresh: {0}'.format(e))

    # Create new rule object from the params.
    new_rule = SecurityRule(**rule_spec)
    parent.add(new_rule)

    # Which action shall we take on the rule object?
    changed = helper.apply_state(new_rule, rules, module)

    # Move the rule to the correct spot, if applicable.
    if module.params['state'] == 'present':
        changed |= helper.apply_position(new_rule, location, existing_rule,
                                         module)

    # Optional commit.
    if changed and commit:
        helper.commit(module)

    # Done.
    module.exit_json(changed=changed, msg='Done')
def main():
    argument_spec = ovirt_full_argument_spec(
        state=dict(
            choices=['present', 'absent'],
            default='present',
        ),
        name=dict(default=None),
        description=dict(default=None),
        type=dict(
            default=None,
            required=True,
            choices=[
                'os_image',
                'network',
                'os_volume',
                'foreman',
            ],
            aliases=['provider'],
        ),
        url=dict(default=None),
        username=dict(default=None),
        password=dict(default=None, no_log=True),
        tenant_name=dict(default=None, aliases=['tenant']),
        authentication_url=dict(default=None, aliases=['auth_url']),
        data_center=dict(default=None),
        read_only=dict(default=None, type='bool'),
        network_type=dict(
            default='external',
            choices=['external', 'neutron'],
        ),
    )
    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
    )

    if module._name == 'ovirt_external_providers':
        module.deprecate(
            "The 'ovirt_external_providers' module is being renamed 'ovirt_external_provider'",
            version=2.8)

    check_sdk(module)
    check_params(module)

    try:
        auth = module.params.pop('auth')
        connection = create_connection(auth)
        provider_type, external_providers_service = _external_provider_service(
            provider_type=module.params.get('type'),
            system_service=connection.system_service(),
        )
        external_providers_module = ExternalProviderModule(
            connection=connection,
            module=module,
            service=external_providers_service,
        )
        external_providers_module.provider_type(provider_type)

        state = module.params.pop('state')
        if state == 'absent':
            ret = external_providers_module.remove()
        elif state == 'present':
            ret = external_providers_module.create()

        module.exit_json(**ret)
    except Exception as e:
        module.fail_json(msg=str(e), exception=traceback.format_exc())
    finally:
        connection.close(logout=auth.get('token') is None)
Beispiel #28
0
def main():
    argument_spec = vmware_argument_spec()
    argument_spec.update(
        dict(hostname=dict(required=False, aliases=['host']),
             username=dict(required=False, aliases=['login']),
             src=dict(required=True, aliases=['name']),
             datacenter=dict(required=False),
             datastore=dict(required=True),
             dest=dict(required=True, aliases=['path']),
             timeout=dict(default=10, type='int')))

    module = AnsibleModule(
        argument_spec=argument_spec,
        # Implementing check-mode using HEAD is impossible, since size/date is not 100% reliable
        supports_check_mode=False,
    )

    if module.params.get('host'):
        module.deprecate("The 'host' option is being replaced by 'hostname'",
                         version='2.12')
    if module.params.get('login'):
        module.deprecate("The 'login' option is being replaced by 'username'",
                         version='2.12')

    hostname = module.params['hostname']
    username = module.params['username']
    password = module.params.get('password')
    src = module.params.get('src')
    datacenter = module.params.get('datacenter')
    datastore = module.params.get('datastore')
    dest = module.params.get('dest')
    validate_certs = module.params.get('validate_certs')
    timeout = module.params.get('timeout')

    try:
        fd = open(src, "rb")
        atexit.register(fd.close)
    except Exception as e:
        module.fail_json(msg="Failed to open src file %s" % to_native(e))

    if os.stat(src).st_size == 0:
        data = ''
    else:
        data = mmap.mmap(fd.fileno(), 0, access=mmap.ACCESS_READ)
        atexit.register(data.close)

    remote_path = vmware_path(datastore, datacenter, dest)

    if not all([hostname, username, password]):
        module.fail_json(
            msg=
            "One of following parameter is missing - hostname, username, password"
        )
    url = 'https://%s%s' % (hostname, remote_path)

    headers = {
        "Content-Type": "application/octet-stream",
        "Content-Length": str(len(data)),
    }

    try:
        r = open_url(url,
                     data=data,
                     headers=headers,
                     method='PUT',
                     timeout=timeout,
                     url_username=username,
                     url_password=password,
                     validate_certs=validate_certs,
                     force_basic_auth=True)
    except socket.error as e:
        if isinstance(e.args, tuple):
            if len(e.args) > 0:
                if e[0] == errno.ECONNRESET:
                    # vSphere resets connection if the file is in use and cannot be replaced
                    module.fail_json(
                        msg='Failed to upload, image probably in use',
                        status=None,
                        errno=e[0],
                        reason=to_native(e),
                        url=url)
            else:
                module.fail_json(msg=to_native(e))
        else:
            module.fail_json(msg=str(e),
                             status=None,
                             errno=e[0],
                             reason=str(e),
                             url=url,
                             exception=traceback.format_exc())
    except Exception as e:
        error_code = -1
        try:
            if isinstance(e[0], int):
                error_code = e[0]
        except (KeyError, TypeError):
            pass
        module.fail_json(msg=to_native(e),
                         status=None,
                         errno=error_code,
                         reason=to_native(e),
                         url=url,
                         exception=traceback.format_exc())

    status = r.getcode()
    if 200 <= status < 300:
        module.exit_json(changed=True, status=status, reason=r.msg, url=url)
    else:
        length = r.headers.get('content-length', None)
        if r.headers.get('transfer-encoding', '').lower() == 'chunked':
            chunked = 1
        else:
            chunked = 0

        module.fail_json(msg='Failed to upload',
                         errno=None,
                         status=status,
                         reason=r.msg,
                         length=length,
                         headers=dict(r.headers),
                         chunked=chunked,
                         url=url)
Beispiel #29
0
def main():
    argument_spec = url_argument_spec()
    argument_spec.update(dict(
        dest=dict(type='path'),
        url_username=dict(type='str', aliases=['user']),
        url_password=dict(type='str', aliases=['password'], no_log=True),
        body=dict(type='raw'),
        body_format=dict(type='str', default='raw', choices=['raw', 'json']),
        method=dict(type='str', default='GET', choices=['GET', 'POST', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'PATCH', 'TRACE', 'CONNECT', 'REFRESH']),
        return_content=dict(type='bool', default='no'),
        follow_redirects=dict(type='str', default='safe', choices=['all', 'safe', 'none', 'yes', 'no']),
        creates=dict(type='path'),
        removes=dict(type='path'),
        status_code=dict(type='list', default=[200]),
        timeout=dict(type='int', default=30),
        headers=dict(type='dict', default={})
    ))

    module = AnsibleModule(
        argument_spec=argument_spec,
        check_invalid_arguments=False,
        add_file_common_args=True
    )

    url = module.params['url']
    body = module.params['body']
    body_format = module.params['body_format'].lower()
    method = module.params['method']
    dest = module.params['dest']
    return_content = module.params['return_content']
    creates = module.params['creates']
    removes = module.params['removes']
    status_code = [int(x) for x in list(module.params['status_code'])]
    socket_timeout = module.params['timeout']

    dict_headers = module.params['headers']

    if body_format == 'json':
        # Encode the body unless its a string, then assume it is pre-formatted JSON
        if not isinstance(body, six.string_types):
            body = json.dumps(body)
        lower_header_keys = [key.lower() for key in dict_headers]
        if 'content-type' not in lower_header_keys:
            dict_headers['Content-Type'] = 'application/json'

    # Grab all the http headers. Need this hack since passing multi-values is
    # currently a bit ugly. (e.g. headers='{"Content-Type":"application/json"}')
    for key, value in six.iteritems(module.params):
        if key.startswith("HEADER_"):
            module.deprecate('Supplying headers via HEADER_* is deprecated and '
                             'will be removed in a future version. Please use '
                             '`headers` to supply headers for the request')
            skey = key.replace("HEADER_", "")
            dict_headers[skey] = value

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

    if removes is not None:
        # do not run the command if the line contains removes=filename
        # and the filename do not exists.  This allows idempotence
        # of uri executions.
        if not os.path.exists(removes):
            module.exit_json(stdout="skipped, since '%s' does not exist" % removes, changed=False, rc=0)

    # Make the request
    resp, content, dest = uri(module, url, dest, body, body_format, method,
                              dict_headers, socket_timeout)
    resp['status'] = int(resp['status'])

    # Write the file out if requested
    if dest is not None:
        if resp['status'] == 304:
            changed = False
        else:
            write_file(module, url, dest, content)
            # allow file attribute changes
            changed = True
            module.params['path'] = dest
            file_args = module.load_file_common_arguments(module.params)
            file_args['path'] = dest
            changed = module.set_fs_attributes_if_different(file_args, changed)
        resp['path'] = dest
    else:
        changed = False

    # Transmogrify the headers, replacing '-' with '_', since variables don't
    # work with dashes.
    # In python3, the headers are title cased.  Lowercase them to be
    # compatible with the python2 behaviour.
    uresp = {}
    for key, value in six.iteritems(resp):
        ukey = key.replace("-", "_").lower()
        uresp[ukey] = value

    try:
        uresp['location'] = absolute_location(url, uresp['location'])
    except KeyError:
        pass

    # Default content_encoding to try
    content_encoding = 'utf-8'
    if 'content_type' in uresp:
        content_type, params = cgi.parse_header(uresp['content_type'])
        if 'charset' in params:
            content_encoding = params['charset']
        u_content = to_text(content, encoding=content_encoding)
        if 'application/json' in content_type or 'text/json' in content_type:
            try:
                js = json.loads(u_content)
                uresp['json'] = js
            except:
                pass
    else:
        u_content = to_text(content, encoding=content_encoding)

    if resp['status'] not in status_code:
        uresp['msg'] = 'Status code was not %s: %s' % (status_code, uresp.get('msg', ''))
        module.fail_json(content=u_content, **uresp)
    elif return_content:
        module.exit_json(changed=changed, content=u_content, **uresp)
    else:
        module.exit_json(changed=changed, **uresp)
def main():
    argument_spec = ovirt_full_argument_spec(
        state=dict(
            choices=['present', 'absent'],
            default='present',
        ),
        data_center=dict(required=True),
        id=dict(default=None),
        name=dict(required=True),
        description=dict(default=None),
        comment=dict(default=None),
        vlan_tag=dict(default=None, type='int'),
        vm_network=dict(default=None, type='bool'),
        mtu=dict(default=None, type='int'),
        clusters=dict(default=None, type='list'),
        label=dict(default=None),
    )
    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
    )

    if module._name == 'ovirt_networks':
        module.deprecate(
            "The 'ovirt_networks' module is being renamed 'ovirt_network'",
            version=2.8)

    check_sdk(module)
    check_params(module)

    try:
        auth = module.params.pop('auth')
        connection = create_connection(auth)
        clusters_service = connection.system_service().clusters_service()
        networks_service = connection.system_service().networks_service()
        networks_module = NetworksModule(
            connection=connection,
            module=module,
            service=networks_service,
        )
        state = module.params['state']
        search_params = {
            'name': module.params['name'],
            'datacenter': module.params['data_center'],
        }
        if state == 'present':
            ret = networks_module.create(search_params=search_params)

            # Update clusters networks:
            if module.params.get('clusters') is not None:
                for param_cluster in module.params.get('clusters'):
                    cluster = search_by_name(clusters_service,
                                             param_cluster.get('name'))
                    if cluster is None:
                        raise Exception("Cluster '%s' was not found." %
                                        param_cluster.get('name'))
                    cluster_networks_service = clusters_service.service(
                        cluster.id).networks_service()
                    cluster_networks_module = ClusterNetworksModule(
                        network_id=ret['id'],
                        cluster_network=param_cluster,
                        connection=connection,
                        module=module,
                        service=cluster_networks_service,
                    )
                    if param_cluster.get('assigned', True):
                        ret = cluster_networks_module.create()
                    else:
                        ret = cluster_networks_module.remove()

        elif state == 'absent':
            ret = networks_module.remove(search_params=search_params)

        module.exit_json(**ret)
    except Exception as e:
        module.fail_json(msg=str(e), exception=traceback.format_exc())
    finally:
        connection.close(logout=auth.get('token') is None)
Beispiel #31
0
class AzureRMModuleBase(object):
    def __init__(self,
                 derived_arg_spec,
                 bypass_checks=False,
                 no_log=False,
                 check_invalid_arguments=None,
                 mutually_exclusive=None,
                 required_together=None,
                 required_one_of=None,
                 add_file_common_args=False,
                 supports_check_mode=False,
                 required_if=None,
                 supports_tags=True,
                 facts_module=False,
                 skip_exec=False):

        merged_arg_spec = dict()
        merged_arg_spec.update(AZURE_COMMON_ARGS)
        if supports_tags:
            merged_arg_spec.update(AZURE_TAG_ARGS)

        if derived_arg_spec:
            merged_arg_spec.update(derived_arg_spec)

        merged_required_if = list(AZURE_COMMON_REQUIRED_IF)
        if required_if:
            merged_required_if += required_if

        self.module = AnsibleModule(
            argument_spec=merged_arg_spec,
            bypass_checks=bypass_checks,
            no_log=no_log,
            check_invalid_arguments=check_invalid_arguments,
            mutually_exclusive=mutually_exclusive,
            required_together=required_together,
            required_one_of=required_one_of,
            add_file_common_args=add_file_common_args,
            supports_check_mode=supports_check_mode,
            required_if=merged_required_if)

        if not HAS_PACKAGING_VERSION:
            self.fail(
                "Do you have packaging installed? Try `pip install packaging`"
                "- {0}".format(HAS_PACKAGING_VERSION_EXC))

        if not HAS_MSRESTAZURE:
            self.fail(
                "Do you have msrestazure installed? Try `pip install msrestazure`"
                "- {0}".format(HAS_MSRESTAZURE_EXC))

        if not HAS_AZURE:
            self.fail(
                "Do you have azure>={1} installed? Try `pip install ansible[azure]`"
                "- {0}".format(HAS_AZURE_EXC, AZURE_MIN_RELEASE))

        self._cloud_environment = None
        self._network_client = None
        self._storage_client = None
        self._resource_client = None
        self._compute_client = None
        self._dns_client = None
        self._web_client = None
        self._containerservice_client = None
        self._mysql_client = None
        self._postgresql_client = None
        self._adfs_authority_url = None
        self._resource = None

        self.check_mode = self.module.check_mode
        self.api_profile = self.module.params.get('api_profile')
        self.facts_module = facts_module

        # authenticate
        self.credentials = self._get_credentials(self.module.params)
        if not self.credentials:
            if HAS_AZURE_CLI_CORE:
                self.fail(
                    "Failed to get credentials. Either pass as parameters, set environment variables, "
                    "define a profile in ~/.azure/credentials, or log in with Azure CLI (`az login`)."
                )
            else:
                self.fail(
                    "Failed to get credentials. Either pass as parameters, set environment variables, "
                    "define a profile in ~/.azure/credentials, or install Azure CLI and log in (`az login`)."
                )

        # cert validation mode precedence: module-arg, credential profile, env, "validate"
        self._cert_validation_mode = self.module.params['cert_validation_mode'] or self.credentials.get('cert_validation_mode') or \
            os.environ.get('AZURE_CERT_VALIDATION_MODE') or 'validate'

        if self._cert_validation_mode not in ['validate', 'ignore']:
            self.fail('invalid cert_validation_mode: {0}'.format(
                self._cert_validation_mode))

        # if cloud_environment specified, look up/build Cloud object
        raw_cloud_env = self.credentials.get('cloud_environment')
        if self.credentials.get(
                'credentials') is not None and raw_cloud_env is not None:
            self._cloud_environment = raw_cloud_env
        elif not raw_cloud_env:
            self._cloud_environment = azure_cloud.AZURE_PUBLIC_CLOUD  # SDK default
        else:
            # try to look up "well-known" values via the name attribute on azure_cloud members
            all_clouds = [
                x[1] for x in inspect.getmembers(azure_cloud)
                if isinstance(x[1], azure_cloud.Cloud)
            ]
            matched_clouds = [x for x in all_clouds if x.name == raw_cloud_env]
            if len(matched_clouds) == 1:
                self._cloud_environment = matched_clouds[0]
            elif len(matched_clouds) > 1:
                self.fail(
                    "Azure SDK failure: more than one cloud matched for cloud_environment name '{0}'"
                    .format(raw_cloud_env))
            else:
                if not urlparse.urlparse(raw_cloud_env).scheme:
                    self.fail(
                        "cloud_environment must be an endpoint discovery URL or one of {0}"
                        .format([x.name for x in all_clouds]))
                try:
                    self._cloud_environment = azure_cloud.get_cloud_from_metadata_endpoint(
                        raw_cloud_env)
                except Exception as e:
                    self.fail(
                        "cloud_environment {0} could not be resolved: {1}".
                        format(raw_cloud_env, e.message),
                        exception=traceback.format_exc(e))

        if self.credentials.get(
                'subscription_id',
                None) is None and self.credentials.get('credentials') is None:
            self.fail("Credentials did not include a subscription_id value.")
        self.log("setting subscription_id")
        self.subscription_id = self.credentials['subscription_id']

        # get authentication authority
        # for adfs, user could pass in authority or not.
        # for others, use default authority from cloud environment
        if self.credentials.get('adfs_authority_url') is None:
            self._adfs_authority_url = self._cloud_environment.endpoints.active_directory
        else:
            self._adfs_authority_url = self.credentials.get(
                'adfs_authority_url')

        # get resource from cloud environment
        self._resource = self._cloud_environment.endpoints.active_directory_resource_id

        if self.credentials.get('credentials') is not None:
            # AzureCLI credentials
            self.azure_credentials = self.credentials['credentials']
        elif self.credentials.get('client_id') is not None and \
                self.credentials.get('secret') is not None and \
                self.credentials.get('tenant') is not None:
            self.azure_credentials = ServicePrincipalCredentials(
                client_id=self.credentials['client_id'],
                secret=self.credentials['secret'],
                tenant=self.credentials['tenant'],
                cloud_environment=self._cloud_environment,
                verify=self._cert_validation_mode == 'validate')

        elif self.credentials.get('ad_user') is not None and \
                self.credentials.get('password') is not None and \
                self.credentials.get('client_id') is not None and \
                self.credentials.get('tenant') is not None:

            self.azure_credentials = self.acquire_token_with_username_password(
                self._adfs_authority_url, self._resource,
                self.credentials['ad_user'], self.credentials['password'],
                self.credentials['client_id'], self.credentials['tenant'])

        elif self.credentials.get(
                'ad_user') is not None and self.credentials.get(
                    'password') is not None:
            tenant = self.credentials.get('tenant')
            if not tenant:
                tenant = 'common'  # SDK default

            self.azure_credentials = UserPassCredentials(
                self.credentials['ad_user'],
                self.credentials['password'],
                tenant=tenant,
                cloud_environment=self._cloud_environment,
                verify=self._cert_validation_mode == 'validate')
        else:
            self.fail(
                "Failed to authenticate with provided credentials. Some attributes were missing. "
                "Credentials must include client_id, secret and tenant or ad_user and password, or "
                "ad_user, password, client_id, tenant and adfs_authority_url(optional) for ADFS authentication, or "
                "be logged in using AzureCLI.")

        # common parameter validation
        if self.module.params.get('tags'):
            self.validate_tags(self.module.params['tags'])

        if not skip_exec:
            res = self.exec_module(**self.module.params)
            self.module.exit_json(**res)

    def acquire_token_with_username_password(self, authority, resource,
                                             username, password, client_id,
                                             tenant):
        authority_uri = authority

        if tenant is not None:
            authority_uri = authority + '/' + tenant

        context = AuthenticationContext(authority_uri)
        token_response = context.acquire_token_with_username_password(
            resource, username, password, client_id)

        return AADTokenCredentials(token_response)

    def check_client_version(self, client_type):
        # Ensure Azure modules are at least 2.0.0rc5.
        package_version = AZURE_PKG_VERSIONS.get(client_type.__name__, None)
        if package_version is not None:
            client_name = package_version.get('package_name')
            try:
                client_module = importlib.import_module(client_type.__module__)
                client_version = client_module.VERSION
            except RuntimeError:
                # can't get at the module version for some reason, just fail silently...
                return
            expected_version = package_version.get('expected_version')
            if Version(client_version) < Version(expected_version):
                self.fail(
                    "Installed azure-mgmt-{0} client version is {1}. The minimum supported version is {2}. Try "
                    "`pip install ansible[azure]`".format(
                        client_name, client_version, expected_version))
            if Version(client_version) != Version(expected_version):
                self.module.warn(
                    "Installed azure-mgmt-{0} client version is {1}. The expected version is {2}. Try "
                    "`pip install ansible[azure]`".format(
                        client_name, client_version, expected_version))

    def exec_module(self, **kwargs):
        self.fail("Error: {0} failed to implement exec_module method.".format(
            self.__class__.__name__))

    def fail(self, msg, **kwargs):
        '''
        Shortcut for calling module.fail()

        :param msg: Error message text.
        :param kwargs: Any key=value pairs
        :return: None
        '''
        self.module.fail_json(msg=msg, **kwargs)

    def deprecate(self, msg, version=None):
        self.module.deprecate(msg, version)

    def log(self, msg, pretty_print=False):
        if pretty_print:
            self.module.debug(json.dumps(msg, indent=4, sort_keys=True))
        else:
            self.module.debug(msg)

    def validate_tags(self, tags):
        '''
        Check if tags dictionary contains string:string pairs.

        :param tags: dictionary of string:string pairs
        :return: None
        '''
        if not self.facts_module:
            if not isinstance(tags, dict):
                self.fail("Tags must be a dictionary of string:string values.")
            for key, value in tags.items():
                if not isinstance(value, str):
                    self.fail(
                        "Tags values must be strings. Found {0}:{1}".format(
                            str(key), str(value)))

    def update_tags(self, tags):
        '''
        Call from the module to update metadata tags. Returns tuple
        with bool indicating if there was a change and dict of new
        tags to assign to the object.

        :param tags: metadata tags from the object
        :return: bool, dict
        '''
        new_tags = copy.copy(tags) if isinstance(tags, dict) else dict()
        param_tags = self.module.params.get('tags') if isinstance(
            self.module.params.get('tags'), dict) else dict()
        append_tags = self.module.params.get(
            'append_tags') if self.module.params.get(
                'append_tags') is not None else True
        changed = False
        # check add or update
        for key, value in param_tags.items():
            if not new_tags.get(key) or new_tags[key] != value:
                changed = True
                new_tags[key] = value
        # check remove
        if not append_tags:
            for key, value in tags.items():
                if not param_tags.get(key):
                    new_tags.pop(key)
                    changed = True
        return changed, new_tags

    def has_tags(self, obj_tags, tag_list):
        '''
        Used in fact modules to compare object tags to list of parameter tags. Return true if list of parameter tags
        exists in object tags.

        :param obj_tags: dictionary of tags from an Azure object.
        :param tag_list: list of tag keys or tag key:value pairs
        :return: bool
        '''

        if not obj_tags and tag_list:
            return False

        if not tag_list:
            return True

        matches = 0
        result = False
        for tag in tag_list:
            tag_key = tag
            tag_value = None
            if ':' in tag:
                tag_key, tag_value = tag.split(':')
            if tag_value and obj_tags.get(tag_key) == tag_value:
                matches += 1
            elif not tag_value and obj_tags.get(tag_key):
                matches += 1
        if matches == len(tag_list):
            result = True
        return result

    def get_resource_group(self, resource_group):
        '''
        Fetch a resource group.

        :param resource_group: name of a resource group
        :return: resource group object
        '''
        try:
            return self.rm_client.resource_groups.get(resource_group)
        except CloudError as cloud_error:
            self.fail("Error retrieving resource group {0} - {1}".format(
                resource_group, cloud_error.message))
        except Exception as exc:
            self.fail("Error retrieving resource group {0} - {1}".format(
                resource_group, str(exc)))

    def _get_profile(self, profile="default"):
        path = expanduser("~/.azure/credentials")
        try:
            config = configparser.ConfigParser()
            config.read(path)
        except Exception as exc:
            self.fail(
                "Failed to access {0}. Check that the file exists and you have read "
                "access. {1}".format(path, str(exc)))
        credentials = dict()
        for key in AZURE_CREDENTIAL_ENV_MAPPING:
            try:
                credentials[key] = config.get(profile, key, raw=True)
            except:
                pass

        if credentials.get('subscription_id'):
            return credentials

        return None

    def _get_msi_credentials(self, subscription_id_param=None):
        credentials = MSIAuthentication()
        subscription_id = subscription_id_param or os.environ.get(
            AZURE_CREDENTIAL_ENV_MAPPING['subscription_id'], None)
        if not subscription_id:
            try:
                # use the first subscription of the MSI
                subscription_client = SubscriptionClient(credentials)
                subscription = next(subscription_client.subscriptions.list())
                subscription_id = str(subscription.subscription_id)
            except Exception as exc:
                self.fail(
                    "Failed to get MSI token: {0}. "
                    "Please check whether your machine enabled MSI or grant access to any subscription."
                    .format(str(exc)))
        return {'credentials': credentials, 'subscription_id': subscription_id}

    def _get_azure_cli_credentials(self):
        credentials, subscription_id = get_azure_cli_credentials()
        cloud_environment = get_cli_active_cloud()

        cli_credentials = {
            'credentials': credentials,
            'subscription_id': subscription_id,
            'cloud_environment': cloud_environment
        }
        return cli_credentials

    def _get_env_credentials(self):
        env_credentials = dict()
        for attribute, env_variable in AZURE_CREDENTIAL_ENV_MAPPING.items():
            env_credentials[attribute] = os.environ.get(env_variable, None)

        if env_credentials['profile']:
            credentials = self._get_profile(env_credentials['profile'])
            return credentials

        if env_credentials.get('subscription_id') is not None:
            return env_credentials

        return None

    def _get_credentials(self, params):
        # Get authentication credentials.
        self.log('Getting credentials')

        arg_credentials = dict()
        for attribute, env_variable in AZURE_CREDENTIAL_ENV_MAPPING.items():
            arg_credentials[attribute] = params.get(attribute, None)

        auth_source = params.get('auth_source', None)
        if not auth_source:
            auth_source = os.environ.get('ANSIBLE_AZURE_AUTH_SOURCE', 'auto')

        if auth_source == 'msi':
            self.log('Retrieving credenitals from MSI')
            return self._get_msi_credentials(
                arg_credentials['subscription_id'])

        if auth_source == 'cli':
            if not HAS_AZURE_CLI_CORE:
                self.fail(
                    "Azure auth_source is `cli`, but azure-cli package is not available. Try `pip install azure-cli --upgrade`"
                )
            try:
                self.log('Retrieving credentials from Azure CLI profile')
                cli_credentials = self._get_azure_cli_credentials()
                return cli_credentials
            except CLIError as err:
                self.fail(
                    "Azure CLI profile cannot be loaded - {0}".format(err))

        if auth_source == 'env':
            self.log('Retrieving credentials from environment')
            env_credentials = self._get_env_credentials()
            return env_credentials

        if auth_source == 'credential_file':
            self.log("Retrieving credentials from credential file")
            profile = params.get('profile', 'default')
            default_credentials = self._get_profile(profile)
            return default_credentials

        # auto, precedence: module parameters -> environment variables -> default profile in ~/.azure/credentials
        # try module params
        if arg_credentials['profile'] is not None:
            self.log('Retrieving credentials with profile parameter.')
            credentials = self._get_profile(arg_credentials['profile'])
            return credentials

        if arg_credentials['subscription_id']:
            self.log('Received credentials from parameters.')
            return arg_credentials

        # try environment
        env_credentials = self._get_env_credentials()
        if env_credentials:
            self.log('Received credentials from env.')
            return env_credentials

        # try default profile from ~./azure/credentials
        default_credentials = self._get_profile()
        if default_credentials:
            self.log(
                'Retrieved default profile credentials from ~/.azure/credentials.'
            )
            return default_credentials

        try:
            if HAS_AZURE_CLI_CORE:
                self.log('Retrieving credentials from AzureCLI profile')
            cli_credentials = self._get_azure_cli_credentials()
            return cli_credentials
        except CLIError as ce:
            self.log(
                'Error getting AzureCLI profile credentials - {0}'.format(ce))

        return None

    def parse_resource_to_dict(self, resource):
        '''
        Return a dict of the give resource, which contains name and resource group.

        :param resource: It can be a resource name, id or a dict contains name and resource group.
        '''
        resource_dict = parse_resource_id(resource) if not isinstance(
            resource, dict) else resource
        resource_dict['resource_group'] = resource_dict.get(
            'resource_group', self.resource_group)
        resource_dict['subscription_id'] = resource_dict.get(
            'subscription_id', self.subscription_id)
        return resource_dict

    def serialize_obj(self, obj, class_name, enum_modules=None):
        '''
        Return a JSON representation of an Azure object.

        :param obj: Azure object
        :param class_name: Name of the object's class
        :param enum_modules: List of module names to build enum dependencies from.
        :return: serialized result
        '''
        enum_modules = [] if enum_modules is None else enum_modules

        dependencies = dict()
        if enum_modules:
            for module_name in enum_modules:
                mod = importlib.import_module(module_name)
                for mod_class_name, mod_class_obj in inspect.getmembers(
                        mod, predicate=inspect.isclass):
                    dependencies[mod_class_name] = mod_class_obj
            self.log("dependencies: ")
            self.log(str(dependencies))
        serializer = Serializer(classes=dependencies)
        return serializer.body(obj, class_name, keep_readonly=True)

    def get_poller_result(self, poller, wait=5):
        '''
        Consistent method of waiting on and retrieving results from Azure's long poller

        :param poller Azure poller object
        :return object resulting from the original request
        '''
        try:
            delay = wait
            while not poller.done():
                self.log("Waiting for {0} sec".format(delay))
                poller.wait(timeout=delay)
            return poller.result()
        except Exception as exc:
            self.log(str(exc))
            raise

    def check_provisioning_state(self,
                                 azure_object,
                                 requested_state='present'):
        '''
        Check an Azure object's provisioning state. If something did not complete the provisioning
        process, then we cannot operate on it.

        :param azure_object An object such as a subnet, storageaccount, etc. Must have provisioning_state
                            and name attributes.
        :return None
        '''

        if hasattr(azure_object, 'properties') and hasattr(azure_object.properties, 'provisioning_state') and \
           hasattr(azure_object, 'name'):
            # resource group object fits this model
            if isinstance(azure_object.properties.provisioning_state, Enum):
                if azure_object.properties.provisioning_state.value != AZURE_SUCCESS_STATE and \
                   requested_state != 'absent':
                    self.fail(
                        "Error {0} has a provisioning state of {1}. Expecting state to be {2}."
                        .format(azure_object.name,
                                azure_object.properties.provisioning_state,
                                AZURE_SUCCESS_STATE))
                return
            if azure_object.properties.provisioning_state != AZURE_SUCCESS_STATE and \
               requested_state != 'absent':
                self.fail(
                    "Error {0} has a provisioning state of {1}. Expecting state to be {2}."
                    .format(azure_object.name,
                            azure_object.properties.provisioning_state,
                            AZURE_SUCCESS_STATE))
            return

        if hasattr(azure_object,
                   'provisioning_state') or not hasattr(azure_object, 'name'):
            if isinstance(azure_object.provisioning_state, Enum):
                if azure_object.provisioning_state.value != AZURE_SUCCESS_STATE and requested_state != 'absent':
                    self.fail(
                        "Error {0} has a provisioning state of {1}. Expecting state to be {2}."
                        .format(azure_object.name,
                                azure_object.provisioning_state,
                                AZURE_SUCCESS_STATE))
                return
            if azure_object.provisioning_state != AZURE_SUCCESS_STATE and requested_state != 'absent':
                self.fail(
                    "Error {0} has a provisioning state of {1}. Expecting state to be {2}."
                    .format(azure_object.name, azure_object.provisioning_state,
                            AZURE_SUCCESS_STATE))

    def get_blob_client(self,
                        resource_group_name,
                        storage_account_name,
                        storage_blob_type='block'):
        keys = dict()
        try:
            # Get keys from the storage account
            self.log('Getting keys')
            account_keys = self.storage_client.storage_accounts.list_keys(
                resource_group_name, storage_account_name)
        except Exception as exc:
            self.fail("Error getting keys for account {0} - {1}".format(
                storage_account_name, str(exc)))

        try:
            self.log('Create blob service')
            if storage_blob_type == 'page':
                return CloudStorageAccount(
                    storage_account_name,
                    account_keys.keys[0].value).create_page_blob_service()
            elif storage_blob_type == 'block':
                return CloudStorageAccount(
                    storage_account_name,
                    account_keys.keys[0].value).create_block_blob_service()
            else:
                raise Exception("Invalid storage blob type defined.")
        except Exception as exc:
            self.fail(
                "Error creating blob service client for storage account {0} - {1}"
                .format(storage_account_name, str(exc)))

    def create_default_pip(self,
                           resource_group,
                           location,
                           public_ip_name,
                           allocation_method='Dynamic'):
        '''
        Create a default public IP address <public_ip_name> to associate with a network interface.
        If a PIP address matching <public_ip_name> exists, return it. Otherwise, create one.

        :param resource_group: name of an existing resource group
        :param location: a valid azure location
        :param public_ip_name: base name to assign the public IP address
        :param allocation_method: one of 'Static' or 'Dynamic'
        :return: PIP object
        '''
        pip = None

        self.log("Starting create_default_pip {0}".format(public_ip_name))
        self.log("Check to see if public IP {0} exists".format(public_ip_name))
        try:
            pip = self.network_client.public_ip_addresses.get(
                resource_group, public_ip_name)
        except CloudError:
            pass

        if pip:
            self.log("Public ip {0} found.".format(public_ip_name))
            self.check_provisioning_state(pip)
            return pip

        params = self.network_models.PublicIPAddress(
            location=location,
            public_ip_allocation_method=allocation_method,
        )
        self.log('Creating default public IP {0}'.format(public_ip_name))
        try:
            poller = self.network_client.public_ip_addresses.create_or_update(
                resource_group, public_ip_name, params)
        except Exception as exc:
            self.fail("Error creating {0} - {1}".format(
                public_ip_name, str(exc)))

        return self.get_poller_result(poller)

    def create_default_securitygroup(self, resource_group, location,
                                     security_group_name, os_type, open_ports):
        '''
        Create a default security group <security_group_name> to associate with a network interface. If a security group matching
        <security_group_name> exists, return it. Otherwise, create one.

        :param resource_group: Resource group name
        :param location: azure location name
        :param security_group_name: base name to use for the security group
        :param os_type: one of 'Windows' or 'Linux'. Determins any default rules added to the security group.
        :param ssh_port: for os_type 'Linux' port used in rule allowing SSH access.
        :param rdp_port: for os_type 'Windows' port used in rule allowing RDP access.
        :return: security_group object
        '''
        group = None

        self.log("Create security group {0}".format(security_group_name))
        self.log("Check to see if security group {0} exists".format(
            security_group_name))
        try:
            group = self.network_client.network_security_groups.get(
                resource_group, security_group_name)
        except CloudError:
            pass

        if group:
            self.log("Security group {0} found.".format(security_group_name))
            self.check_provisioning_state(group)
            return group

        parameters = self.network_models.NetworkSecurityGroup()
        parameters.location = location

        if not open_ports:
            # Open default ports based on OS type
            if os_type == 'Linux':
                # add an inbound SSH rule
                parameters.security_rules = [
                    self.network_models.SecurityRule(
                        protocol='Tcp',
                        source_address_prefix='*',
                        destination_address_prefix='*',
                        access='Allow',
                        direction='Inbound',
                        description='Allow SSH Access',
                        source_port_range='*',
                        destination_port_range='22',
                        priority=100,
                        name='SSH')
                ]
                parameters.location = location
            else:
                # for windows add inbound RDP and WinRM rules
                parameters.security_rules = [
                    self.network_models.SecurityRule(
                        protocol='Tcp',
                        source_address_prefix='*',
                        destination_address_prefix='*',
                        access='Allow',
                        direction='Inbound',
                        description='Allow RDP port 3389',
                        source_port_range='*',
                        destination_port_range='3389',
                        priority=100,
                        name='RDP01'),
                    self.network_models.SecurityRule(
                        protocol='Tcp',
                        source_address_prefix='*',
                        destination_address_prefix='*',
                        access='Allow',
                        direction='Inbound',
                        description='Allow WinRM HTTPS port 5986',
                        source_port_range='*',
                        destination_port_range='5986',
                        priority=101,
                        name='WinRM01'),
                ]
        else:
            # Open custom ports
            parameters.security_rules = []
            priority = 100
            for port in open_ports:
                priority += 1
                rule_name = "Rule_{0}".format(priority)
                parameters.security_rules.append(
                    self.network_models.SecurityRule(
                        protocol='Tcp',
                        source_address_prefix='*',
                        destination_address_prefix='*',
                        access='Allow',
                        direction='Inbound',
                        source_port_range='*',
                        destination_port_range=str(port),
                        priority=priority,
                        name=rule_name))

        self.log(
            'Creating default security group {0}'.format(security_group_name))
        try:
            poller = self.network_client.network_security_groups.create_or_update(
                resource_group, security_group_name, parameters)
        except Exception as exc:
            self.fail("Error creating default security rule {0} - {1}".format(
                security_group_name, str(exc)))

        return self.get_poller_result(poller)

    @staticmethod
    def _validation_ignore_callback(session, global_config, local_config,
                                    **kwargs):
        session.verify = False

    def get_api_profile(self, client_type_name, api_profile_name):
        profile_all_clients = AZURE_API_PROFILES.get(api_profile_name)

        if not profile_all_clients:
            raise KeyError(
                "unknown Azure API profile: {0}".format(api_profile_name))

        profile_raw = profile_all_clients.get(client_type_name, None)

        if not profile_raw:
            self.module.warn(
                "Azure API profile {0} does not define an entry for {1}".
                format(api_profile_name, client_type_name))

        if isinstance(profile_raw, dict):
            if not profile_raw.get('default_api_version'):
                raise KeyError(
                    "Azure API profile {0} does not define 'default_api_version'"
                    .format(api_profile_name))
            return profile_raw

        # wrap basic strings in a dict that just defines the default
        return dict(default_api_version=profile_raw)

    def get_mgmt_svc_client(self,
                            client_type,
                            base_url=None,
                            api_version=None):
        self.log('Getting management service client {0}'.format(
            client_type.__name__))
        self.check_client_version(client_type)

        client_argspec = inspect.getargspec(client_type.__init__)

        if not base_url:
            # most things are resource_manager, don't make everyone specify
            base_url = self._cloud_environment.endpoints.resource_manager

        client_kwargs = dict(credentials=self.azure_credentials,
                             subscription_id=self.subscription_id,
                             base_url=base_url)

        api_profile_dict = {}

        if self.api_profile:
            api_profile_dict = self.get_api_profile(client_type.__name__,
                                                    self.api_profile)

        # unversioned clients won't accept profile; only send it if necessary
        # clients without a version specified in the profile will use the default
        if api_profile_dict and 'profile' in client_argspec.args:
            client_kwargs['profile'] = api_profile_dict

        # If the client doesn't accept api_version, it's unversioned.
        # If it does, favor explicitly-specified api_version, fall back to api_profile
        if 'api_version' in client_argspec.args:
            profile_default_version = api_profile_dict.get(
                'default_api_version', None)
            if api_version or profile_default_version:
                client_kwargs[
                    'api_version'] = api_version or profile_default_version
                if 'profile' in client_kwargs:
                    # remove profile; only pass API version if specified
                    client_kwargs.pop('profile')

        client = client_type(**client_kwargs)

        # FUTURE: remove this once everything exposes models directly (eg, containerinstance)
        try:
            getattr(client, "models")
        except AttributeError:

            def _ansible_get_models(self, *arg, **kwarg):
                return self._ansible_models

            setattr(client, '_ansible_models',
                    importlib.import_module(client_type.__module__).models)
            client.models = types.MethodType(_ansible_get_models, client)

        # Add user agent for Ansible
        client.config.add_user_agent(ANSIBLE_USER_AGENT)
        # Add user agent when running from Cloud Shell
        if CLOUDSHELL_USER_AGENT_KEY in os.environ:
            client.config.add_user_agent(os.environ[CLOUDSHELL_USER_AGENT_KEY])
        # Add user agent when running from VSCode extension
        if VSCODEEXT_USER_AGENT_KEY in os.environ:
            client.config.add_user_agent(os.environ[VSCODEEXT_USER_AGENT_KEY])

        if self._cert_validation_mode == 'ignore':
            client.config.session_configuration_callback = self._validation_ignore_callback

        return client

    @property
    def storage_client(self):
        self.log('Getting storage client...')
        if not self._storage_client:
            self._storage_client = self.get_mgmt_svc_client(
                StorageManagementClient,
                base_url=self._cloud_environment.endpoints.resource_manager,
                api_version='2017-10-01')
        return self._storage_client

    @property
    def storage_models(self):
        return StorageManagementClient.models("2017-10-01")

    @property
    def network_client(self):
        self.log('Getting network client')
        if not self._network_client:
            self._network_client = self.get_mgmt_svc_client(
                NetworkManagementClient,
                base_url=self._cloud_environment.endpoints.resource_manager,
                api_version='2017-11-01')
        return self._network_client

    @property
    def network_models(self):
        self.log("Getting network models...")
        return NetworkManagementClient.models("2017-11-01")

    @property
    def rm_client(self):
        self.log('Getting resource manager client')
        if not self._resource_client:
            self._resource_client = self.get_mgmt_svc_client(
                ResourceManagementClient,
                base_url=self._cloud_environment.endpoints.resource_manager,
                api_version='2017-05-10')
        return self._resource_client

    @property
    def rm_models(self):
        self.log("Getting resource manager models")
        return ResourceManagementClient.models("2017-05-10")

    @property
    def compute_client(self):
        self.log('Getting compute client')
        if not self._compute_client:
            self._compute_client = self.get_mgmt_svc_client(
                ComputeManagementClient,
                base_url=self._cloud_environment.endpoints.resource_manager,
                api_version='2017-03-30')
        return self._compute_client

    @property
    def compute_models(self):
        self.log("Getting compute models")
        return ComputeManagementClient.models("2017-03-30")

    @property
    def dns_client(self):
        self.log('Getting dns client')
        if not self._dns_client:
            self._dns_client = self.get_mgmt_svc_client(
                DnsManagementClient,
                base_url=self._cloud_environment.endpoints.resource_manager)
        return self._dns_client

    @property
    def web_client(self):
        self.log('Getting web client')
        if not self._web_client:
            self._web_client = self.get_mgmt_svc_client(
                WebSiteManagementClient,
                base_url=self._cloud_environment.endpoints.resource_manager,
                api_version='2016-08-01')
        return self._web_client

    @property
    def containerservice_client(self):
        self.log('Getting container service client')
        if not self._containerservice_client:
            self._containerservice_client = self.get_mgmt_svc_client(
                ContainerServiceClient,
                base_url=self._cloud_environment.endpoints.resource_manager)
        return self._containerservice_client

    @property
    def postgresql_client(self):
        self.log('Getting PostgreSQL client')
        if not self._postgresql_client:
            self._postgresql_client = self.get_mgmt_svc_client(
                PostgreSQLManagementClient,
                base_url=self._cloud_environment.endpoints.resource_manager)
        return self._postgresql_client

    @property
    def mysql_client(self):
        self.log('Getting MySQL client')
        if not self._mysql_client:
            self._mysql_client = self.get_mgmt_svc_client(
                MySQLManagementClient,
                base_url=self._cloud_environment.endpoints.resource_manager)
        return self._mysql_client
Beispiel #32
0
def main():
    argument_spec = ec2_argument_spec()
    argument_spec.update(
        dict(
            bucket=dict(required=True),
            dest=dict(default=None),
            encrypt=dict(default=True, type='bool'),
            expiry=dict(default=600, type='int', aliases=['expiration']),
            headers=dict(type='dict'),
            marker=dict(default=""),
            max_keys=dict(default=1000, type='int'),
            metadata=dict(type='dict'),
            mode=dict(choices=['get', 'put', 'delete', 'create', 'geturl', 'getstr', 'delobj', 'list'], required=True),
            object=dict(),
            permission=dict(type='list', default=['private']),
            version=dict(default=None),
            overwrite=dict(aliases=['force'], default='always'),
            prefix=dict(default=""),
            retries=dict(aliases=['retry'], type='int', default=0),
            s3_url=dict(aliases=['S3_URL']),
            rgw=dict(default='no', type='bool'),
            src=dict(),
            ignore_nonexistent_bucket=dict(default=False, type='bool')
        ),
    )
    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
    )

    if module._name == 's3':
        module.deprecate("The 's3' module is being renamed 'aws_s3'", version=2.7)

    if not HAS_BOTO3:
        module.fail_json(msg='boto3 and botocore required for this module')

    bucket = module.params.get('bucket')
    encrypt = module.params.get('encrypt')
    expiry = module.params.get('expiry')
    dest = module.params.get('dest', '')
    headers = module.params.get('headers')
    marker = module.params.get('marker')
    max_keys = module.params.get('max_keys')
    metadata = module.params.get('metadata')
    mode = module.params.get('mode')
    obj = module.params.get('object')
    version = module.params.get('version')
    overwrite = module.params.get('overwrite')
    prefix = module.params.get('prefix')
    retries = module.params.get('retries')
    s3_url = module.params.get('s3_url')
    rgw = module.params.get('rgw')
    src = module.params.get('src')
    ignore_nonexistent_bucket = module.params.get('ignore_nonexistent_bucket')

    if dest:
        dest = os.path.expanduser(dest)

    object_canned_acl = ["private", "public-read", "public-read-write", "aws-exec-read", "authenticated-read", "bucket-owner-read", "bucket-owner-full-control"]
    bucket_canned_acl = ["private", "public-read", "public-read-write", "authenticated-read"]

    if overwrite not in ['always', 'never', 'different']:
        if module.boolean(overwrite):
            overwrite = 'always'
        else:
            overwrite = 'never'

    region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)

    if region in ('us-east-1', '', None):
        # default to US Standard region
        location = 'us-east-1'
    else:
        # Boto uses symbolic names for locations but region strings will
        # actually work fine for everything except us-east-1 (US Standard)
        location = region

    if module.params.get('object'):
        obj = module.params['object']
        # If there is a top level object, do nothing - if the object starts with /
        # remove the leading character to maintain compatibility with Ansible versions < 2.4
        if obj.startswith('/'):
            obj = obj[1:]

    # Bucket deletion does not require obj.  Prevents ambiguity with delobj.
    if obj and mode == "delete":
        module.fail_json(msg='Parameter obj cannot be used with mode=delete')

    # allow eucarc environment variables to be used if ansible vars aren't set
    if not s3_url and 'S3_URL' in os.environ:
        s3_url = os.environ['S3_URL']

    # rgw requires an explicit url
    if rgw and not s3_url:
        module.fail_json(msg='rgw flavour requires s3_url')

    # Look at s3_url and tweak connection settings
    # if connecting to RGW, Walrus or fakes3
    for key in ['validate_certs', 'security_token', 'profile_name']:
        aws_connect_kwargs.pop(key, None)
    try:
        s3 = get_s3_connection(module, aws_connect_kwargs, location, rgw, s3_url)
    except (botocore.exceptions.NoCredentialsError, botocore.exceptions.ProfileNotFound) as e:
        module.fail_json(msg="Can't authorize connection. Check your credentials and profile.",
                         exceptions=traceback.format_exc(), **camel_dict_to_snake_dict(e.response))

    validate = not ignore_nonexistent_bucket

    # separate types of ACLs
    bucket_acl = [acl for acl in module.params.get('permission') if acl in bucket_canned_acl]
    object_acl = [acl for acl in module.params.get('permission') if acl in object_canned_acl]
    error_acl = [acl for acl in module.params.get('permission') if acl not in bucket_canned_acl and acl not in object_canned_acl]
    if error_acl:
        module.fail_json(msg='Unknown permission specified: %s' % error_acl)

    # First, we check to see if the bucket exists, we get "bucket" returned.
    bucketrtn = bucket_check(module, s3, bucket, validate=validate)

    if validate and mode not in ('create', 'put', 'delete') and not bucketrtn:
        module.fail_json(msg="Source bucket cannot be found.")

    # If our mode is a GET operation (download), go through the procedure as appropriate ...
    if mode == 'get':
        # Next, we check to see if the key in the bucket exists. If it exists, it also returns key_matches md5sum check.
        keyrtn = key_check(module, s3, bucket, obj, version=version, validate=validate)
        if keyrtn is False:
            module.fail_json(msg="Key %s with version id %s does not exist." % (obj, version))

        # If the destination path doesn't exist or overwrite is True, no need to do the md5um etag check, so just download.
        # Compare the remote MD5 sum of the object with the local dest md5sum, if it already exists.
        if path_check(dest):
            # Determine if the remote and local object are identical
            if keysum(module, s3, bucket, obj, version=version) == module.md5(dest):
                sum_matches = True
                if overwrite == 'always':
                    download_s3file(module, s3, bucket, obj, dest, retries, version=version)
                else:
                    module.exit_json(msg="Local and remote object are identical, ignoring. Use overwrite=always parameter to force.", changed=False)
            else:
                sum_matches = False

                if overwrite in ('always', 'different'):
                    download_s3file(module, s3, bucket, obj, dest, retries, version=version)
                else:
                    module.exit_json(msg="WARNING: Checksums do not match. Use overwrite parameter to force download.")
        else:
            download_s3file(module, s3, bucket, obj, dest, retries, version=version)

    # if our mode is a PUT operation (upload), go through the procedure as appropriate ...
    if mode == 'put':

        # if putting an object in a bucket yet to be created, acls for the bucket and/or the object may be specified
        # these were separated into the variables bucket_acl and object_acl above

        # Lets check the src path.
        if not path_check(src):
            module.fail_json(msg="Local object for PUT does not exist")

        # Lets check to see if bucket exists to get ground truth.
        if bucketrtn:
            keyrtn = key_check(module, s3, bucket, obj, version=version, validate=validate)

        # Lets check key state. Does it exist and if it does, compute the etag md5sum.
        if bucketrtn and keyrtn:
            # Compare the local and remote object
            if module.md5(src) == keysum(module, s3, bucket, obj):
                sum_matches = True
                if overwrite == 'always':
                    # only use valid object acls for the upload_s3file function
                    module.params['permission'] = object_acl
                    upload_s3file(module, s3, bucket, obj, src, expiry, metadata, encrypt, headers)
                else:
                    get_download_url(module, s3, bucket, obj, expiry, changed=False)
            else:
                sum_matches = False
                if overwrite in ('always', 'different'):
                    # only use valid object acls for the upload_s3file function
                    module.params['permission'] = object_acl
                    upload_s3file(module, s3, bucket, obj, src, expiry, metadata, encrypt, headers)
                else:
                    module.exit_json(msg="WARNING: Checksums do not match. Use overwrite parameter to force upload.")

        # If neither exist (based on bucket existence), we can create both.
        if not bucketrtn:
            # only use valid bucket acls for create_bucket function
            module.params['permission'] = bucket_acl
            create_bucket(module, s3, bucket, location)
            # only use valid object acls for the upload_s3file function
            module.params['permission'] = object_acl
            upload_s3file(module, s3, bucket, obj, src, expiry, metadata, encrypt, headers)

        # If bucket exists but key doesn't, just upload.
        if bucketrtn and not keyrtn:
            # only use valid object acls for the upload_s3file function
            module.params['permission'] = object_acl
            upload_s3file(module, s3, bucket, obj, src, expiry, metadata, encrypt, headers)

    # Delete an object from a bucket, not the entire bucket
    if mode == 'delobj':
        if obj is None:
            module.fail_json(msg="object parameter is required")
        if bucket:
            deletertn = delete_key(module, s3, bucket, obj)
            if deletertn is True:
                module.exit_json(msg="Object deleted from bucket %s." % bucket, changed=True)
        else:
            module.fail_json(msg="Bucket parameter is required.")

    # Delete an entire bucket, including all objects in the bucket
    if mode == 'delete':
        if bucket:
            deletertn = delete_bucket(module, s3, bucket)
            if deletertn is True:
                module.exit_json(msg="Bucket %s and all keys have been deleted." % bucket, changed=True)
        else:
            module.fail_json(msg="Bucket parameter is required.")

    # Support for listing a set of keys
    if mode == 'list':
        exists = bucket_check(module, s3, bucket)

        # If the bucket does not exist then bail out
        if not exists:
            module.fail_json(msg="Target bucket (%s) cannot be found" % bucket)

        list_keys(module, s3, bucket, prefix, marker, max_keys)

    # Need to research how to create directories without "populating" a key, so this should just do bucket creation for now.
    # WE SHOULD ENABLE SOME WAY OF CREATING AN EMPTY KEY TO CREATE "DIRECTORY" STRUCTURE, AWS CONSOLE DOES THIS.
    if mode == 'create':

        # if both creating a bucket and putting an object in it, acls for the bucket and/or the object may be specified
        # these were separated above into the variables bucket_acl and object_acl

        if bucket and not obj:
            if bucketrtn:
                module.exit_json(msg="Bucket already exists.", changed=False)
            else:
                # only use valid bucket acls when creating the bucket
                module.params['permission'] = bucket_acl
                module.exit_json(msg="Bucket created successfully", changed=create_bucket(module, s3, bucket, location))
        if bucket and obj:
            if obj.endswith('/'):
                dirobj = obj
            else:
                dirobj = obj + "/"
            if bucketrtn:
                if key_check(module, s3, bucket, dirobj):
                    module.exit_json(msg="Bucket %s and key %s already exists." % (bucket, obj), changed=False)
                else:
                    # setting valid object acls for the create_dirkey function
                    module.params['permission'] = object_acl
                    create_dirkey(module, s3, bucket, dirobj)
            else:
                # only use valid bucket acls for the create_bucket function
                module.params['permission'] = bucket_acl
                created = create_bucket(module, s3, bucket, location)
                # only use valid object acls for the create_dirkey function
                module.params['permission'] = object_acl
                create_dirkey(module, s3, bucket, dirobj)

    # Support for grabbing the time-expired URL for an object in S3/Walrus.
    if mode == 'geturl':
        if not bucket and not obj:
            module.fail_json(msg="Bucket and Object parameters must be set")

        keyrtn = key_check(module, s3, bucket, obj, version=version, validate=validate)
        if keyrtn:
            get_download_url(module, s3, bucket, obj, expiry)
        else:
            module.fail_json(msg="Key %s does not exist." % obj)

    if mode == 'getstr':
        if bucket and obj:
            keyrtn = key_check(module, s3, bucket, obj, version=version, validate=validate)
            if keyrtn:
                download_s3str(module, s3, bucket, obj, version=version)
            elif version is not None:
                module.fail_json(msg="Key %s with version id %s does not exist." % (obj, version))
            else:
                module.fail_json(msg="Key %s does not exist." % obj)

    module.exit_json(failed=False)
def main():
    result = {}
    module = AnsibleModule(argument_spec=dict(
        category=dict(required=True),
        command=dict(required=True, type='list'),
        baseuri=dict(required=True),
        username=dict(required=True),
        password=dict(required=True, no_log=True),
        manager_attribute_name=dict(default=None),
        manager_attribute_value=dict(default=None),
        manager_attributes=dict(type='dict', default={}),
        timeout=dict(type='int', default=10),
        resource_id=dict()),
                           supports_check_mode=False)

    category = module.params['category']
    command_list = module.params['command']

    # admin credentials used for authentication
    creds = {
        'user': module.params['username'],
        'pswd': module.params['password']
    }

    # timeout
    timeout = module.params['timeout']

    # System, Manager or Chassis ID to modify
    resource_id = module.params['resource_id']

    # Build root URI
    root_uri = "https://" + module.params['baseuri']
    rf_utils = IdracRedfishUtils(creds,
                                 root_uri,
                                 timeout,
                                 module,
                                 resource_id=resource_id,
                                 data_modification=True)

    # Check that Category is valid
    if category not in CATEGORY_COMMANDS_ALL:
        module.fail_json(
            msg=to_native("Invalid Category '%s'. Valid Categories = %s" %
                          (category, CATEGORY_COMMANDS_ALL.keys())))

    # Check that all commands are valid
    for cmd in command_list:
        # Fail if even one command given is invalid
        if cmd not in CATEGORY_COMMANDS_ALL[category]:
            module.fail_json(
                msg=to_native("Invalid Command '%s'. Valid Commands = %s" %
                              (cmd, CATEGORY_COMMANDS_ALL[category])))

    # check for mutually exclusive commands
    try:
        # check_mutually_exclusive accepts a single list or list of lists that
        # are groups of terms that should be mutually exclusive with one another
        # and checks that against a dictionary
        check_mutually_exclusive(
            CATEGORY_COMMANDS_MUTUALLY_EXCLUSIVE[category],
            dict.fromkeys(command_list, True))

    except TypeError as e:
        module.fail_json(msg=to_native(e))

    # Organize by Categories / Commands

    if category == "Manager":
        # execute only if we find a Manager resource
        result = rf_utils._find_managers_resource()
        if result['ret'] is False:
            module.fail_json(msg=to_native(result['msg']))

        for command in command_list:
            if command in [
                    "SetManagerAttributes", "SetLifecycleControllerAttributes",
                    "SetSystemAttributes"
            ]:
                result = rf_utils.set_manager_attributes(command)

    if any((module.params['manager_attribute_name'],
            module.params['manager_attribute_value'])):
        module.deprecate(msg='Arguments `manager_attribute_name` and '
                         '`manager_attribute_value` are deprecated. '
                         'Use `manager_attributes` instead for passing in '
                         'the manager attribute name and value pairs',
                         version='2.13')

    # Return data back or fail with proper message
    if result['ret'] is True:
        module.exit_json(changed=result['changed'],
                         msg=to_native(result['msg']))
    else:
        module.fail_json(msg=to_native(result['msg']))
Beispiel #34
0
def main():
    argument_spec = url_argument_spec()

    # setup aliases
    argument_spec['url_username']['aliases'] = ['username']
    argument_spec['url_password']['aliases'] = ['password']

    argument_spec.update(
        url=dict(type='str', required=True),
        dest=dict(type='path', required=True),
        backup=dict(type='bool'),
        sha256sum=dict(type='str', default=''),
        checksum=dict(type='str', default=''),
        timeout=dict(type='int', default=10),
        headers=dict(type='raw'),
        tmp_dest=dict(type='path'),
    )

    module = AnsibleModule(
        # not checking because of daisy chain to file module
        argument_spec=argument_spec,
        add_file_common_args=True,
        supports_check_mode=True,
        mutually_exclusive=[['checksum', 'sha256sum']],
    )

    url = module.params['url']
    dest = module.params['dest']
    backup = module.params['backup']
    force = module.params['force']
    sha256sum = module.params['sha256sum']
    checksum = module.params['checksum']
    use_proxy = module.params['use_proxy']
    timeout = module.params['timeout']
    tmp_dest = module.params['tmp_dest']

    result = dict(
        changed=False,
        checksum_dest=None,
        checksum_src=None,
        dest=dest,
        elapsed=0,
        url=url,
    )

    # Parse headers to dict
    if isinstance(module.params['headers'], dict):
        headers = module.params['headers']
    elif module.params['headers']:
        try:
            headers = dict(item.split(':', 1) for item in module.params['headers'].split(','))
            module.deprecate('Supplying `headers` as a string is deprecated. Please use dict/hash format for `headers`', version='2.10')
        except Exception:
            module.fail_json(msg="The string representation for the `headers` parameter requires a key:value,key:value syntax to be properly parsed.", **result)
    else:
        headers = None

    dest_is_dir = os.path.isdir(dest)
    last_mod_time = None

    # workaround for usage of deprecated sha256sum parameter
    if sha256sum:
        checksum = 'sha256:%s' % (sha256sum)

    # checksum specified, parse for algorithm and checksum
    if checksum:
        try:
            algorithm, checksum = checksum.split(':', 1)
            if checksum.startswith('http://') or checksum.startswith('https://') or checksum.startswith('ftp://'):
                checksum_url = checksum
                # download checksum file to checksum_tmpsrc
                checksum_tmpsrc, checksum_info = url_get(module, checksum_url, dest, use_proxy, last_mod_time, force, timeout, headers, tmp_dest)
                with open(checksum_tmpsrc) as f:
                    lines = [line.rstrip('\n') for line in f]
                os.remove(checksum_tmpsrc)
                lines = dict(s.split(None, 1) for s in lines)
                filename = url_filename(url)

                # Look through each line in the checksum file for a hash corresponding to
                # the filename in the url, returning the first hash that is found.
                for cksum in (s for (s, f) in lines.items() if f.strip('./') == filename):
                    checksum = cksum
                    break
                else:
                    checksum = None

                if checksum is None:
                    module.fail_json(msg="Unable to find a checksum for file '%s' in '%s'" % (filename, checksum_url))
            # Remove any non-alphanumeric characters, including the infamous
            # Unicode zero-width space
            checksum = re.sub(r'\W+', '', checksum).lower()
            # Ensure the checksum portion is a hexdigest
            int(checksum, 16)
        except ValueError:
            module.fail_json(msg="The checksum parameter has to be in format <algorithm>:<checksum>", **result)

    if not dest_is_dir and os.path.exists(dest):
        checksum_mismatch = False

        # If the download is not forced and there is a checksum, allow
        # checksum match to skip the download.
        if not force and checksum != '':
            destination_checksum = module.digest_from_file(dest, algorithm)

            if checksum != destination_checksum:
                checksum_mismatch = True

        # Not forcing redownload, unless checksum does not match
        if not force and not checksum_mismatch:
            # Not forcing redownload, unless checksum does not match
            # allow file attribute changes
            module.params['path'] = dest
            file_args = module.load_file_common_arguments(module.params)
            file_args['path'] = dest
            result['changed'] = module.set_fs_attributes_if_different(file_args, False)
            if result['changed']:
                module.exit_json(msg="file already exists but file attributes changed", **result)
            module.exit_json(msg="file already exists", **result)

        # If the file already exists, prepare the last modified time for the
        # request.
        mtime = os.path.getmtime(dest)
        last_mod_time = datetime.datetime.utcfromtimestamp(mtime)

        # If the checksum does not match we have to force the download
        # because last_mod_time may be newer than on remote
        if checksum_mismatch:
            force = True

    # download to tmpsrc
    start = datetime.datetime.utcnow()
    tmpsrc, info = url_get(module, url, dest, use_proxy, last_mod_time, force, timeout, headers, tmp_dest)
    result['elapsed'] = (datetime.datetime.utcnow() - start).seconds
    result['src'] = tmpsrc

    # Now the request has completed, we can finally generate the final
    # destination file name from the info dict.

    if dest_is_dir:
        filename = extract_filename_from_headers(info)
        if not filename:
            # Fall back to extracting the filename from the URL.
            # Pluck the URL from the info, since a redirect could have changed
            # it.
            filename = url_filename(info['url'])
        dest = os.path.join(dest, filename)

    # If the remote URL exists, we're done with check mode
    if module.check_mode:
        os.remove(tmpsrc)
        result['changed'] = True
        module.exit_json(msg=info.get('msg', ''), **result)

    # raise an error if there is no tmpsrc file
    if not os.path.exists(tmpsrc):
        os.remove(tmpsrc)
        module.fail_json(msg="Request failed", status_code=info['status'], response=info['msg'], **result)
    if not os.access(tmpsrc, os.R_OK):
        os.remove(tmpsrc)
        module.fail_json(msg="Source %s is not readable" % (tmpsrc), **result)
    result['checksum_src'] = module.sha1(tmpsrc)

    # check if there is no dest file
    if os.path.exists(dest):
        # raise an error if copy has no permission on dest
        if not os.access(dest, os.W_OK):
            os.remove(tmpsrc)
            module.fail_json(msg="Destination %s is not writable" % (dest), **result)
        if not os.access(dest, os.R_OK):
            os.remove(tmpsrc)
            module.fail_json(msg="Destination %s is not readable" % (dest), **result)
        result['checksum_dest'] = module.sha1(dest)
    else:
        if not os.path.exists(os.path.dirname(dest)):
            os.remove(tmpsrc)
            module.fail_json(msg="Destination %s does not exist" % (os.path.dirname(dest)), **result)
        if not os.access(os.path.dirname(dest), os.W_OK):
            os.remove(tmpsrc)
            module.fail_json(msg="Destination %s is not writable" % (os.path.dirname(dest)), **result)

    backup_file = None
    if result['checksum_src'] != result['checksum_dest']:
        try:
            if backup:
                if os.path.exists(dest):
                    backup_file = module.backup_local(dest)
            module.atomic_move(tmpsrc, dest)
        except Exception as e:
            if os.path.exists(tmpsrc):
                os.remove(tmpsrc)
            module.fail_json(msg="failed to copy %s to %s: %s" % (tmpsrc, dest, to_native(e)),
                             exception=traceback.format_exc(), **result)
        result['changed'] = True
    else:
        result['changed'] = False
        if os.path.exists(tmpsrc):
            os.remove(tmpsrc)

    if checksum != '':
        destination_checksum = module.digest_from_file(dest, algorithm)

        if checksum != destination_checksum:
            os.remove(dest)
            module.fail_json(msg="The checksum for %s did not match %s; it was %s." % (dest, checksum, destination_checksum), **result)

    # allow file attribute changes
    module.params['path'] = dest
    file_args = module.load_file_common_arguments(module.params)
    file_args['path'] = dest
    result['changed'] = module.set_fs_attributes_if_different(file_args, result['changed'])

    # Backwards compat only.  We'll return None on FIPS enabled systems
    try:
        result['md5sum'] = module.md5(dest)
    except ValueError:
        result['md5sum'] = None

    if backup_file:
        result['backup_file'] = backup_file

    # Mission complete
    module.exit_json(msg=info.get('msg', ''), status_code=info.get('status', ''), **result)
Beispiel #35
0
def main():
    argument_spec = url_argument_spec()
    argument_spec.update(
        dest=dict(type='path'),
        url_username=dict(type='str', aliases=['user']),
        url_password=dict(type='str', aliases=['password'], no_log=True),
        body=dict(type='raw'),
        body_format=dict(type='str', default='raw', choices=['form-urlencoded', 'json', 'raw']),
        src=dict(type='path'),
        method=dict(type='str', default='GET', choices=['CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT', 'REFRESH', 'TRACE']),
        return_content=dict(type='bool', default=False),
        follow_redirects=dict(type='str', default='safe', choices=['all', 'no', 'none', 'safe', 'urllib2', 'yes']),
        creates=dict(type='path'),
        removes=dict(type='path'),
        status_code=dict(type='list', default=[200]),
        timeout=dict(type='int', default=30),
        headers=dict(type='dict', default={}),
        unix_socket=dict(type='path'),
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        # TODO: Remove check_invalid_arguments in 2.9
        check_invalid_arguments=False,
        add_file_common_args=True,
        mutually_exclusive=[['body', 'src']],
    )

    url = module.params['url']
    body = module.params['body']
    body_format = module.params['body_format'].lower()
    method = module.params['method']
    dest = module.params['dest']
    return_content = module.params['return_content']
    creates = module.params['creates']
    removes = module.params['removes']
    status_code = [int(x) for x in list(module.params['status_code'])]
    socket_timeout = module.params['timeout']

    dict_headers = module.params['headers']

    if body_format == 'json':
        # Encode the body unless its a string, then assume it is pre-formatted JSON
        if not isinstance(body, string_types):
            body = json.dumps(body)
        if 'content-type' not in [header.lower() for header in dict_headers]:
            dict_headers['Content-Type'] = 'application/json'
    elif body_format == 'form-urlencoded':
        if not isinstance(body, string_types):
            try:
                body = form_urlencoded(body)
            except ValueError as e:
                module.fail_json(msg='failed to parse body as form_urlencoded: %s' % to_native(e), elapsed=0)
        if 'content-type' not in [header.lower() for header in dict_headers]:
            dict_headers['Content-Type'] = 'application/x-www-form-urlencoded'

    # TODO: Deprecated section.  Remove in Ansible 2.9
    # Grab all the http headers. Need this hack since passing multi-values is
    # currently a bit ugly. (e.g. headers='{"Content-Type":"application/json"}')
    for key, value in iteritems(module.params):
        if key.startswith("HEADER_"):
            module.deprecate('Supplying headers via HEADER_* is deprecated. Please use `headers` to'
                             ' supply headers for the request', version='2.9')
            skey = key.replace("HEADER_", "")
            dict_headers[skey] = value
    # End deprecated section

    if creates is not None:
        # do not run the command if the line contains creates=filename
        # and the filename already exists.  This allows idempotence
        # of uri executions.
        if os.path.exists(creates):
            module.exit_json(stdout="skipped, since '%s' exists" % creates, changed=False)

    if removes is not None:
        # do not run the command if the line contains removes=filename
        # and the filename does not exist.  This allows idempotence
        # of uri executions.
        if not os.path.exists(removes):
            module.exit_json(stdout="skipped, since '%s' does not exist" % removes, changed=False)

    # Make the request
    start = datetime.datetime.utcnow()
    resp, content, dest = uri(module, url, dest, body, body_format, method,
                              dict_headers, socket_timeout)
    resp['elapsed'] = (datetime.datetime.utcnow() - start).seconds
    resp['status'] = int(resp['status'])

    # Write the file out if requested
    if dest is not None:
        if resp['status'] == 304:
            resp['changed'] = False
        else:
            write_file(module, url, dest, content, resp)
            # allow file attribute changes
            resp['changed'] = True
            module.params['path'] = dest
            file_args = module.load_file_common_arguments(module.params)
            file_args['path'] = dest
            resp['changed'] = module.set_fs_attributes_if_different(file_args, resp['changed'])
        resp['path'] = dest
    else:
        resp['changed'] = False

    # Transmogrify the headers, replacing '-' with '_', since variables don't
    # work with dashes.
    # In python3, the headers are title cased.  Lowercase them to be
    # compatible with the python2 behaviour.
    uresp = {}
    for key, value in iteritems(resp):
        ukey = key.replace("-", "_").lower()
        uresp[ukey] = value

    if 'location' in uresp:
        uresp['location'] = absolute_location(url, uresp['location'])

    # Default content_encoding to try
    content_encoding = 'utf-8'
    if 'content_type' in uresp:
        content_type, params = cgi.parse_header(uresp['content_type'])
        if 'charset' in params:
            content_encoding = params['charset']
        u_content = to_text(content, encoding=content_encoding)
        if any(candidate in content_type for candidate in JSON_CANDIDATES):
            try:
                js = json.loads(u_content)
                uresp['json'] = js
            except Exception:
                if PY2:
                    sys.exc_clear()  # Avoid false positive traceback in fail_json() on Python 2
    else:
        u_content = to_text(content, encoding=content_encoding)

    if resp['status'] not in status_code:
        uresp['msg'] = 'Status code was %s and not %s: %s' % (resp['status'], status_code, uresp.get('msg', ''))
        module.fail_json(content=u_content, **uresp)
    elif return_content:
        module.exit_json(content=u_content, **uresp)
    else:
        module.exit_json(**uresp)
def main():

    module = AnsibleModule(
        argument_spec=dict(
            state=dict(type='str', default='present', choices=['present', 'absent']),
            size=dict(type='int', default=4096),
            type=dict(type='str', default='RSA', choices=[
                'DSA', 'ECC', 'Ed25519', 'Ed448', 'RSA', 'X25519', 'X448'
            ]),
            curve=dict(type='str', choices=[
                'secp384r1', 'secp521r1', 'secp224r1', 'secp192r1', 'secp256r1',
                'secp256k1', 'brainpoolP256r1', 'brainpoolP384r1', 'brainpoolP512r1',
                'sect571k1', 'sect409k1', 'sect283k1', 'sect233k1', 'sect163k1',
                'sect571r1', 'sect409r1', 'sect283r1', 'sect233r1', 'sect163r2',
            ]),
            force=dict(type='bool', default=False),
            path=dict(type='path', required=True),
            passphrase=dict(type='str', no_log=True),
            cipher=dict(type='str'),
            backup=dict(type='bool', default=False),
            format=dict(type='str', default='auto_ignore', choices=['pkcs1', 'pkcs8', 'raw', 'auto', 'auto_ignore']),
            format_mismatch=dict(type='str', default='regenerate', choices=['regenerate', 'convert']),
            select_crypto_backend=dict(type='str', choices=['auto', 'pyopenssl', 'cryptography'], default='auto'),
            return_content=dict(type='bool', default=False),
            regenerate=dict(
                type='str',
                default='full_idempotence',
                choices=['never', 'fail', 'partial_idempotence', 'full_idempotence', 'always']
            ),
        ),
        supports_check_mode=True,
        add_file_common_args=True,
        required_together=[
            ['cipher', 'passphrase']
        ],
        required_if=[
            ['type', 'ECC', ['curve']],
        ],
    )

    base_dir = os.path.dirname(module.params['path']) or '.'
    if not os.path.isdir(base_dir):
        module.fail_json(
            name=base_dir,
            msg='The directory %s does not exist or the file is not a directory' % base_dir
        )

    backend = module.params['select_crypto_backend']
    if backend == 'auto':
        # Detection what is possible
        can_use_cryptography = CRYPTOGRAPHY_FOUND and CRYPTOGRAPHY_VERSION >= LooseVersion(MINIMAL_CRYPTOGRAPHY_VERSION)
        can_use_pyopenssl = PYOPENSSL_FOUND and PYOPENSSL_VERSION >= LooseVersion(MINIMAL_PYOPENSSL_VERSION)

        # Decision
        if module.params['cipher'] and module.params['passphrase'] and module.params['cipher'] != 'auto':
            # First try pyOpenSSL, then cryptography
            if can_use_pyopenssl:
                backend = 'pyopenssl'
            elif can_use_cryptography:
                backend = 'cryptography'
        else:
            # First try cryptography, then pyOpenSSL
            if can_use_cryptography:
                backend = 'cryptography'
            elif can_use_pyopenssl:
                backend = 'pyopenssl'

        # Success?
        if backend == 'auto':
            module.fail_json(msg=("Can't detect any of the required Python libraries "
                                  "cryptography (>= {0}) or PyOpenSSL (>= {1})").format(
                                      MINIMAL_CRYPTOGRAPHY_VERSION,
                                      MINIMAL_PYOPENSSL_VERSION))
    try:
        if backend == 'pyopenssl':
            if not PYOPENSSL_FOUND:
                module.fail_json(msg=missing_required_lib('pyOpenSSL >= {0}'.format(MINIMAL_PYOPENSSL_VERSION)),
                                 exception=PYOPENSSL_IMP_ERR)
            module.deprecate('The module is using the PyOpenSSL backend. This backend has been deprecated', version='2.13')
            private_key = PrivateKeyPyOpenSSL(module)
        elif backend == 'cryptography':
            if not CRYPTOGRAPHY_FOUND:
                module.fail_json(msg=missing_required_lib('cryptography >= {0}'.format(MINIMAL_CRYPTOGRAPHY_VERSION)),
                                 exception=CRYPTOGRAPHY_IMP_ERR)
            private_key = PrivateKeyCryptography(module)

        if private_key.state == 'present':
            if module.check_mode:
                result = private_key.dump()
                result['changed'] = private_key.force \
                    or not private_key.check(module, ignore_conversion=True) \
                    or not private_key.check(module, ignore_conversion=False)
                module.exit_json(**result)

            private_key.generate(module)
        else:
            if module.check_mode:
                result = private_key.dump()
                result['changed'] = os.path.exists(module.params['path'])
                module.exit_json(**result)

            private_key.remove(module)

        result = private_key.dump()
        module.exit_json(**result)
    except OpenSSLObjectError as exc:
        module.fail_json(msg=to_native(exc))
Beispiel #37
0
def main():
    helper = get_connection(
        vsys_importable=True,
        template=True,
        with_classic_provider_spec=True,
        with_state=True,
        min_pandevice_version=(0, 8, 0),
        argument_spec=dict(
            if_name=dict(required=True),
            ip=dict(type='list', elements='str'),
            ipv6_enabled=dict(type='bool'),
            management_profile=dict(),
            mtu=dict(type='int'),
            netflow_profile=dict(),
            comment=dict(),
            zone_name=dict(),
            vr_name=dict(),
            commit=dict(type='bool', default=False),

            # TODO(gfreeman) - remove this in 2.12
            vsys_dg=dict(),
        ),
    )

    module = AnsibleModule(
        argument_spec=helper.argument_spec,
        supports_check_mode=True,
        required_one_of=helper.required_one_of,
    )

    # Get the object params.
    spec = {
        'name': module.params['if_name'],
        'ip': module.params['ip'],
        'ipv6_enabled': module.params['ipv6_enabled'],
        'management_profile': module.params['management_profile'],
        'mtu': module.params['mtu'],
        'netflow_profile': module.params['netflow_profile'],
        'comment': module.params['comment'],
    }

    # Get other info.
    state = module.params['state']
    zone_name = module.params['zone_name']
    vr_name = module.params['vr_name']
    vsys = module.params['vsys']
    vsys_dg = module.params['vsys_dg']
    commit = module.params['commit']

    # TODO(gfreeman) - Remove vsys_dg in 2.12, as well as this code chunk.
    # In the mean time, we'll need to do this special handling.
    if vsys_dg is not None:
        module.deprecate('Param "vsys_dg" is deprecated, use "vsys"',
                         version='3.0.0',
                         collection_name='paloaltonetworks.panos')

        if vsys is None:
            vsys = vsys_dg
        else:
            msg = [
                'Params "vsys" and "vsys_dg" both given',
                'Specify one or the other, not both.',
            ]
            module.fail_json(msg='.  '.join(msg))
    elif vsys is None:
        # TODO(gfreeman) - v2.12, just set the default for vsys to 'vsys1'.
        vsys = 'vsys1'

    # Make sure 'vsys' is set appropriately.
    module.params['vsys'] = vsys

    # Verify libs are present, get the parent object.
    parent = helper.get_pandevice_parent(module)

    # Retrieve the current config.
    try:
        interfaces = TunnelInterface.refreshall(parent,
                                                add=False,
                                                matching_vsys=False)
    except PanDeviceError as e:
        module.fail_json(msg='Failed refresh: {0}'.format(e))

    # Build the object based on the user spec.
    obj = TunnelInterface(**spec)
    parent.add(obj)

    # Which action should we take on the interface?
    changed = False
    diff = None
    reference_params = {
        'refresh': True,
        'update': not module.check_mode,
        'return_type': 'bool',
    }
    if state == 'present':
        for item in interfaces:
            if item.name != obj.name:
                continue
            diff = dict(before=eltostr(item))
            # Interfaces have children, so don't compare them.
            if not item.equal(obj, compare_children=False):
                changed = True
                obj.extend(item.children)
                diff['after'] = eltostr(obj)
                if not module.check_mode:
                    try:
                        obj.apply()
                    except PanDeviceError as e:
                        module.fail_json(msg='Failed apply: {0}'.format(e))
            break
        else:
            changed = True
            diff = dict(before="", after=eltostr(obj))
            if not module.check_mode:
                try:
                    obj.create()
                except PanDeviceError as e:
                    module.fail_json(msg='Failed create: {0}'.format(e))

        # Set references.
        try:
            changed |= obj.set_vsys(vsys, **reference_params)
            changed |= obj.set_zone(zone_name,
                                    mode='layer3',
                                    **reference_params)
            changed |= obj.set_virtual_router(vr_name, **reference_params)
        except PanDeviceError as e:
            module.fail_json(msg='Failed setref: {0}'.format(e))
    elif state == 'absent':
        # Remove references.
        try:
            changed |= obj.set_virtual_router(None, **reference_params)
            changed |= obj.set_zone(None, mode='layer3', **reference_params)
            changed |= obj.set_vsys(None, **reference_params)
        except PanDeviceError as e:
            module.fail_json(msg='Failed setref: {0}'.format(e))

        # Remove the interface.
        if obj.name in [x.name for x in interfaces]:
            changed = True
            diff = dict(before=eltostr(obj), after="")
            if not module.check_mode:
                try:
                    obj.delete()
                except PanDeviceError as e:
                    module.fail_json(msg='Failed delete: {0}'.format(e))

    # Commit if we were asked to do so.
    if changed and commit:
        helper.commit(module)

    # Done!
    module.exit_json(changed=changed, diff=diff, msg='Done')
def main():
    argument_spec = openstack_full_argument_spec(
        server=dict(required=True),
        action=dict(required=True, choices=['stop', 'start', 'pause', 'unpause',
                                            'lock', 'unlock', 'suspend', 'resume',
                                            'rebuild']),
        image=dict(required=False),
    )

    module_kwargs = openstack_module_kwargs()
    module = AnsibleModule(argument_spec, supports_check_mode=True,
                           required_if=[('action', 'rebuild', ['image'])],
                           **module_kwargs)

    if module._name == 'os_server_actions':
        module.deprecate("The 'os_server_actions' module is being renamed 'os_server_action'", version=2.8)

    action = module.params['action']
    wait = module.params['wait']
    timeout = module.params['timeout']
    image = module.params['image']

    if action in _admin_actions:
        shade, cloud = openstack_cloud_from_module(module)
    else:
        shade, cloud = openstack_cloud_from_module(module)
    try:
        server = cloud.get_server(module.params['server'])
        if not server:
            module.fail_json(msg='Could not find server %s' % server)
        status = server.status

        if module.check_mode:
            module.exit_json(changed=_system_state_change(action, status))

        if action == 'stop':
            if not _system_state_change(action, status):
                module.exit_json(changed=False)

            cloud.nova_client.servers.stop(server=server.id)
            if wait:
                _wait(timeout, cloud, server, action, module, shade)
                module.exit_json(changed=True)

        if action == 'start':
            if not _system_state_change(action, status):
                module.exit_json(changed=False)

            cloud.nova_client.servers.start(server=server.id)
            if wait:
                _wait(timeout, cloud, server, action, module, shade)
                module.exit_json(changed=True)

        if action == 'pause':
            if not _system_state_change(action, status):
                module.exit_json(changed=False)

            cloud.nova_client.servers.pause(server=server.id)
            if wait:
                _wait(timeout, cloud, server, action, module, shade)
                module.exit_json(changed=True)

        elif action == 'unpause':
            if not _system_state_change(action, status):
                module.exit_json(changed=False)

            cloud.nova_client.servers.unpause(server=server.id)
            if wait:
                _wait(timeout, cloud, server, action, module, shade)
            module.exit_json(changed=True)

        elif action == 'lock':
            # lock doesn't set a state, just do it
            cloud.nova_client.servers.lock(server=server.id)
            module.exit_json(changed=True)

        elif action == 'unlock':
            # unlock doesn't set a state, just do it
            cloud.nova_client.servers.unlock(server=server.id)
            module.exit_json(changed=True)

        elif action == 'suspend':
            if not _system_state_change(action, status):
                module.exit_json(changed=False)

            cloud.nova_client.servers.suspend(server=server.id)
            if wait:
                _wait(timeout, cloud, server, action, module, shade)
            module.exit_json(changed=True)

        elif action == 'resume':
            if not _system_state_change(action, status):
                module.exit_json(changed=False)

            cloud.nova_client.servers.resume(server=server.id)
            if wait:
                _wait(timeout, cloud, server, action, module, shade)
            module.exit_json(changed=True)

        elif action == 'rebuild':
            image = cloud.get_image(image)

            if image is None:
                module.fail_json(msg="Image does not exist")

            # rebuild doesn't set a state, just do it
            cloud.nova_client.servers.rebuild(server=server.id, image=image.id)
            if wait:
                _wait(timeout, cloud, server, action, module, shade)
            module.exit_json(changed=True)

    except shade.OpenStackCloudException as e:
        module.fail_json(msg=str(e), extra_data=e.extra_data)
Beispiel #39
0
def main():
    module = AnsibleModule(
        argument_spec=dict(
            name=dict(type='list', aliases=['pkg', 'package']),
            state=dict(type='str',
                       default='present',
                       choices=[
                           'present', 'installed', 'latest', 'absent',
                           'removed'
                       ]),
            recurse=dict(type='bool', default=False),
            force=dict(type='bool', default=False),
            extra_args=dict(type='str', default=''),
            upgrade=dict(type='bool', default=False),
            upgrade_extra_args=dict(type='str', default=''),
            update_cache=dict(type='bool',
                              default=False,
                              aliases=['update-cache']),
            update_cache_extra_args=dict(type='str', default=''),
        ),
        required_one_of=[['name', 'update_cache', 'upgrade']],
        supports_check_mode=True,
    )

    pacman_path = module.get_bin_path('pacman', True)

    p = module.params

    # normalize the state parameter
    if p['state'] in ['present', 'installed']:
        p['state'] = 'present'
    elif p['state'] in ['absent', 'removed']:
        p['state'] = 'absent'

    if p['recurse']:
        module.deprecate(
            'Option `recurse` is deprecated and will be removed in '
            'version 2.10. Please use `extra_args=--recursive` '
            'instead', '2.10')
        if p['state'] == 'absent':
            p['extra_args'] += " --recursive"

    if p["update_cache"] and not module.check_mode:
        update_package_db(module, pacman_path)
        if not (p['name'] or p['upgrade']):
            module.exit_json(changed=True,
                             msg='Updated the package master lists')

    if p['update_cache'] and module.check_mode and not (p['name']
                                                        or p['upgrade']):
        module.exit_json(changed=True,
                         msg='Would have updated the package cache')

    if p['upgrade']:
        upgrade(module, pacman_path)

    if p['name']:
        pkgs = expand_package_groups(module, pacman_path, p['name'])

        pkg_files = []
        for i, pkg in enumerate(pkgs):
            if not pkg:  # avoid empty strings
                continue
            elif re.match(r".*\.pkg\.tar(\.(gz|bz2|xz|lrz|lzo|Z))?$", pkg):
                # The package given is a filename, extract the raw pkg name from
                # it and store the filename
                pkg_files.append(pkg)
                pkgs[i] = re.sub(r'-[0-9].*$', '', pkgs[i].split('/')[-1])
            else:
                pkg_files.append(None)

        if module.check_mode:
            check_packages(module, pacman_path, pkgs, p['state'])

        if p['state'] in ['present', 'latest']:
            install_packages(module, pacman_path, p['state'], pkgs, pkg_files)
        elif p['state'] == 'absent':
            remove_packages(module, pacman_path, pkgs)
Beispiel #40
0
def main():
    argument_spec = url_argument_spec()

    # setup aliases
    argument_spec['url_username']['aliases'] = ['username']
    argument_spec['url_password']['aliases'] = ['password']

    argument_spec.update(
        url=dict(type='str', required=True),
        dest=dict(type='path', required=True),
        backup=dict(type='bool', default=False),
        sha256sum=dict(type='str', default=''),
        checksum=dict(type='str', default=''),
        timeout=dict(type='int', default=10),
        headers=dict(type='dict'),
        tmp_dest=dict(type='path'),
        unredirected_headers=dict(type='list', elements='str', default=[]),
    )

    module = AnsibleModule(
        # not checking because of daisy chain to file module
        argument_spec=argument_spec,
        add_file_common_args=True,
        supports_check_mode=True,
        mutually_exclusive=[['checksum', 'sha256sum']],
    )

    if module.params.get('sha256sum'):
        module.deprecate(
            'The parameter "sha256sum" has been deprecated and will be removed, use "checksum" instead',
            version='2.14',
            collection_name='ansible.builtin')

    url = module.params['url']
    dest = module.params['dest']
    backup = module.params['backup']
    force = module.params['force']
    sha256sum = module.params['sha256sum']
    checksum = module.params['checksum']
    use_proxy = module.params['use_proxy']
    timeout = module.params['timeout']
    headers = module.params['headers']
    tmp_dest = module.params['tmp_dest']
    unredirected_headers = module.params['unredirected_headers']

    result = dict(
        changed=False,
        checksum_dest=None,
        checksum_src=None,
        dest=dest,
        elapsed=0,
        url=url,
    )

    dest_is_dir = os.path.isdir(dest)
    last_mod_time = None

    # workaround for usage of deprecated sha256sum parameter
    if sha256sum:
        checksum = 'sha256:%s' % (sha256sum)

    # checksum specified, parse for algorithm and checksum
    if checksum:
        try:
            algorithm, checksum = checksum.split(':', 1)
        except ValueError:
            module.fail_json(
                msg=
                "The checksum parameter has to be in format <algorithm>:<checksum>",
                **result)

        if is_url(checksum):
            checksum_url = checksum
            # download checksum file to checksum_tmpsrc
            checksum_tmpsrc, checksum_info = url_get(
                module,
                checksum_url,
                dest,
                use_proxy,
                last_mod_time,
                force,
                timeout,
                headers,
                tmp_dest,
                unredirected_headers=unredirected_headers)
            with open(checksum_tmpsrc) as f:
                lines = [line.rstrip('\n') for line in f]
            os.remove(checksum_tmpsrc)
            checksum_map = []
            for line in lines:
                # Split by one whitespace to keep the leading type char ' ' (whitespace) for text and '*' for binary
                parts = line.split(" ", 1)
                if len(parts) == 2:
                    # Remove the leading type char, we expect
                    if parts[1].startswith((
                            " ",
                            "*",
                    )):
                        parts[1] = parts[1][1:]

                    # Append checksum and path without potential leading './'
                    checksum_map.append((parts[0], parts[1].lstrip("./")))

            filename = url_filename(url)

            # Look through each line in the checksum file for a hash corresponding to
            # the filename in the url, returning the first hash that is found.
            for cksum in (s for (s, f) in checksum_map if f == filename):
                checksum = cksum
                break
            else:
                checksum = None

            if checksum is None:
                module.fail_json(
                    msg="Unable to find a checksum for file '%s' in '%s'" %
                    (filename, checksum_url))
        # Remove any non-alphanumeric characters, including the infamous
        # Unicode zero-width space
        checksum = re.sub(r'\W+', '', checksum).lower()
        # Ensure the checksum portion is a hexdigest
        try:
            int(checksum, 16)
        except ValueError:
            module.fail_json(msg='The checksum format is invalid', **result)

    if not dest_is_dir and os.path.exists(dest):
        checksum_mismatch = False

        # If the download is not forced and there is a checksum, allow
        # checksum match to skip the download.
        if not force and checksum != '':
            destination_checksum = module.digest_from_file(dest, algorithm)

            if checksum != destination_checksum:
                checksum_mismatch = True

        # Not forcing redownload, unless checksum does not match
        if not force and checksum and not checksum_mismatch:
            # Not forcing redownload, unless checksum does not match
            # allow file attribute changes
            file_args = module.load_file_common_arguments(module.params,
                                                          path=dest)
            result['changed'] = module.set_fs_attributes_if_different(
                file_args, False)
            if result['changed']:
                module.exit_json(
                    msg="file already exists but file attributes changed",
                    **result)
            module.exit_json(msg="file already exists", **result)

        # If the file already exists, prepare the last modified time for the
        # request.
        mtime = os.path.getmtime(dest)
        last_mod_time = datetime.datetime.utcfromtimestamp(mtime)

        # If the checksum does not match we have to force the download
        # because last_mod_time may be newer than on remote
        if checksum_mismatch:
            force = True

    # download to tmpsrc
    start = datetime.datetime.utcnow()
    method = 'HEAD' if module.check_mode else 'GET'
    tmpsrc, info = url_get(module,
                           url,
                           dest,
                           use_proxy,
                           last_mod_time,
                           force,
                           timeout,
                           headers,
                           tmp_dest,
                           method,
                           unredirected_headers=unredirected_headers)
    result['elapsed'] = (datetime.datetime.utcnow() - start).seconds
    result['src'] = tmpsrc

    # Now the request has completed, we can finally generate the final
    # destination file name from the info dict.

    if dest_is_dir:
        filename = extract_filename_from_headers(info)
        if not filename:
            # Fall back to extracting the filename from the URL.
            # Pluck the URL from the info, since a redirect could have changed
            # it.
            filename = url_filename(info['url'])
        dest = os.path.join(dest, filename)
        result['dest'] = dest

    # raise an error if there is no tmpsrc file
    if not os.path.exists(tmpsrc):
        os.remove(tmpsrc)
        module.fail_json(msg="Request failed",
                         status_code=info['status'],
                         response=info['msg'],
                         **result)
    if not os.access(tmpsrc, os.R_OK):
        os.remove(tmpsrc)
        module.fail_json(msg="Source %s is not readable" % (tmpsrc), **result)
    result['checksum_src'] = module.sha1(tmpsrc)

    # check if there is no dest file
    if os.path.exists(dest):
        # raise an error if copy has no permission on dest
        if not os.access(dest, os.W_OK):
            os.remove(tmpsrc)
            module.fail_json(msg="Destination %s is not writable" % (dest),
                             **result)
        if not os.access(dest, os.R_OK):
            os.remove(tmpsrc)
            module.fail_json(msg="Destination %s is not readable" % (dest),
                             **result)
        result['checksum_dest'] = module.sha1(dest)
    else:
        if not os.path.exists(os.path.dirname(dest)):
            os.remove(tmpsrc)
            module.fail_json(msg="Destination %s does not exist" %
                             (os.path.dirname(dest)),
                             **result)
        if not os.access(os.path.dirname(dest), os.W_OK):
            os.remove(tmpsrc)
            module.fail_json(msg="Destination %s is not writable" %
                             (os.path.dirname(dest)),
                             **result)

    if module.check_mode:
        if os.path.exists(tmpsrc):
            os.remove(tmpsrc)
        result['changed'] = ('checksum_dest' not in result or
                             result['checksum_src'] != result['checksum_dest'])
        module.exit_json(msg=info.get('msg', ''), **result)

    backup_file = None
    if result['checksum_src'] != result['checksum_dest']:
        try:
            if backup:
                if os.path.exists(dest):
                    backup_file = module.backup_local(dest)
            module.atomic_move(tmpsrc,
                               dest,
                               unsafe_writes=module.params['unsafe_writes'])
        except Exception as e:
            if os.path.exists(tmpsrc):
                os.remove(tmpsrc)
            module.fail_json(msg="failed to copy %s to %s: %s" %
                             (tmpsrc, dest, to_native(e)),
                             exception=traceback.format_exc(),
                             **result)
        result['changed'] = True
    else:
        result['changed'] = False
        if os.path.exists(tmpsrc):
            os.remove(tmpsrc)

    if checksum != '':
        destination_checksum = module.digest_from_file(dest, algorithm)

        if checksum != destination_checksum:
            os.remove(dest)
            module.fail_json(
                msg="The checksum for %s did not match %s; it was %s." %
                (dest, checksum, destination_checksum),
                **result)

    # allow file attribute changes
    file_args = module.load_file_common_arguments(module.params, path=dest)
    result['changed'] = module.set_fs_attributes_if_different(
        file_args, result['changed'])

    # Backwards compat only.  We'll return None on FIPS enabled systems
    try:
        result['md5sum'] = module.md5(dest)
    except ValueError:
        result['md5sum'] = None

    if backup_file:
        result['backup_file'] = backup_file

    # Mission complete
    module.exit_json(msg=info.get('msg', ''),
                     status_code=info.get('status', ''),
                     **result)
Beispiel #41
0
def main():
    argument_spec = dict(
        ip_address=dict(required=True),
        password=dict(no_log=True),
        username=dict(default='admin'),
        api_key=dict(no_log=True),
        rule_name=dict(required=True),
        description=dict(default=''),
        tag=dict(),
        to_zone=dict(type='list', default=['any']),
        from_zone=dict(type='list', default=['any']),
        source=dict(type='list', default=["any"]),
        source_user=dict(type='list', default=['any']),
        destination=dict(type='list', default=["any"]),
        category=dict(type='list', default=['any']),
        application=dict(type='list', default=['any']),
        service=dict(type='list', default=['application-default']),
        hip_profiles=dict(type='list', default=['any']),
        group_profile=dict(),
        antivirus=dict(),
        vulnerability=dict(),
        spyware=dict(),
        url_filtering=dict(),
        file_blocking=dict(),
        data_filtering=dict(),
        wildfire_analysis=dict(),
        log_start=dict(type='bool', default=False),
        log_end=dict(type='bool', default=True),
        rule_type=dict(default='universal'),
        action=dict(default='allow'),
        devicegroup=dict(),
        commit=dict(type='bool', default=True)
    )
    module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False,
                           required_one_of=[['api_key', 'password']])

    if module._name == 'panos_security_policy':
        module.deprecate("The 'panos_security_policy' module is being renamed 'panos_security_rule'", version=2.8)

    if not HAS_LIB:
        module.fail_json(msg='Missing required pan-python and pandevice modules.')

    ip_address = module.params["ip_address"]
    password = module.params["password"]
    username = module.params['username']
    api_key = module.params['api_key']
    rule_name = module.params['rule_name']
    description = module.params['description']
    tag = module.params['tag']
    from_zone = module.params['from_zone']
    to_zone = module.params['to_zone']
    source = module.params['source']
    source_user = module.params['source_user']
    destination = module.params['destination']
    category = module.params['category']
    application = module.params['application']
    service = module.params['service']
    hip_profiles = module.params['hip_profiles']
    log_start = module.params['log_start']
    log_end = module.params['log_end']
    rule_type = module.params['rule_type']
    action = module.params['action']

    group_profile = module.params['group_profile']
    antivirus = module.params['antivirus']
    vulnerability = module.params['vulnerability']
    spyware = module.params['spyware']
    url_filtering = module.params['url_filtering']
    file_blocking = module.params['file_blocking']
    data_filtering = module.params['data_filtering']
    wildfire_analysis = module.params['wildfire_analysis']

    devicegroup = module.params['devicegroup']

    commit = module.params['commit']

    if devicegroup:
        device = pandevice.panorama.Panorama(ip_address, username, password, api_key=api_key)
        dev_grps = device.refresh_devices()

        for grp in dev_grps:
            if grp.name == devicegroup:
                break
            module.fail_json(msg=' \'%s\' device group not found in Panorama. Is the name correct?' % devicegroup)
    else:
        device = pandevice.firewall.Firewall(ip_address, username, password, api_key=api_key)

    sec_rule = create_security_rule(
        rule_name=rule_name,
        description=description,
        tag=tag,
        from_zone=from_zone,
        to_zone=to_zone,
        source=source,
        source_user=source_user,
        destination=destination,
        category=category,
        application=application,
        service=service,
        hip_profiles=hip_profiles,
        group_profile=group_profile,
        antivirus=antivirus,
        vulnerability=vulnerability,
        spyware=spyware,
        url_filtering=url_filtering,
        file_blocking=file_blocking,
        data_filtering=data_filtering,
        wildfire_analysis=wildfire_analysis,
        log_start=log_start,
        log_end=log_end,
        rule_type=rule_type,
        action=action
    )

    rule_exist = security_rule_exists(device, sec_rule)
    if rule_exist is True:
        module.fail_json(msg='Rule with the same name but different objects exists.')
    try:
        changed = add_security_rule(device, sec_rule, rule_exist)
    except PanXapiError:
        exc = get_exception()
        module.fail_json(msg=exc.message)

    if changed and commit:
        result = _commit(device, devicegroup)

    module.exit_json(changed=changed, msg="okey dokey")
def main():

    module = AnsibleModule(
        argument_spec=dict(
            state=dict(type='str',
                       default='present',
                       choices=['present', 'absent']),
            force=dict(type='bool', default=False),
            path=dict(type='path', required=True),
            privatekey_path=dict(type='path'),
            privatekey_content=dict(type='str'),
            format=dict(type='str', default='PEM', choices=['OpenSSH', 'PEM']),
            privatekey_passphrase=dict(type='str', no_log=True),
            backup=dict(type='bool', default=False),
            select_crypto_backend=dict(
                type='str',
                choices=['auto', 'pyopenssl', 'cryptography'],
                default='auto'),
            return_content=dict(type='bool', default=False),
        ),
        supports_check_mode=True,
        add_file_common_args=True,
        required_if=[('state', 'present',
                      ['privatekey_path', 'privatekey_content'], True)],
        mutually_exclusive=(['privatekey_path', 'privatekey_content'], ),
    )

    minimal_cryptography_version = MINIMAL_CRYPTOGRAPHY_VERSION
    if module.params['format'] == 'OpenSSH':
        minimal_cryptography_version = MINIMAL_CRYPTOGRAPHY_VERSION_OPENSSH

    backend = module.params['select_crypto_backend']
    if backend == 'auto':
        # Detection what is possible
        can_use_cryptography = CRYPTOGRAPHY_FOUND and CRYPTOGRAPHY_VERSION >= LooseVersion(
            minimal_cryptography_version)
        can_use_pyopenssl = PYOPENSSL_FOUND and PYOPENSSL_VERSION >= LooseVersion(
            MINIMAL_PYOPENSSL_VERSION)

        # Decision
        if can_use_cryptography:
            backend = 'cryptography'
        elif can_use_pyopenssl:
            if module.params['format'] == 'OpenSSH':
                module.fail_json(msg=missing_required_lib(
                    'cryptography >= {0}'.format(
                        MINIMAL_CRYPTOGRAPHY_VERSION_OPENSSH)),
                                 exception=CRYPTOGRAPHY_IMP_ERR)
            backend = 'pyopenssl'

        # Success?
        if backend == 'auto':
            module.fail_json(msg=(
                "Can't detect any of the required Python libraries "
                "cryptography (>= {0}) or PyOpenSSL (>= {1})"
            ).format(minimal_cryptography_version, MINIMAL_PYOPENSSL_VERSION))

    if module.params['format'] == 'OpenSSH' and backend != 'cryptography':
        module.fail_json(
            msg="Format OpenSSH requires the cryptography backend.")

    if backend == 'pyopenssl':
        if not PYOPENSSL_FOUND:
            module.fail_json(msg=missing_required_lib(
                'pyOpenSSL >= {0}'.format(MINIMAL_PYOPENSSL_VERSION)),
                             exception=PYOPENSSL_IMP_ERR)
        module.deprecate(
            'The module is using the PyOpenSSL backend. This backend has been deprecated',
            version='2.13')
    elif backend == 'cryptography':
        if not CRYPTOGRAPHY_FOUND:
            module.fail_json(msg=missing_required_lib(
                'cryptography >= {0}'.format(minimal_cryptography_version)),
                             exception=CRYPTOGRAPHY_IMP_ERR)

    base_dir = os.path.dirname(module.params['path']) or '.'
    if not os.path.isdir(base_dir):
        module.fail_json(
            name=base_dir,
            msg=
            "The directory '%s' does not exist or the file is not a directory"
            % base_dir)

    try:
        public_key = PublicKey(module, backend)

        if public_key.state == 'present':
            if module.check_mode:
                result = public_key.dump()
                result['changed'] = module.params[
                    'force'] or not public_key.check(module)
                module.exit_json(**result)

            public_key.generate(module)
        else:
            if module.check_mode:
                result = public_key.dump()
                result['changed'] = os.path.exists(module.params['path'])
                module.exit_json(**result)

            public_key.remove(module)

        result = public_key.dump()
        module.exit_json(**result)
    except crypto_utils.OpenSSLObjectError as exc:
        module.fail_json(msg=to_native(exc))
def main():
    argument_spec = ovirt_full_argument_spec(
        state=dict(
            choices=['present', 'absent'],
            default='present',
        ),
        name=dict(default=None),
        description=dict(default=None),
        type=dict(
            default=None,
            required=True,
            choices=[
                'os_image', 'network', 'os_volume', 'foreman',
            ],
            aliases=['provider'],
        ),
        url=dict(default=None),
        username=dict(default=None),
        password=dict(default=None, no_log=True),
        tenant_name=dict(default=None, aliases=['tenant']),
        authentication_url=dict(default=None, aliases=['auth_url']),
        data_center=dict(default=None),
        read_only=dict(default=None, type='bool'),
        network_type=dict(
            default='external',
            choices=['external', 'neutron'],
        ),
    )
    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
    )

    if module._name == 'ovirt_external_providers':
        module.deprecate("The 'ovirt_external_providers' module is being renamed 'ovirt_external_provider'", version=2.8)

    check_sdk(module)
    check_params(module)

    try:
        auth = module.params.pop('auth')
        connection = create_connection(auth)
        provider_type, external_providers_service = _external_provider_service(
            provider_type=module.params.get('type'),
            system_service=connection.system_service(),
        )
        external_providers_module = ExternalProviderModule(
            connection=connection,
            module=module,
            service=external_providers_service,
        )
        external_providers_module.provider_type(provider_type)

        state = module.params.pop('state')
        if state == 'absent':
            ret = external_providers_module.remove()
        elif state == 'present':
            ret = external_providers_module.create()

        module.exit_json(**ret)
    except Exception as e:
        module.fail_json(msg=str(e), exception=traceback.format_exc())
    finally:
        connection.close(logout=auth.get('token') is None)
def main():
    argument_spec = ecs_argument_spec()
    argument_spec.update(dict(
        availability_zone=dict(aliases=['alicloud_zone']),
        instance_ids=dict(type='list', elements='str', aliases=['ids']),
        instance_names=dict(type='list', elements='str', aliases=['names']),
        name_prefix=dict(type='str'),
        tags=dict(type='dict', aliases=['instance_tags']),
        filters=dict(type='dict')
    )
    )
    module = AnsibleModule(argument_spec=argument_spec)
    if module._name in ('ali_instance_facts', 'community.general.ali_instance_facts'):
        module.deprecate("The 'ali_instance_facts' module has been renamed to 'ali_instance_info'",
                         version='3.0.0', collection_name='community.general')  # was Ansible 2.13

    if HAS_FOOTMARK is False:
        module.fail_json(msg=missing_required_lib('footmark'), exception=FOOTMARK_IMP_ERR)

    ecs = ecs_connect(module)

    instances = []
    instance_ids = []
    ids = module.params['instance_ids']
    name_prefix = module.params['name_prefix']
    names = module.params['instance_names']
    zone_id = module.params['availability_zone']
    if ids and (not isinstance(ids, list) or len(ids) < 1):
        module.fail_json(msg='instance_ids should be a list of instances, aborting')

    if names and (not isinstance(names, list) or len(names) < 1):
        module.fail_json(msg='instance_names should be a list of instances, aborting')

    filters = module.params['filters']
    if not filters:
        filters = {}
    if not ids:
        ids = []
    for key, value in list(filters.items()):
        if key in ["InstanceIds", "instance_ids", "instance-ids"] and isinstance(ids, list):
            for id in value:
                if id not in ids:
                    ids.append(value)
    if ids:
        filters['instance_ids'] = ids
    if module.params['tags']:
        filters['tags'] = module.params['tags']
    if zone_id:
        filters['zone_id'] = zone_id
    if names:
        filters['instance_name'] = names[0]

    for inst in ecs.describe_instances(**filters):
        if name_prefix:
            if not str(inst.instance_name).startswith(name_prefix):
                continue
        volumes = ecs.describe_disks(instance_id=inst.id)
        setattr(inst, 'block_device_mappings', volumes)
        setattr(inst, 'user_data', inst.describe_user_data())
        instances.append(inst.read())
        instance_ids.append(inst.id)

    module.exit_json(changed=False, ids=instance_ids, instances=instances)
Beispiel #45
0
def main():
    argument_spec = url_argument_spec()
    argument_spec.update(dict(
        dest=dict(type='path'),
        url_username=dict(type='str', aliases=['user']),
        url_password=dict(type='str', aliases=['password'], no_log=True),
        body=dict(type='raw'),
        body_format=dict(type='str', default='raw', choices=['raw', 'json']),
        method=dict(type='str', default='GET', choices=['GET', 'POST', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'PATCH', 'TRACE', 'CONNECT', 'REFRESH']),
        return_content=dict(type='bool', default='no'),
        follow_redirects=dict(type='str', default='safe', choices=['all', 'no', 'none', 'safe', 'urllib2', 'yes']),
        creates=dict(type='path'),
        removes=dict(type='path'),
        status_code=dict(type='list', default=[200]),
        timeout=dict(type='int', default=30),
        headers=dict(type='dict', default={})
    ))

    module = AnsibleModule(
        argument_spec=argument_spec,
        # TODO: Remove check_invalid_arguments in 2.9
        check_invalid_arguments=False,
        add_file_common_args=True
    )

    url = module.params['url']
    body = module.params['body']
    body_format = module.params['body_format'].lower()
    method = module.params['method']
    dest = module.params['dest']
    return_content = module.params['return_content']
    creates = module.params['creates']
    removes = module.params['removes']
    status_code = [int(x) for x in list(module.params['status_code'])]
    socket_timeout = module.params['timeout']

    dict_headers = module.params['headers']

    if body_format == 'json':
        # Encode the body unless its a string, then assume it is pre-formatted JSON
        if not isinstance(body, six.string_types):
            body = json.dumps(body)
        lower_header_keys = [key.lower() for key in dict_headers]
        if 'content-type' not in lower_header_keys:
            dict_headers['Content-Type'] = 'application/json'

    # TODO: Deprecated section.  Remove in Ansible 2.9
    # Grab all the http headers. Need this hack since passing multi-values is
    # currently a bit ugly. (e.g. headers='{"Content-Type":"application/json"}')
    for key, value in six.iteritems(module.params):
        if key.startswith("HEADER_"):
            module.deprecate('Supplying headers via HEADER_* is deprecated. Please use `headers` to'
                             ' supply headers for the request', version='2.9')
            skey = key.replace("HEADER_", "")
            dict_headers[skey] = value
    # End deprecated section

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

    if removes is not None:
        # do not run the command if the line contains removes=filename
        # and the filename do not exists.  This allows idempotence
        # of uri executions.
        if not os.path.exists(removes):
            module.exit_json(stdout="skipped, since '%s' does not exist" % removes, changed=False, rc=0)

    # Make the request
    resp, content, dest = uri(module, url, dest, body, body_format, method,
                              dict_headers, socket_timeout)
    resp['status'] = int(resp['status'])

    # Write the file out if requested
    if dest is not None:
        if resp['status'] == 304:
            changed = False
        else:
            write_file(module, url, dest, content)
            # allow file attribute changes
            changed = True
            module.params['path'] = dest
            file_args = module.load_file_common_arguments(module.params)
            file_args['path'] = dest
            changed = module.set_fs_attributes_if_different(file_args, changed)
        resp['path'] = dest
    else:
        changed = False

    # Transmogrify the headers, replacing '-' with '_', since variables don't
    # work with dashes.
    # In python3, the headers are title cased.  Lowercase them to be
    # compatible with the python2 behaviour.
    uresp = {}
    for key, value in six.iteritems(resp):
        ukey = key.replace("-", "_").lower()
        uresp[ukey] = value

    try:
        uresp['location'] = absolute_location(url, uresp['location'])
    except KeyError:
        pass

    # Default content_encoding to try
    content_encoding = 'utf-8'
    if 'content_type' in uresp:
        content_type, params = cgi.parse_header(uresp['content_type'])
        if 'charset' in params:
            content_encoding = params['charset']
        u_content = to_text(content, encoding=content_encoding)
        if any(candidate in content_type for candidate in JSON_CANDIDATES):
            try:
                js = json.loads(u_content)
                uresp['json'] = js
            except:
                pass
    else:
        u_content = to_text(content, encoding=content_encoding)

    if resp['status'] not in status_code:
        uresp['msg'] = 'Status code was %s and not %s: %s' % (resp['status'], status_code, uresp.get('msg', ''))
        module.fail_json(content=u_content, **uresp)
    elif return_content:
        module.exit_json(changed=changed, content=u_content, **uresp)
    else:
        module.exit_json(changed=changed, **uresp)
Beispiel #46
0
def main():
    module = AnsibleModule(
        argument_spec=dict(
            state=dict(type='str', default='present', choices=['absent', 'build-dep', 'installed', 'latest', 'present', 'removed', 'present', 'fixed']),
            update_cache=dict(type='bool', aliases=['update-cache']),
            cache_valid_time=dict(type='int', default=0),
            purge=dict(type='bool', default=False),
            package=dict(type='list', 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']),
            dpkg_options=dict(type='str', default=DPKG_OPTIONS),
            autoremove=dict(type='bool', default=False),
            autoclean=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:
            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 and p.get('upgrade', None) in ['full', 'safe', 'yes']:
        module.warn("Could not find aptitude. Using apt-get instead.")
        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']
    autoclean = p['autoclean']

    # Deal with deprecated aliases
    if p['state'] == 'installed':
        module.deprecate("State 'installed' is deprecated. Using state 'present' instead.", version="2.9")
        p['state'] = 'present'
    if p['state'] == 'removed':
        module.deprecate("State 'removed' is deprecated. Using state 'absent' instead.", version="2.9")
        p['state'] = 'absent'

    # 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 up to 3 times
                err = ''
                for retry in range(3):
                    try:
                        cache.update()
                        break
                    except apt.cache.FetchFailedException as e:
                        err = to_native(e)
                else:
                    module.fail_json(msg='Failed to update apt cache: %s' % err)
                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, 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, dpkg_options=p['dpkg_options'])

        unfiltered_packages = p['package'] or ()
        packages = [package 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, 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,
                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:
        module.fail_json(msg="Failed to lock apt for exclusive operation")
    except apt.cache.FetchFailedException:
        module.fail_json(msg="Could not fetch updated apt files")
Beispiel #47
0
def main():
    argument_spec = url_argument_spec()
    argument_spec.update(
        url=dict(type='str', required=True),
        dest=dict(type='path', required=True),
        backup=dict(type='bool'),
        sha256sum=dict(type='str', default=''),
        checksum=dict(type='str', default=''),
        timeout=dict(type='int', default=10),
        headers=dict(type='raw'),
        tmp_dest=dict(type='path'),
    )

    module = AnsibleModule(
        # not checking because of daisy chain to file module
        argument_spec=argument_spec,
        add_file_common_args=True,
        supports_check_mode=True,
        mutually_exclusive=(['checksum', 'sha256sum']),
    )

    url = module.params['url']
    dest = module.params['dest']
    backup = module.params['backup']
    force = module.params['force']
    sha256sum = module.params['sha256sum']
    checksum = module.params['checksum']
    use_proxy = module.params['use_proxy']
    timeout = module.params['timeout']
    tmp_dest = module.params['tmp_dest']

    # Parse headers to dict
    if isinstance(module.params['headers'], dict):
        headers = module.params['headers']
    elif module.params['headers']:
        try:
            headers = dict(item.split(':', 1) for item in module.params['headers'].split(','))
            module.deprecate('Supplying `headers` as a string is deprecated. Please use dict/hash format for `headers`', version='2.10')
        except Exception:
            module.fail_json(msg="The string representation for the `headers` parameter requires a key:value,key:value syntax to be properly parsed.")
    else:
        headers = None

    dest_is_dir = os.path.isdir(dest)
    last_mod_time = None

    # workaround for usage of deprecated sha256sum parameter
    if sha256sum:
        checksum = 'sha256:%s' % (sha256sum)

    # checksum specified, parse for algorithm and checksum
    if checksum:
        try:
            algorithm, checksum = checksum.rsplit(':', 1)
            # Remove any non-alphanumeric characters, including the infamous
            # Unicode zero-width space
            checksum = re.sub(r'\W+', '', checksum).lower()
            # Ensure the checksum portion is a hexdigest
            int(checksum, 16)
        except ValueError:
            module.fail_json(msg="The checksum parameter has to be in format <algorithm>:<checksum>")

    if not dest_is_dir and os.path.exists(dest):
        checksum_mismatch = False

        # If the download is not forced and there is a checksum, allow
        # checksum match to skip the download.
        if not force and checksum != '':
            destination_checksum = module.digest_from_file(dest, algorithm)

            if checksum == destination_checksum:
                module.exit_json(msg="file already exists", dest=dest, url=url, changed=False)

            checksum_mismatch = True

        # Not forcing redownload, unless checksum does not match
        if not force and not checksum_mismatch:
            # allow file attribute changes
            module.params['path'] = dest
            file_args = module.load_file_common_arguments(module.params)
            file_args['path'] = dest
            changed = module.set_fs_attributes_if_different(file_args, False)

            if changed:
                module.exit_json(msg="file already exists but file attributes changed", dest=dest, url=url, changed=changed)
            module.exit_json(msg="file already exists", dest=dest, url=url, changed=changed)

        # If the file already exists, prepare the last modified time for the
        # request.
        mtime = os.path.getmtime(dest)
        last_mod_time = datetime.datetime.utcfromtimestamp(mtime)

        # If the checksum does not match we have to force the download
        # because last_mod_time may be newer than on remote
        if checksum_mismatch:
            force = True

    # download to tmpsrc
    tmpsrc, info = url_get(module, url, dest, use_proxy, last_mod_time, force, timeout, headers, tmp_dest)

    # Now the request has completed, we can finally generate the final
    # destination file name from the info dict.

    if dest_is_dir:
        filename = extract_filename_from_headers(info)
        if not filename:
            # Fall back to extracting the filename from the URL.
            # Pluck the URL from the info, since a redirect could have changed
            # it.
            filename = url_filename(info['url'])
        dest = os.path.join(dest, filename)

    checksum_src = None
    checksum_dest = None

    # If the remote URL exists, we're done with check mode
    if module.check_mode:
        os.remove(tmpsrc)
        res_args = dict(url=url, dest=dest, src=tmpsrc, changed=True, msg=info.get('msg', ''))
        module.exit_json(**res_args)

    # raise an error if there is no tmpsrc file
    if not os.path.exists(tmpsrc):
        os.remove(tmpsrc)
        module.fail_json(msg="Request failed", status_code=info['status'], response=info['msg'])
    if not os.access(tmpsrc, os.R_OK):
        os.remove(tmpsrc)
        module.fail_json(msg="Source %s is not readable" % (tmpsrc))
    checksum_src = module.sha1(tmpsrc)

    # check if there is no dest file
    if os.path.exists(dest):
        # raise an error if copy has no permission on dest
        if not os.access(dest, os.W_OK):
            os.remove(tmpsrc)
            module.fail_json(msg="Destination %s is not writable" % (dest))
        if not os.access(dest, os.R_OK):
            os.remove(tmpsrc)
            module.fail_json(msg="Destination %s is not readable" % (dest))
        checksum_dest = module.sha1(dest)
    else:
        if not os.path.exists(os.path.dirname(dest)):
            os.remove(tmpsrc)
            module.fail_json(msg="Destination %s does not exist" % (os.path.dirname(dest)))
        if not os.access(os.path.dirname(dest), os.W_OK):
            os.remove(tmpsrc)
            module.fail_json(msg="Destination %s is not writable" % (os.path.dirname(dest)))

    backup_file = None
    if checksum_src != checksum_dest:
        try:
            if backup:
                if os.path.exists(dest):
                    backup_file = module.backup_local(dest)
            module.atomic_move(tmpsrc, dest)
        except Exception as e:
            if os.path.exists(tmpsrc):
                os.remove(tmpsrc)
            module.fail_json(msg="failed to copy %s to %s: %s" % (tmpsrc, dest, to_native(e)),
                             exception=traceback.format_exc())
        changed = True
    else:
        changed = False
        if os.path.exists(tmpsrc):
            os.remove(tmpsrc)

    if checksum != '':
        destination_checksum = module.digest_from_file(dest, algorithm)

        if checksum != destination_checksum:
            os.remove(dest)
            module.fail_json(msg="The checksum for %s did not match %s; it was %s." % (dest, checksum, destination_checksum))

    # allow file attribute changes
    module.params['path'] = dest
    file_args = module.load_file_common_arguments(module.params)
    file_args['path'] = dest
    changed = module.set_fs_attributes_if_different(file_args, changed)

    # Backwards compat only.  We'll return None on FIPS enabled systems
    try:
        md5sum = module.md5(dest)
    except ValueError:
        md5sum = None

    res_args = dict(
        url=url, dest=dest, src=tmpsrc, md5sum=md5sum, checksum_src=checksum_src,
        checksum_dest=checksum_dest, changed=changed, msg=info.get('msg', ''), status_code=info.get('status', '')
    )
    if backup_file:
        res_args['backup_file'] = backup_file

    # Mission complete
    module.exit_json(**res_args)
Beispiel #48
0
def main():
    module = AnsibleModule(
        argument_spec=dict(server_url=dict(type='str',
                                           required=True,
                                           aliases=['url']),
                           login_user=dict(type='str', required=True),
                           login_password=dict(type='str',
                                               required=True,
                                               no_log=True),
                           http_login_user=dict(type='str',
                                                required=False,
                                                default=None),
                           http_login_password=dict(type='str',
                                                    required=False,
                                                    default=None,
                                                    no_log=True),
                           validate_certs=dict(type='bool',
                                               required=False,
                                               default=True),
                           template_name=dict(type='str', required=False),
                           template_json=dict(type='json', required=False),
                           template_xml=dict(type='str', required=False),
                           template_groups=dict(type='list', required=False),
                           link_templates=dict(type='list', required=False),
                           clear_templates=dict(type='list', required=False),
                           macros=dict(type='list', required=False),
                           dump_format=dict(type='str',
                                            required=False,
                                            default='json',
                                            choices=['json', 'xml']),
                           state=dict(default="present",
                                      choices=['present', 'absent', 'dump']),
                           timeout=dict(type='int', default=10)),
        required_one_of=[['template_name', 'template_json', 'template_xml']],
        mutually_exclusive=[['template_name', 'template_json',
                             'template_xml']],
        required_if=[['state', 'absent', ['template_name']],
                     ['state', 'dump', ['template_name']]],
        supports_check_mode=True)

    if not HAS_ZABBIX_API:
        module.fail_json(msg=missing_required_lib(
            'zabbix-api', url='https://pypi.org/project/zabbix-api/'),
                         exception=ZBX_IMP_ERR)

    server_url = module.params['server_url']
    login_user = module.params['login_user']
    login_password = module.params['login_password']
    http_login_user = module.params['http_login_user']
    http_login_password = module.params['http_login_password']
    validate_certs = module.params['validate_certs']
    template_name = module.params['template_name']
    template_json = module.params['template_json']
    template_xml = module.params['template_xml']
    template_groups = module.params['template_groups']
    link_templates = module.params['link_templates']
    clear_templates = module.params['clear_templates']
    template_macros = module.params['macros']
    dump_format = module.params['dump_format']
    state = module.params['state']
    timeout = module.params['timeout']

    zbx = None
    try:
        zbx = ZabbixAPI(server_url,
                        timeout=timeout,
                        user=http_login_user,
                        passwd=http_login_password,
                        validate_certs=validate_certs)
        zbx.login(login_user, login_password)
        atexit.register(zbx.logout)
    except ZabbixAPIException as e:
        module.fail_json(msg="Failed to connect to Zabbix server: %s" % e)

    template = Template(module, zbx)

    # Identify template names for IDs retrieval
    # Template names are expected to reside in ['zabbix_export']['templates'][*]['template'] for both data types
    template_content, template_type = None, None
    if template_json is not None:
        template_type = 'json'
        template_content = template_json
        json_parsed = template.load_json_template(template_content)
        template_names = list(
            t['template'] for t in json_parsed['zabbix_export']['templates'])

    elif template_xml is not None:
        template_type = 'xml'
        template_content = template_xml
        xml_parsed = template.load_xml_template(template_content)
        template_names = list(
            t.find('template').text
            for t in list(xml_parsed.find('templates')))

    else:
        template_names = [template_name]

    template_ids = template.get_template_ids(template_names)

    if state == "absent":
        if not template_ids:
            module.exit_json(changed=False,
                             msg="Template not found. No changed: %s" %
                             template_name)

        template.delete_template(template_ids)
        module.exit_json(changed=True,
                         result="Successfully deleted template %s" %
                         template_name)

    elif state == "dump":
        module.deprecate(
            "The 'dump' state has been deprecated and will be removed, use 'zabbix_template_info' module instead.",
            version='2.14')
        if not template_ids:
            module.fail_json(msg='Template not found: %s' % template_name)

        if dump_format == 'json':
            module.exit_json(changed=False,
                             template_json=template.dump_template(
                                 template_ids, template_type='json'))
        elif dump_format == 'xml':
            module.exit_json(changed=False,
                             template_xml=template.dump_template(
                                 template_ids, template_type='xml'))

    elif state == "present":
        # Load all subelements for template that were provided by user
        group_ids = None
        if template_groups is not None:
            group_ids = template.get_group_ids_by_group_names(template_groups)

        link_template_ids = None
        if link_templates is not None:
            link_template_ids = template.get_template_ids(link_templates)

        clear_template_ids = None
        if clear_templates is not None:
            clear_template_ids = template.get_template_ids(clear_templates)

        if template_macros is not None:
            # Zabbix configuration.export does not differentiate python types (numbers are returned as strings)
            for macroitem in template_macros:
                for key in macroitem:
                    macroitem[key] = str(macroitem[key])

        if not template_ids:
            # Assume new templates are being added when no ID's were found
            if template_content is not None:
                template.import_template(template_content, template_type)
                module.exit_json(changed=True,
                                 result="Template import successful")

            else:
                if group_ids is None:
                    module.fail_json(
                        msg=
                        'template_groups are required when creating a new Zabbix template'
                    )

                template.add_template(template_name, group_ids,
                                      link_template_ids, template_macros)
                module.exit_json(changed=True,
                                 result="Successfully added template: %s" %
                                 template_name)

        else:
            changed = template.check_template_changed(
                template_ids, template_groups, link_templates, clear_templates,
                template_macros, template_content, template_type)

            if module.check_mode:
                module.exit_json(changed=changed)

            if changed:
                if template_type is not None:
                    template.import_template(template_content, template_type)
                else:
                    template.update_template(template_ids, group_ids,
                                             link_template_ids,
                                             clear_template_ids,
                                             template_macros)

            module.exit_json(changed=changed,
                             result="Template successfully updated")
Beispiel #49
0
def main():
    module = AnsibleModule(argument_spec={}, supports_check_mode=True)
    module.deprecate(msg)
    module.exit_json(changed=False)
Beispiel #50
0
def main():
    argument_spec = ovirt_full_argument_spec(
        state=dict(
            choices=['present', 'absent', 'attached', 'detached', 'exported'],
            default='present'),
        id=dict(default=None),
        name=dict(default=None, aliases=['alias']),
        vm_name=dict(default=None),
        vm_id=dict(default=None),
        size=dict(default=None),
        interface=dict(default=None, ),
        storage_domain=dict(default=None),
        storage_domains=dict(default=None, type='list'),
        profile=dict(default=None),
        format=dict(default='cow', choices=['raw', 'cow']),
        bootable=dict(default=None, type='bool'),
        shareable=dict(default=None, type='bool'),
        logical_unit=dict(default=None, type='dict'),
        download_image_path=dict(default=None),
        upload_image_path=dict(default=None, aliases=['image_path']),
        force=dict(default=False, type='bool'),
        sparsify=dict(default=None, type='bool'),
        openstack_volume_type=dict(default=None),
        image_provider=dict(default=None),
    )
    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
    )

    if module._name == 'ovirt_disks':
        module.deprecate(
            "The 'ovirt_disks' module is being renamed 'ovirt_disk'",
            version=2.8)

    check_sdk(module)
    check_params(module)

    try:
        disk = None
        state = module.params['state']
        auth = module.params.get('auth')
        connection = create_connection(auth)
        disks_service = connection.system_service().disks_service()
        disks_module = DisksModule(
            connection=connection,
            module=module,
            service=disks_service,
        )

        lun = module.params.get('logical_unit')
        if lun:
            disk = _search_by_lun(disks_service, lun.get('id'))

        ret = None
        # First take care of creating the VM, if needed:
        if state in ('present', 'detached', 'attached'):
            ret = disks_module.create(
                entity=disk,
                result_state=otypes.DiskStatus.OK if lun is None else None,
            )
            is_new_disk = ret['changed']
            ret['changed'] = ret[
                'changed'] or disks_module.update_storage_domains(ret['id'])
            # We need to pass ID to the module, so in case we want detach/attach disk
            # we have this ID specified to attach/detach method:
            module.params['id'] = ret['id'] if disk is None else disk.id

            # Upload disk image in case it's new disk or force parameter is passed:
            if module.params['upload_image_path'] and (is_new_disk or
                                                       module.params['force']):
                uploaded = upload_disk_image(connection, module)
                ret['changed'] = ret['changed'] or uploaded
            # Download disk image in case it's file don't exist or force parameter is passed:
            if (module.params['download_image_path'] and
                (not os.path.isfile(module.params['download_image_path'])
                 or module.params['force'])):
                downloaded = download_disk_image(connection, module)
                ret['changed'] = ret['changed'] or downloaded

            # Disk sparsify, only if disk is of image type:
            disk = disks_service.disk_service(module.params['id']).get()
            if disk.storage_type == otypes.DiskStorageType.IMAGE:
                ret = disks_module.action(
                    action='sparsify',
                    action_condition=lambda d: module.params['sparsify'],
                    wait_condition=lambda d: d.status == otypes.DiskStatus.OK,
                )

        # Export disk as image to glance domain
        elif state == 'exported':
            disk = disks_module.search_entity()
            if disk is None:
                module.fail_json(
                    msg="Can not export given disk '%s', it doesn't exist" %
                    module.params.get('name') or module.params.get('id'))
            if disk.storage_type == otypes.DiskStorageType.IMAGE:
                ret = disks_module.action(
                    action='export',
                    action_condition=lambda d: module.params['image_provider'],
                    wait_condition=lambda d: d.status == otypes.DiskStatus.OK,
                    storage_domain=otypes.StorageDomain(
                        name=module.params['image_provider']),
                )
        elif state == 'absent':
            ret = disks_module.remove()

        # If VM was passed attach/detach disks to/from the VM:
        if module.params.get('vm_id') is not None or module.params.get(
                'vm_name') is not None and state != 'absent':
            vms_service = connection.system_service().vms_service()

            # If `vm_id` isn't specified, find VM by name:
            vm_id = module.params['vm_id']
            if vm_id is None:
                vm_id = getattr(
                    search_by_name(vms_service, module.params['vm_name']),
                    'id', None)

            if vm_id is None:
                module.fail_json(
                    msg="VM don't exists, please create it first.")

            disk_attachments_service = vms_service.vm_service(
                vm_id).disk_attachments_service()
            disk_attachments_module = DiskAttachmentsModule(
                connection=connection,
                module=module,
                service=disk_attachments_service,
                changed=ret['changed'] if ret else False,
            )

            if state == 'present' or state == 'attached':
                ret = disk_attachments_module.create()
                if lun is None:
                    wait(
                        service=disk_attachments_service.service(ret['id']),
                        condition=lambda d: follow_link(connection, d.disk).
                        status == otypes.DiskStatus.OK,
                        wait=module.params['wait'],
                        timeout=module.params['timeout'],
                    )
            elif state == 'detached':
                ret = disk_attachments_module.remove()

        module.exit_json(**ret)
    except Exception as e:
        module.fail_json(msg=str(e), exception=traceback.format_exc())
    finally:
        connection.close(logout=auth.get('token') is None)
Beispiel #51
0
def main():
    argument_spec = ovirt_full_argument_spec(
        state=dict(
            choices=['present', 'absent'],
            default='present',
        ),
        name=dict(default=None, required=True),
        ballooning=dict(default=None, type='bool', aliases=['balloon']),
        gluster=dict(default=None, type='bool'),
        virt=dict(default=None, type='bool'),
        threads_as_cores=dict(default=None, type='bool'),
        ksm_numa=dict(default=None, type='bool'),
        ksm=dict(default=None, type='bool'),
        ha_reservation=dict(default=None, type='bool'),
        trusted_service=dict(default=None, type='bool'),
        vm_reason=dict(default=None, type='bool'),
        host_reason=dict(default=None, type='bool'),
        memory_policy=dict(default=None, choices=['disabled', 'server', 'desktop']),
        rng_sources=dict(default=None, type='list'),
        spice_proxy=dict(default=None),
        fence_enabled=dict(default=None, type='bool'),
        fence_skip_if_sd_active=dict(default=None, type='bool'),
        fence_skip_if_connectivity_broken=dict(default=None, type='bool'),
        fence_connectivity_threshold=dict(default=None, type='int'),
        resilience_policy=dict(default=None, choices=['migrate_highly_available', 'migrate', 'do_not_migrate']),
        migration_bandwidth=dict(default=None, choices=['auto', 'hypervisor_default', 'custom']),
        migration_bandwidth_limit=dict(default=None, type='int'),
        migration_auto_converge=dict(default=None, choices=['true', 'false', 'inherit']),
        migration_compressed=dict(default=None, choices=['true', 'false', 'inherit']),
        migration_policy=dict(
            default=None,
            choices=['legacy', 'minimal_downtime', 'suspend_workload', 'post_copy']
        ),
        serial_policy=dict(default=None, choices=['vm', 'host', 'custom']),
        serial_policy_value=dict(default=None),
        scheduling_policy=dict(default=None),
        data_center=dict(default=None),
        description=dict(default=None),
        comment=dict(default=None),
        network=dict(default=None),
        cpu_arch=dict(default=None, choices=['ppc64', 'undefined', 'x86_64']),
        cpu_type=dict(default=None),
        switch_type=dict(default=None, choices=['legacy', 'ovs']),
        compatibility_version=dict(default=None),
        mac_pool=dict(default=None),
    )
    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
    )

    if module._name == 'ovirt_clusters':
        module.deprecate("The 'ovirt_clusters' module is being renamed 'ovirt_cluster'", version=2.8)

    check_sdk(module)

    try:
        auth = module.params.pop('auth')
        connection = create_connection(auth)
        clusters_service = connection.system_service().clusters_service()
        clusters_module = ClustersModule(
            connection=connection,
            module=module,
            service=clusters_service,
        )

        state = module.params['state']
        if state == 'present':
            ret = clusters_module.create()
        elif state == 'absent':
            ret = clusters_module.remove()

        module.exit_json(**ret)
    except Exception as e:
        module.fail_json(msg=str(e), exception=traceback.format_exc())
    finally:
        connection.close(logout=auth.get('token') is None)
Beispiel #52
0
class AzureRMModuleBase(object):
    def __init__(self, derived_arg_spec, bypass_checks=False, no_log=False,
                 check_invalid_arguments=None, mutually_exclusive=None, required_together=None,
                 required_one_of=None, add_file_common_args=False, supports_check_mode=False,
                 required_if=None, supports_tags=True, facts_module=False, skip_exec=False):

        merged_arg_spec = dict()
        merged_arg_spec.update(AZURE_COMMON_ARGS)
        if supports_tags:
            merged_arg_spec.update(AZURE_TAG_ARGS)

        if derived_arg_spec:
            merged_arg_spec.update(derived_arg_spec)

        merged_required_if = list(AZURE_COMMON_REQUIRED_IF)
        if required_if:
            merged_required_if += required_if

        self.module = AnsibleModule(argument_spec=merged_arg_spec,
                                    bypass_checks=bypass_checks,
                                    no_log=no_log,
                                    check_invalid_arguments=check_invalid_arguments,
                                    mutually_exclusive=mutually_exclusive,
                                    required_together=required_together,
                                    required_one_of=required_one_of,
                                    add_file_common_args=add_file_common_args,
                                    supports_check_mode=supports_check_mode,
                                    required_if=merged_required_if)

        if not HAS_PACKAGING_VERSION:
            self.fail("Do you have packaging installed? Try `pip install packaging`"
                      "- {0}".format(HAS_PACKAGING_VERSION_EXC))

        if not HAS_MSRESTAZURE:
            self.fail("Do you have msrestazure installed? Try `pip install msrestazure`"
                      "- {0}".format(HAS_MSRESTAZURE_EXC))

        if not HAS_AZURE:
            self.fail("Do you have azure>={1} installed? Try `pip install ansible[azure]`"
                      "- {0}".format(HAS_AZURE_EXC, AZURE_MIN_RELEASE))

        self._cloud_environment = None
        self._network_client = None
        self._storage_client = None
        self._resource_client = None
        self._compute_client = None
        self._dns_client = None
        self._web_client = None
        self._containerservice_client = None

        self.check_mode = self.module.check_mode
        self.api_profile = self.module.params.get('api_profile')
        self.facts_module = facts_module
        # self.debug = self.module.params.get('debug')

        # authenticate
        self.credentials = self._get_credentials(self.module.params)
        if not self.credentials:
            if HAS_AZURE_CLI_CORE:
                self.fail("Failed to get credentials. Either pass as parameters, set environment variables, "
                          "define a profile in ~/.azure/credentials, or log in with Azure CLI (`az login`).")
            else:
                self.fail("Failed to get credentials. Either pass as parameters, set environment variables, "
                          "define a profile in ~/.azure/credentials, or install Azure CLI and log in (`az login`).")

        # cert validation mode precedence: module-arg, credential profile, env, "validate"
        self._cert_validation_mode = self.module.params['cert_validation_mode'] or self.credentials.get('cert_validation_mode') or \
            os.environ.get('AZURE_CERT_VALIDATION_MODE') or 'validate'

        if self._cert_validation_mode not in ['validate', 'ignore']:
            self.fail('invalid cert_validation_mode: {0}'.format(self._cert_validation_mode))

        # if cloud_environment specified, look up/build Cloud object
        raw_cloud_env = self.credentials.get('cloud_environment')
        if self.credentials.get('credentials') is not None and raw_cloud_env is not None:
            self._cloud_environment = raw_cloud_env
        elif not raw_cloud_env:
            self._cloud_environment = azure_cloud.AZURE_PUBLIC_CLOUD  # SDK default
        else:
            # try to look up "well-known" values via the name attribute on azure_cloud members
            all_clouds = [x[1] for x in inspect.getmembers(azure_cloud) if isinstance(x[1], azure_cloud.Cloud)]
            matched_clouds = [x for x in all_clouds if x.name == raw_cloud_env]
            if len(matched_clouds) == 1:
                self._cloud_environment = matched_clouds[0]
            elif len(matched_clouds) > 1:
                self.fail("Azure SDK failure: more than one cloud matched for cloud_environment name '{0}'".format(raw_cloud_env))
            else:
                if not urlparse.urlparse(raw_cloud_env).scheme:
                    self.fail("cloud_environment must be an endpoint discovery URL or one of {0}".format([x.name for x in all_clouds]))
                try:
                    self._cloud_environment = azure_cloud.get_cloud_from_metadata_endpoint(raw_cloud_env)
                except Exception as e:
                    self.fail("cloud_environment {0} could not be resolved: {1}".format(raw_cloud_env, e.message), exception=traceback.format_exc(e))

        if self.credentials.get('subscription_id', None) is None and self.credentials.get('credentials') is None:
            self.fail("Credentials did not include a subscription_id value.")
        self.log("setting subscription_id")
        self.subscription_id = self.credentials['subscription_id']

        if self.credentials.get('credentials') is not None:
            # AzureCLI credentials
            self.azure_credentials = self.credentials['credentials']
        elif self.credentials.get('client_id') is not None and \
                self.credentials.get('secret') is not None and \
                self.credentials.get('tenant') is not None:
                self.azure_credentials = ServicePrincipalCredentials(client_id=self.credentials['client_id'],
                                                                     secret=self.credentials['secret'],
                                                                     tenant=self.credentials['tenant'],
                                                                     cloud_environment=self._cloud_environment,
                                                                     verify=self._cert_validation_mode == 'validate')

        elif self.credentials.get('ad_user') is not None and self.credentials.get('password') is not None:
            tenant = self.credentials.get('tenant')
            if not tenant:
                tenant = 'common'  # SDK default

            self.azure_credentials = UserPassCredentials(self.credentials['ad_user'],
                                                         self.credentials['password'],
                                                         tenant=tenant,
                                                         cloud_environment=self._cloud_environment,
                                                         verify=self._cert_validation_mode == 'validate')
        else:
            self.fail("Failed to authenticate with provided credentials. Some attributes were missing. "
                      "Credentials must include client_id, secret and tenant or ad_user and password or "
                      "be logged using AzureCLI.")

        # common parameter validation
        if self.module.params.get('tags'):
            self.validate_tags(self.module.params['tags'])

        if not skip_exec:
            res = self.exec_module(**self.module.params)
            self.module.exit_json(**res)

    def check_client_version(self, client_type):
        # Ensure Azure modules are at least 2.0.0rc5.
        package_version = AZURE_PKG_VERSIONS.get(client_type.__name__, None)
        if package_version is not None:
            client_name = package_version.get('package_name')
            try:
                client_module = importlib.import_module(client_type.__module__)
                client_version = client_module.VERSION
            except RuntimeError:
                # can't get at the module version for some reason, just fail silently...
                return
            expected_version = package_version.get('expected_version')
            if Version(client_version) < Version(expected_version):
                self.fail("Installed azure-mgmt-{0} client version is {1}. The supported version is {2}. Try "
                          "`pip install ansible[azure]`".format(client_name, client_version, expected_version))

    def exec_module(self, **kwargs):
        self.fail("Error: {0} failed to implement exec_module method.".format(self.__class__.__name__))

    def fail(self, msg, **kwargs):
        '''
        Shortcut for calling module.fail()

        :param msg: Error message text.
        :param kwargs: Any key=value pairs
        :return: None
        '''
        self.module.fail_json(msg=msg, **kwargs)

    def deprecate(self, msg, version=None):
        self.module.deprecate(msg, version)

    def log(self, msg, pretty_print=False):
        pass
        # Use only during module development
        # if self.debug:
        #     log_file = open('azure_rm.log', 'a')
        #     if pretty_print:
        #         log_file.write(json.dumps(msg, indent=4, sort_keys=True))
        #     else:
        #         log_file.write(msg + u'\n')

    def validate_tags(self, tags):
        '''
        Check if tags dictionary contains string:string pairs.

        :param tags: dictionary of string:string pairs
        :return: None
        '''
        if not self.facts_module:
            if not isinstance(tags, dict):
                self.fail("Tags must be a dictionary of string:string values.")
            for key, value in tags.items():
                if not isinstance(value, str):
                    self.fail("Tags values must be strings. Found {0}:{1}".format(str(key), str(value)))

    def update_tags(self, tags):
        '''
        Call from the module to update metadata tags. Returns tuple
        with bool indicating if there was a change and dict of new
        tags to assign to the object.

        :param tags: metadata tags from the object
        :return: bool, dict
        '''
        new_tags = copy.copy(tags) if isinstance(tags, dict) else dict()
        changed = False
        if isinstance(self.module.params.get('tags'), dict):
            for key, value in self.module.params['tags'].items():
                if not new_tags.get(key) or new_tags[key] != value:
                    changed = True
                    new_tags[key] = value
            if isinstance(tags, dict):
                for key, value in tags.items():
                    if not self.module.params['tags'].get(key):
                        new_tags.pop(key)
                        changed = True
        return changed, new_tags

    def has_tags(self, obj_tags, tag_list):
        '''
        Used in fact modules to compare object tags to list of parameter tags. Return true if list of parameter tags
        exists in object tags.

        :param obj_tags: dictionary of tags from an Azure object.
        :param tag_list: list of tag keys or tag key:value pairs
        :return: bool
        '''

        if not obj_tags and tag_list:
            return False

        if not tag_list:
            return True

        matches = 0
        result = False
        for tag in tag_list:
            tag_key = tag
            tag_value = None
            if ':' in tag:
                tag_key, tag_value = tag.split(':')
            if tag_value and obj_tags.get(tag_key) == tag_value:
                matches += 1
            elif not tag_value and obj_tags.get(tag_key):
                matches += 1
        if matches == len(tag_list):
            result = True
        return result

    def get_resource_group(self, resource_group):
        '''
        Fetch a resource group.

        :param resource_group: name of a resource group
        :return: resource group object
        '''
        try:
            return self.rm_client.resource_groups.get(resource_group)
        except CloudError as cloud_error:
            self.fail("Error retrieving resource group {0} - {1}".format(resource_group, cloud_error.message))
        except Exception as exc:
            self.fail("Error retrieving resource group {0} - {1}".format(resource_group, str(exc)))

    def _get_profile(self, profile="default"):
        path = expanduser("~/.azure/credentials")
        try:
            config = configparser.ConfigParser()
            config.read(path)
        except Exception as exc:
            self.fail("Failed to access {0}. Check that the file exists and you have read "
                      "access. {1}".format(path, str(exc)))
        credentials = dict()
        for key in AZURE_CREDENTIAL_ENV_MAPPING:
            try:
                credentials[key] = config.get(profile, key, raw=True)
            except:
                pass

        if credentials.get('subscription_id'):
            return credentials

        return None

    def _get_msi_credentials(self, subscription_id_param=None):
        credentials = MSIAuthentication()
        subscription_id = subscription_id_param or os.environ.get(AZURE_CREDENTIAL_ENV_MAPPING['subscription_id'], None)
        if not subscription_id:
            try:
                # use the first subscription of the MSI
                subscription_client = SubscriptionClient(credentials)
                subscription = next(subscription_client.subscriptions.list())
                subscription_id = str(subscription.subscription_id)
            except Exception as exc:
                self.fail("Failed to get MSI token: {0}. "
                          "Please check whether your machine enabled MSI or grant access to any subscription.".format(str(exc)))
        return {
            'credentials': credentials,
            'subscription_id': subscription_id
        }

    def _get_azure_cli_credentials(self):
        credentials, subscription_id = get_azure_cli_credentials()
        cloud_environment = get_cli_active_cloud()

        cli_credentials = {
            'credentials': credentials,
            'subscription_id': subscription_id,
            'cloud_environment': cloud_environment
        }
        return cli_credentials

    def _get_env_credentials(self):
        env_credentials = dict()
        for attribute, env_variable in AZURE_CREDENTIAL_ENV_MAPPING.items():
            env_credentials[attribute] = os.environ.get(env_variable, None)

        if env_credentials['profile']:
            credentials = self._get_profile(env_credentials['profile'])
            return credentials

        if env_credentials.get('subscription_id') is not None:
            return env_credentials

        return None

    def _get_credentials(self, params):
        # Get authentication credentials.
        self.log('Getting credentials')

        arg_credentials = dict()
        for attribute, env_variable in AZURE_CREDENTIAL_ENV_MAPPING.items():
            arg_credentials[attribute] = params.get(attribute, None)

        auth_source = params.get('auth_source', None)
        if not auth_source:
            auth_source = os.environ.get('ANSIBLE_AZURE_AUTH_SOURCE', 'auto')

        if auth_source == 'msi':
            self.log('Retrieving credenitals from MSI')
            return self._get_msi_credentials(arg_credentials['subscription_id'])

        if auth_source == 'cli':
            if not HAS_AZURE_CLI_CORE:
                self.fail("Azure auth_source is `cli`, but azure-cli package is not available. Try `pip install azure-cli --upgrade`")
            try:
                self.log('Retrieving credentials from Azure CLI profile')
                cli_credentials = self._get_azure_cli_credentials()
                return cli_credentials
            except CLIError as err:
                self.fail("Azure CLI profile cannot be loaded - {0}".format(err))

        if auth_source == 'env':
            self.log('Retrieving credentials from environment')
            env_credentials = self._get_env_credentials()
            return env_credentials

        if auth_source == 'credential_file':
            self.log("Retrieving credentials from credential file")
            profile = params.get('profile', 'default')
            default_credentials = self._get_profile(profile)
            return default_credentials

        # auto, precedence: module parameters -> environment variables -> default profile in ~/.azure/credentials
        # try module params
        if arg_credentials['profile'] is not None:
            self.log('Retrieving credentials with profile parameter.')
            credentials = self._get_profile(arg_credentials['profile'])
            return credentials

        if arg_credentials['subscription_id']:
            self.log('Received credentials from parameters.')
            return arg_credentials

        # try environment
        env_credentials = self._get_env_credentials()
        if env_credentials:
            self.log('Received credentials from env.')
            return env_credentials

        # try default profile from ~./azure/credentials
        default_credentials = self._get_profile()
        if default_credentials:
            self.log('Retrieved default profile credentials from ~/.azure/credentials.')
            return default_credentials

        try:
            if HAS_AZURE_CLI_CORE:
                self.log('Retrieving credentials from AzureCLI profile')
            cli_credentials = self._get_azure_cli_credentials()
            return cli_credentials
        except CLIError as ce:
            self.log('Error getting AzureCLI profile credentials - {0}'.format(ce))

        return None

    def serialize_obj(self, obj, class_name, enum_modules=None):
        '''
        Return a JSON representation of an Azure object.

        :param obj: Azure object
        :param class_name: Name of the object's class
        :param enum_modules: List of module names to build enum dependencies from.
        :return: serialized result
        '''
        enum_modules = [] if enum_modules is None else enum_modules

        dependencies = dict()
        if enum_modules:
            for module_name in enum_modules:
                mod = importlib.import_module(module_name)
                for mod_class_name, mod_class_obj in inspect.getmembers(mod, predicate=inspect.isclass):
                    dependencies[mod_class_name] = mod_class_obj
            self.log("dependencies: ")
            self.log(str(dependencies))
        serializer = Serializer(classes=dependencies)
        return serializer.body(obj, class_name, keep_readonly=True)

    def get_poller_result(self, poller, wait=5):
        '''
        Consistent method of waiting on and retrieving results from Azure's long poller

        :param poller Azure poller object
        :return object resulting from the original request
        '''
        try:
            delay = wait
            while not poller.done():
                self.log("Waiting for {0} sec".format(delay))
                poller.wait(timeout=delay)
            return poller.result()
        except Exception as exc:
            self.log(str(exc))
            raise

    def check_provisioning_state(self, azure_object, requested_state='present'):
        '''
        Check an Azure object's provisioning state. If something did not complete the provisioning
        process, then we cannot operate on it.

        :param azure_object An object such as a subnet, storageaccount, etc. Must have provisioning_state
                            and name attributes.
        :return None
        '''

        if hasattr(azure_object, 'properties') and hasattr(azure_object.properties, 'provisioning_state') and \
           hasattr(azure_object, 'name'):
            # resource group object fits this model
            if isinstance(azure_object.properties.provisioning_state, Enum):
                if azure_object.properties.provisioning_state.value != AZURE_SUCCESS_STATE and \
                   requested_state != 'absent':
                    self.fail("Error {0} has a provisioning state of {1}. Expecting state to be {2}.".format(
                              azure_object.name, azure_object.properties.provisioning_state, AZURE_SUCCESS_STATE))
                return
            if azure_object.properties.provisioning_state != AZURE_SUCCESS_STATE and \
               requested_state != 'absent':
                self.fail("Error {0} has a provisioning state of {1}. Expecting state to be {2}.".format(
                    azure_object.name, azure_object.properties.provisioning_state, AZURE_SUCCESS_STATE))
            return

        if hasattr(azure_object, 'provisioning_state') or not hasattr(azure_object, 'name'):
            if isinstance(azure_object.provisioning_state, Enum):
                if azure_object.provisioning_state.value != AZURE_SUCCESS_STATE and requested_state != 'absent':
                    self.fail("Error {0} has a provisioning state of {1}. Expecting state to be {2}.".format(
                        azure_object.name, azure_object.provisioning_state, AZURE_SUCCESS_STATE))
                return
            if azure_object.provisioning_state != AZURE_SUCCESS_STATE and requested_state != 'absent':
                self.fail("Error {0} has a provisioning state of {1}. Expecting state to be {2}.".format(
                    azure_object.name, azure_object.provisioning_state, AZURE_SUCCESS_STATE))

    def get_blob_client(self, resource_group_name, storage_account_name, storage_blob_type='block'):
        keys = dict()
        try:
            # Get keys from the storage account
            self.log('Getting keys')
            account_keys = self.storage_client.storage_accounts.list_keys(resource_group_name, storage_account_name)
        except Exception as exc:
            self.fail("Error getting keys for account {0} - {1}".format(storage_account_name, str(exc)))

        try:
            self.log('Create blob service')
            if storage_blob_type == 'page':
                return CloudStorageAccount(storage_account_name, account_keys.keys[0].value).create_page_blob_service()
            elif storage_blob_type == 'block':
                return CloudStorageAccount(storage_account_name, account_keys.keys[0].value).create_block_blob_service()
            else:
                raise Exception("Invalid storage blob type defined.")
        except Exception as exc:
            self.fail("Error creating blob service client for storage account {0} - {1}".format(storage_account_name,
                                                                                                str(exc)))

    def create_default_pip(self, resource_group, location, public_ip_name, allocation_method='Dynamic'):
        '''
        Create a default public IP address <public_ip_name> to associate with a network interface.
        If a PIP address matching <public_ip_name> exists, return it. Otherwise, create one.

        :param resource_group: name of an existing resource group
        :param location: a valid azure location
        :param public_ip_name: base name to assign the public IP address
        :param allocation_method: one of 'Static' or 'Dynamic'
        :return: PIP object
        '''
        pip = None

        self.log("Starting create_default_pip {0}".format(public_ip_name))
        self.log("Check to see if public IP {0} exists".format(public_ip_name))
        try:
            pip = self.network_client.public_ip_addresses.get(resource_group, public_ip_name)
        except CloudError:
            pass

        if pip:
            self.log("Public ip {0} found.".format(public_ip_name))
            self.check_provisioning_state(pip)
            return pip

        params = self.network_models.PublicIPAddress(
            location=location,
            public_ip_allocation_method=allocation_method,
        )
        self.log('Creating default public IP {0}'.format(public_ip_name))
        try:
            poller = self.network_client.public_ip_addresses.create_or_update(resource_group, public_ip_name, params)
        except Exception as exc:
            self.fail("Error creating {0} - {1}".format(public_ip_name, str(exc)))

        return self.get_poller_result(poller)

    def create_default_securitygroup(self, resource_group, location, security_group_name, os_type, open_ports):
        '''
        Create a default security group <security_group_name> to associate with a network interface. If a security group matching
        <security_group_name> exists, return it. Otherwise, create one.

        :param resource_group: Resource group name
        :param location: azure location name
        :param security_group_name: base name to use for the security group
        :param os_type: one of 'Windows' or 'Linux'. Determins any default rules added to the security group.
        :param ssh_port: for os_type 'Linux' port used in rule allowing SSH access.
        :param rdp_port: for os_type 'Windows' port used in rule allowing RDP access.
        :return: security_group object
        '''
        group = None

        self.log("Create security group {0}".format(security_group_name))
        self.log("Check to see if security group {0} exists".format(security_group_name))
        try:
            group = self.network_client.network_security_groups.get(resource_group, security_group_name)
        except CloudError:
            pass

        if group:
            self.log("Security group {0} found.".format(security_group_name))
            self.check_provisioning_state(group)
            return group

        parameters = self.network_models.NetworkSecurityGroup()
        parameters.location = location

        if not open_ports:
            # Open default ports based on OS type
            if os_type == 'Linux':
                # add an inbound SSH rule
                parameters.security_rules = [
                    self.network_models.SecurityRule(protocol='Tcp',
                                                     source_address_prefix='*',
                                                     destination_address_prefix='*',
                                                     access='Allow',
                                                     direction='Inbound',
                                                     description='Allow SSH Access',
                                                     source_port_range='*',
                                                     destination_port_range='22',
                                                     priority=100,
                                                     name='SSH')
                ]
                parameters.location = location
            else:
                # for windows add inbound RDP and WinRM rules
                parameters.security_rules = [
                    self.network_models.SecurityRule(protocol='Tcp',
                                                     source_address_prefix='*',
                                                     destination_address_prefix='*',
                                                     access='Allow',
                                                     direction='Inbound',
                                                     description='Allow RDP port 3389',
                                                     source_port_range='*',
                                                     destination_port_range='3389',
                                                     priority=100,
                                                     name='RDP01'),
                    self.network_models.SecurityRule(protocol='Tcp',
                                                     source_address_prefix='*',
                                                     destination_address_prefix='*',
                                                     access='Allow',
                                                     direction='Inbound',
                                                     description='Allow WinRM HTTPS port 5986',
                                                     source_port_range='*',
                                                     destination_port_range='5986',
                                                     priority=101,
                                                     name='WinRM01'),
                ]
        else:
            # Open custom ports
            parameters.security_rules = []
            priority = 100
            for port in open_ports:
                priority += 1
                rule_name = "Rule_{0}".format(priority)
                parameters.security_rules.append(
                    self.network_models.SecurityRule(protocol='Tcp',
                                                     source_address_prefix='*',
                                                     destination_address_prefix='*',
                                                     access='Allow',
                                                     direction='Inbound',
                                                     source_port_range='*',
                                                     destination_port_range=str(port),
                                                     priority=priority,
                                                     name=rule_name)
                )

        self.log('Creating default security group {0}'.format(security_group_name))
        try:
            poller = self.network_client.network_security_groups.create_or_update(resource_group,
                                                                                  security_group_name,
                                                                                  parameters)
        except Exception as exc:
            self.fail("Error creating default security rule {0} - {1}".format(security_group_name, str(exc)))

        return self.get_poller_result(poller)

    @staticmethod
    def _validation_ignore_callback(session, global_config, local_config, **kwargs):
        session.verify = False

    def get_api_profile(self, client_type_name, api_profile_name):
        profile_all_clients = AZURE_API_PROFILES.get(api_profile_name)

        if not profile_all_clients:
            raise KeyError("unknown Azure API profile: {0}".format(api_profile_name))

        profile_raw = profile_all_clients.get(client_type_name, None)

        if not profile_raw:
            self.module.warn("Azure API profile {0} does not define an entry for {1}".format(api_profile_name, client_type_name))

        if isinstance(profile_raw, dict):
            if not profile_raw.get('default_api_version'):
                raise KeyError("Azure API profile {0} does not define 'default_api_version'".format(api_profile_name))
            return profile_raw

        # wrap basic strings in a dict that just defines the default
        return dict(default_api_version=profile_raw)

    def get_mgmt_svc_client(self, client_type, base_url=None, api_version=None):
        self.log('Getting management service client {0}'.format(client_type.__name__))
        self.check_client_version(client_type)

        client_argspec = inspect.getargspec(client_type.__init__)

        client_kwargs = dict(credentials=self.azure_credentials, subscription_id=self.subscription_id, base_url=base_url)

        api_profile_dict = {}

        if self.api_profile:
            api_profile_dict = self.get_api_profile(client_type.__name__, self.api_profile)

        if not base_url:
            # most things are resource_manager, don't make everyone specify
            base_url = self._cloud_environment.endpoints.resource_manager

        # unversioned clients won't accept profile; only send it if necessary
        # clients without a version specified in the profile will use the default
        if api_profile_dict and 'profile' in client_argspec.args:
            client_kwargs['profile'] = api_profile_dict

        # If the client doesn't accept api_version, it's unversioned.
        # If it does, favor explicitly-specified api_version, fall back to api_profile
        if 'api_version' in client_argspec.args:
            profile_default_version = api_profile_dict.get('default_api_version', None)
            if api_version or profile_default_version:
                client_kwargs['api_version'] = api_version or profile_default_version

        client = client_type(**client_kwargs)

        # FUTURE: remove this once everything exposes models directly (eg, containerinstance)
        try:
            getattr(client, "models")
        except AttributeError:
            def _ansible_get_models(self, *arg, **kwarg):
                return self._ansible_models

            setattr(client, '_ansible_models', importlib.import_module(client_type.__module__).models)
            client.models = types.MethodType(_ansible_get_models, client)

        # Add user agent for Ansible
        client.config.add_user_agent(ANSIBLE_USER_AGENT)
        # Add user agent when running from Cloud Shell
        if CLOUDSHELL_USER_AGENT_KEY in os.environ:
            client.config.add_user_agent(os.environ[CLOUDSHELL_USER_AGENT_KEY])
        # Add user agent when running from VSCode extension
        if VSCODEEXT_USER_AGENT_KEY in os.environ:
            client.config.add_user_agent(os.environ[VSCODEEXT_USER_AGENT_KEY])

        if self._cert_validation_mode == 'ignore':
            client.config.session_configuration_callback = self._validation_ignore_callback

        return client

    @property
    def storage_client(self):
        self.log('Getting storage client...')
        if not self._storage_client:
            self._storage_client = self.get_mgmt_svc_client(StorageManagementClient,
                                                            base_url=self._cloud_environment.endpoints.resource_manager,
                                                            api_version='2017-10-01')
        return self._storage_client

    @property
    def storage_models(self):
        self.log('Getting storage models...')
        return StorageManagementClient.models("2017-10-01")

    @property
    def network_client(self):
        self.log('Getting network client')
        if not self._network_client:
            self._network_client = self.get_mgmt_svc_client(NetworkManagementClient,
                                                            base_url=self._cloud_environment.endpoints.resource_manager,
                                                            api_version='2017-11-01')
        return self._network_client

    @property
    def network_models(self):
        self.log("Getting network models...")
        return NetworkManagementClient.models("2017-11-01")

    @property
    def rm_client(self):
        self.log('Getting resource manager client')
        if not self._resource_client:
            self._resource_client = self.get_mgmt_svc_client(ResourceManagementClient,
                                                             base_url=self._cloud_environment.endpoints.resource_manager,
                                                             api_version='2017-05-10')
        return self._resource_client

    @property
    def rm_models(self):
        self.log("Getting resource manager models")
        return ResourceManagementClient.models("2017-05-10")

    @property
    def compute_client(self):
        self.log('Getting compute client')
        if not self._compute_client:
            self._compute_client = self.get_mgmt_svc_client(ComputeManagementClient,
                                                            base_url=self._cloud_environment.endpoints.resource_manager,
                                                            api_version='2017-03-30')
        return self._compute_client

    @property
    def compute_models(self):
        self.log("Getting compute models")
        return ComputeManagementClient.models("2017-03-30")

    @property
    def dns_client(self):
        self.log('Getting dns client')
        if not self._dns_client:
            self._dns_client = self.get_mgmt_svc_client(DnsManagementClient,
                                                        base_url=self._cloud_environment.endpoints.resource_manager)
        return self._dns_client

    @property
    def web_client(self):
        self.log('Getting web client')
        if not self._web_client:
            self._web_client = self.get_mgmt_svc_client(WebSiteManagementClient,
                                                        base_url=self._cloud_environment.endpoints.resource_manager)
        return self._web_client

    @property
    def containerservice_client(self):
        self.log('Getting container service client')
        if not self._containerservice_client:
            self._containerservice_client = self.get_mgmt_svc_client(ContainerServiceClient,
                                                                     base_url=self._cloud_environment.endpoints.resource_manager)
        return self._containerservice_client