7from __future__
import absolute_import, division, print_function
10ANSIBLE_METADATA = {
'metadata_version':
'1.1',
11 'status': [
'preview'],
12 'supported_by':
'certified'}
16module: aci_static_binding_to_epg
17short_description: Bind static paths to EPGs (fv:RsPathAtt)
19- Bind static paths to EPGs on Cisco ACI fabrics.
24 - Name of an existing tenant.
26 aliases: [ tenant_name ]
29 - Name of an existing application network profile, that will contain the EPGs.
31 aliases: [ app_profile, app_profile_name ]
34 - The name of the end point group.
39 - Description for the static path to EPG binding.
45 - The encapsulation ID associating the C(epg)
with the interface path.
46 - This acts
as the secondary C(encap_id) when using micro-segmentation.
47 - Accepted values are any valid encap ID
for specified encap, currently ranges between C(1)
and C(4096).
49 aliases: [ vlan, vlan_id ]
52 - Determines the primary encapsulation ID associating the C(epg)
53 with the interface path when using micro-segmentation.
54 - Accepted values are any valid encap ID
for specified encap, currently ranges between C(1)
and C(4096).
56 aliases: [ primary_vlan, primary_vlan_id ]
59 - The Deployment Immediacy of Static EPG on PC, VPC
or Interface.
60 - The APIC defaults to C(lazy) when unset during creation.
62 choices: [ immediate, lazy ]
65 - Determines how layer 2 tags will be read
from and added to frames.
66 - Values C(802.1p)
and C(native) are identical.
67 - Values C(access)
and C(untagged) are identical.
68 - Values C(regular), C(tagged)
and C(trunk) are identical.
69 - The APIC defaults to C(trunk) when unset during creation.
71 choices: [ 802.1p, access, native, regular, tagged, trunk, untagged ]
72 aliases: [ interface_mode_name, mode ]
75 - The type of interface
for the static EPG deployment.
77 choices: [ fex, port_channel, switch_port, vpc ]
81 - The pod number part of the tDn.
82 - C(pod_id)
is usually an integer below C(10).
84 aliases: [ pod, pod_number ]
87 - The switch ID(s) that the C(interface) belongs to.
88 - When C(interface_type)
is C(switch_port), C(port_channel),
or C(fex), then C(leafs)
is a string of the leaf ID.
89 - When C(interface_type)
is C(vpc), then C(leafs)
is a list
with both leaf IDs.
90 - The C(leafs) value
is usually something like
'101' or '101-102' depending on C(connection_type).
92 aliases: [ leaves, nodes, paths, switches ]
95 - The C(interface) string value part of the tDn.
96 - Usually a policy group like C(test-IntPolGrp)
or an interface of the following format C(1/7) depending on C(interface_type).
100 - The C(extpaths) integer value part of the tDn.
101 - C(extpaths)
is only used
if C(interface_type)
is C(fex).
102 - Usually something like C(1011).
106 - Use C(present)
or C(absent)
for adding
or removing.
107 - Use C(query)
for listing an object
or multiple objects.
109 choices: [ absent, present, query ]
111extends_documentation_fragment: aci
113- The C(tenant), C(ap), C(epg) used must exist before using this module
in your playbook.
114 The M(aci_tenant), M(aci_ap), M(aci_epg) modules can be used
for this.
119- name: APIC Management Information Model reference
120 description: More information about the internal APIC
class B(fv:RsPathAtt).
121 link: https://developer.cisco.com/docs/apic-mim-ref/
123- Bruno Calogero (
@brunocalogero)
127- name: Deploy Static Path binding for given EPG
128 aci_static_binding_to_epg:
131 password: SomeSecretPassword
132 tenant: accessport-code-cert
133 ap: accessport_code_app
136 deploy_immediacy: lazy
137 interface_mode: untagged
138 interface_type: switch_port
143 delegate_to: localhost
145- name: Remove Static Path binding
for given EPG
146 aci_static_binding_to_epg:
149 password: SomeSecretPassword
150 tenant: accessport-code-cert
151 ap: accessport_code_app
153 interface_type: switch_port
158 delegate_to: localhost
160- name: Get specific Static Path binding
for given EPG
161 aci_static_binding_to_epg:
164 password: SomeSecretPassword
165 tenant: accessport-code-cert
166 ap: accessport_code_app
168 interface_type: switch_port
173 delegate_to: localhost
174 register: query_result
179 description: The existing configuration from the APIC after the module has finished
187 "descr":
"Production environment",
188 "dn":
"uni/tn-production",
189 "name":
"production",
198 description: The error information
as returned
from the APIC
204 "text":
"unknown managed object class foo"
207 description: The raw output returned by the APIC REST API (xml
or json)
208 returned: parse error
210 sample:
'<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
212 description: The actual/minimal configuration pushed to the APIC
219 "descr":
"Production environment"
224 description: The original configuration
from the APIC before the module has started
232 "descr":
"Production",
233 "dn":
"uni/tn-production",
234 "name":
"production",
243 description: The assembled configuration
from the user-provided parameters
250 "descr":
"Production environment",
256 description: The filter string used
for the request
257 returned: failure
or debug
259 sample: ?rsp-prop-include=config-only
261 description: The HTTP method used
for the request to the APIC
262 returned: failure
or debug
266 description: The HTTP response
from the APIC
267 returned: failure
or debug
269 sample: OK (30 bytes)
271 description: The HTTP status
from the APIC
272 returned: failure
or debug
276 description: The HTTP url used
for the request to the APIC
277 returned: failure
or debug
279 sample: https://10.11.12.13/api/mo/uni/tn-production.json
282from ansible.module_utils.basic import AnsibleModule
283from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
285INTERFACE_MODE_MAPPING = {
287 'access':
'untagged',
289 'regular':
'regular',
292 'untagged':
'untagged',
295INTERFACE_TYPE_MAPPING = dict(
296 fex=
'topology/pod-{pod_id}/paths-{leafs}/extpaths-{extpaths}/pathep-[eth{interface}]',
297 port_channel=
'topology/pod-{pod_id}/paths-{leafs}/pathep-[{interface}]',
298 switch_port=
'topology/pod-{pod_id}/paths-{leafs}/pathep-[eth{interface}]',
299 vpc=
'topology/pod-{pod_id}/protpaths-{leafs}/pathep-[{interface}]',
307 argument_spec.update(
308 tenant=dict(type=
'str', aliases=[
'tenant_name']),
309 ap=dict(type=
'str', aliases=[
'app_profile',
'app_profile_name']),
310 epg=dict(type=
'str', aliases=[
'epg_name']),
311 description=dict(type=
'str', aliases=[
'descr']),
312 encap_id=dict(type=
'int', aliases=[
'vlan',
'vlan_id']),
313 primary_encap_id=dict(type=
'int', aliases=[
'primary_vlan',
'primary_vlan_id']),
314 deploy_immediacy=dict(type=
'str', choices=[
'immediate',
'lazy']),
315 interface_mode=dict(type=
'str', choices=[
'802.1p',
'access',
'native',
'regular',
'tagged',
'trunk',
'untagged'],
316 aliases=[
'interface_mode_name',
'mode']),
317 interface_type=dict(type=
'str', default=
'switch_port', choices=[
'fex',
'port_channel',
'switch_port',
'vpc']),
318 pod_id=dict(type=
'int', aliases=[
'pod',
'pod_number']),
319 leafs=dict(type=
'list', aliases=[
'leaves',
'nodes',
'paths',
'switches']),
320 interface=dict(type=
'str'),
321 extpaths=dict(type=
'int'),
322 state=dict(type=
'str', default=
'present', choices=[
'absent',
'present',
'query']),
326 argument_spec=argument_spec,
327 supports_check_mode=
True,
329 [
'interface_type',
'fex', [
'extpaths']],
330 [
'state',
'absent', [
'ap',
'epg',
'interface',
'leafs',
'pod_id',
'tenant']],
331 [
'state',
'present', [
'ap',
'encap_id',
'epg',
'interface',
'leafs',
'pod_id',
'tenant']],
335 tenant = module.params[
'tenant']
336 ap = module.params[
'ap']
337 epg = module.params[
'epg']
338 description = module.params[
'description']
339 encap_id = module.params[
'encap_id']
340 primary_encap_id = module.params[
'primary_encap_id']
341 deploy_immediacy = module.params[
'deploy_immediacy']
342 interface_mode = module.params[
'interface_mode']
343 interface_type = module.params[
'interface_type']
344 pod_id = module.params[
'pod_id']
345 leafs = module.params[
'leafs']
346 if leafs
is not None:
349 for leaf
in module.params[
'leafs']:
351 leafs.extend(str(leaf).
split(
'-'))
353 if interface_type ==
'vpc':
354 module.fail_json(msg=
'A interface_type of "vpc" requires 2 leafs')
356 elif len(leafs) == 2:
357 if interface_type !=
'vpc':
358 module.fail_json(msg=
'The interface_types "switch_port", "port_channel", and "fex" \
359 do not support using multiple leafs for a single binding')
360 leafs =
"-".join(leafs)
362 module.fail_json(msg=
'The "leafs" parameter must not have more than 2 entries')
363 interface = module.params[
'interface']
364 extpaths = module.params[
'extpaths']
365 state = module.params[
'state']
367 if encap_id
is not None:
368 if encap_id
not in range(1, 4097):
369 module.fail_json(msg=
'Valid VLAN assigments are from 1 to 4096')
370 encap_id =
'vlan-{0}'.
format(encap_id)
372 if primary_encap_id
is not None:
373 if primary_encap_id
not in range(1, 4097):
374 module.fail_json(msg=
'Valid VLAN assigments are from 1 to 4096')
375 primary_encap_id =
'vlan-{0}'.
format(primary_encap_id)
377 static_path = INTERFACE_TYPE_MAPPING[interface_type].
format(pod_id=pod_id, leafs=leafs, extpaths=extpaths, interface=interface)
379 path_target_filter = {}
380 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):
381 path_target_filter = {
'tDn': static_path}
383 if interface_mode
is not None:
384 interface_mode = INTERFACE_MODE_MAPPING[interface_mode]
389 aci_class=
'fvTenant',
390 aci_rn=
'tn-{0}'.
format(tenant),
391 module_object=tenant,
392 target_filter={
'name': tenant},
396 aci_rn=
'ap-{0}'.
format(ap),
398 target_filter={
'name': ap},
402 aci_rn=
'epg-{0}'.
format(epg),
404 target_filter={
'name': epg},
407 aci_class=
'fvRsPathAtt',
408 aci_rn=
'rspathAtt-[{0}]'.
format(static_path),
409 module_object=static_path,
410 target_filter=path_target_filter,
416 if state ==
'present':
418 aci_class=
'fvRsPathAtt',
422 primaryEncap=primary_encap_id,
423 instrImedcy=deploy_immediacy,
429 aci.get_diff(aci_class=
'fvRsPathAtt')
433 elif state ==
'absent':
439if __name__ ==
"__main__":