6from __future__
import absolute_import, division, print_function
9ANSIBLE_METADATA = {
'metadata_version':
'1.1',
10 'status': [
'preview'],
11 'supported_by':
'certified'}
16short_description: Manage Layer 3 Outside (L3Out) objects (l3ext:Out)
18- Manage Layer 3 Outside (L3Out) on Cisco ACI fabrics.
23 - Name of an existing tenant.
26 aliases: [ tenant_name ]
29 - Name of L3Out being created.
32 aliases: [ l3out_name, name ]
35 - Name of the VRF being associated with the L3Out.
41 - Name of the external L3 domain being associated
with the L3Out.
44 aliases: [ ext_routed_domain_name, routed_domain ]
47 - The target Differentiated Service (DSCP) value.
48 - The APIC defaults to C(unspecified) when unset during creation.
50 choices: [ AF11, AF12, AF13, AF21, AF22, AF23, AF31, AF32, AF33, AF41, AF42, AF43, CS0, CS1, CS2, CS3, CS4, CS5, CS6, CS7, EF, VA, unspecified ]
54 - Route Control enforcement direction. The only allowed values are export
or import,export.
56 choices: [ export,
import ]
57 aliases: [ route_control_enforcement ]
60 - Routing protocol
for the L3Out
62 choices: [ bgp, eigrp, ospf, pim, static ]
65 - The AS number
for the L3Out.
66 - Only applicable when using
'eigrp' as the l3protocol
68 aliases: [ as_number ]
72 - Description
for the L3Out.
77 - Use C(present)
or C(absent)
for adding
or removing.
78 - Use C(query)
for listing an object
or multiple objects.
80 choices: [ absent, present, query ]
82extends_documentation_fragment: aci
84- The C(tenant)
and C(domain)
and C(vrf) used must exist before using this module
in your playbook.
85 The M(aci_tenant)
and M(aci_domain)
and M(aci_vrf) modules can be used
for this.
90- name: APIC Management Information Model reference
91 description: More information about the internal APIC
class B(l3ext:Out).
92 link: https://developer.cisco.com/docs/apic-mim-ref/
94- Rostyslav Davydenko (
@rost-d)
98- name: Add a new L3Out
102 password: SomeSecretPassword
105 description: L3Out for Production tenant
110 delegate_to: localhost
116 password: SomeSecretPassword
120 delegate_to: localhost
122- name: Query L3Out information
126 password: SomeSecretPassword
130 delegate_to: localhost
131 register: query_result
136 description: The existing configuration from the APIC after the module has finished
144 "descr":
"Production environment",
145 "dn":
"uni/tn-production",
146 "name":
"production",
155 description: The error information
as returned
from the APIC
161 "text":
"unknown managed object class foo"
164 description: The raw output returned by the APIC REST API (xml
or json)
165 returned: parse error
167 sample:
'<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
169 description: The actual/minimal configuration pushed to the APIC
176 "descr":
"Production environment"
181 description: The original configuration
from the APIC before the module has started
189 "descr":
"Production",
190 "dn":
"uni/tn-production",
191 "name":
"production",
200 description: The assembled configuration
from the user-provided parameters
207 "descr":
"Production environment",
213 description: The filter string used
for the request
214 returned: failure
or debug
216 sample: ?rsp-prop-include=config-only
218 description: The HTTP method used
for the request to the APIC
219 returned: failure
or debug
223 description: The HTTP response
from the APIC
224 returned: failure
or debug
226 sample: OK (30 bytes)
228 description: The HTTP status
from the APIC
229 returned: failure
or debug
233 description: The HTTP url used
for the request to the APIC
234 returned: failure
or debug
236 sample: https://10.11.12.13/api/mo/uni/tn-production.json
239from ansible.module_utils.basic import AnsibleModule
240from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
245 argument_spec.update(
246 tenant=dict(type='str', aliases=[
'tenant_name']),
247 l3out=dict(type=
'str', aliases=[
'l3out_name',
'name']),
248 domain=dict(type=
'str', aliases=[
'ext_routed_domain_name',
'routed_domain']),
249 vrf=dict(type=
'str', aliases=[
'vrf_name']),
250 description=dict(type=
'str', aliases=[
'descr']),
251 route_control=dict(type=
'list', choices=[
'export',
'import'], aliases=[
'route_control_enforcement']),
252 dscp=dict(type=
'str',
253 choices=[
'AF11',
'AF12',
'AF13',
'AF21',
'AF22',
'AF23',
'AF31',
'AF32',
'AF33',
'AF41',
'AF42',
254 'AF43',
'CS0',
'CS1',
'CS2',
'CS3',
'CS4',
'CS5',
'CS6',
'CS7',
'EF',
'VA',
'unspecified'],
256 l3protocol=dict(type=
'list', choices=[
'bgp',
'eigrp',
'ospf',
'pim',
'static']),
257 asn=dict(type=
'int', aliases=[
'as_number']),
258 state=dict(type=
'str', default=
'present', choices=[
'absent',
'present',
'query'])
262 argument_spec=argument_spec,
263 supports_check_mode=
True,
265 [
'state',
'absent', [
'l3out',
'tenant']],
266 [
'state',
'present', [
'l3out',
'tenant',
'domain',
'vrf']],
272 l3out = module.params[
'l3out']
273 domain = module.params[
'domain']
274 dscp = module.params[
'dscp']
275 description = module.params[
'description']
276 enforceRtctrl = module.params[
'route_control']
277 vrf = module.params[
'vrf']
278 l3protocol = module.params[
'l3protocol']
279 asn = module.params[
'asn']
280 state = module.params[
'state']
281 tenant = module.params[
'tenant']
284 if 'eigrp' in l3protocol
and asn
is None:
285 module.fail_json(msg=
"Parameter 'asn' is required when l3protocol is 'eigrp'")
286 if 'eigrp' not in l3protocol
and asn
is not None:
287 module.warn(
"Parameter 'asn' is only applicable when l3protocol is 'eigrp'. The ASN will be ignored")
290 if enforceRtctrl
is not None:
291 if len(enforceRtctrl) == 1
and enforceRtctrl[0] ==
'import':
293 "The route_control parameter is invalid: allowed options are export or import,export only")
294 elif len(enforceRtctrl) == 1
and enforceRtctrl[0] ==
'export':
295 enforce_ctrl =
'export'
297 enforce_ctrl =
'export,import'
298 child_classes = [
'l3extRsL3DomAtt',
'l3extRsEctx',
'bgpExtP',
'ospfExtP',
'eigrpExtP',
'pimExtP']
302 aci_class=
'fvTenant',
303 aci_rn=
'tn-{0}'.
format(tenant),
304 module_object=tenant,
305 target_filter={
'name': tenant},
308 aci_class=
'l3extOut',
309 aci_rn=
'out-{0}'.
format(l3out),
311 target_filter={
'name': l3out},
313 child_classes=child_classes,
319 dict(l3extRsL3DomAtt=dict(attributes=dict(
320 tDn=
'uni/l3dom-{0}'.
format(domain)))),
321 dict(l3extRsEctx=dict(attributes=dict(tnFvCtxName=vrf))),
323 if l3protocol
is not None:
324 for protocol
in l3protocol:
325 if protocol ==
'bgp':
326 child_configs.append(
327 dict(bgpExtP=dict(attributes=dict(descr=
'', nameAlias=
''))))
328 elif protocol ==
'eigrp':
329 child_configs.append(
330 dict(eigrpExtP=dict(attributes=dict(descr=
'', nameAlias=
'', asn=asn))))
331 elif protocol ==
'ospf':
332 child_configs.append(
333 dict(ospfExtP=dict(attributes=dict(descr=
'', nameAlias=
''))))
334 elif protocol ==
'pim':
335 child_configs.append(
336 dict(pimExtP=dict(attributes=dict(descr=
'', nameAlias=
''))))
338 if state ==
'present':
340 aci_class=
'l3extOut',
344 dn=
'uni/tn-{0}/out-{1}'.
format(tenant, l3out),
345 enforceRtctrl=enforce_ctrl,
348 child_configs=child_configs,
351 aci.get_diff(aci_class=
'l3extOut')
355 elif state ==
'absent':
361if __name__ ==
"__main__":