def main(): argument_spec = aci_argument_spec() argument_spec.update( tenant=dict(type='str', aliases=['tenant_name' ]), # Not required for querying all objects ap=dict(type='str', aliases=['app_profile', 'app_profile_name' ]), # Not required for querying all objects epg=dict(type='str', aliases=['epg_name' ]), # Not required for querying all objects description=dict(type='str', aliases=['descr']), encap_id=dict(type='int', aliases=['vlan', 'vlan_id']), primary_encap_id=dict(type='str', aliases=['primary_vlan', 'primary_vlan_id']), deploy_immediacy=dict(type='str', choices=['immediate', 'lazy']), interface_mode=dict(type='str', choices=[ '802.1p', 'access', 'native', 'regular', 'tagged', 'trunk', 'untagged' ], aliases=['interface_mode_name', 'mode']), interface_type=dict(type='str', default='switch_port', choices=[ 'fex', 'port_channel', 'switch_port', 'vpc', 'fex_port_channel', 'fex_vpc' ]), pod_id=dict(type='int', aliases=['pod', 'pod_number' ]), # Not required for querying all objects leafs=dict(type='list', elements='str', aliases=['leaves', 'nodes', 'paths', 'switches' ]), # Not required for querying all objects interface=dict(type='str'), # Not required for querying all objects extpaths=dict(type='list', elements='str'), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, required_if=[ ['interface_type', 'fex', ['extpaths']], ['interface_type', 'fex_vpc', ['extpaths']], ['interface_type', 'fex_port_channel', ['extpaths']], [ 'state', 'absent', ['ap', 'epg', 'interface', 'leafs', 'pod_id', 'tenant'] ], [ 'state', 'present', [ 'ap', 'encap_id', 'epg', 'interface', 'leafs', 'pod_id', 'tenant' ] ], ], ) tenant = module.params.get('tenant') ap = module.params.get('ap') epg = module.params.get('epg') description = module.params.get('description') encap_id = module.params.get('encap_id') primary_encap_id = module.params.get('primary_encap_id') deploy_immediacy = module.params.get('deploy_immediacy') interface_mode = module.params.get('interface_mode') interface_type = module.params.get('interface_type') pod_id = module.params.get('pod_id') leafs = module.params.get('leafs') interface = module.params.get('interface') extpaths = module.params.get('extpaths') state = module.params.get('state') aci = ACIModule(module) if leafs is not None: # Process leafs, and support dash-delimited leafs leafs = [] for leaf in module.params.get('leafs'): # Users are likely to use integers for leaf IDs, which would raise an exception when using the join method leafs.extend(str(leaf).split('-')) if len(leafs) == 1: if interface_type in ['vpc', 'fex_vpc']: aci.fail_json(msg='A interface_type of "vpc" requires 2 leafs') leafs = leafs[0] elif len(leafs) == 2: if interface_type not in ['vpc', 'fex_vpc']: aci.fail_json( msg= 'The interface_types "switch_port", "port_channel", and "fex" \ do not support using multiple leafs for a single binding') leafs = "-".join(leafs) else: aci.fail_json( msg='The "leafs" parameter must not have more than 2 entries') if extpaths is not None: # Process extpaths, and support dash-delimited extpaths extpaths = [] for extpath in module.params.get('extpaths'): # Users are likely to use integers for extpaths IDs, which would raise an exception when using the join method extpaths.extend(str(extpath).split('-')) if len(extpaths) == 1: if interface_type == 'fex_vpc': aci.fail_json( msg='A interface_type of "fex_vpc" requires 2 extpaths') extpaths = extpaths[0] elif len(extpaths) == 2: if interface_type != 'fex_vpc': aci.fail_json(msg='The interface_types "fex" \ and "fex_port_channel" do not support using multiple extpaths for a single binding' ) extpaths = "-".join(extpaths) else: aci.fail_json( msg='The "extpaths" parameter must not have more than 2 entries' ) if encap_id is not None: if encap_id not in range(1, 4097): aci.fail_json(msg='Valid VLAN assignments are from 1 to 4096') encap_id = 'vlan-{0}'.format(encap_id) if primary_encap_id is not None: try: primary_encap_id = int(primary_encap_id) if isinstance(primary_encap_id, int) and primary_encap_id in range( 1, 4097): primary_encap_id = 'vlan-{0}'.format(primary_encap_id) else: aci.fail_json( msg='Valid VLAN assignments are from 1 to 4096 or unknown.' ) except Exception as e: if isinstance(primary_encap_id, str) and primary_encap_id != 'unknown': aci.fail_json( msg= 'Valid VLAN assignments are from 1 to 4096 or unknown. %s' % e) static_path = INTERFACE_TYPE_MAPPING[interface_type].format( pod_id=pod_id, leafs=leafs, extpaths=extpaths, interface=interface) path_target_filter = {} if pod_id is not None and leafs is not None and interface is not None and ( interface_type != 'fex' or extpaths is not None): path_target_filter = {'tDn': static_path} if interface_mode is not None: interface_mode = INTERFACE_MODE_MAPPING[interface_mode] aci.construct_url( root_class=dict( aci_class='fvTenant', aci_rn='tn-{0}'.format(tenant), module_object=tenant, target_filter={'name': tenant}, ), subclass_1=dict( aci_class='fvAp', aci_rn='ap-{0}'.format(ap), module_object=ap, target_filter={'name': ap}, ), subclass_2=dict( aci_class='fvAEPg', aci_rn='epg-{0}'.format(epg), module_object=epg, target_filter={'name': epg}, ), subclass_3=dict( aci_class='fvRsPathAtt', aci_rn='rspathAtt-[{0}]'.format(static_path), module_object=static_path, target_filter=path_target_filter, ), ) aci.get_existing() if state == 'present': aci.payload( aci_class='fvRsPathAtt', class_config=dict( descr=description, encap=encap_id, primaryEncap=primary_encap_id, instrImedcy=deploy_immediacy, mode=interface_mode, tDn=static_path, ), ) aci.get_diff(aci_class='fvRsPathAtt') aci.post_config() elif state == 'absent': aci.delete_config() aci.exit_json()
def main(): argument_spec = aci_argument_spec() argument_spec.update( tenant=dict(type='str', aliases=['tenant_name' ]), # Not required for querying all objects l3out=dict(type='str', aliases=['l3out_name', 'name']), # Not required for querying all objects domain=dict(type='str', aliases=['ext_routed_domain_name', 'routed_domain']), vrf=dict(type='str', aliases=['vrf_name']), description=dict(type='str', aliases=['descr']), route_control=dict(type='list', choices=['export', 'import'], aliases=['route_control_enforcement']), 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']), l3protocol=dict(type='list', choices=['bgp', 'eigrp', 'ospf', 'pim', 'static']), asn=dict(type='int', aliases=['as_number']), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), name_alias=dict(type='str'), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, required_if=[ ['state', 'absent', ['l3out', 'tenant']], ['state', 'present', ['l3out', 'tenant', 'domain', 'vrf']], ], ) aci = ACIModule(module) l3out = module.params.get('l3out') domain = module.params.get('domain') dscp = module.params.get('dscp') description = module.params.get('description') enforceRtctrl = module.params.get('route_control') vrf = module.params.get('vrf') l3protocol = module.params.get('l3protocol') asn = module.params.get('asn') state = module.params.get('state') tenant = module.params.get('tenant') name_alias = module.params.get('name_alias') if l3protocol: if 'eigrp' in l3protocol and asn is None: module.fail_json( msg="Parameter 'asn' is required when l3protocol is 'eigrp'") if 'eigrp' not in l3protocol and asn is not None: module.warn( "Parameter 'asn' is only applicable when l3protocol is 'eigrp'. The ASN will be ignored" ) enforce_ctrl = '' if enforceRtctrl is not None: if len(enforceRtctrl) == 1 and enforceRtctrl[0] == 'import': aci.fail_json( "The route_control parameter is invalid: allowed options are export or import,export only" ) elif len(enforceRtctrl) == 1 and enforceRtctrl[0] == 'export': enforce_ctrl = 'export' else: enforce_ctrl = 'export,import' child_classes = [ 'l3extRsL3DomAtt', 'l3extRsEctx', 'bgpExtP', 'ospfExtP', 'eigrpExtP', 'pimExtP' ] aci.construct_url( root_class=dict( aci_class='fvTenant', aci_rn='tn-{0}'.format(tenant), module_object=tenant, target_filter={'name': tenant}, ), subclass_1=dict( aci_class='l3extOut', aci_rn='out-{0}'.format(l3out), module_object=l3out, target_filter={'name': l3out}, ), child_classes=child_classes, ) aci.get_existing() child_configs = [ dict(l3extRsL3DomAtt=dict(attributes=dict( tDn='uni/l3dom-{0}'.format(domain)))), dict(l3extRsEctx=dict(attributes=dict(tnFvCtxName=vrf))), ] if l3protocol is not None: for protocol in l3protocol: if protocol == 'bgp': child_configs.append( dict(bgpExtP=dict( attributes=dict(descr='', nameAlias='')))) elif protocol == 'eigrp': child_configs.append( dict(eigrpExtP=dict( attributes=dict(descr='', nameAlias='', asn=asn)))) elif protocol == 'ospf': child_configs.append( dict(ospfExtP=dict( attributes=dict(descr='', nameAlias='')))) elif protocol == 'pim': child_configs.append( dict(pimExtP=dict( attributes=dict(descr='', nameAlias='')))) if state == 'present': aci.payload( aci_class='l3extOut', class_config=dict( name=l3out, descr=description, dn='uni/tn-{0}/out-{1}'.format(tenant, l3out), enforceRtctrl=enforce_ctrl, targetDscp=dscp, nameAlias=name_alias, ), child_configs=child_configs, ) aci.get_diff(aci_class='l3extOut') aci.post_config() elif state == 'absent': aci.delete_config() aci.exit_json()
def main(): argument_spec = aci_argument_spec() argument_spec.update(aci_annotation_spec()) argument_spec.update(aci_owner_spec()) argument_spec.update( # NOTE: Since this module needs to include both infra:AccBndlGrp (for PC and VPC) and infra:AccPortGrp (for leaf access port policy group): # NOTE: I'll allow the user to make the choice here (link(PC), node(VPC), leaf(leaf-access port policy group)) lag_type=dict(type="str", required=True, aliases=["lag_type_name"], choices=["leaf", "link", "node"]), policy_group=dict(type="str", aliases=["name", "policy_group_name"]), # Not required for querying all objects description=dict(type="str", aliases=["descr"]), link_level_policy=dict(type="str", aliases=["link_level_policy_name"]), cdp_policy=dict(type="str", aliases=["cdp_policy_name"]), mcp_policy=dict(type="str", aliases=["mcp_policy_name"]), lldp_policy=dict(type="str", aliases=["lldp_policy_name"]), stp_interface_policy=dict(type="str", aliases=["stp_interface_policy_name"]), egress_data_plane_policing_policy=dict(type="str", aliases=["egress_data_plane_policing_policy_name"]), ingress_data_plane_policing_policy=dict(type="str", aliases=["ingress_data_plane_policing_policy_name"]), priority_flow_control_policy=dict(type="str", aliases=["priority_flow_control_policy_name"]), fibre_channel_interface_policy=dict(type="str", aliases=["fibre_channel_interface_policy_name"]), slow_drain_policy=dict(type="str", aliases=["slow_drain_policy_name"]), port_channel_policy=dict(type="str", aliases=["port_channel_policy_name"]), monitoring_policy=dict(type="str", aliases=["monitoring_policy_name"]), storm_control_interface_policy=dict(type="str", aliases=["storm_control_interface_policy_name"]), l2_interface_policy=dict(type="str", aliases=["l2_interface_policy_name"]), port_security_policy=dict(type="str", aliases=["port_security_policy_name"]), aep=dict(type="str", aliases=["aep_name"]), state=dict(type="str", default="present", choices=["absent", "present", "query"]), name_alias=dict(type="str"), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, required_if=[ ["state", "absent", ["policy_group"]], ["state", "present", ["policy_group"]], ], ) policy_group = module.params.get("policy_group") description = module.params.get("description") lag_type = module.params.get("lag_type") link_level_policy = module.params.get("link_level_policy") cdp_policy = module.params.get("cdp_policy") mcp_policy = module.params.get("mcp_policy") lldp_policy = module.params.get("lldp_policy") stp_interface_policy = module.params.get("stp_interface_policy") egress_data_plane_policing_policy = module.params.get("egress_data_plane_policing_policy") ingress_data_plane_policing_policy = module.params.get("ingress_data_plane_policing_policy") priority_flow_control_policy = module.params.get("priority_flow_control_policy") fibre_channel_interface_policy = module.params.get("fibre_channel_interface_policy") slow_drain_policy = module.params.get("slow_drain_policy") port_channel_policy = module.params.get("port_channel_policy") monitoring_policy = module.params.get("monitoring_policy") storm_control_interface_policy = module.params.get("storm_control_interface_policy") l2_interface_policy = module.params.get("l2_interface_policy") port_security_policy = module.params.get("port_security_policy") aep = module.params.get("aep") state = module.params.get("state") name_alias = module.params.get("name_alias") aci = ACIModule(module) if lag_type == "leaf" and port_channel_policy is not None: aci.fail_json( "port_channel_policy is not a valid parameter for leaf\ (leaf access port policy group), if used\ assign null to it (port_channel_policy: null)." ) if lag_type == "leaf": aci_class_name = "infraAccPortGrp" dn_name = "accportgrp" class_config_dict = dict( name=policy_group, descr=description, nameAlias=name_alias, ) # Reset for target_filter lag_type = None elif lag_type in ("link", "node"): aci_class_name = "infraAccBndlGrp" dn_name = "accbundle" class_config_dict = dict( name=policy_group, descr=description, lagT=lag_type, nameAlias=name_alias, ) child_configs = [ dict( infraRsCdpIfPol=dict( attributes=dict( tnCdpIfPolName=cdp_policy, ), ), ), dict( infraRsFcIfPol=dict( attributes=dict( tnFcIfPolName=fibre_channel_interface_policy, ), ), ), dict( infraRsHIfPol=dict( attributes=dict( tnFabricHIfPolName=link_level_policy, ), ), ), dict( infraRsL2IfPol=dict( attributes=dict( tnL2IfPolName=l2_interface_policy, ), ), ), dict( infraRsL2PortSecurityPol=dict( attributes=dict( tnL2PortSecurityPolName=port_security_policy, ), ), ), dict( infraRsLacpPol=dict( attributes=dict( tnLacpLagPolName=port_channel_policy, ), ), ), dict( infraRsLldpIfPol=dict( attributes=dict( tnLldpIfPolName=lldp_policy, ), ), ), dict( infraRsMcpIfPol=dict( attributes=dict( tnMcpIfPolName=mcp_policy, ), ), ), dict( infraRsMonIfInfraPol=dict( attributes=dict( tnMonInfraPolName=monitoring_policy, ), ), ), dict( infraRsQosEgressDppIfPol=dict( attributes=dict( tnQosDppPolName=egress_data_plane_policing_policy, ), ), ), dict( infraRsQosIngressDppIfPol=dict( attributes=dict( tnQosDppPolName=ingress_data_plane_policing_policy, ), ), ), dict( infraRsQosPfcIfPol=dict( attributes=dict( tnQosPfcIfPolName=priority_flow_control_policy, ), ), ), dict( infraRsQosSdIfPol=dict( attributes=dict( tnQosSdIfPolName=slow_drain_policy, ), ), ), dict( infraRsStormctrlIfPol=dict( attributes=dict( tnStormctrlIfPolName=storm_control_interface_policy, ), ), ), dict( infraRsStpIfPol=dict( attributes=dict( tnStpIfPolName=stp_interface_policy, ), ), ), ] # Add infraRsattEntP binding only when aep was defined if aep is not None: child_configs.append( dict( infraRsAttEntP=dict( attributes=dict( tDn="uni/infra/attentp-{0}".format(aep), ), ), ) ) aci.construct_url( root_class=dict( aci_class=aci_class_name, aci_rn="infra/funcprof/{0}-{1}".format(dn_name, policy_group), module_object=policy_group, target_filter={"name": policy_group, "lagT": lag_type}, ), child_classes=[ "infraRsAttEntP", "infraRsCdpIfPol", "infraRsFcIfPol", "infraRsHIfPol", "infraRsL2IfPol", "infraRsL2PortSecurityPol", "infraRsLacpPol", "infraRsLldpIfPol", "infraRsMcpIfPol", "infraRsMonIfInfraPol", "infraRsQosEgressDppIfPol", "infraRsQosIngressDppIfPol", "infraRsQosPfcIfPol", "infraRsQosSdIfPol", "infraRsStormctrlIfPol", "infraRsStpIfPol", ], ) aci.get_existing() if state == "present": aci.payload( aci_class=aci_class_name, class_config=class_config_dict, child_configs=child_configs, ) aci.get_diff(aci_class=aci_class_name) aci.post_config() elif state == "absent": aci.delete_config() aci.exit_json()
def main(): argument_spec = aci_argument_spec() argument_spec.update( # NOTE: Since this module needs to include both infra:AccBndlGrp (for PC and VPC) and infra:AccPortGrp (for leaf access port policy group): # NOTE: I'll allow the user to make the choice here (link(PC), node(VPC), leaf(leaf-access port policy group)) lag_type=dict(type='str', required=True, aliases=['lag_type_name'], choices=['leaf', 'link', 'node']), policy_group=dict(type='str', aliases=['name', 'policy_group_name' ]), # Not required for querying all objects description=dict(type='str', aliases=['descr']), link_level_policy=dict(type='str', aliases=['link_level_policy_name']), cdp_policy=dict(type='str', aliases=['cdp_policy_name']), mcp_policy=dict(type='str', aliases=['mcp_policy_name']), lldp_policy=dict(type='str', aliases=['lldp_policy_name']), stp_interface_policy=dict(type='str', aliases=['stp_interface_policy_name']), egress_data_plane_policing_policy=dict( type='str', aliases=['egress_data_plane_policing_policy_name']), ingress_data_plane_policing_policy=dict( type='str', aliases=['ingress_data_plane_policing_policy_name']), priority_flow_control_policy=dict( type='str', aliases=['priority_flow_control_policy_name']), fibre_channel_interface_policy=dict( type='str', aliases=['fibre_channel_interface_policy_name']), slow_drain_policy=dict(type='str', aliases=['slow_drain_policy_name']), port_channel_policy=dict(type='str', aliases=['port_channel_policy_name']), monitoring_policy=dict(type='str', aliases=['monitoring_policy_name']), storm_control_interface_policy=dict( type='str', aliases=['storm_control_interface_policy_name']), l2_interface_policy=dict(type='str', aliases=['l2_interface_policy_name']), port_security_policy=dict(type='str', aliases=['port_security_policy_name']), aep=dict(type='str', aliases=['aep_name']), state=dict(type='str', default='present', choices=['absent', 'present', 'query']), name_alias=dict(type='str'), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, required_if=[ ['state', 'absent', ['policy_group']], ['state', 'present', ['policy_group']], ], ) policy_group = module.params.get('policy_group') description = module.params.get('description') lag_type = module.params.get('lag_type') link_level_policy = module.params.get('link_level_policy') cdp_policy = module.params.get('cdp_policy') mcp_policy = module.params.get('mcp_policy') lldp_policy = module.params.get('lldp_policy') stp_interface_policy = module.params.get('stp_interface_policy') egress_data_plane_policing_policy = module.params.get( 'egress_data_plane_policing_policy') ingress_data_plane_policing_policy = module.params.get( 'ingress_data_plane_policing_policy') priority_flow_control_policy = module.params.get( 'priority_flow_control_policy') fibre_channel_interface_policy = module.params.get( 'fibre_channel_interface_policy') slow_drain_policy = module.params.get('slow_drain_policy') port_channel_policy = module.params.get('port_channel_policy') monitoring_policy = module.params.get('monitoring_policy') storm_control_interface_policy = module.params.get( 'storm_control_interface_policy') l2_interface_policy = module.params.get('l2_interface_policy') port_security_policy = module.params.get('port_security_policy') aep = module.params.get('aep') state = module.params.get('state') name_alias = module.params.get('name_alias') aci = ACIModule(module) if lag_type == 'leaf' and port_channel_policy is not None: aci.fail_json('port_channel_policy is not a valid parameter for leaf\ (leaf access port policy group), if used\ assign null to it (port_channel_policy: null).') if lag_type == 'leaf': aci_class_name = 'infraAccPortGrp' dn_name = 'accportgrp' class_config_dict = dict( name=policy_group, descr=description, nameAlias=name_alias, ) # Reset for target_filter lag_type = None elif lag_type in ('link', 'node'): aci_class_name = 'infraAccBndlGrp' dn_name = 'accbundle' class_config_dict = dict( name=policy_group, descr=description, lagT=lag_type, nameAlias=name_alias, ) child_configs = [ dict(infraRsCdpIfPol=dict(attributes=dict( tnCdpIfPolName=cdp_policy, ), ), ), dict(infraRsFcIfPol=dict(attributes=dict( tnFcIfPolName=fibre_channel_interface_policy, ), ), ), dict(infraRsHIfPol=dict(attributes=dict( tnFabricHIfPolName=link_level_policy, ), ), ), dict(infraRsL2IfPol=dict(attributes=dict( tnL2IfPolName=l2_interface_policy, ), ), ), dict(infraRsL2PortSecurityPol=dict(attributes=dict( tnL2PortSecurityPolName=port_security_policy, ), ), ), dict(infraRsLacpPol=dict(attributes=dict( tnLacpLagPolName=port_channel_policy, ), ), ), dict(infraRsLldpIfPol=dict(attributes=dict( tnLldpIfPolName=lldp_policy, ), ), ), dict(infraRsMcpIfPol=dict(attributes=dict( tnMcpIfPolName=mcp_policy, ), ), ), dict(infraRsMonIfInfraPol=dict(attributes=dict( tnMonInfraPolName=monitoring_policy, ), ), ), dict(infraRsQosEgressDppIfPol=dict(attributes=dict( tnQosDppPolName=egress_data_plane_policing_policy, ), ), ), dict(infraRsQosIngressDppIfPol=dict(attributes=dict( tnQosDppPolName=ingress_data_plane_policing_policy, ), ), ), dict(infraRsQosPfcIfPol=dict(attributes=dict( tnQosPfcIfPolName=priority_flow_control_policy, ), ), ), dict(infraRsQosSdIfPol=dict(attributes=dict( tnQosSdIfPolName=slow_drain_policy, ), ), ), dict(infraRsStormctrlIfPol=dict(attributes=dict( tnStormctrlIfPolName=storm_control_interface_policy, ), ), ), dict(infraRsStpIfPol=dict(attributes=dict( tnStpIfPolName=stp_interface_policy, ), ), ), ] # Add infraRsattEntP binding only when aep was defined if aep is not None: child_configs.append( dict(infraRsAttEntP=dict(attributes=dict( tDn='uni/infra/attentp-{0}'.format(aep), ), ), )) aci.construct_url( root_class=dict( aci_class=aci_class_name, aci_rn='infra/funcprof/{0}-{1}'.format(dn_name, policy_group), module_object=policy_group, target_filter={ 'name': policy_group, 'lagT': lag_type }, ), child_classes=[ 'infraRsAttEntP', 'infraRsCdpIfPol', 'infraRsFcIfPol', 'infraRsHIfPol', 'infraRsL2IfPol', 'infraRsL2PortSecurityPol', 'infraRsLacpPol', 'infraRsLldpIfPol', 'infraRsMcpIfPol', 'infraRsMonIfInfraPol', 'infraRsQosEgressDppIfPol', 'infraRsQosIngressDppIfPol', 'infraRsQosPfcIfPol', 'infraRsQosSdIfPol', 'infraRsStormctrlIfPol', 'infraRsStpIfPol', ], ) aci.get_existing() if state == 'present': aci.payload( aci_class=aci_class_name, class_config=class_config_dict, child_configs=child_configs, ) aci.get_diff(aci_class=aci_class_name) aci.post_config() elif state == 'absent': aci.delete_config() aci.exit_json()
def main(): argument_spec = aci_argument_spec() argument_spec.update(aci_annotation_spec()) argument_spec.update(aci_owner_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects l3out=dict(type="str", aliases=["l3out_name", "name"]), # Not required for querying all objects domain=dict(type="str", aliases=["ext_routed_domain_name", "routed_domain"]), vrf=dict(type="str", aliases=["vrf_name"]), description=dict(type="str", aliases=["descr"]), route_control=dict(type="list", elements="str", choices=["export", "import"], aliases=["route_control_enforcement"]), 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"], ), l3protocol=dict(type="list", elements="str", choices=["bgp", "eigrp", "ospf", "pim", "static"]), asn=dict(type="int", aliases=["as_number"]), state=dict(type="str", default="present", choices=["absent", "present", "query"]), name_alias=dict(type="str"), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, required_if=[ ["state", "absent", ["l3out", "tenant"]], ["state", "present", ["l3out", "tenant", "domain", "vrf"]], ], ) aci = ACIModule(module) l3out = module.params.get("l3out") domain = module.params.get("domain") dscp = module.params.get("dscp") description = module.params.get("description") enforceRtctrl = module.params.get("route_control") vrf = module.params.get("vrf") l3protocol = module.params.get("l3protocol") asn = module.params.get("asn") state = module.params.get("state") tenant = module.params.get("tenant") name_alias = module.params.get("name_alias") if l3protocol: if "eigrp" in l3protocol and asn is None: module.fail_json(msg="Parameter 'asn' is required when l3protocol is 'eigrp'") if "eigrp" not in l3protocol and asn is not None: module.warn("Parameter 'asn' is only applicable when l3protocol is 'eigrp'. The ASN will be ignored") enforce_ctrl = "" if enforceRtctrl is not None: if len(enforceRtctrl) == 1 and enforceRtctrl[0] == "import": aci.fail_json("The route_control parameter is invalid: allowed options are export or import,export only") elif len(enforceRtctrl) == 1 and enforceRtctrl[0] == "export": enforce_ctrl = "export" else: enforce_ctrl = "export,import" child_classes = ["l3extRsL3DomAtt", "l3extRsEctx", "bgpExtP", "ospfExtP", "eigrpExtP", "pimExtP"] aci.construct_url( root_class=dict( aci_class="fvTenant", aci_rn="tn-{0}".format(tenant), module_object=tenant, target_filter={"name": tenant}, ), subclass_1=dict( aci_class="l3extOut", aci_rn="out-{0}".format(l3out), module_object=l3out, target_filter={"name": l3out}, ), child_classes=child_classes, ) aci.get_existing() child_configs = [ dict(l3extRsL3DomAtt=dict(attributes=dict(tDn="uni/l3dom-{0}".format(domain)))), dict(l3extRsEctx=dict(attributes=dict(tnFvCtxName=vrf))), ] if l3protocol is not None: for protocol in l3protocol: if protocol == "bgp": child_configs.append(dict(bgpExtP=dict(attributes=dict(descr="", nameAlias="")))) elif protocol == "eigrp": child_configs.append(dict(eigrpExtP=dict(attributes=dict(descr="", nameAlias="", asn=asn)))) elif protocol == "ospf": child_configs.append(dict(ospfExtP=dict(attributes=dict(descr="", nameAlias="")))) elif protocol == "pim": child_configs.append(dict(pimExtP=dict(attributes=dict(descr="", nameAlias="")))) if state == "present": aci.payload( aci_class="l3extOut", class_config=dict( name=l3out, descr=description, dn="uni/tn-{0}/out-{1}".format(tenant, l3out), enforceRtctrl=enforce_ctrl, targetDscp=dscp, nameAlias=name_alias, ), child_configs=child_configs, ) aci.get_diff(aci_class="l3extOut") aci.post_config() elif state == "absent": aci.delete_config() aci.exit_json()
def main(): argument_spec = aci_argument_spec() argument_spec.update(aci_annotation_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name" ]), # Not required for querying all objects ap=dict(type="str", aliases=["app_profile", "app_profile_name" ]), # Not required for querying all objects epg=dict(type="str", aliases=["epg_name" ]), # Not required for querying all objects description=dict(type="str", aliases=["descr"]), encap_id=dict(type="int", aliases=["vlan", "vlan_id"]), primary_encap_id=dict(type="str", aliases=["primary_vlan", "primary_vlan_id"]), deploy_immediacy=dict(type="str", choices=["immediate", "lazy"]), interface_mode=dict(type="str", choices=[ "802.1p", "access", "native", "regular", "tagged", "trunk", "untagged" ], aliases=["interface_mode_name", "mode"]), interface_type=dict(type="str", default="switch_port", choices=[ "fex", "port_channel", "switch_port", "vpc", "fex_port_channel", "fex_vpc" ]), pod_id=dict(type="int", aliases=["pod", "pod_number" ]), # Not required for querying all objects leafs=dict(type="list", elements="str", aliases=["leaves", "nodes", "paths", "switches" ]), # Not required for querying all objects interface=dict(type="str"), # Not required for querying all objects extpaths=dict(type="list", elements="str"), state=dict(type="str", default="present", choices=["absent", "present", "query"]), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, required_if=[ ["interface_type", "fex", ["extpaths"]], ["interface_type", "fex_vpc", ["extpaths"]], ["interface_type", "fex_port_channel", ["extpaths"]], [ "state", "absent", ["ap", "epg", "interface", "leafs", "pod_id", "tenant"] ], [ "state", "present", [ "ap", "encap_id", "epg", "interface", "leafs", "pod_id", "tenant" ] ], ], ) tenant = module.params.get("tenant") ap = module.params.get("ap") epg = module.params.get("epg") description = module.params.get("description") encap_id = module.params.get("encap_id") primary_encap_id = module.params.get("primary_encap_id") deploy_immediacy = module.params.get("deploy_immediacy") interface_mode = module.params.get("interface_mode") interface_type = module.params.get("interface_type") pod_id = module.params.get("pod_id") leafs = module.params.get("leafs") interface = module.params.get("interface") extpaths = module.params.get("extpaths") state = module.params.get("state") aci = ACIModule(module) if leafs is not None: # Process leafs, and support dash-delimited leafs leafs = [] for leaf in module.params.get("leafs"): # Users are likely to use integers for leaf IDs, which would raise an exception when using the join method leafs.extend(str(leaf).split("-")) if len(leafs) == 1: if interface_type in ["vpc", "fex_vpc"]: aci.fail_json(msg='A interface_type of "vpc" requires 2 leafs') leafs = leafs[0] elif len(leafs) == 2: if interface_type not in ["vpc", "fex_vpc"]: aci.fail_json( msg= 'The interface_types "switch_port", "port_channel", and "fex" \ do not support using multiple leafs for a single binding') leafs = "-".join(leafs) else: aci.fail_json( msg='The "leafs" parameter must not have more than 2 entries') if extpaths is not None: # Process extpaths, and support dash-delimited extpaths extpaths = [] for extpath in module.params.get("extpaths"): # Users are likely to use integers for extpaths IDs, which would raise an exception when using the join method extpaths.extend(str(extpath).split("-")) if len(extpaths) == 1: if interface_type == "fex_vpc": aci.fail_json( msg='A interface_type of "fex_vpc" requires 2 extpaths') extpaths = extpaths[0] elif len(extpaths) == 2: if interface_type != "fex_vpc": aci.fail_json(msg='The interface_types "fex" \ and "fex_port_channel" do not support using multiple extpaths for a single binding' ) extpaths = "-".join(extpaths) else: aci.fail_json( msg='The "extpaths" parameter must not have more than 2 entries' ) if encap_id is not None: if encap_id not in range(1, 4097): aci.fail_json(msg="Valid VLAN assignments are from 1 to 4096") encap_id = "vlan-{0}".format(encap_id) if primary_encap_id is not None: try: primary_encap_id = int(primary_encap_id) if isinstance(primary_encap_id, int) and primary_encap_id in range( 1, 4097): primary_encap_id = "vlan-{0}".format(primary_encap_id) else: aci.fail_json( msg="Valid VLAN assignments are from 1 to 4096 or unknown." ) except Exception as e: if isinstance(primary_encap_id, str) and primary_encap_id != "unknown": aci.fail_json( msg= "Valid VLAN assignments are from 1 to 4096 or unknown. %s" % e) static_path = INTERFACE_TYPE_MAPPING[interface_type].format( pod_id=pod_id, leafs=leafs, extpaths=extpaths, interface=interface) path_target_filter = {} if pod_id is not None and leafs is not None and interface is not None and ( interface_type != "fex" or extpaths is not None): path_target_filter = {"tDn": static_path} if interface_mode is not None: interface_mode = INTERFACE_MODE_MAPPING[interface_mode] aci.construct_url( root_class=dict( aci_class="fvTenant", aci_rn="tn-{0}".format(tenant), module_object=tenant, target_filter={"name": tenant}, ), subclass_1=dict( aci_class="fvAp", aci_rn="ap-{0}".format(ap), module_object=ap, target_filter={"name": ap}, ), subclass_2=dict( aci_class="fvAEPg", aci_rn="epg-{0}".format(epg), module_object=epg, target_filter={"name": epg}, ), subclass_3=dict( aci_class="fvRsPathAtt", aci_rn="rspathAtt-[{0}]".format(static_path), module_object=static_path, target_filter=path_target_filter, ), ) aci.get_existing() if state == "present": aci.payload( aci_class="fvRsPathAtt", class_config=dict( descr=description, encap=encap_id, primaryEncap=primary_encap_id, instrImedcy=deploy_immediacy, mode=interface_mode, tDn=static_path, ), ) aci.get_diff(aci_class="fvRsPathAtt") aci.post_config() elif state == "absent": aci.delete_config() aci.exit_json()