def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        ap=dict(type='str', aliases=['app_profile', 'app_profile_name']),
        epg=dict(type='str', aliases=['epg_name']),
        contract=dict(type='str', aliases=['contract_name']),
        contract_type=dict(type='str', required=True, choices=['consumer', 'provider']),
        priority=dict(type='str', choices=['level1', 'level2', 'level3', 'unspecified']),
        provider_match=dict(type='str', choices=['all', 'at_least_one', 'at_most_one', 'none']),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        tenant=dict(type='str', aliases=['tenant_name']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[['state', 'absent', ['ap', 'contract', 'epg', 'tenant']],
                     ['state', 'present', ['ap', 'contract', 'epg', 'tenant']]]
    )

    contract = module.params['contract']
    contract_type = module.params['contract_type']
    aci_class = ACI_CLASS_MAPPING[contract_type]
    priority = module.params['priority']
    provider_match = module.params['provider_match']
    state = module.params['state']

    if contract_type == "consumer" and provider_match is not None:
        module.fail_json(msg="the 'provider_match' is only configurable for Provided Contracts")

    # Construct contract_class key and add to module.params for building URL
    contract_class = 'epg_' + contract_type
    module.params[contract_class] = contract

    aci = ACIModule(module)
    aci.construct_url(root_class='tenant', subclass_1='ap', subclass_2='epg', subclass_3=contract_class)
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(aci_class=aci_class, class_config=dict(matchT=provider_match, prio=priority, tnVzBrCPName=contract))

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class=aci_class)

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    # Remove contract_class that is used to build URL from module.params
    module.params.pop(contract_class)

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        l2_policy=dict(type='str', required=False, aliases=['name']),  # Not required for querying all policies
        description=dict(type='str', aliases=['descr']),
        vlan_scope=dict(type='str', choices=['global', 'portlocal']),  # No default provided on purpose
        qinq=dict(type='str', choices=['core', 'disabled', 'edge']),
        vepa=dict(type='str', choices=['disabled', 'enabled']),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['l2_policy']],
            ['state', 'present', ['l2_policy']],
        ],
    )

    l2_policy = module.params['l2_policy']
    vlan_scope = module.params['vlan_scope']
    qinq = module.params['qinq']
    if qinq is not None:
        qinq = QINQ_MAPPING[qinq]
    vepa = module.params['vepa']
    description = module.params['description']
    state = module.params['state']

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='l2IfPol',
            aci_rn='infra/l2IfP-{}'.format(l2_policy),
            filter_target='eq(l2IfPol.name, "{}")'.format(l2_policy),
            module_object=l2_policy,
        ),
    )

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='l2IfPol',
            class_config=dict(
                name=l2_policy,
                descr=description,
                vlanScope=vlan_scope,
                qinq=qinq, vepa=vepa,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='l2IfPol')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #3
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        path=dict(type='str', required=True, aliases=['uri']),
        method=dict(type='str', default='get', choices=['delete', 'get', 'post'], aliases=['action']),
        src=dict(type='path', aliases=['config_file']),
        content=dict(type='raw'),
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        mutually_exclusive=[['content', 'src']],
    )

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

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

    # Report missing file
    file_exists = False
    if src:
        if os.path.isfile(src):
            file_exists = True
        else:
            module.fail_json(msg="Cannot find/access src '%s'" % src)

    # Find request type
    if path.find('.xml') != -1:
        rest_type = 'xml'
        if not HAS_LXML_ETREE:
            module.fail_json(msg='The lxml python library is missing, or lacks etree support.')
        if not HAS_XMLJSON_COBRA:
            module.fail_json(msg='The xmljson python library is missing, or lacks cobra support.')
    elif path.find('.json') != -1:
        rest_type = 'json'
    else:
        module.fail_json(msg='Failed to find REST API content type (neither .xml nor .json).')

    aci = ACIModule(module)

    # We include the payload as it may be templated
    payload = content
    if file_exists:
        with open(src, 'r') as config_object:
            # TODO: Would be nice to template this, requires action-plugin
            payload = config_object.read()

    # Validate content
    if rest_type == 'json':
        if content and isinstance(content, dict):
            # Validate inline YAML/JSON
            payload = json.dumps(payload)
        elif payload and isinstance(payload, str) and HAS_YAML:
            try:
                # Validate YAML/JSON string
                payload = json.dumps(yaml.safe_load(payload))
            except Exception as e:
                module.fail_json(msg='Failed to parse provided JSON/YAML content: %s' % to_text(e), exception=to_text(e), payload=payload)
    elif rest_type == 'xml' and HAS_LXML_ETREE:
        if content and isinstance(content, dict) and HAS_XMLJSON_COBRA:
            # Validate inline YAML/JSON
            # FIXME: Converting from a dictionary to XML is unsupported at this time
            # payload = etree.tostring(payload)
            pass
        elif payload and isinstance(payload, str):
            try:
                # Validate XML string
                payload = lxml.etree.tostring(lxml.etree.fromstring(payload))
            except Exception as e:
                module.fail_json(msg='Failed to parse provided XML content: %s' % to_text(e), payload=payload)

    # Perform actual request using auth cookie (Same as aci_request,but also supports XML)
    url = '%(protocol)s://%(hostname)s/' % aci.params + path.lstrip('/')
    if method != 'get':
        url = update_qsl(url, {'rsp-subtree': 'modified'})
    aci.result['url'] = url

    resp, info = fetch_url(module, url, data=payload, method=method.upper(), timeout=timeout, headers=aci.headers)
    aci.result['response'] = info['msg']
    aci.result['status'] = info['status']

    # Report failure
    if info['status'] != 200:
        try:
            aci_response(aci.result, info['body'], rest_type)
            module.fail_json(msg='Request failed: %(error_code)s %(error_text)s' % aci.result, payload=payload, **aci.result)
        except KeyError:
            module.fail_json(msg='Request failed for %(url)s. %(msg)s' % info, payload=payload, **aci.result)

    aci_response(aci.result, resp.read(), rest_type)

    # Report success
    module.exit_json(**aci.result)
Exemple #4
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        epg=dict(type='str', aliases=['name', 'epg_name']),
        bd=dict(type='str', aliases=['bd_name', 'bridge_domain']),
        ap=dict(type='str', aliases=['app_profile', 'app_profile_name']),
        tenant=dict(type='str', aliases=['tenant_name']),
        description=dict(type='str', aliases=['descr']),
        priority=dict(type='str',
                      choices=['level1', 'level2', 'level3', 'unspecified']),
        intra_epg_isolation=dict(choices=['enforced', 'unenforced']),
        fwd_control=dict(type='str', choices=['none', 'proxy-arp']),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[['state', 'absent', ['ap', 'epg', 'tenant']],
                     ['state', 'present', ['ap', 'epg', 'tenant']]])

    epg = module.params['epg']
    bd = module.params['bd']
    description = module.params['description']
    priority = module.params['priority']
    intra_epg_isolation = module.params['intra_epg_isolation']
    fwd_control = module.params['fwd_control']
    state = module.params['state']

    aci = ACIModule(module)
    aci.construct_url(root_class="tenant",
                      subclass_1="ap",
                      subclass_2="epg",
                      child_classes=['fvRsBd'])
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='fvAEPg',
            class_config=dict(name=epg,
                              descr=description,
                              prio=priority,
                              pcEnfPref=intra_epg_isolation,
                              fwdCtrl=fwd_control),
            child_configs=[dict(fvRsBd=dict(attributes=dict(tnFvBDName=bd)))])

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvAEPg')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #5
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        description=dict(type='str', aliases=['descr']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
        policy_control_direction=dict(choices=['ingress', 'egress'],
                                      type='str'),
        policy_control_preference=dict(choices=['enforced', 'unenforced'],
                                       type='str'),
        state=dict(choices=['absent', 'present', 'query'],
                   type='str',
                   default='present'),
        tenant=dict(type='str', required=False,
                    aliases=['tenant_name'
                             ]),  # Not required for querying all objects
        vrf=dict(type='str',
                 required=False,
                 aliases=['context', 'name', 'vrf_name'
                          ]),  # Not required for querying all objects
    )

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

    description = module.params['description']
    policy_control_direction = module.params['policy_control_direction']
    policy_control_preference = module.params['policy_control_preference']
    state = module.params['state']
    tenant = module.params['tenant']
    vrf = module.params['vrf']

    aci = ACIModule(module)

    if vrf is not None:
        if tenant is not None:
            path = 'api/mo/uni/tn-%(tenant)s/ctx-%(vrf)s.json' % module.params
        elif state == 'query':
            path = 'api/mo/uni/tn-%(tenant)s.json?rsp-subtree=children&rsp-subtree-class=fvCtx&rsp-subtree-include=no-scoped' % module.params
        else:
            module.fail_json(
                msg=
                "Parameter 'tenant' is required for state 'absent' or 'present'"
            )
    elif state == 'query':
        path = 'api/class/fvCtx.json'
    else:
        module.fail_json(
            msg="Parameter 'vrf' is required for state 'absent' or 'present'")

    aci.result['url'] = '%(protocol)s://%(hostname)s/' % aci.params + path

    aci.get_existing()

    if state == 'present':
        # Filter out module params with null values
        aci.payload(aci_class='fvCtx',
                    class_config=dict(descr=description,
                                      pcEnfDir=policy_control_direction,
                                      pcEnfPref=policy_control_preference,
                                      name=vrf))

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvCtx')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #6
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        rtp=dict(type='str', required=False,
                 aliases=['name', 'rtp_name'
                          ]),  # Not required for querying all objects
        tenant=dict(type='str', required=False,
                    aliases=['tenant_name'
                             ]),  # Not required for quering all objects
        description=dict(type='str', aliases=['descr']),
        tag=dict(type='int'),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['rtp', 'tenant']],
            ['state', 'present', ['rtp', 'tenant']],
        ],
    )

    rtp = module.params['rtp']
    description = module.params['description']
    tag = module.params['tag']
    state = module.params['state']
    tenant = module.params['tenant']

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='fvTenant',
            aci_rn='tn-{}'.format(tenant),
            filter_target='(fvTenant.name, "{}")'.format(tenant),
            module_object=tenant,
        ),
        subclass_1=dict(
            aci_class='l3extRouteTagPol',
            aci_rn='rttag-{}'.format(rtp),
            filter_target='(l3extRouteTagPol.name, "{}")'.format(rtp),
            module_object=rtp,
        ),
    )

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='l3extRouteTagPol',
            class_config=dict(
                name=rtp,
                descr=description,
                tag=tag,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='l3extRouteTagPol')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #7
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        epg=dict(type='str', aliases=['name', 'epg_name']),
        bd=dict(type='str', aliases=['bd_name', 'bridge_domain']),
        ap=dict(type='str', aliases=['app_profile', 'app_profile_name']),
        tenant=dict(type='str', aliases=['tenant_name']),
        description=dict(type='str', aliases=['descr']),
        priority=dict(type='str', choices=['level1', 'level2', 'level3', 'unspecified']),
        intra_epg_isolation=dict(choices=['enforced', 'unenforced']),
        fwd_control=dict(type='str', choices=['none', 'proxy-arp']),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['ap', 'epg', 'tenant']],
            ['state', 'present', ['ap', 'epg', 'tenant']],
        ],
    )

    epg = module.params['epg']
    bd = module.params['bd']
    description = module.params['description']
    priority = module.params['priority']
    intra_epg_isolation = module.params['intra_epg_isolation']
    fwd_control = module.params['fwd_control']
    state = module.params['state']

    aci = ACIModule(module)
    aci.construct_url(root_class="tenant", subclass_1="ap", subclass_2="epg", child_classes=['fvRsBd'])
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='fvAEPg',
            class_config=dict(
                name=epg,
                descr=description,
                prio=priority,
                pcEnfPref=intra_epg_isolation,
                fwdCtrl=fwd_control,
            ),
            child_configs=[
                dict(fvRsBd=dict(attributes=dict(tnFvBDName=bd))),
            ],
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvAEPg')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        contract=dict(type='str', required=False, aliases=['contract_name', 'name']),  # Not required for querying all objects
        tenant=dict(type='str', required=False, aliases=['tenant_name']),  # Not required for querying all objects
        description=dict(type='str', aliases=['descr']),
        scope=dict(type='str', choices=['application-profile', 'context', 'global', 'tenant']),
        priority=dict(type='str', choices=['level1', 'level2', 'level3', 'unspecified']),  # No default provided on purpose
        dscp=dict(type='str',
                  choices=['AF11', 'AF12', 'AF13', 'AF21', 'AF22', 'AF23', 'AF31', 'AF32', 'AF33', 'AF41', 'AF42', 'AF43',
                           'CS0', 'CS1', 'CS2', 'CS3', 'CS4', 'CS5', 'CS6', 'CS7', 'EF', 'VA', 'unspecified'],
                  aliases=['target']),  # No default provided on purpose
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['tenant', 'contract']],
            ['state', 'present', ['tenant', 'contract']],
        ],
    )

    contract = module.params['contract']
    description = module.params['description']
    scope = module.params['scope']
    priority = module.params['priority']
    dscp = module.params['dscp']
    state = module.params['state']
    tenant = module.params['tenant']

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='fvTenant',
            aci_rn='tn-{}'.format(tenant),
            filter_target='eq(fvTenant.name, "{}")'.format(tenant),
            module_object=tenant,
        ),
        subclass_1=dict(
            aci_class='vzBrCP',
            aci_rn='brc-{}'.format(contract),
            filter_target='eq(vzBrCP.name, "{}")'.format(contract),
            module_object=contract,
        ),
    )

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='vzBrCP',
            class_config=dict(
                name=contract,
                descr=description,
                scope=scope,
                prio=priority,
                targetDscp=dscp,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='vzBrCP')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #9
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        description=dict(type='str', aliases=['descr']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
        policy_control_direction=dict(choices=['ingress', 'egress'], type='str'),
        policy_control_preference=dict(choices=['enforced', 'unenforced'], type='str'),
        state=dict(choices=['absent', 'present', 'query'], type='str', default='present'),
        tenant=dict(type='str', required=False, aliases=['tenant_name']),  # Not required for querying all objects
        vrf=dict(type='str', required=False, aliases=['context', 'name', 'vrf_name']),  # Not required for querying all objects
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['tenant', 'vrf']],
            ['state', 'present', ['tenant', 'vrf']],
        ],
    )

    description = module.params['description']
    policy_control_direction = module.params['policy_control_direction']
    policy_control_preference = module.params['policy_control_preference']
    state = module.params['state']
    tenant = module.params['tenant']
    vrf = module.params['vrf']

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='fvTenant',
            aci_rn='tn-{}'.format(tenant),
            filter_target='eq(fvTenant.name, "{}")'.format(tenant),
            module_object=tenant,
        ),
        subclass_1=dict(
            aci_class='fvCtx',
            aci_rn='ctx-{}'.format(vrf),
            filter_target='eq(fvCtx.name, "{}")'.format(vrf),
            module_object=vrf,
        ),
    )
    aci.get_existing()

    if state == 'present':
        # Filter out module params with null values
        aci.payload(
            aci_class='fvCtx',
            class_config=dict(
                descr=description,
                pcEnfDir=policy_control_direction,
                pcEnfPref=policy_control_preference,
                name=vrf,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvCtx')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #10
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        aep=dict(type='str', aliases=['name', 'aep_name']),  # not required for querying all AEPs
        description=dict(type='str', aliases=['descr']),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[['state', 'absent', ['aep']],
                     ['state', 'present', ['aep']]]
    )

    aep = module.params['aep']
    description = module.params['description']
    state = module.params['state']

    aci = ACIModule(module)
    aci.construct_url(root_class="aep")
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(aci_class='infraAttEntityP', class_config=dict(name=aep, descr=description))

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='infraAttEntityP')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        bd=dict(type='str', aliases=['bd_name', 'bridge_domain']),
        l3out=dict(type='str'),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        tenant=dict(type='str', aliases=['tenant_name']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6')  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_together=[['gateway', 'mask']],
        required_if=[
            ['state', 'present', ['bd', 'l3out', 'tenant']],
            ['state', 'absent', ['bd', 'l3out', 'tenant']],
        ],
    )

    bd = module.params['bd']
    l3out = module.params['l3out']
    state = module.params['state']
    tenant = module.params['tenant']

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='fvTenant',
            aci_rn='tn-{}'.format(tenant),
            filter_target='eq(fvTenant.name, "{}")'.format(tenant),
            module_object=tenant,
        ),
        subclass_1=dict(
            aci_class='fvBD',
            aci_rn='BD-{}'.format(bd),
            filter_target='eq(fvBD.name, "{}")'.format(bd),
            module_object=bd,
        ),
        subclass_2=dict(
            aci_class='fvRsBDToOut',
            aci_rn='rsBDToOut-{}'.format(l3out),
            filter_target='eq(fvRsBDToOut.tnL3extOutName, "{}")'.format(l3out),
            module_object=l3out,
        ),
    )

    aci.get_existing()

    if state == 'present':
        # Filter out module params with null values
        aci.payload(
            aci_class='fvRsBDToOut',
            class_config=dict(tnL3extOutName=l3out),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvRsBDToOut')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        arp_flag=dict(type='str', choices=VALID_ARP_FLAGS),
        description=dict(type='str'),
        dst_port=dict(type='str'),
        dst_port_end=dict(type='str'),
        dst_port_start=dict(type='str'),
        entry=dict(type='str', aliases=['entry_name', 'filter_entry', 'name']),
        ether_type=dict(choices=VALID_ETHER_TYPES, type='str'),
        filter=dict(type='str', aliases=['filter_name']),
        icmp_msg_type=dict(type='str', choices=VALID_ICMP_TYPES),
        icmp6_msg_type=dict(type='str', choices=VALID_ICMP6_TYPES),
        ip_protocol=dict(choices=VALID_IP_PROTOCOLS, type='str'),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        stateful=dict(type='str', choices=['no', 'yes']),
        tenant=dict(type="str", aliases=['tenant_name']),
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['entry', 'filter', 'tenant']],
            ['state', 'present', ['entry', 'filter', 'tenant']],
        ],
    )

    arp_flag = module.params['arp_flag']
    if arp_flag is not None:
        arp_flag = ARP_FLAG_MAPPING[arp_flag]
    description = module.params['description']
    dst_port = module.params['dst_port']
    if dst_port in FILTER_PORT_MAPPING.keys():
        dst_port = FILTER_PORT_MAPPING[dst_port]
    dst_end = module.params['dst_port_end']
    if dst_end in FILTER_PORT_MAPPING.keys():
        dst_end = FILTER_PORT_MAPPING[dst_end]
    dst_start = module.params['dst_port_start']
    if dst_start in FILTER_PORT_MAPPING.keys():
        dst_start = FILTER_PORT_MAPPING[dst_start]
    entry = module.params['entry']
    ether_type = module.params['ether_type']
    filter_name = module.params['filter']
    icmp_msg_type = module.params['icmp_msg_type']
    if icmp_msg_type is not None:
        icmp_msg_type = ICMP_MAPPING[icmp_msg_type]
    icmp6_msg_type = module.params['icmp6_msg_type']
    if icmp6_msg_type is not None:
        icmp6_msg_type = ICMP6_MAPPING[icmp6_msg_type]
    ip_protocol = module.params['ip_protocol']
    state = module.params['state']
    stateful = module.params['stateful']
    tenant = module.params['tenant']

    # validate that dst_port is not passed with dst_start or dst_end
    if dst_port is not None and (dst_end is not None or dst_start is not None):
        module.fail_json(msg="Parameter 'dst_port' cannot be used with 'dst_end' and 'dst_start'")
    elif dst_port is not None:
        dst_end = dst_port
        dst_start = dst_port

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='fvTenant',
            aci_rn='tn-{}'.format(tenant),
            filter_target='eq(fvTenant.name, "{}")'.format(tenant),
            module_object=tenant,
        ),
        subclass_1=dict(
            aci_class='vzFilter',
            aci_rn='flt-{}'.format(filter_name),
            filter_target='eq(vzFilter.name, "{}")'.format(filter_name),
            module_object=filter_name,
        ),
        subclass_2=dict(
            aci_class='vzEntry',
            aci_rn='e-{}'.format(entry),
            filter_target='eq(vzEntry.name, "{}")'.format(entry),
            module_object=entry
        ),
    )

    aci.get_existing()

    if state == 'present':
        # Filter out module params with null values
        aci.payload(
            aci_class='vzEntry',
            class_config=dict(
                arpOpc=arp_flag,
                descr=description,
                dFromPort=dst_start,
                dToPort=dst_end,
                etherT=ether_type,
                icmpv4T=icmp_msg_type,
                icmpv6T=icmp6_msg_type,
                name=entry,
                prot=ip_protocol,
                stateful=stateful,
            ),
        )

        # generate config diff which will be used as POST request body
        aci.get_diff(aci_class='vzEntry')

        # submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        allow_useg=dict(type='str', choices=['encap', 'useg']),
        ap=dict(type='str', aliases=['app_profile', 'app_profile_name']),
        deploy_immediacy=dict(type='str', choices=['immediate', 'on-demand']),
        domain=dict(type='str', aliases=['domain_name', 'domain_profile']),
        domain_type=dict(type='str', choices=['phys', 'vmm'], aliases=['type']),
        encap=dict(type='int'),
        encap_mode=dict(type='str', choices=['auto', 'vlan', 'vxlan']),
        epg=dict(type='str', aliases=['name', 'epg_name']),
        netflow=dict(type='str', choices=['disabled', 'enabled']),
        primary_encap=dict(type='int'),
        resolution_immediacy=dict(type='str', choices=['immdediate', 'lazy', 'pre-provision']),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        tenant=dict(type='str', aliases=['tenant_name']),
        vm_provider=dict(type='str', choices=['vmware']),  # TODO: Find out OVS and Hyper-V options
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[['domain_type', 'vmm', ['vm_provider']],
                     ['state', 'absent', ['ap', 'domain', 'domain_type', 'epg', 'tenant']],
                     ['state', 'present', ['ap', 'domain', 'domain_type', 'epg', 'tenant']]]
    )

    allow_useg = module.params['allow_useg']
    deploy_immediacy = module.params['deploy_immediacy']
    domain = module.params['domain']
    domain_type = module.params['domain_type']
    vm_provider = module.params['vm_provider']
    encap = module.params['encap']
    if encap is not None:
        if encap in range(1, 4097):
            encap = 'vlan-{}'.format(encap)
        else:
            module.fail_json(msg='Valid VLAN assigments are from 1 to 4096')
    encap_mode = module.params['encap_mode']
    netflow = module.params['netflow']
    primary_encap = module.params['primary_encap']
    if primary_encap is not None:
        if primary_encap in range(1, 4097):
            primary_encap = 'vlan-{}'.format(primary_encap)
        else:
            module.fail_json(msg='Valid VLAN assigments are from 1 to 4096')
    resolution_immediacy = module.params['resolution_immediacy']
    state = module.params['state']

    if domain_type == 'phys' and vm_provider is not None:
        module.fail_json(msg="Domain type 'phys' cannot have a 'vm_provider'")

    # Compile the full domain and add it to module.params for URL building
    if domain_type == 'vmm':
        module.params["epg_domain"] = VM_PROVIDER_MAPPING[vm_provider] + domain
    elif domain_type is not None:
        module.params["epg_domain"] = 'uni/phys-' + domain

    aci = ACIModule(module)
    aci.construct_url(root_class="tenant", subclass_1="ap", subclass_2="epg", subclass_3="epg_domain")
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='fvRsDomAtt',
            class_config=dict(
                classPref=allow_useg, encap=encap, encapMode=encap_mode, instrImedcy=deploy_immediacy,
                netflowPref=netflow, primaryEncap=primary_encap, resImedcy=resolution_immediacy
            )
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvRsDomAtt')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    # Pop the epg_domain key that was added for URL building
    module.params.pop("epg_domain")

    module.exit_json(**aci.result)
Exemple #14
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        bd=dict(type='str', aliases=['bd_name']),
        description=dict(type='str', aliases=['descr']),
        enable_vip=dict(type='str', choices=['no', 'yes']),
        gateway=dict(type='str', aliases=['gateway_ip']),
        mask=dict(type='int', aliases=['subnet_mask']),
        subnet_name=dict(type='str', aliases=['name']),
        nd_prefix_policy=dict(type='str'),
        preferred=dict(type='str', choices=['no', 'yes']),
        route_profile=dict(type='str'),
        route_profile_l3_out=dict(type='str'),
        scope=dict(type='str', choices=['private', 'public', 'shared']),
        subnet_control=dict(type='str', choices=['nd_ra', 'no_gw', 'querier_ip', 'unspecified']),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        tenant=dict(type='str', aliases=['tenant_name']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_together=[['gateway', 'mask']],
        required_if=[
            ['state', 'present', ['bd', 'gateway', 'mask', 'tenant']],
            ['state', 'absent', ['bd', 'gateway', 'mask', 'tenant']],
        ],
    )

    description = module.params['description']
    enable_vip = module.params['enable_vip']
    gateway = module.params['gateway']
    mask = module.params['mask']
    if mask is not None and mask not in range(0, 129):
        # TODO: split checkes between IPv4 and IPv6 Addresses
        module.fail_json(msg='Valid Subnet Masks are 0 to 32 for IPv4 Addresses and 0 to 128 for IPv6 addresses')
    subnet_name = module.params['subnet_name']
    nd_prefix_policy = module.params['nd_prefix_policy']
    preferred = module.params['preferred']
    route_profile = module.params['route_profile']
    route_profile_l3_out = module.params['route_profile_l3_out']
    scope = module.params['scope']
    state = module.params['state']
    subnet_control = module.params['subnet_control']
    if subnet_control:
        subnet_control = SUBNET_CONTROL_MAPPING[subnet_control]

    # Construct gateway_addr and add to module.params for constructing URL
    if gateway is not None and mask is not None:
        gateway_addr = '{}/{}'.format(gateway, str(mask))
        module.params['gateway_addr'] = gateway_addr

    aci = ACIModule(module)
    aci.construct_url(
        root_class='tenant', subclass_1='bd', subclass_2='gateway_addr',
        child_classes=['fvRsBDSubnetToProfile', 'fvRsNdPfxPol'],
    )
    aci.get_existing()

    if state == 'present':
        # Filter out module params with null values
        aci.payload(
            aci_class='fvSubnet',
            class_config=dict(
                ctrl=subnet_control,
                descr=description,
                ip=gateway_addr,
                name=subnet_name,
                preferred=preferred,
                scope=scope,
                virtual=enable_vip,
            ),
            child_configs=[
                {'fvRsBDSubnetToProfile': {'attributes': {'tnL3extOutName': route_profile_l3_out, 'tnRtctrlProfileName': route_profile}}},
                {'fvRsNdPfxPol': {'attributes': {'tnNdPfxPolName': nd_prefix_policy}}},
            ],
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvSubnet')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    # Remove gateway_addr used to form URL from module.params
    module.params.pop("gateway_addr", None)

    module.exit_json(**aci.result)
Exemple #15
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        arp_flag=dict(type='str', choices=VALID_ARP_FLAGS),
        description=dict(type='str'),
        dst_port=dict(type='str'),
        dst_port_end=dict(type='str'),
        dst_port_start=dict(type='str'),
        entry=dict(type='str', aliases=['entry_name', 'filter_entry', 'name']),
        ether_type=dict(choices=VALID_ETHER_TYPES, type='str'),
        filter=dict(type='str', aliases=['filter_name']),
        icmp_msg_type=dict(type='str', choices=VALID_ICMP_TYPES),
        icmp6_msg_type=dict(type='str', choices=VALID_ICMP6_TYPES),
        ip_protocol=dict(choices=VALID_IP_PROTOCOLS, type='str'),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        stateful=dict(type='str', choices=['no', 'yes']),
        tenant=dict(type="str", aliases=['tenant_name']),
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['entry', 'filter', 'tenant']],
            ['state', 'present', ['entry', 'filter', 'tenant']],
        ],
    )

    arp_flag = module.params['arp_flag']
    if arp_flag is not None:
        arp_flag = ARP_FLAG_MAPPING[arp_flag]
    description = module.params['description']
    dst_port = module.params['dst_port']
    if dst_port in FILTER_PORT_MAPPING.keys():
        dst_port = FILTER_PORT_MAPPING[dst_port]
    dst_end = module.params['dst_port_end']
    if dst_end in FILTER_PORT_MAPPING.keys():
        dst_end = FILTER_PORT_MAPPING[dst_end]
    dst_start = module.params['dst_port_start']
    if dst_start in FILTER_PORT_MAPPING.keys():
        dst_start = FILTER_PORT_MAPPING[dst_start]
    entry = module.params['entry']
    ether_type = module.params['ether_type']
    filter_name = module.params['filter']
    icmp_msg_type = module.params['icmp_msg_type']
    if icmp_msg_type is not None:
        icmp_msg_type = ICMP_MAPPING[icmp_msg_type]
    icmp6_msg_type = module.params['icmp6_msg_type']
    if icmp6_msg_type is not None:
        icmp6_msg_type = ICMP6_MAPPING[icmp6_msg_type]
    ip_protocol = module.params['ip_protocol']
    state = module.params['state']
    stateful = module.params['stateful']
    tenant = module.params['tenant']

    # validate that dst_port is not passed with dst_start or dst_end
    if dst_port is not None and (dst_end is not None or dst_start is not None):
        module.fail_json(
            msg=
            "Parameter 'dst_port' cannot be used with 'dst_end' and 'dst_start'"
        )
    elif dst_port is not None:
        dst_end = dst_port
        dst_start = dst_port

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='fvTenant',
            aci_rn='tn-{}'.format(tenant),
            filter_target='(fvTenant.name, "{}")'.format(tenant),
            module_object=tenant,
        ),
        subclass_1=dict(
            aci_class='vzFilter',
            aci_rn='flt-{}'.format(filter_name),
            filter_target='(vzFilter.name, "{}")'.format(filter_name),
            module_object=filter_name,
        ),
        subclass_2=dict(aci_class='vzEntry',
                        aci_rn='e-{}'.format(entry),
                        filter_target='(vzEntry.name, "{}")'.format(entry),
                        module_object=entry),
    )

    aci.get_existing()

    if state == 'present':
        # Filter out module params with null values
        aci.payload(
            aci_class='vzEntry',
            class_config=dict(
                arpOpc=arp_flag,
                descr=description,
                dFromPort=dst_start,
                dToPort=dst_end,
                etherT=ether_type,
                icmpv4T=icmp_msg_type,
                icmpv6T=icmp6_msg_type,
                name=entry,
                prot=ip_protocol,
                stateful=stateful,
            ),
        )

        # generate config diff which will be used as POST request body
        aci.get_diff(aci_class='vzEntry')

        # submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        compare_export_policy=dict(type='str'),
        compare_snapshot=dict(type='str'),
        description=dict(type='str', aliases=['descr']),
        export_policy=dict(type='str'),
        fail_on_decrypt=dict(type='bool'),
        import_mode=dict(type='str', choices=['atomic', 'best-effort']),
        import_policy=dict(type='str'),
        import_type=dict(type='str', choices=['merge', 'replace']),
        snapshot=dict(type='str', required=True),
        state=dict(type='str', default='rollback', choices=['preview', 'rollback']),
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=False,
        required_if=[
            ['state', 'preview', ['compare_export_policy', 'compare_snapshot']],
            ['state', 'rollback', ['import_policy']],
        ],
    )

    description = module.params['description']
    export_policy = module.params['export_policy']
    fail_on_decrypt = module.params['fail_on_decrypt']
    if fail_on_decrypt is True:
        fail_on_decrypt = 'yes'
    elif fail_on_decrypt is False:
        fail_on_decrypt = 'no'
    import_mode = module.params['import_mode']
    import_policy = module.params['import_policy']
    import_type = module.params['import_type']
    snapshot = module.params['snapshot']
    state = module.params['state']

    aci = ACIModule(module)

    if state == 'rollback':
        if snapshot.startswith('run-'):
            snapshot = snapshot.replace('run-', '', 1)

        if not snapshot.endswith('.tar.gz'):
            snapshot += '.tar.gz'

        filename = 'ce2_{}-{}'.format(export_policy, snapshot)

        aci.construct_url(root_class="import_policy")
        aci.get_existing()

        # Filter out module parameters with null values
        aci.payload(
            aci_class='configImportP',
            class_config=dict(
                adminSt='triggered',
                descr=description,
                failOnDecryptErrors=fail_on_decrypt,
                fileName=filename,
                importMode=import_mode,
                importType=import_type,
                name=import_policy,
                snapshot='yes',
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='configImportP')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'preview':
        aci.result['url'] = '%(protocol)s://%(hostname)s/mqapi2/snapshots.diff.xml' % module.params
        aci.result['filter_string'] = (
            '?s1dn=uni/backupst/snapshots-[uni/fabric/configexp-%(export_policy)s]/snapshot-%(snapshot)s&'
            's2dn=uni/backupst/snapshots-[uni/fabric/configexp-%(compare_export_policy)s]/snapshot-%(compare_snapshot)s'
        ) % module.params

        # Generate rollback comparison
        get_preview(aci)

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        mcp=dict(type='str', required=False,
                 aliases=['mcp_interface',
                          'name']),  # Not required for querying all objects
        description=dict(type='str', aliases=['descr']),
        admin_state=dict(type='str', choices=['disabled', 'enabled']),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['mcp']],
            ['state', 'present', ['mcp']],
        ],
    )

    mcp = module.params['mcp']
    description = module.params['description']
    admin_state = module.params['admin_state']
    state = module.params['state']

    aci = ACIModule(module)
    aci.construct_url(root_class=dict(
        aci_class='mcpIfPol',
        aci_rn='infra/mcpIfP-{}'.format(mcp),
        filter_target='(mcpIfPol.name, "{}")'.format(mcp),
        module_object=mcp,
    ), )

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='mcpIfPol',
            class_config=dict(
                name=mcp,
                descr=description,
                adminSt=admin_state,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='mcpIfPol')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        tenant=dict(type='str', aliases=['tenant_name']),  # not required for querying all EPRs
        epr_policy=dict(type='str', aliases=['epr_name', 'name']),
        bounce_age=dict(type='int'),
        bounce_trigger=dict(type='str', choices=['coop', 'flood']),
        hold_interval=dict(type='int'),
        local_ep_interval=dict(type='int'),
        remote_ep_interval=dict(type='int'),
        description=dict(type='str', aliases=['descr']),
        move_frequency=dict(type='int'),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['epr_policy', 'tenant']],
            ['state', 'present', ['epr_policy', 'tenant']],
        ],
    )

    epr_policy = module.params['epr_policy']
    bounce_age = module.params['bounce_age']
    if bounce_age is not None and bounce_age != 0 and bounce_age not in range(150, 65536):
        module.fail_json(msg="The bounce_age must be a value of 0 or between 150 and 65535")
    if bounce_age == 0:
        bounce_age = 'infinite'
    bounce_trigger = module.params['bounce_trigger']
    if bounce_trigger is not None:
        bounce_trigger = BOUNCE_TRIG_MAPPING[bounce_trigger]
    description = module.params['description']
    hold_interval = module.params['hold_interval']
    if hold_interval is not None and hold_interval not in range(5, 65536):
        module.fail_json(msg="The hold_interval must be a value between 5 and 65535")
    local_ep_interval = module.params['local_ep_interval']
    if local_ep_interval is not None and local_ep_interval != 0 and local_ep_interval not in range(120, 65536):
        module.fail_json(msg="The local_ep_interval must be a value of 0 or between 120 and 65535")
    if local_ep_interval == 0:
        local_ep_interval = "infinite"
    move_frequency = module.params['move_frequency']
    if move_frequency is not None and move_frequency not in range(65536):
        module.fail_json(msg="The move_frequency must be a value between 0 and 65535")
    if move_frequency == 0:
        move_frequency = "none"
    remote_ep_interval = module.params['remote_ep_interval']
    if remote_ep_interval is not None and remote_ep_interval not in range(120, 65536):
        module.fail_json(msg="The remote_ep_interval must be a value of 0 or between 120 and 65535")
    if remote_ep_interval == 0:
        remote_ep_interval = "infinite"
    state = module.params['state']

    aci = ACIModule(module)
    aci.construct_url(root_class='tenant', subclass_1='epr_policy')
    aci.get_existing()

    if state == 'present':
        # filter out module parameters with null values
        aci.payload(
            aci_class='fvEpRetPol',
            class_config=dict(
                name=epr_policy,
                descr=description,
                bounceAgeIntvl=bounce_age,
                bounceTrig=bounce_trigger,
                holdIntvl=hold_interval,
                localEpAgeIntvl=local_ep_interval,
                remoteEpAgeIntvl=remote_ep_interval,
                moveFreq=move_frequency,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvEpRetPol')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #19
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        admin_state=dict(type='str', choices=['enabled', 'disabled']),
        description=dict(type='str', aliases=['descr']),
        dst_group=dict(type='str'),
        src_group=dict(type='str', required=False,
                       aliases=['name'
                                ]),  # Not required for querying all objects
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        tenant=dict(type='str', required=False,
                    aliases=['tenant_name'
                             ]),  # Not required for querying all objects
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[['state', 'absent', ['src_group', 'tenant']],
                     ['state', 'present', ['src_group', 'tenant']]],
    )

    admin_state = module.params['admin_state']
    description = module.params['description']
    dst_group = module.params['dst_group']
    src_group = module.params['src_group']
    state = module.params['state']

    # Add tenant_span_dst_grp to module.params for URL building
    module.params['tenant_span_src_grp'] = src_group

    aci = ACIModule(module)
    aci.construct_url(root_class='tenant',
                      subclass_1='tenant_span_src_grp',
                      child_classes=['spanSpanLbl'])
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='spanSrcGrp',
            class_config=dict(adminSt=admin_state,
                              descr=description,
                              name=src_group),
            child_configs=[{
                'spanSpanLbl': {
                    'attributes': {
                        'name': dst_group
                    }
                }
            }],
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='spanSrcGrp')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    # Remove tenant_span_src_grp that was used to build URL from module.params
    module.params.pop('tenant_span_src_grp')

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        contract=dict(type='str', aliases=['contract_name']),
        filter=dict(type='str', aliases=['filter_name']),
        log=dict(tyep='str', choices=['log', 'none'], aliases=['directive']),
        subject=dict(type='str', aliases=['contract_subject', 'subject_name']),
        tenant=dict(type='str', aliases=['tenant_name']),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[['state', 'absent', ['contract', 'filter', 'subject', 'tenant']],
                     ['state', 'present', ['contract', 'filter', 'subject', 'tenant']]]
    )

    # contract = module.params['contract']
    filter_name = module.params['filter']
    log = module.params['log']
    # subject = module.params['subject']
    # tenant = module.params['tenant']
    state = module.params['state']

    # Add subject_filter key to modul.params for building the URL
    module.params['subject_filter'] = filter_name

    # Convert log to empty string if none, as that is what API expects. An empty string is not a good option to present the user.
    if log == 'none':
        log = ''

    aci = ACIModule(module)
    aci.construct_url(root_class='tenant', subclass_1='contract', subclass_2='subject', subclass_3='subject_filter')
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(aci_class='vzRsSubjFiltAtt', class_config=dict(tnVzFilterName=filter_name, directives=log))

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='vzRsSubjFiltAtt')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    # Remove subject_filter used to build URL from module.params
    module.params.pop('subject_filter')

    module.exit_json(**aci.result)
Exemple #21
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        path=dict(type='str', required=True, aliases=['uri']),
        method=dict(type='str',
                    default='get',
                    choices=['delete', 'get', 'post'],
                    aliases=['action']),
        src=dict(type='path', aliases=['config_file']),
        content=dict(type='str'),
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        mutually_exclusive=[['content', 'src']],
        supports_check_mode=True,
    )

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

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

    # Report missing file
    file_exists = False
    if src:
        if os.path.isfile(src):
            file_exists = True
        else:
            module.fail_json(msg="Cannot find/access src '%s'" % src)

    # Find request type
    if path.find('.xml') != -1:
        rest_type = 'xml'
        if not HAS_LXML_ETREE:
            module.fail_json(
                msg=
                'The lxml python library is missing, or lacks etree support.')
        if not HAS_XMLJSON_COBRA:
            module.fail_json(
                msg=
                'The xmljson python library is missing, or lacks cobra support.'
            )
    elif path.find('.json') != -1:
        rest_type = 'json'
    else:
        module.fail_json(
            msg='Failed to find REST API content type (neither .xml nor .json).'
        )

    aci = ACIModule(module)

    if method == 'get':
        aci.request(path)
        module.exit_json(**aci.result)
    elif module.check_mode:
        # In check_mode we assume it works, but we don't actually perform the requested change
        # TODO: Could we turn this request in a GET instead ?
        aci.result['changed'] = True
        module.exit_json(response='OK (Check mode)', status=200, **aci.result)

    # Prepare request data
    if content:
        # We include the payload as it may be templated
        payload = content
    elif file_exists:
        with open(src, 'r') as config_object:
            # TODO: Would be nice to template this, requires action-plugin
            payload = config_object.read()

    # Perform actual request using auth cookie (Same as aci_request,but also supports XML)
    url = '%(protocol)s://%(hostname)s/' % aci.params + path.lstrip('/')

    resp, info = fetch_url(module,
                           url,
                           data=payload,
                           method=method.upper(),
                           timeout=timeout,
                           headers=aci.headers)
    aci.result['response'] = info['msg']
    aci.result['status'] = info['status']

    # Report failure
    if info['status'] != 200:
        try:
            aci_response(aci.result, info['body'], rest_type)
            module.fail_json(
                msg='Request failed: %(error_code)s %(error_text)s' %
                aci.result,
                **aci.result)
        except KeyError:
            module.fail_json(msg='Request failed for %(url)s. %(msg)s' % info,
                             **aci.result)

    aci_response(aci.result, resp.read(), rest_type)

    # Report success
    module.exit_json(**aci.result)
Exemple #22
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        lldp_policy=dict(type='str', require=False, aliases=['name']),
        description=dict(type='str', aliases=['descr']),
        receive_state=dict(type='str', choices=['disabled', 'enabled']),
        transmit_state=dict(type='str', choices=['disabled', 'enabled']),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['lldp_policy']],
            ['state', 'present', ['lldp_policy']],
        ],
    )

    lldp_policy = module.params['lldp_policy']
    description = module.params['description']
    receive_state = module.params['receive_state']
    transmit_state = module.params['transmit_state']
    state = module.params['state']

    aci = ACIModule(module)
    aci.construct_url(root_class='lldp_policy')
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='lldpIfPol',
            class_config=dict(
                name=lldp_policy,
                descr=description,
                adminRxSt=receive_state,
                adminTxSt=transmit_state,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='lldpIfPol')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        taboo_contract=dict(
            type='str', required=False,
            aliases=['name']),  # Not required for querying all contracts
        tenant=dict(type='str', required=False,
                    aliases=['tenant_name'
                             ]),  # Not required for querying all contracts
        scope=dict(
            type='str',
            choices=['application-profile', 'context', 'global', 'tenant']),
        description=dict(type='str', aliases=['descr']),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['tenant', 'taboo_contract']],
            ['state', 'present', ['tenant', 'taboo_contract']],
        ],
    )

    taboo_contract = module.params['taboo_contract']
    description = module.params['description']
    scope = module.params['scope']
    state = module.params['state']

    aci = ACIModule(module)
    aci.construct_url(root_class='tenant', subclass_1='taboo_contract')
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='vzTaboo',
            class_config=dict(
                name=taboo_contract,
                descr=description,
                scope=scope,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='vzTaboo')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #24
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        ap=dict(type='str', aliases=['app_profile', 'app_profile_name']),
        epg=dict(type='str', aliases=['epg_name']),
        contract=dict(type='str', aliases=['contract_name']),
        contract_type=dict(type='str',
                           required=True,
                           choices=['consumer', 'provider']),
        priority=dict(type='str',
                      choices=['level1', 'level2', 'level3', 'unspecified']),
        provider_match=dict(
            type='str', choices=['all', 'at_least_one', 'at_most_one',
                                 'none']),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        tenant=dict(type='str', aliases=['tenant_name']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['ap', 'contract', 'epg', 'tenant']],
            ['state', 'present', ['ap', 'contract', 'epg', 'tenant']],
        ],
    )

    ap = module.params['ap']
    contract = module.params['contract']
    contract_type = module.params['contract_type']
    epg = module.params['epg']
    priority = module.params['priority']
    provider_match = module.params['provider_match']
    if provider_match is not None:
        provider_match = PROVIDER_MATCH_MAPPING[provider_match]
    state = module.params['state']
    tenant = module.params['tenant']

    aci_class = ACI_CLASS_MAPPING[contract_type]["class"]
    aci_rn = ACI_CLASS_MAPPING[contract_type]["rn"]

    if contract_type == "consumer" and provider_match is not None:
        module.fail_json(
            msg=
            "the 'provider_match' is only configurable for Provided Contracts")

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='fvTenant',
            aci_rn='tn-{}'.format(tenant),
            filter_target='(fvTenant.name, "{}")'.format(tenant),
            module_object=tenant,
        ),
        subclass_1=dict(
            aci_class='fvAp',
            aci_rn='ap-{}'.format(ap),
            filter_target='(fvAp.name, "{}")'.format(ap),
            module_object=ap,
        ),
        subclass_2=dict(
            aci_class='fvAEPg',
            aci_rn='epg-{}'.format(epg),
            filter_target='(fvAEPg.name, "{}")'.format(epg),
            module_object=epg,
        ),
        subclass_3=dict(
            aci_class=aci_class,
            aci_rn='{}{}'.format(aci_rn, contract),
            filter_target='({}.tnVzBrCPName, "{}'.format(aci_class, contract),
            module_object=contract,
        ),
    )

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class=aci_class,
            class_config=dict(
                matchT=provider_match,
                prio=priority,
                tnVzBrCPName=contract,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class=aci_class)

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #25
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        filter=dict(type='str',
                    required=False,
                    aliases=['name', 'filter_name'
                             ]),  # Not required for querying all objects
        tenant=dict(type='str', required=True,
                    aliases=['tenant_name'
                             ]),  # Not required for querying all objects
        description=dict(type='str', aliases=['descr']),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

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

    filter_name = module.params['filter']
    tenant = module.params['tenant']
    description = module.params['description']
    state = module.params['state']

    aci = ACIModule(module)

    # TODO: Currently we require a tenant for a query, we could make this optional
    # TODO: Investigate for a URI to query objects for a specific tenant
    if filter_name is not None:
        # Work with a specific object
        path = 'api/mo/uni/tn-%(tenant)s/flt-%(filter_name)s.json' % module.params
    elif state == 'query':
        # Query all objects
        path = 'api/node/class/vzFilter.json'
    else:
        module.fail_json(
            msg="Parameter 'filter' is required for state 'absent' or 'present'"
        )

    aci.result['url'] = '%(protocol)s://%(hostname)s/' % aci.params + path

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(aci_class='vzFilter',
                    class_config=dict(name=filter_name, descr=description))

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='vzFilter')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        ap=dict(type='str', aliases=['app_profile', 'app_profile_name']),
        epg=dict(type='str', aliases=['epg_name']),
        contract=dict(type='str', aliases=['contract_name']),
        contract_type=dict(type='str', required=True, choices=['consumer', 'provider']),
        priority=dict(type='str', choices=['level1', 'level2', 'level3', 'unspecified']),
        provider_match=dict(type='str', choices=['all', 'at_least_one', 'at_most_one', 'none']),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        tenant=dict(type='str', aliases=['tenant_name']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['ap', 'contract', 'epg', 'tenant']],
            ['state', 'present', ['ap', 'contract', 'epg', 'tenant']],
        ],
    )

    ap = module.params['ap']
    contract = module.params['contract']
    contract_type = module.params['contract_type']
    epg = module.params['epg']
    priority = module.params['priority']
    provider_match = module.params['provider_match']
    if provider_match is not None:
        provider_match = PROVIDER_MATCH_MAPPING[provider_match]
    state = module.params['state']
    tenant = module.params['tenant']

    aci_class = ACI_CLASS_MAPPING[contract_type]["class"]
    aci_rn = ACI_CLASS_MAPPING[contract_type]["rn"]

    if contract_type == "consumer" and provider_match is not None:
        module.fail_json(msg="the 'provider_match' is only configurable for Provided Contracts")

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='fvTenant',
            aci_rn='tn-{}'.format(tenant),
            filter_target='eq(fvTenant.name, "{}")'.format(tenant),
            module_object=tenant,
        ),
        subclass_1=dict(
            aci_class='fvAp',
            aci_rn='ap-{}'.format(ap),
            filter_target='eq(fvAp.name, "{}")'.format(ap),
            module_object=ap,
        ),
        subclass_2=dict(
            aci_class='fvAEPg',
            aci_rn='epg-{}'.format(epg),
            filter_target='eq(fvAEPg.name, "{}")'.format(epg),
            module_object=epg,
        ),
        subclass_3=dict(
            aci_class=aci_class,
            aci_rn='{}{}'.format(aci_rn, contract),
            filter_target='eq({}.tnVzBrCPName, "{}'.format(aci_class, contract),
            module_object=contract,
        ),
    )

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class=aci_class,
            class_config=dict(
                matchT=provider_match,
                prio=priority,
                tnVzBrCPName=contract,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class=aci_class)

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        description=dict(type='str', aliases=['descr']),
        dst_group=dict(type='str'),
        src_group=dict(type='str'),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        tenant=dict(type='str', aliases=['tenant_name']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['dst_group', 'src_group', 'tenant']],
            ['state', 'present', ['dst_group', 'src_group', 'tenant']],
        ],
    )

    description = module.params['description']
    dst_group = module.params['dst_group']
    src_group = module.params['src_group']
    state = module.params['state']

    # Add tenant_span_src_grp and tenant_span_src_grp_dst_grp to module.params for URL building
    module.params['tenant_span_src_grp'] = src_group
    module.params['tenant_span_src_grp_dst_grp'] = dst_group

    aci = ACIModule(module)
    aci.construct_url(root_class='tenant', subclass_1='tenant_span_src_grp', subclass_2='tenant_span_src_grp_dst_grp')
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='spanSpanLbl',
            class_config=dict(
                descr=description,
                name=dst_group,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='spanSpanLbl')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    # Remove tenant_span_src_grp and tenant_span_src_grp_dst_grp that was used to build URL from module.params
    module.params.pop('tenant_span_src_grp')
    module.params.pop('tenant_span_src_grp_dst_grp')

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        port_channel=dict(type='str', required=False,
                          aliases=['name'
                                   ]),  # Not required for querying all objects
        description=dict(type='str', aliases=['descr']),
        min_links=dict(type='int'),
        max_links=dict(type='int'),
        mode=dict(
            type='str',
            choices=['off', 'mac-pin', 'active', 'passive',
                     'mac-pin-nicload']),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

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

    port_channel = module.params['port_channel']
    description = module.params['description']
    # TODO: Validate min_links is in the acceptable range
    min_links = module.params['min_link']
    # TODO: Validate max_links is in the acceptable range
    min_links = str(min_links)
    max_links = module.params['max_link']
    max_links = str(max_links)
    mode = module.params['mode']
    state = module.params['state']

    aci = ACIModule(module)

    # TODO: This logic could be cleaner.
    if port_channel is not None:
        path = 'api/mo/uni/infra/lacplagp-%(port_channel)s.json' % module.params
    elif state == 'query':
        # Query all objects
        path = 'api/node/class/lacplagPol.json'
    else:
        module.fail_json(
            msg=
            "Parameter 'port_channel' is required for state 'absent' or 'present'"
        )

    aci.result['url'] = '%(protocol)s://%(hostname)s/' % aci.params + path

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(aci_class='lacpLagPol',
                    class_config=dict(name=port_channel,
                                      descr=description,
                                      minLinks=min_links,
                                      maxLinks=max_links,
                                      mode=mode))

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='lacpLagPol')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        contract=dict(type='str', aliases=['contract_name']),
        filter=dict(type='str', aliases=['filter_name']),
        log=dict(tyep='str', choices=['log', 'none'], aliases=['directive']),
        subject=dict(type='str', aliases=['contract_subject', 'subject_name']),
        tenant=dict(type='str', aliases=['tenant_name']),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['contract', 'filter', 'subject', 'tenant']],
            ['state', 'present', ['contract', 'filter', 'subject', 'tenant']],
        ],
    )

    contract = module.params['contract']
    filter_name = module.params['filter']
    log = module.params['log']
    subject = module.params['subject']
    tenant = module.params['tenant']
    state = module.params['state']

    # Add subject_filter key to modul.params for building the URL
    module.params['subject_filter'] = filter_name

    # Convert log to empty string if none, as that is what API expects. An empty string is not a good option to present the user.
    if log == 'none':
        log = ''

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='fvTenant',
            aci_rn='tn-{}'.format(tenant),
            filter_target='eq(fvTenant.name, "{}")'.format(tenant),
            module_object=tenant,
        ),
        subclass_1=dict(
            aci_class='vzBrCP',
            aci_rn='brc-{}'.format(contract),
            filter_target='eq(vzBrCP.name, "{}")'.format(contract),
            module_object=contract,
        ),
        subclass_2=dict(
            aci_class='vzSubj',
            aci_rn='subj-{}'.format(subject),
            filter_target='eq(vzSubj.name, "{}")'.format(subject),
            module_object=subject,
        ),
        subclass_3=dict(
            aci_class='vzRsSubjFiltAtt',
            aci_rn='rssubjFiltAtt-{}'.format(filter_name),
            filter_target='eq(vzRsSubjFiltAtt.tnVzFilterName, "{}")'.format(
                filter_name),
            module_object=filter_name,
        ),
    )

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='vzRsSubjFiltAtt',
            class_config=dict(
                tnVzFilterName=filter_name,
                directives=log,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='vzRsSubjFiltAtt')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    # Remove subject_filter used to build URL from module.params
    module.params.pop('subject_filter')

    module.exit_json(**aci.result)
Exemple #30
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        bd=dict(type='str', aliases=['bd_name']),
        description=dict(type='str', aliases=['descr']),
        enable_vip=dict(type='str', choices=['no', 'yes']),
        gateway=dict(type='str', aliases=['gateway_ip']),
        mask=dict(type='int', aliases=['subnet_mask']),
        subnet_name=dict(type='str', aliases=['name']),
        nd_prefix_policy=dict(type='str'),
        preferred=dict(type='str', choices=['no', 'yes']),
        route_profile=dict(type='str'),
        route_profile_l3_out=dict(type='str'),
        scope=dict(type='str', choices=['private', 'public', 'shared']),
        subnet_control=dict(
            type='str',
            choices=['nd_ra', 'no_gw', 'querier_ip', 'unspecified']),
        state=dict(type='str', choices=['absent', 'present', 'query']),
        tenant=dict(type='str', aliases=['tenant_name']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_together=[['gateway', 'mask']],
        required_if=[
            ['state', 'present', ['bd', 'gateway', 'mask', 'tenant']],
            ['state', 'absent', ['bd', 'gateway', 'mask', 'tenant']],
        ],
    )

    description = module.params['description']
    enable_vip = module.params['enable_vip']
    gateway = module.params['gateway']
    mask = module.params['mask']
    if mask is not None and mask not in range(0, 129):
        # TODO: split checkes between IPv4 and IPv6 Addresses
        module.fail_json(
            msg=
            'Valid Subnet Masks are 0 to 32 for IPv4 Addresses and 0 to 128 for IPv6 addresses'
        )
    subnet_name = module.params['subnet_name']
    nd_prefix_policy = module.params['nd_prefix_policy']
    preferred = module.params['preferred']
    route_profile = module.params['route_profile']
    route_profile_l3_out = module.params['route_profile_l3_out']
    scope = module.params['scope']
    state = module.params['state']
    subnet_control = module.params['subnet_control']
    if subnet_control:
        subnet_control = SUBNET_CONTROL_MAPPING[subnet_control]

    # Construct gateway_addr and add to module.params for constructing URL
    if gateway is not None and mask is not None:
        gateway_addr = '{}/{}'.format(gateway, str(mask))
        module.params['gateway_addr'] = gateway_addr

    aci = ACIModule(module)
    aci.construct_url(
        root_class='tenant',
        subclass_1='bd',
        subclass_2='gateway_addr',
        child_classes=['fvRsBDSubnetToProfile', 'fvRsNdPfxPol'],
    )
    aci.get_existing()

    if state == 'present':
        # Filter out module params with null values
        aci.payload(
            aci_class='fvSubnet',
            class_config=dict(
                ctrl=subnet_control,
                descr=description,
                ip=gateway_addr,
                name=subnet_name,
                preferred=preferred,
                scope=scope,
                virtual=enable_vip,
            ),
            child_configs=[
                {
                    'fvRsBDSubnetToProfile': {
                        'attributes': {
                            'tnL3extOutName': route_profile_l3_out,
                            'tnRtctrlProfileName': route_profile
                        }
                    }
                },
                {
                    'fvRsNdPfxPol': {
                        'attributes': {
                            'tnNdPfxPolName': nd_prefix_policy
                        }
                    }
                },
            ],
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvSubnet')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    # Remove gateway_addr used to form URL from module.params
    module.params.pop("gateway_addr", None)

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        compare_export_policy=dict(type='str'),
        compare_snapshot=dict(type='str'),
        description=dict(type='str', aliases=['descr']),
        export_policy=dict(type='str'),
        fail_on_decrypt=dict(type='bool'),
        import_mode=dict(type='str', choices=['atomic', 'best-effort']),
        import_policy=dict(type='str'),
        import_type=dict(type='str', choices=['merge', 'replace']),
        snapshot=dict(type='str', required=True),
        state=dict(type='str',
                   default='rollback',
                   choices=['preview', 'rollback']),
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=False,
        required_if=[
            [
                'state', 'preview',
                ['compare_export_policy', 'compare_snapshot']
            ],
            ['state', 'rollback', ['import_policy']],
        ],
    )

    description = module.params['description']
    export_policy = module.params['export_policy']
    fail_on_decrypt = module.params['fail_on_decrypt']
    if fail_on_decrypt is True:
        fail_on_decrypt = 'yes'
    elif fail_on_decrypt is False:
        fail_on_decrypt = 'no'
    import_mode = module.params['import_mode']
    import_policy = module.params['import_policy']
    import_type = module.params['import_type']
    snapshot = module.params['snapshot']
    state = module.params['state']

    aci = ACIModule(module)

    if state == 'rollback':
        if snapshot.startswith('run-'):
            snapshot = snapshot.replace('run-', '', 1)

        if not snapshot.endswith('.tar.gz'):
            snapshot += '.tar.gz'

        filename = 'ce2_{0}-{1}'.format(export_policy, snapshot)

        aci.construct_url(root_class="import_policy")
        aci.get_existing()

        # Filter out module parameters with null values
        aci.payload(
            aci_class='configImportP',
            class_config=dict(
                adminSt='triggered',
                descr=description,
                failOnDecryptErrors=fail_on_decrypt,
                fileName=filename,
                importMode=import_mode,
                importType=import_type,
                name=import_policy,
                snapshot='yes',
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='configImportP')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'preview':
        aci.result[
            'url'] = '%(protocol)s://%(hostname)s/mqapi2/snapshots.diff.xml' % module.params
        aci.result['filter_string'] = (
            '?s1dn=uni/backupst/snapshots-[uni/fabric/configexp-%(export_policy)s]/snapshot-%(snapshot)s&'
            's2dn=uni/backupst/snapshots-[uni/fabric/configexp-%(compare_export_policy)s]/snapshot-%(compare_snapshot)s'
        ) % module.params

        # Generate rollback comparison
        get_preview(aci)

    module.exit_json(**aci.result)
Exemple #32
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        tenant=dict(type='str',
                    aliases=['tenant_name'
                             ]),  # tenant not required for querying all anps
        app_profile=dict(type='str', aliases=['app_profile_name', 'name']),
        description=dict(type='str', aliases=['descr'], required=False),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[['state', 'absent', ['tenant', 'app_profile']],
                     ['state', 'present', ['tenant', 'app_profile']]])

    tenant = module.params['tenant']
    app_profile = module.params['app_profile']
    description = module.params['description']
    state = module.params['state']

    aci = ACIModule(module)

    if tenant is not None and app_profile is not None:
        path = 'api/mo/uni/tn-%(tenant)s/ap-%(app_profile)s.json' % module.params
        filter_string = ''
    elif tenant is None and app_profile is None:
        path = 'api/class/fvAp.json'
        filter_string = ''
    elif tenant is not None:
        path = 'api/mo/uni/tn-%(tenant)s.json' % module.params
        filter_string = '?rsp-subtree=children&rsp-subtree-class=fvAp&rsp-subtree-include=no-scoped'
    else:
        path = 'api/class/fvAp.json'
        filter_string = '?query-target-filter=eq(fvAp.name, \"%(app_profile)s\")' % module.params

    aci.result['url'] = '%(protocol)s://%(hostname)s/' % aci.params + path

    aci.get_existing(filter_string=filter_string)

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(aci_class='fvAp',
                    class_config=dict(name=app_profile, descr=description))

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvAp')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #33
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        aep=dict(type='str',
                 aliases=['name',
                          'aep_name']),  # not required for querying all AEPs
        description=dict(type='str', aliases=['descr']),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['aep']],
            ['state', 'present', ['aep']],
        ],
    )

    aep = module.params['aep']
    description = module.params['description']
    state = module.params['state']

    aci = ACIModule(module)
    aci.construct_url(root_class=dict(
        aci_class='infraAttEntityP',
        aci_rn='infra/attentp-{}'.format(aep),
        filter_target='eq(infraAttEntityP.name, "{}")'.format(aep),
        module_object=aep,
    ), )
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='infraAttEntityP',
            class_config=dict(
                name=aep,
                descr=description,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='infraAttEntityP')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        port_security=dict(type='str', required=False, aliases=['name']),  # Not required for querying all objects
        description=dict(type='str', aliases=['descr']),
        max_end_points=dict(type='int'),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['port_security']],
            ['state', 'present', ['port_security']],
        ],
    )

    port_security = module.params['port_security']
    description = module.params['description']
    max_end_points = module.params['max_end_points']
    if max_end_points is not None and max_end_points not in range(12001):
        module.fail_json(msg='The "max_end_points" must be between 0 and 12000')
    state = module.params['state']

    aci = ACIModule(module)
    aci.construct_url(root_class='port_security')
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='l2PortSecurityPol',
            class_config=dict(
                name=port_security,
                descr=description,
                maximum=max_end_points,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='l2PortSecurityPol')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        port_channel=dict(type='str', required=False, aliases=['name']),  # Not required for querying all objects
        description=dict(type='str', aliases=['descr']),
        min_links=dict(type='int'),
        max_links=dict(type='int'),
        mode=dict(type='str', choices=['off', 'mac-pin', 'active', 'passive', 'mac-pin-nicload']),
        fast_select=dict(type='bool'),
        graceful_convergence=dict(type='bool'),
        load_defer=dict(type='bool'),
        suspend_individual=dict(type='bool'),
        symmetric_hash=dict(type='bool'),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['port_channel']],
            ['state', 'present', ['port_channel']],
        ],
    )

    port_channel = module.params['port_channel']
    description = module.params['description']
    min_links = module.params['min_links']
    if min_links is not None and min_links not in range(1, 17):
        module.fail_json(msg='The "min_links" must be a value between 1 and 16')
    max_links = module.params['max_links']
    if max_links is not None and max_links not in range(1, 17):
        module.fail_json(msg='The "max_links" must be a value between 1 and 16')
    mode = module.params['mode']
    state = module.params['state']

    # Build ctrl value for request
    ctrl = []
    if module.params['fast_select'] is True:
        ctrl.append('fast-sel-hot-stdby')
    if module.params['graceful_convergence'] is True:
        ctrl.append('graceful-conv')
    if module.params['load_defer'] is True:
        ctrl.append('load-defer')
    if module.params['suspend_individual'] is True:
        ctrl.append('susp-individual')
    if module.params['symmetric_hash'] is True:
        ctrl.append('symmetric-hash')
    if not ctrl:
        ctrl = None
    else:
        ctrl = ",".join(ctrl)

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='lacpLagPol',
            aci_rn='infra/lacplagp-{}'.format(port_channel),
            filter_target='eq(lacpLagPol.name, "{}")'.format(port_channel),
            module_object=port_channel,
        ),
    )

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='lacpLagPol',
            class_config=dict(
                name=port_channel,
                ctrl=ctrl,
                descr=description,
                minLinks=min_links,
                maxLinks=max_links,
                mode=mode,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='lacpLagPol')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        port_security=dict(type='str', required=False, aliases=['name']),  # Not required for querying all objects
        description=dict(type='str', aliases=['descr']),
        max_end_points=dict(type='int'),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[['state', 'absent', ['port_security']],
                     ['state', 'present', ['port_security']]],
    )

    port_security = module.params['port_security']
    description = module.params['description']
    max_end_points = module.params['max_end_points']
    if max_end_points is not None and max_end_points not in range(12001):
        module.fail_json(msg='The "max_end_points" must be between 0 and 12000')
    state = module.params['state']

    aci = ACIModule(module)
    aci.construct_url(root_class='port_security')
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='l2PortSecurityPol',
            class_config=dict(name=port_security, descr=description, maximum=max_end_points),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='l2PortSecurityPol')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        tenant=dict(type='str',
                    aliases=['tenant_name'
                             ]),  # not required for querying all EPRs
        epr_policy=dict(type='str', aliases=['epr_name', 'name']),
        bounce_age=dict(type='int'),
        bounce_trigger=dict(type='str', choices=['coop', 'flood']),
        hold_interval=dict(type='int'),
        local_ep_interval=dict(type='int'),
        remote_ep_interval=dict(type='int'),
        description=dict(type='str', aliases=['descr']),
        move_frequency=dict(type='int'),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['epr_policy', 'tenant']],
            ['state', 'present', ['epr_policy', 'tenant']],
        ],
    )

    epr_policy = module.params['epr_policy']
    bounce_age = module.params['bounce_age']
    if bounce_age is not None and bounce_age != 0 and bounce_age not in range(
            150, 65536):
        module.fail_json(
            msg="The bounce_age must be a value of 0 or between 150 and 65535")
    if bounce_age == 0:
        bounce_age = 'infinite'
    bounce_trigger = module.params['bounce_trigger']
    if bounce_trigger is not None:
        bounce_trigger = BOUNCE_TRIG_MAPPING[bounce_trigger]
    description = module.params['description']
    hold_interval = module.params['hold_interval']
    if hold_interval is not None and hold_interval not in range(5, 65536):
        module.fail_json(
            msg="The hold_interval must be a value between 5 and 65535")
    local_ep_interval = module.params['local_ep_interval']
    if local_ep_interval is not None and local_ep_interval != 0 and local_ep_interval not in range(
            120, 65536):
        module.fail_json(
            msg=
            "The local_ep_interval must be a value of 0 or between 120 and 65535"
        )
    if local_ep_interval == 0:
        local_ep_interval = "infinite"
    move_frequency = module.params['move_frequency']
    if move_frequency is not None and move_frequency not in range(65536):
        module.fail_json(
            msg="The move_frequency must be a value between 0 and 65535")
    if move_frequency == 0:
        move_frequency = "none"
    remote_ep_interval = module.params['remote_ep_interval']
    if remote_ep_interval is not None and remote_ep_interval not in range(
            120, 65536):
        module.fail_json(
            msg=
            "The remote_ep_interval must be a value of 0 or between 120 and 65535"
        )
    if remote_ep_interval == 0:
        remote_ep_interval = "infinite"
    state = module.params['state']
    tenant = module.params['tenant']

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='fvTenant',
            aci_rn='tn-{}'.format(tenant),
            filter_target='(fvTenant.name, "{}")'.format(tenant),
            module_object=tenant,
        ),
        subclass_1=dict(
            aci_class='fvEpRetPol',
            aci_rn='epRPol-{}'.format(epr_policy),
            filter_target='(fvEpRetPol.name, "{}")'.format(epr_policy),
            module_object=epr_policy,
        ),
    )

    aci.get_existing()

    if state == 'present':
        # filter out module parameters with null values
        aci.payload(
            aci_class='fvEpRetPol',
            class_config=dict(
                name=epr_policy,
                descr=description,
                bounceAgeIntvl=bounce_age,
                bounceTrig=bounce_trigger,
                holdIntvl=hold_interval,
                localEpAgeIntvl=local_ep_interval,
                remoteEpAgeIntvl=remote_ep_interval,
                moveFreq=move_frequency,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvEpRetPol')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #38
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        epg=dict(type='str', aliases=['name', 'epg_name']),
        bridge_domain=dict(type='str', aliases=['bd_name']),
        app_profile=dict(type='str', aliases=['app_profile_name']),
        tenant=dict(type='str', aliases=['tenant_name']),
        description=dict(type='str', aliases=['descr']),
        priority=dict(type='str',
                      choices=['level1', 'level2', 'level3', 'unspecified']),
        intra_epg_isolation=dict(choices=['enforced', 'unenforced']),
        fwd_control=dict(type='str', choices=['none', 'proxy-arp']),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[['state', 'absent', ['app_profile', 'epg', 'tenant']],
                     ['state', 'present', ['app_profile', 'epg', 'tenant']]])

    epg = module.params['epg']
    # app_profile = module.params['app_profile']
    # tenant = module.params['tenant']
    bridge_domain = module.params['bridge_domain']
    description = module.params['description']
    priority = module.params['priority']
    intra_epg_isolation = module.params['intra_epg_isolation']
    fwd_control = module.params['fwd_control']
    state = module.params['state']

    aci = ACIModule(module)

    # TODO: Add logic to handle multiple input variations when query
    if state != 'query':
        # Work with a specific EPG
        path = 'api/mo/uni/tn-%(tenant)s/ap-%(app_profile)s/epg-%(epg)s.json' % module.params
        filter_string = '?rsp-subtree=children&rsp-subtree-class=fvRsBd&rsp-prop-include=config-only'
    else:
        # Query all EPGs
        path = 'api/class/fvAEPg.json'
        filter_string = '?rsp-subtree=children&rsp-subtree-class=fvRsBd'

    aci.result['url'] = '%(protocol)s://%(hostname)s/' % aci.params + path

    aci.get_existing(filter_string=filter_string)

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='fvAEPg',
            class_config=dict(name=epg,
                              descr=description,
                              prio=priority,
                              pcEnfPref=intra_epg_isolation,
                              fwdCtrl=fwd_control),
            child_configs=[
                dict(fvRsBd=dict(attributes=dict(tnFvBDName=bridge_domain)))
            ])

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvAEPg')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #39
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        arp_flooding=dict(choices=['no', 'yes']),
        bd=dict(type='str', aliases=['bd_name', 'name']),
        bd_type=dict(type='str', choices=['ethernet', 'fc']),
        description=dict(type='str'),
        enable_multicast=dict(type='str', choices=['no', 'yes']),
        enable_routing=dict(type='str', choices=['no', 'yes']),
        endpoint_clear=dict(type='str', choices=['no', 'yes']),
        endpoint_move_detect=dict(type='str', choices=['default', 'garp']),
        endpoint_retention_action=dict(type='str', choices=['inherit', 'resolve']),
        endpoint_retention_policy=dict(type='str'),
        igmp_snoop_policy=dict(type='str'),
        ip_learning=dict(type='str', choices=['no', 'yes']),
        ipv6_nd_policy=dict(type='str'),
        l2_unknown_unicast=dict(choices=['proxy', 'flood']),
        l3_unknown_multicast=dict(choices=['flood', 'opt-flood']),
        limit_ip_learn=dict(type='str', choices=['no', 'yes']),
        multi_dest=dict(choices=['bd-flood', 'drop', 'encap-flood']),
        state=dict(choices=['absent', 'present', 'query'], type='str', default='present'),
        tenant=dict(type='str', aliases=['tenant_name']),
        vrf=dict(type='str', aliases=['vrf_name']),
        gateway_ip=dict(type='str', removed_in_version='2.4'),  # Deprecated starting from v2.4
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
        scope=dict(type='str', removed_in_version='2.4'),  # Deprecated starting from v2.4
        subnet_mask=dict(type='str', removed_in_version='2.4'),  # Deprecated starting from v2.4
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['bd', 'tenant']],
            ['state', 'present', ['bd', 'tenant']],
        ],
    )

    arp_flooding = module.params['arp_flooding']
    bd = module.params['bd']
    bd_type = module.params['bd_type']
    if bd_type == 'ethernet':
        # ethernet type is represented as regular, but that is not clear to the users
        bd_type = 'regular'
    description = module.params['description']
    enable_multicast = module.params['enable_multicast']
    enable_routing = module.params['enable_routing']
    endpoint_clear = module.params['endpoint_clear']
    endpoint_move_detect = module.params['endpoint_move_detect']
    if endpoint_move_detect == 'default':
        # the ACI default setting is an empty string, but that is not a good input value
        endpoint_move_detect = ''
    endpoint_retention_action = module.params['endpoint_retention_action']
    endpoint_retention_policy = module.params['endpoint_retention_policy']
    igmp_snoop_policy = module.params['igmp_snoop_policy']
    ip_learning = module.params['ip_learning']
    ipv6_nd_policy = module.params['ipv6_nd_policy']
    l2_unknown_unicast = module.params['l2_unknown_unicast']
    l3_unknown_multicast = module.params['l3_unknown_multicast']
    limit_ip_learn = module.params['limit_ip_learn']
    multi_dest = module.params['multi_dest']
    state = module.params['state']
    tenant = module.params['tenant']
    vrf = module.params['vrf']

    # Give warning when fvSubnet parameters are passed as those have been moved to the aci_subnet module
    if module.params['gateway_ip'] or module.params['subnet_mask'] or module.params['scope']:
        module._warnings = ["The support for managing Subnets has been moved to its own module, aci_subnet. \
                            The new modules still supports 'gateway_ip' and 'subnet_mask' along with more features"]

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='fvTenant',
            aci_rn='tn-{}'.format(tenant),
            filter_target='(fvTenant.name, "{}")'.format(tenant),
            module_object=tenant,
        ),
        subclass_1=dict(
            aci_class='fvBD',
            aci_rn='BD-{}'.format(bd),
            filter_target='(fvBD.name, "{}")'.format(bd),
            module_object=bd,
        ),
        child_classes=['fvRsCtx', 'fvRsIgmpsn', 'fvRsBDToNdP', 'fvRsBdToEpRet'],
    )

    aci.get_existing()

    if state == 'present':
        # Filter out module params with null values
        aci.payload(
            aci_class='fvBD',
            class_config=dict(
                arpFlood=arp_flooding,
                descr=description,
                epClear=endpoint_clear,
                epMoveDetectMode=endpoint_move_detect,
                ipLearning=ip_learning,
                limitIpLearnToSubnets=limit_ip_learn,
                mcastAllow=enable_multicast,
                multiDstPktAct=multi_dest,
                name=bd,
                type=bd_type,
                unicastRoute=enable_routing,
                unkMacUcastAct=l2_unknown_unicast,
                unkMcastAct=l3_unknown_multicast,
            ),
            child_configs=[
                {'fvRsCtx': {'attributes': {'tnFvCtxName': vrf}}},
                {'fvRsIgmpsn': {'attributes': {'tnIgmpSnoopPolName': igmp_snoop_policy}}},
                {'fvRsBDToNdP': {'attributes': {'tnNdIfPolName': ipv6_nd_policy}}},
                {'fvRsBdToEpRet': {'attributes': {'resolveAct': endpoint_retention_action, 'tnFvEpRetPolName': endpoint_retention_policy}}},
            ],
        )

        # generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvBD')

        # submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        rtp=dict(type='str', required=False,
                 aliases=['name', 'rtp_name'
                          ]),  # Not required for querying all objects
        tenant=dict(type='str', required=False,
                    aliases=['tenant_name'
                             ]),  # Not required for quering all objects
        description=dict(type='str', aliases=['descr']),
        tag=dict(type='int'),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

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

    rtp = module.params['rtp']
    tenant = module.params['tenant']
    description = module.params['description']
    tag = module.params['tag']
    state = module.params['state']

    aci = ACIModule(module)

    if rtp is not None:
        # Work with a specific object
        if tenant is not None:
            path = 'api/mo/uni/tn-%(tenant)s/rttag-%(rtp)s.json' % module.params
        else:
            path = 'api/class/l3extRouteTagPol.json?query-target-filter=eq(l3extRouteTagPol.name,"%(rtp)s")' % module.params
    elif state == 'query':
        # Query all objects
        if tenant is not None:
            path = 'api/mo/uni/tn-%(tenant)s.json?rsp-subtree=children&rsp-subtree-class=l3extRouteTagPol&rsp-subtree-include=no-scoped' % module.params
        else:
            path = 'api/node/class/l3extRouteTagPol.json'
    else:
        module.fail_json(
            msg="Parameter 'rtp' is required for state 'absent' or 'present'")

    aci.result['url'] = '%(protocol)s://%(hostname)s/' % aci.params + path

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(aci_class='l3extRouteTagPol',
                    class_config=dict(name=rtp, descr=description, tag=tag))

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='l3extRouteTagPol')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        allow_useg=dict(type='str', choices=['encap', 'useg']),
        ap=dict(type='str', aliases=['app_profile', 'app_profile_name']),
        deploy_immediacy=dict(type='str', choices=['immediate', 'on-demand']),
        domain=dict(type='str', aliases=['domain_name', 'domain_profile']),
        domain_type=dict(type='str', choices=['phys', 'vmm'],
                         aliases=['type']),
        encap=dict(type='int'),
        encap_mode=dict(type='str', choices=['auto', 'vlan', 'vxlan']),
        epg=dict(type='str', aliases=['name', 'epg_name']),
        netflow=dict(type='str', choices=['disabled', 'enabled']),
        primary_encap=dict(type='int'),
        resolution_immediacy=dict(
            type='str', choices=['immediate', 'lazy', 'pre-provision']),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        tenant=dict(type='str', aliases=['tenant_name']),
        vm_provider=dict(type='str',
                         choices=['microsoft', 'openstack', 'vmware']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['domain_type', 'vmm', ['vm_provider']],
            [
                'state', 'absent',
                ['ap', 'domain', 'domain_type', 'epg', 'tenant']
            ],
            [
                'state', 'present',
                ['ap', 'domain', 'domain_type', 'epg', 'tenant']
            ],
        ],
    )

    allow_useg = module.params['allow_useg']
    ap = module.params['ap']
    deploy_immediacy = module.params['deploy_immediacy']
    domain = module.params['domain']
    domain_type = module.params['domain_type']
    vm_provider = module.params['vm_provider']
    encap = module.params['encap']
    if encap is not None:
        if encap in range(1, 4097):
            encap = 'vlan-{}'.format(encap)
        else:
            module.fail_json(msg='Valid VLAN assigments are from 1 to 4096')
    encap_mode = module.params['encap_mode']
    epg = module.params['epg']
    netflow = module.params['netflow']
    primary_encap = module.params['primary_encap']
    if primary_encap is not None:
        if primary_encap in range(1, 4097):
            primary_encap = 'vlan-{}'.format(primary_encap)
        else:
            module.fail_json(msg='Valid VLAN assigments are from 1 to 4096')
    resolution_immediacy = module.params['resolution_immediacy']
    state = module.params['state']
    tenant = module.params['tenant']

    if domain_type == 'phys' and vm_provider is not None:
        module.fail_json(msg="Domain type 'phys' cannot have a 'vm_provider'")

    # Compile the full domain for URL building
    if domain_type == 'vmm':
        epg_domain = '{}{}'.format(VM_PROVIDER_MAPPING[vm_provider], domain)
    elif domain_type is not None:
        epg_domain = 'uni/phys-{}'.format(domain)
    else:
        epg_domain = None

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='fvTenant',
            aci_rn='tn-{}'.format(tenant),
            filter_target='(fvTenant.name, "{}")'.format(tenant),
            module_object=tenant,
        ),
        subclass_1=dict(
            aci_class='fvAp',
            aci_rn='ap-{}'.format(ap),
            filter_target='(fvAp.name, "{}")'.format(ap),
            module_object=ap,
        ),
        subclass_2=dict(
            aci_class='fvAEPg',
            aci_rn='epg-{}'.format(epg),
            filter_target='(fvTenant.name, "{}")'.format(epg),
            module_object=epg,
        ),
        subclass_3=dict(
            aci_class='fvRsDomAtt',
            aci_rn='rsdomAtt-[{}]'.format(epg_domain),
            filter_target='(fvRsDomAtt.tDn, "{}")'.format(epg_domain),
            module_object=epg_domain,
        ),
    )

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='fvRsDomAtt',
            class_config=dict(
                classPref=allow_useg,
                encap=encap,
                encapMode=encap_mode,
                instrImedcy=deploy_immediacy,
                netflowPref=netflow,
                primaryEncap=primary_encap,
                resImedcy=resolution_immediacy,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvRsDomAtt')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #42
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        port_channel=dict(type='str', required=False,
                          aliases=['name'
                                   ]),  # Not required for querying all objects
        description=dict(type='str', aliases=['descr']),
        min_links=dict(type='int'),
        max_links=dict(type='int'),
        mode=dict(
            type='str',
            choices=['off', 'mac-pin', 'active', 'passive',
                     'mac-pin-nicload']),
        fast_select=dict(type='bool'),
        graceful_convergence=dict(type='bool'),
        load_defer=dict(type='bool'),
        suspend_individual=dict(type='bool'),
        symmetric_hash=dict(type='bool'),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['port_channel']],
            ['state', 'present', ['port_channel']],
        ],
    )

    port_channel = module.params['port_channel']
    description = module.params['description']
    min_links = module.params['min_links']
    if min_links is not None and min_links not in range(1, 17):
        module.fail_json(
            msg='The "min_links" must be a value between 1 and 16')
    max_links = module.params['max_links']
    if max_links is not None and max_links not in range(1, 17):
        module.fail_json(
            msg='The "max_links" must be a value between 1 and 16')
    mode = module.params['mode']
    state = module.params['state']

    # Build ctrl value for request
    ctrl = []
    if module.params['fast_select'] is True:
        ctrl.append('fast-sel-hot-stdby')
    if module.params['graceful_convergence'] is True:
        ctrl.append('graceful-conv')
    if module.params['load_defer'] is True:
        ctrl.append('load-defer')
    if module.params['suspend_individual'] is True:
        ctrl.append('susp-individual')
    if module.params['symmetric_hash'] is True:
        ctrl.append('symmetric-hash')
    if not ctrl:
        ctrl = None
    else:
        ctrl = ",".join(ctrl)

    aci = ACIModule(module)
    aci.construct_url(root_class='port_channel')
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='lacpLagPol',
            class_config=dict(
                name=port_channel,
                ctrl=ctrl,
                descr=description,
                minLinks=min_links,
                maxLinks=max_links,
                mode=mode,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='lacpLagPol')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #43
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        dst_group=dict(type='str', required=False,
                       aliases=['name'
                                ]),  # Not required for querying all objects
        tenant=dict(type='str', required=True,
                    aliases=['tenant_name'
                             ]),  # Not required for querying all objects
        description=dict(type='str', aliases=['descr']),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

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

    dst_group = module.params['dst_group']
    # tenant = module.params['tenant']
    description = module.params['description']
    state = module.params['state']

    aci = ACIModule(module)

    # TODO: This logic could be cleaner.
    if dst_group is not None:
        path = 'api/mo/uni/tn-%(tenant)s/destgrp-%(dst_group)s.json' % module.params
    elif state == 'query':
        # Query all contracts
        path = 'api/node/class/spanDestGrp.json'
    else:
        module.fail_json(
            msg=
            "Parameter 'dst_group' is required for state 'absent' or 'present'"
        )

    aci.result['url'] = '%(protocol)s://%(hostname)s/' % aci.params + path

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(aci_class='spanDestGrp',
                    class_config=dict(name=dst_group, descr=description))

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='spanDestGrp')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        contract=dict(type='str', aliases=['contract_name']),
        subject=dict(type='str', aliases=['contract_subject', 'name', 'subject_name']),
        tenant=dict(type='str', aliases=['tenant_name']),
        priority=dict(type='str', choices=['unspecified', 'level1', 'level2', 'level3']),
        reverse_filter=dict(type='str', choices=['yes', 'no']),
        dscp=dict(type='str', aliases=['target']),
        description=dict(type='str', aliases=['descr']),
        consumer_match=dict(type='str', choices=['all', 'at_least_one', 'at_most_one', 'none']),
        provider_match=dict(type='str', choices=['all', 'at_least_one', 'at_most_one', 'none']),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
        directive=dict(type='str', removed_in_version='2.4'),  # Deprecated starting from v2.4
        filter=dict(type='str', aliases=['filter_name'], removed_in_version='2.4'),  # Deprecated starting from v2.4
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['contract', 'subject', 'tenant']],
            ['state', 'present', ['contract', 'subject', 'tenant']],
        ],
    )

    subject = module.params['subject']
    priority = module.params['priority']
    reverse_filter = module.params['reverse_filter']
    dscp = module.params['dscp']
    description = module.params['description']
    filter_name = module.params['filter']
    directive = module.params['directive']
    consumer_match = module.params['consumer_match']
    provider_match = module.params['provider_match']
    state = module.params['state']

    if directive is not None or filter_name is not None:
        module.fail_json(msg='Managing Contract Subjects to Filter bindings has been moved to M(aci_subject_bind_filter)')

    aci = ACIModule(module)
    aci.construct_url(root_class='tenant', subclass_1='contract', subclass_2='subject')
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='vzSubj',
            class_config=dict(
                name=subject,
                prio=priority,
                revFltPorts=reverse_filter,
                targetDscp=dscp,
                consMatchT=consumer_match,
                provMatchT=provider_match,
                descr=description,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='vzSubj')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #45
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        filter=dict(type='str', required=False, aliases=['name', 'filter_name']),  # Not required for querying all objects
        tenant=dict(type='str', required=False, aliases=['tenant_name']),  # Not required for querying all objects
        description=dict(type='str', aliases=['descr']),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[['state', 'absent', ['filter', 'tenant']],
                     ['state', 'present', ['filter', 'tenant']]]
    )

    filter_name = module.params['filter']
    description = module.params['description']
    state = module.params['state']

    aci = ACIModule(module)
    aci.construct_url(root_class="tenant", subclass_1="filter")
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='vzFilter',
            class_config=dict(name=filter_name, descr=description)
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='vzFilter')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #46
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        path=dict(type='str', required=True, aliases=['uri']),
        method=dict(type='str',
                    default='get',
                    choices=['delete', 'get', 'post'],
                    aliases=['action']),
        src=dict(type='path', aliases=['config_file']),
        content=dict(type='raw'),
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        mutually_exclusive=[['content', 'src']],
    )

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

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

    # Report missing file
    file_exists = False
    if src:
        if os.path.isfile(src):
            file_exists = True
        else:
            module.fail_json(msg="Cannot find/access src '%s'" % src)

    # Find request type
    if path.find('.xml') != -1:
        rest_type = 'xml'
        if not HAS_LXML_ETREE:
            module.fail_json(
                msg=
                'The lxml python library is missing, or lacks etree support.')
        if not HAS_XMLJSON_COBRA:
            module.fail_json(
                msg=
                'The xmljson python library is missing, or lacks cobra support.'
            )
    elif path.find('.json') != -1:
        rest_type = 'json'
    else:
        module.fail_json(
            msg='Failed to find REST API content type (neither .xml nor .json).'
        )

    aci = ACIModule(module)

    # We include the payload as it may be templated
    payload = content
    if file_exists:
        with open(src, 'r') as config_object:
            # TODO: Would be nice to template this, requires action-plugin
            payload = config_object.read()

    # Validate content
    if rest_type == 'json':
        if content and isinstance(content, dict):
            # Validate inline YAML/JSON
            payload = json.dumps(payload)
        elif payload and isinstance(payload, str) and HAS_YAML:
            try:
                # Validate YAML/JSON string
                payload = json.dumps(yaml.safe_load(payload))
            except Exception as e:
                module.fail_json(
                    msg='Failed to parse provided JSON/YAML content: %s' %
                    to_text(e),
                    exception=to_text(e),
                    payload=payload)
    elif rest_type == 'xml' and HAS_LXML_ETREE:
        if content and isinstance(content, dict) and HAS_XMLJSON_COBRA:
            # Validate inline YAML/JSON
            # FIXME: Converting from a dictionary to XML is unsupported at this time
            # payload = etree.tostring(payload)
            pass
        elif payload and isinstance(payload, str):
            try:
                # Validate XML string
                payload = lxml.etree.tostring(lxml.etree.fromstring(payload))
            except Exception as e:
                module.fail_json(
                    msg='Failed to parse provided XML content: %s' %
                    to_text(e),
                    payload=payload)

    # Perform actual request using auth cookie (Same as aci_request,but also supports XML)
    url = '%(protocol)s://%(hostname)s/' % aci.params + path.lstrip('/')
    if method != 'get':
        url = update_qsl(url, {'rsp-subtree': 'modified'})
    aci.result['url'] = url

    resp, info = fetch_url(module,
                           url,
                           data=payload,
                           method=method.upper(),
                           timeout=timeout,
                           headers=aci.headers)
    aci.result['response'] = info['msg']
    aci.result['status'] = info['status']

    # Report failure
    if info['status'] != 200:
        try:
            aci_response(aci.result, info['body'], rest_type)
            module.fail_json(
                msg='Request failed: %(error_code)s %(error_text)s' %
                aci.result,
                payload=payload,
                **aci.result)
        except KeyError:
            module.fail_json(msg='Request failed for %(url)s. %(msg)s' % info,
                             payload=payload,
                             **aci.result)

    aci_response(aci.result, resp.read(), rest_type)

    # Report success
    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        contract=dict(type='str', aliases=['contract_name']),
        filter_name=dict(type='str'),
        log=dict(tyep='str', choices=['log', 'none'], aliases=['directive']),
        subject=dict(type='str', aliases=['subject_name']),
        tenant=dict(type='str', aliases=['tenant_name']),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[['state', 'absent', ['contract', 'filter_name', 'subject', 'tenant']],
                     ['state', 'present', ['contract', 'filter_name', 'subject', 'tenant']]]
    )

    # contract = module.params['contract']
    filter_name = module.params['filter_name']
    log = module.params['log']
    # subject = module.params['subject']
    # tenant = module.params['tenant']
    state = module.params['state']

    # Convert log to empty string if none, as that is what API expects. An empty string is not a good option to present the user.
    if log == 'none':
        log = ''

    # TODO: cleanup this logic and provide better filter_strings for all options
    if filter_name is not None:
        # Work with specific binding
        path = 'api/mo/uni/tn-%(tenant)s/brc-%(contract)s/subj-%(subject)s/rssubjFiltAtt-%(filter_name)s.json' % module.params
    else:
        path = 'api/class/vzRsSubjFiltAtt.json'

    aci = ACIModule(module)

    aci.result['url'] = '%(protocol)s://%(hostname)s/' % aci.params + path

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(aci_class='vzRsSubjFiltAtt', class_config=dict(tnVzFilterName=filter_name, directives=log))

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='vzRsSubjFiltAtt')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #48
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        lldp_policy=dict(type='str', require=False, aliases=['name']),
        description=dict(type='str', aliases=['descr']),
        receive_state=dict(type='str', choices=['disabled', 'enabled']),
        transmit_state=dict(type='str', choices=['disabled', 'enabled']),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

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

    lldp_policy = module.params['lldp_policy']
    description = module.params['description']
    receive_state = module.params['receive_state']
    transmit_state = module.params['transmit_state']
    state = module.params['state']

    aci = ACIModule(module)

    if lldp_policy is not None:
        # Work with a specific object
        path = 'api/mo/uni/infra/lldpIfP-%(lldp_policy)s.json' % module.params
    elif state == 'query':
        # Query all objects
        path = 'api/node/class/lldpIfPol.json'
    else:
        module.fail_json(
            msg=
            "Parameter 'lldp_policy' is required for state 'absent' or 'present'"
        )

    aci.result['url'] = '%(protocol)s://%(hostname)s/' % aci.params + path

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(aci_class='lldpIfPol',
                    class_config=dict(name=lldp_policy,
                                      descr=description,
                                      adminRxSt=receive_state,
                                      adminTxSt=transmit_state))

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='lldpIfPol')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        monitoring_policy=dict(type='str', required=False, aliases=['name']),  # Not required for querying all objects
        tenant=dict(type='str', required=False, aliases=['tenant_name']),  # Not required for querying all objects
        description=dict(type='str', aliases=['descr']),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['monitoring_policy', 'tenant']],
            ['state', 'present', ['monitoring_policy', 'tenant']],
        ],
    )

    monitoring_policy = module.params['monitoring_policy']
    description = module.params['description']
    state = module.params['state']
    tenant = module.params['tenant']

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='fvTenant',
            aci_rn='tn-{}'.format(tenant),
            filter_target='eq(fvTenant.name, "{}")'.format(tenant),
            module_object=tenant,
        ),
        subclass_1=dict(
            aci_class='monEPGPol',
            aci_rn='monepg-{}'.format(monitoring_policy),
            filter_target='eq(monEPGPol.name, "{}")'.format(monitoring_policy),
            module_object=monitoring_policy,
        ),
    )

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='monEPGPol',
            class_config=dict(
                name=monitoring_policy,
                descr=description,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='monEPGPol')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        contract=dict(type='str', aliases=['contract_name']),
        subject=dict(type='str',
                     aliases=['contract_subject', 'name', 'subject_name']),
        tenant=dict(type='str', aliases=['tenant_name']),
        priority=dict(type='str',
                      choices=['unspecified', 'level1', 'level2', 'level3']),
        reverse_filter=dict(type='str', choices=['yes', 'no']),
        dscp=dict(type='str', aliases=['target']),
        description=dict(type='str', aliases=['descr']),
        consumer_match=dict(
            type='str', choices=['all', 'at_least_one', 'at_most_one',
                                 'none']),
        provider_match=dict(
            type='str', choices=['all', 'at_least_one', 'at_most_one',
                                 'none']),
        state=dict(type='str',
                   default='present',
                   choices=['absent', 'present', 'query']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
        directive=dict(
            type='str',
            removed_in_version='2.4'),  # Deprecated starting from v2.4
        filter=dict(type='str',
                    aliases=['filter_name'],
                    removed_in_version='2.4'),  # Deprecated starting from v2.4
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['contract', 'subject', 'tenant']],
            ['state', 'present', ['contract', 'subject', 'tenant']],
        ],
    )

    subject = module.params['subject']
    priority = module.params['priority']
    reverse_filter = module.params['reverse_filter']
    dscp = module.params['dscp']
    description = module.params['description']
    filter_name = module.params['filter']
    directive = module.params['directive']
    consumer_match = module.params['consumer_match']
    provider_match = module.params['provider_match']
    state = module.params['state']

    if directive is not None or filter_name is not None:
        module.fail_json(
            msg=
            'Managing Contract Subjects to Filter bindings has been moved to M(aci_subject_bind_filter)'
        )

    aci = ACIModule(module)
    aci.construct_url(root_class='tenant',
                      subclass_1='contract',
                      subclass_2='subject')
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='vzSubj',
            class_config=dict(
                name=subject,
                prio=priority,
                revFltPorts=reverse_filter,
                targetDscp=dscp,
                consMatchT=consumer_match,
                provMatchT=provider_match,
                descr=description,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='vzSubj')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #51
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        arp_flooding=dict(choices=['no', 'yes']),
        bd=dict(type='str', aliases=['bd_name', 'name']),
        bd_type=dict(type='str', choices=['ethernet', 'fc']),
        description=dict(type='str'),
        enable_multicast=dict(type='str', choices=['no', 'yes']),
        enable_routing=dict(type='str', choices=['no', 'yes']),
        endpoint_clear=dict(type='str', choices=['no', 'yes']),
        endpoint_move_detect=dict(type='str', choices=['default', 'garp']),
        endpoint_retention_action=dict(type='str', choices=['inherit', 'resolve']),
        endpoint_retention_policy=dict(type='str'),
        igmp_snoop_policy=dict(type='str'),
        ip_learning=dict(type='str', choices=['no', 'yes']),
        ipv6_nd_policy=dict(type='str'),
        l2_unknown_unicast=dict(choices=['proxy', 'flood']),
        l3_unknown_multicast=dict(choices=['flood', 'opt-flood']),
        limit_ip_learn=dict(type='str', choices=['no', 'yes']),
        multi_dest=dict(choices=['bd-flood', 'drop', 'encap-flood']),
        state=dict(choices=['absent', 'present', 'query'], type='str', default='present'),
        tenant=dict(type='str', aliases=['tenant_name']),
        vrf=dict(type='str', aliases=['vrf_name']),
        gateway_ip=dict(type='str', removed_in_version='2.4'),  # Deprecated starting from v2.4
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
        scope=dict(type='str', removed_in_version='2.4'),  # Deprecated starting from v2.4
        subnet_mask=dict(type='str', removed_in_version='2.4'),  # Deprecated starting from v2.4
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['bd', 'tenant']],
            ['state', 'present', ['bd', 'tenant']],
        ],
    )

    arp_flooding = module.params['arp_flooding']
    bd = module.params['bd']
    bd_type = module.params['bd_type']
    if bd_type == 'ethernet':
        # ethernet type is represented as regular, but that is not clear to the users
        bd_type = 'regular'
    description = module.params['description']
    enable_multicast = module.params['enable_multicast']
    enable_routing = module.params['enable_routing']
    endpoint_clear = module.params['endpoint_clear']
    endpoint_move_detect = module.params['endpoint_move_detect']
    if endpoint_move_detect == 'default':
        # the ACI default setting is an empty string, but that is not a good input value
        endpoint_move_detect = ''
    endpoint_retention_action = module.params['endpoint_retention_action']
    endpoint_retention_policy = module.params['endpoint_retention_policy']
    igmp_snoop_policy = module.params['igmp_snoop_policy']
    ip_learning = module.params['ip_learning']
    ipv6_nd_policy = module.params['ipv6_nd_policy']
    l2_unknown_unicast = module.params['l2_unknown_unicast']
    l3_unknown_multicast = module.params['l3_unknown_multicast']
    limit_ip_learn = module.params['limit_ip_learn']
    multi_dest = module.params['multi_dest']
    state = module.params['state']
    vrf = module.params['vrf']

    # Give warning when fvSubnet parameters are passed as those have been moved to the aci_subnet module
    if module.params['gateway_ip'] or module.params['subnet_mask'] or module.params['scope']:
        module._warnings = ["The support for managing Subnets has been moved to its own module, aci_subnet. \
                            The new modules still supports 'gateway_ip' and 'subnet_mask' along with more features"]

    aci = ACIModule(module)
    aci.construct_url(root_class="tenant", subclass_1="bd", child_classes=['fvRsCtx', 'fvRsIgmpsn', 'fvRsBDToNdP', 'fvRsBdToEpRet'])
    aci.get_existing()

    if state == 'present':
        # Filter out module params with null values
        aci.payload(
            aci_class='fvBD',
            class_config=dict(
                arpFlood=arp_flooding,
                descr=description,
                epClear=endpoint_clear,
                epMoveDetectMode=endpoint_move_detect,
                ipLearning=ip_learning,
                limitIpLearnToSubnets=limit_ip_learn,
                mcastAllow=enable_multicast,
                multiDstPktAct=multi_dest,
                name=bd,
                type=bd_type,
                unicastRoute=enable_routing,
                unkMacUcastAct=l2_unknown_unicast,
                unkMcastAct=l3_unknown_multicast,
            ),
            child_configs=[
                {'fvRsCtx': {'attributes': {'tnFvCtxName': vrf}}},
                {'fvRsIgmpsn': {'attributes': {'tnIgmpSnoopPolName': igmp_snoop_policy}}},
                {'fvRsBDToNdP': {'attributes': {'tnNdIfPolName': ipv6_nd_policy}}},
                {'fvRsBdToEpRet': {'attributes': {'resolveAct': endpoint_retention_action, 'tnFvEpRetPolName': endpoint_retention_policy}}},
            ],
        )

        # generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvBD')

        # submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #52
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        description=dict(type='str', aliases=['descr']),
        method=dict(type='str',
                    choices=['delete', 'get', 'post'],
                    aliases=['action'],
                    removed_in_version='2.6'),  # Deprecated starting from v2.6
        policy_control_direction=dict(choices=['ingress', 'egress'],
                                      type='str'),
        policy_control_preference=dict(choices=['enforced', 'unenforced'],
                                       type='str'),
        state=dict(choices=['absent', 'present', 'query'],
                   type='str',
                   default='present'),
        tenant=dict(type='str', required=False,
                    aliases=['tenant_name'
                             ]),  # Not required for querying all objects
        vrf=dict(type='str',
                 required=False,
                 aliases=['context', 'name', 'vrf_name'
                          ]),  # Not required for querying all objects
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['state', 'absent', ['tenant', 'vrf']],
            ['state', 'present', ['tenant', 'vrf']],
        ],
    )

    description = module.params['description']
    policy_control_direction = module.params['policy_control_direction']
    policy_control_preference = module.params['policy_control_preference']
    state = module.params['state']
    tenant = module.params['tenant']
    vrf = module.params['vrf']

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='fvTenant',
            aci_rn='tn-{}'.format(tenant),
            filter_target='(fvTenant.name, "{}")'.format(tenant),
            module_object=tenant,
        ),
        subclass_1=dict(
            aci_class='fvCtx',
            aci_rn='ctx-{}'.format(vrf),
            filter_target='(fvCtx.name, "{}")'.format(vrf),
            module_object=vrf,
        ),
    )
    aci.get_existing()

    if state == 'present':
        # Filter out module params with null values
        aci.payload(
            aci_class='fvCtx',
            class_config=dict(
                descr=description,
                pcEnfDir=policy_control_direction,
                pcEnfPref=policy_control_preference,
                name=vrf,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvCtx')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        description=dict(type='str', aliases=['descr']),
        export_policy=dict(type='str', aliases=['name']),
        format=dict(type='str', choices=['json', 'xml']),
        include_secure=dict(type='str', choices=['no', 'yes']),
        max_count=dict(type='int'),
        snapshot=dict(type='str'),
        state=dict(type='str', choices=['absent', 'present', 'query'], default='present'),
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=False,
        required_if=[
            ['state', 'absent', ['export_policy', 'snapshot']],
            ['state', 'present', ['export_policy']],
        ],
    )

    description = module.params['description']
    export_policy = module.params['export_policy']
    file_format = module.params['format']
    include_secure = module.params['include_secure']
    max_count = module.params['max_count']
    if max_count is not None:
        if max_count in range(1, 11):
            max_count = str(max_count)
        else:
            module.fail_json(msg='The "max_count" must be a number between 1 and 10')
    snapshot = module.params['snapshot']
    if snapshot is not None and not snapshot.startswith('run-'):
        snapshot = 'run-' + snapshot
    state = module.params['state']

    aci = ACIModule(module)

    if state == 'present':
        aci.construct_url(
            root_class=dict(
                aci_class='configExportP',
                aci_rn='fabric/configexp-{}'.format(export_policy),
                filter_target='eq(configExportP.name, "{}")'.format(export_policy),
                module_object=export_policy,
            ),
        )

        aci.get_existing()

        # Filter out module params with null values
        aci.payload(
            aci_class='configExportP',
            class_config=dict(
                adminSt='triggered',
                descr=description,
                format=file_format,
                includeSecureFields=include_secure,
                maxSnapshotCount=max_count,
                name=export_policy,
                snapshot='yes',
            ),
        )

        aci.get_diff('configExportP')

        # Create a new Snapshot
        aci.post_config()

    else:
        # Prefix the proper url to export_policy
        if export_policy is not None:
            export_policy = 'uni/fabric/configexp-{}'.format(export_policy)

        aci.construct_url(
            root_class=dict(
                aci_class='configSnapshotCont',
                aci_rn='backupst/snapshots-[{}]'.format(export_policy),
                filter_target='(configSnapshotCont.name, "{}")'.format(export_policy),
                module_object=export_policy,
            ),
            subclass_1=dict(
                aci_class='configSnapshot',
                aci_rn='snapshot-{}'.format(snapshot),
                filter_target='(configSnapshot.name, "{}")'.format(snapshot),
                module_object=snapshot,
            ),
        )

        aci.get_existing()

        if state == 'absent':
            # Build POST request to used to remove Snapshot
            aci.payload(
                aci_class='configSnapshot',
                class_config=dict(
                    name=snapshot,
                    retire="yes",
                ),
            )

            if aci.result['existing']:
                aci.get_diff('configSnapshot')

                # Mark Snapshot for Deletion
                aci.post_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        allow_useg=dict(type='str', choices=['encap', 'useg']),
        ap=dict(type='str', aliases=['app_profile', 'app_profile_name']),
        deploy_immediacy=dict(type='str', choices=['immediate', 'on-demand']),
        domain=dict(type='str', aliases=['domain_name', 'domain_profile']),
        domain_type=dict(type='str', choices=['phys', 'vmm'], aliases=['type']),
        encap=dict(type='int'),
        encap_mode=dict(type='str', choices=['auto', 'vlan', 'vxlan']),
        epg=dict(type='str', aliases=['name', 'epg_name']),
        netflow=dict(type='str', choices=['disabled', 'enabled']),
        primary_encap=dict(type='int'),
        resolution_immediacy=dict(type='str', choices=['immediate', 'lazy', 'pre-provision']),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        tenant=dict(type='str', aliases=['tenant_name']),
        vm_provider=dict(type='str', choices=['microsoft', 'openstack', 'vmware']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6'),  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[
            ['domain_type', 'vmm', ['vm_provider']],
            ['state', 'absent', ['ap', 'domain', 'domain_type', 'epg', 'tenant']],
            ['state', 'present', ['ap', 'domain', 'domain_type', 'epg', 'tenant']],
        ],
    )

    allow_useg = module.params['allow_useg']
    ap = module.params['ap']
    deploy_immediacy = module.params['deploy_immediacy']
    domain = module.params['domain']
    domain_type = module.params['domain_type']
    vm_provider = module.params['vm_provider']
    encap = module.params['encap']
    if encap is not None:
        if encap in range(1, 4097):
            encap = 'vlan-{}'.format(encap)
        else:
            module.fail_json(msg='Valid VLAN assigments are from 1 to 4096')
    encap_mode = module.params['encap_mode']
    epg = module.params['epg']
    netflow = module.params['netflow']
    primary_encap = module.params['primary_encap']
    if primary_encap is not None:
        if primary_encap in range(1, 4097):
            primary_encap = 'vlan-{}'.format(primary_encap)
        else:
            module.fail_json(msg='Valid VLAN assigments are from 1 to 4096')
    resolution_immediacy = module.params['resolution_immediacy']
    state = module.params['state']
    tenant = module.params['tenant']

    if domain_type == 'phys' and vm_provider is not None:
        module.fail_json(msg="Domain type 'phys' cannot have a 'vm_provider'")

    # Compile the full domain for URL building
    if domain_type == 'vmm':
        epg_domain = '{}{}'.format(VM_PROVIDER_MAPPING[vm_provider], domain)
    elif domain_type is not None:
        epg_domain = 'uni/phys-{}'.format(domain)
    else:
        epg_domain = None

    aci = ACIModule(module)
    aci.construct_url(
        root_class=dict(
            aci_class='fvTenant',
            aci_rn='tn-{}'.format(tenant),
            filter_target='eq(fvTenant.name, "{}")'.format(tenant),
            module_object=tenant,
        ),
        subclass_1=dict(
            aci_class='fvAp',
            aci_rn='ap-{}'.format(ap),
            filter_target='eq(fvAp.name, "{}")'.format(ap),
            module_object=ap,
        ),
        subclass_2=dict(
            aci_class='fvAEPg',
            aci_rn='epg-{}'.format(epg),
            filter_target='eq(fvTenant.name, "{}")'.format(epg),
            module_object=epg,
        ),
        subclass_3=dict(
            aci_class='fvRsDomAtt',
            aci_rn='rsdomAtt-[{}]'.format(epg_domain),
            filter_target='eq(fvRsDomAtt.tDn, "{}")'.format(epg_domain),
            module_object=epg_domain,
        ),
    )

    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='fvRsDomAtt',
            class_config=dict(
                classPref=allow_useg,
                encap=encap,
                encapMode=encap_mode,
                instrImedcy=deploy_immediacy,
                netflowPref=netflow,
                primaryEncap=primary_encap,
                resImedcy=resolution_immediacy,
            ),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvRsDomAtt')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        lldp_policy=dict(type='str', require=False, aliases=['name']),
        description=dict(type='str', aliases=['descr']),
        receive_state=dict(type='str', choices=['disabled', 'enabled']),
        transmit_state=dict(type='str', choices=['disabled', 'enabled']),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6')  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_if=[['state', 'absent', ['lldp_policy']],
                     ['state', 'present', ['lldp_policy']]]
    )

    lldp_policy = module.params['lldp_policy']
    description = module.params['description']
    receive_state = module.params['receive_state']
    transmit_state = module.params['transmit_state']
    state = module.params['state']

    aci = ACIModule(module)
    aci.construct_url(root_class='lldp_policy')
    aci.get_existing()

    if state == 'present':
        # Filter out module parameters with null values
        aci.payload(
            aci_class='lldpIfPol',
            class_config=dict(name=lldp_policy, descr=description, adminRxSt=receive_state, adminTxSt=transmit_state)
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='lldpIfPol')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    module.exit_json(**aci.result)
Exemple #56
0
def main():
    argument_spec = aci_argument_spec
    argument_spec.update(
        bd=dict(type='str', aliases=['bd_name', 'bridge_domain']),
        l3out=dict(type='str'),
        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
        tenant=dict(type='str', aliases=['tenant_name']),
        method=dict(type='str', choices=['delete', 'get', 'post'], aliases=['action'], removed_in_version='2.6')  # Deprecated starting from v2.6
    )

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
        required_together=[['gateway', 'mask']],
        required_if=[
            ['state', 'present', ['bd', 'l3out', 'tenant']],
            ['state', 'absent', ['bd', 'l3out', 'tenant']],
        ],
    )

    l3out = module.params['l3out']
    state = module.params['state']

    # Add bd_l3out key to module.params for building the URL
    module.params['bd_l3out'] = l3out

    aci = ACIModule(module)
    aci.construct_url(root_class='tenant', subclass_1='bd', subclass_2='bd_l3out')
    aci.get_existing()

    if state == 'present':
        # Filter out module params with null values
        aci.payload(
            aci_class='fvRsBDToOut',
            class_config=dict(tnL3extOutName=l3out),
        )

        # Generate config diff which will be used as POST request body
        aci.get_diff(aci_class='fvRsBDToOut')

        # Submit changes if module not in check_mode and the proposed is different than existing
        aci.post_config()

    elif state == 'absent':
        aci.delete_config()

    # Remove bd_l3out key used for URL building from module.params
    module.params.pop('bd_l3out')

    module.exit_json(**aci.result)