ansible  2.9.27
About: Ansible is an IT Configuration Management, Deployment \
About: Ansible (2.x) is an IT Configuration Management, Deployment & Orchestration tool.
ansible download page.
  Fossies Dox: ansible-2.9.27.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

mso_schema_site_anp_epg_domain.py
Go to the documentation of this file.
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4# Copyright: (c) 2019, Nirav Katarmal (@nkatarmal-crest) <nirav.katarmal@crestdatasys.com>
5# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
6
7from __future__ import absolute_import, division, print_function
8__metaclass__ = type
9
10ANSIBLE_METADATA = {'metadata_version': '1.1',
11 'status': ['preview'],
12 'supported_by': 'community'}
13
14DOCUMENTATION = r'''
15---
16module: mso_schema_site_anp_epg_domain
17short_description: Manage site-local EPG domains in schema template
18description:
19- Manage site-local EPG domains in schema template on Cisco ACI Multi-Site.
20author:
21- Nirav Katarmal (@nkatarmal-crest)
22version_added: '2.9'
23options:
24 schema:
25 description:
26 - The name of the schema.
27 type: str
28 required: yes
29 site:
30 description:
31 - The name of the site.
32 type: str
33 required: yes
34 template:
35 description:
36 - The name of the template.
37 type: str
38 required: yes
39 anp:
40 description:
41 - The name of the ANP.
42 type: str
43 required: yes
44 epg:
45 description:
46 - The name of the EPG.
47 type: str
48 required: yes
49 domain_association_type:
50 description:
51 - The type of domain to associate.
52 type: str
53 choices: [ vmmDomain, l3ExtDomain, l2ExtDomain, physicalDomain, fibreChannel ]
54 domain_profile:
55 description:
56 - The domain profile name.
57 type: str
58 deployment_immediacy:
59 description:
60 - The deployment immediacy of the domain.
61 - C(immediate) means B(Deploy immediate).
62 - C(lazy) means B(deploy on demand).
63 type: str
64 choices: [ immediate, lazy ]
65 resolution_immediacy:
66 description:
67 - Determines when the policies should be resolved and available.
68 - Defaults to C(lazy) when unset during creation.
69 type: str
70 choices: [ immediate, lazy, pre-provision ]
71 micro_seg_vlan_type:
72 description:
73 - Virtual LAN type for microsegmentation. This attribute can only be used with vmmDomain domain association.
74 type: str
75 micro_seg_vlan:
76 description:
77 - Virtual LAN for microsegmentation. This attribute can only be used with vmmDomain domain association.
78 type: int
79 port_encap_vlan_type:
80 description:
81 - Virtual LAN type for port encap. This attribute can only be used with vmmDomain domain association.
82 type: str
83 port_encap_vlan:
84 description:
85 - Virtual LAN type for port encap. This attribute can only be used with vmmDomain domain association.
86 type: int
87 vlan_encap_mode:
88 description:
89 - Which VLAN enacap mode to use. This attribute can only be used with vmmDomain domain association.
90 type: str
91 choices: [ static, dynamic ]
92 allow_micro_segmentation:
93 description:
94 - Specifies microsegmentation is enabled or not. This attribute can only be used with vmmDomain domain association.
95 type: bool
96 switch_type:
97 description:
98 - Which switch type to use with this domain association. This attribute can only be used with vmmDomain domain association.
99 type: str
100 switching_mode:
101 description:
102 - Which switching mode to use with this domain association. This attribute can only be used with vmmDomain domain association.
103 type: str
104 enhanced_lagpolicy_name:
105 description:
106 - EPG enhanced lagpolicy name. This attribute can only be used with vmmDomain domain association.
107 type: str
108 enhanced_lagpolicy_dn:
109 description:
110 - Distinguished name of EPG lagpolicy. This attribute can only be used with vmmDomain domain association.
111 type: str
112 state:
113 description:
114 - Use C(present) or C(absent) for adding or removing.
115 - Use C(query) for listing an object or multiple objects.
116 type: str
117 choices: [ absent, present, query ]
118 default: present
119notes:
120- The ACI MultiSite PATCH API has a deficiency requiring some objects to be referenced by index.
121 This can cause silent corruption on concurrent access when changing/removing on object as
122 the wrong object may be referenced. This module is affected by this deficiency.
123seealso:
124- module: mso_schema_site_anp_epg
125- module: mso_schema_template_anp_epg
126extends_documentation_fragment: mso
127'''
128
129EXAMPLES = r'''
130- name: Add a new static leaf to a site EPG
131 mso_schema_site_anp_epg_domain:
132 host: mso_host
133 username: admin
134 password: SomeSecretPassword
135 schema: Schema1
136 site: Site1
137 template: Template1
138 anp: ANP1
139 epg: EPG1
140 domain_association_type: vmmDomain
141 domain_profile: 'VMware-VMM'
142 deployment_immediacy: lazy
143 resolution_immediacy: pre-provision
144 state: present
145 delegate_to: localhost
146
147- name: Remove a static leaf from a site EPG
148 mso_schema_site_anp_epg_domain:
149 host: mso_host
150 username: admin
151 password: SomeSecretPassword
152 schema: Schema1
153 site: Site1
154 template: Template1
155 anp: ANP1
156 epg: EPG1
157 domain_association_type: vmmDomain
158 domain_profile: 'VMware-VMM'
159 deployment_immediacy: lazy
160 resolution_immediacy: pre-provision
161 state: absent
162 delegate_to: localhost
163
164- name: Query a specific site EPG static leaf
165 mso_schema_site_anp_epg_domain:
166 host: mso_host
167 username: admin
168 password: SomeSecretPassword
169 schema: Schema1
170 site: Site1
171 template: Template1
172 anp: ANP1
173 epg: EPG1
174 domain_association_type: vmmDomain
175 domain_profile: 'VMware-VMM'
176 state: query
177 delegate_to: localhost
178 register: query_result
179
180- name: Query all site EPG static leafs
181 mso_schema_site_anp_epg_domain:
182 host: mso_host
183 username: admin
184 password: SomeSecretPassword
185 schema: Schema1
186 site: Site1
187 template: Template1
188 anp: ANP1
189 epg: EPG1
190 state: query
191 delegate_to: localhost
192 register: query_result
193'''
194
195RETURN = r'''
196'''
197
198from ansible.module_utils.basic import AnsibleModule
199from ansible.module_utils.network.aci.mso import MSOModule, mso_argument_spec
200
201
202def main():
203 argument_spec = mso_argument_spec()
204 argument_spec.update(
205 schema=dict(type='str', required=True),
206 site=dict(type='str', required=True),
207 template=dict(type='str', required=True),
208 anp=dict(type='str', required=True),
209 epg=dict(type='str', required=True),
210 domain_association_type=dict(type='str', choices=['vmmDomain', 'l3ExtDomain', 'l2ExtDomain', 'physicalDomain', 'fibreChannel']),
211 domain_profile=dict(type='str'),
212 deployment_immediacy=dict(type='str', choices=['immediate', 'lazy']),
213 resolution_immediacy=dict(type='str', choices=['immediate', 'lazy', 'pre-provision']),
214 state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
215 micro_seg_vlan_type=dict(type='str'),
216 micro_seg_vlan=dict(type='int'),
217 port_encap_vlan_type=dict(type='str'),
218 port_encap_vlan=dict(type='int'),
219 vlan_encap_mode=dict(type='str', choices=['static', 'dynamic']),
220 allow_micro_segmentation=dict(type='bool'),
221 switch_type=dict(type='str'),
222 switching_mode=dict(type='str'),
223 enhanced_lagpolicy_name=dict(type='str'),
224 enhanced_lagpolicy_dn=dict(type='str'),
225
226 )
227
228 module = AnsibleModule(
229 argument_spec=argument_spec,
230 supports_check_mode=True,
231 required_if=[
232 ['state', 'absent', ['domain_association_type', 'domain_profile', 'deployment_immediacy', 'resolution_immediacy']],
233 ['state', 'present', ['domain_association_type', 'domain_profile', 'deployment_immediacy', 'resolution_immediacy']],
234 ],
235 )
236
237 schema = module.params['schema']
238 site = module.params['site']
239 template = module.params['template']
240 anp = module.params['anp']
241 epg = module.params['epg']
242 domain_association_type = module.params['domain_association_type']
243 domain_profile = module.params['domain_profile']
244 deployment_immediacy = module.params['deployment_immediacy']
245 resolution_immediacy = module.params['resolution_immediacy']
246 state = module.params['state']
247 micro_seg_vlan_type = module.params['micro_seg_vlan_type']
248 micro_seg_vlan = module.params['micro_seg_vlan']
249 port_encap_vlan_type = module.params['port_encap_vlan_type']
250 port_encap_vlan = module.params['port_encap_vlan']
251 vlan_encap_mode = module.params['vlan_encap_mode']
252 allow_micro_segmentation = module.params['allow_micro_segmentation']
253 switch_type = module.params['switch_type']
254 switching_mode = module.params['switching_mode']
255 enhanced_lagpolicy_name = module.params['enhanced_lagpolicy_name']
256 enhanced_lagpolicy_dn = module.params['enhanced_lagpolicy_dn']
257
258 mso = MSOModule(module)
259
260 # Get schema_id
261 schema_obj = mso.get_obj('schemas', displayName=schema)
262 if not schema_obj:
263 mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
264
265 schema_path = 'schemas/{id}'.format(**schema_obj)
266 schema_id = schema_obj['id']
267
268 # Get site
269 site_id = mso.lookup_site(site)
270
271 # Get site_idx
272 sites = [(s['siteId'], s['templateName']) for s in schema_obj['sites']]
273 if (site_id, template) not in sites:
274 mso.fail_json(msg="Provided site/template '{0}-{1}' does not exist. Existing sites/templates: {2}".format(site, template, ', '.join(sites)))
275
276 # Schema-access uses indexes
277 site_idx = sites.index((site_id, template))
278 # Path-based access uses site_id-template
279 site_template = '{0}-{1}'.format(site_id, template)
280
281 # Get ANP
282 anp_ref = mso.anp_ref(schema_id=schema_id, template=template, anp=anp)
283 anps = [a['anpRef'] for a in schema_obj['sites'][site_idx]['anps']]
284 if anp_ref not in anps:
285 mso.fail_json(msg="Provided anp '{0}' does not exist. Existing anps: {1}".format(anp, ', '.join(anps)))
286 anp_idx = anps.index(anp_ref)
287
288 # Get EPG
289 epg_ref = mso.epg_ref(schema_id=schema_id, template=template, anp=anp, epg=epg)
290 print(epg_ref)
291 epgs = [e['epgRef'] for e in schema_obj['sites'][site_idx]['anps'][anp_idx]['epgs']]
292 if epg_ref not in epgs:
293 mso.fail_json(msg="Provided epg '{0}' does not exist. Existing epgs: {1} epgref {2}".format(epg, str(schema_obj['sites'][site_idx]), epg_ref))
294 epg_idx = epgs.index(epg_ref)
295
296 if domain_association_type == 'vmmDomain':
297 domain_dn = 'uni/vmmp-VMware/dom-{0}'.format(domain_profile)
298 elif domain_association_type == 'l3ExtDomain':
299 domain_dn = 'uni/l3dom-{0}'.format(domain_profile)
300 elif domain_association_type == 'l2ExtDomain':
301 domain_dn = 'uni/l2dom-{0}'.format(domain_profile)
302 elif domain_association_type == 'physicalDomain':
303 domain_dn = 'uni/phys-{0}'.format(domain_profile)
304 elif domain_association_type == 'fibreChannel':
305 domain_dn = 'uni/fc-{0}'.format(domain_profile)
306 else:
307 domain_dn = ''
308
309 # Get Domains
310 domains = [dom['dn'] for dom in schema_obj['sites'][site_idx]['anps'][anp_idx]['epgs'][epg_idx]['domainAssociations']]
311 if domain_dn in domains:
312 domain_idx = domains.index(domain_dn)
313 domain_path = '/sites/{0}/anps/{1}/epgs/{2}/domainAssociations/{3}'.format(site_template, anp, epg, domain_idx)
314 mso.existing = schema_obj['sites'][site_idx]['anps'][anp_idx]['epgs'][epg_idx]['domainAssociations'][domain_idx]
315
316 if state == 'query':
317 if domain_association_type is None or domain_profile is None:
318 mso.existing = schema_obj['sites'][site_idx]['anps'][anp_idx]['epgs'][epg_idx]['domainAssociations']
319 elif not mso.existing:
320 mso.fail_json(msg="Domain association '{domain_association_type}/{domain_profile}' not found".format(
321 domain_association_type=domain_association_type,
322 domain_profile=domain_profile))
323 mso.exit_json()
324
325 domains_path = '/sites/{0}/anps/{1}/epgs/{2}/domainAssociations'.format(site_template, anp, epg)
326 ops = []
327 if domain_association_type == 'vmmDomain':
328 vmmDomainProperties = {}
329 if micro_seg_vlan_type and micro_seg_vlan:
330 microSegVlan = dict(vlanType=micro_seg_vlan_type, vlan=micro_seg_vlan)
331 vmmDomainProperties['microSegVlan'] = microSegVlan
332 elif not micro_seg_vlan_type and micro_seg_vlan:
333 mso.fail_json(msg="micro_seg_vlan_type is required when micro_seg_vlan is provided.")
334 elif micro_seg_vlan_type and not micro_seg_vlan:
335 mso.fail_json(msg="micro_seg_vlan is required when micro_seg_vlan_type is provided.")
336
337 if micro_seg_vlan_type and micro_seg_vlan:
338 portEncapVlan = dict(vlanType=port_encap_vlan_type, vlan=port_encap_vlan)
339 vmmDomainProperties['portEncapVlan'] = portEncapVlan
340 elif not port_encap_vlan_type and port_encap_vlan:
341 mso.fail_json(msg="port_encap_vlan_type is required when port_encap_vlan is provided.")
342 elif port_encap_vlan_type and not port_encap_vlan:
343 mso.fail_json(msg="port_encap_vlan is required when port_encap_vlan_type is provided.")
344
345 if vlan_encap_mode:
346 vmmDomainProperties['vlanEncapMode'] = vlan_encap_mode
347
348 if allow_micro_segmentation:
349 vmmDomainProperties['allowMicroSegmentation'] = allow_micro_segmentation
350 if switch_type:
351 vmmDomainProperties['switchType'] = switch_type
352 if switching_mode:
353 vmmDomainProperties['switchingMode'] = switching_mode
354
355 if enhanced_lagpolicy_name and enhanced_lagpolicy_dn:
356 enhancedLagPol = dict(name=enhanced_lagpolicy_name, dn=enhanced_lagpolicy_dn)
357 epgLagPol = dict(enhancedLagPol=enhancedLagPol)
358 vmmDomainProperties['epgLagPol'] = epgLagPol
359 elif not enhanced_lagpolicy_name and enhanced_lagpolicy_dn:
360 mso.fail_json(msg="enhanced_lagpolicy_name is required when enhanced_lagpolicy_dn is provided.")
361 elif enhanced_lagpolicy_name and not enhanced_lagpolicy_dn:
362 mso.fail_json(msg="enhanced_lagpolicy_dn is required when enhanced_lagpolicy_name is provided.")
363
364 payload = dict(
365 dn=domain_dn,
366 domainType=domain_association_type,
367 deploymentImmediacy=deployment_immediacy,
368 resolutionImmediacy=resolution_immediacy,
369 )
370
371 if vmmDomainProperties:
372 payload['vmmDomainProperties'] = vmmDomainProperties
373 else:
374 payload = dict(
375 dn=domain_dn,
376 domainType=domain_association_type,
377 deploymentImmediacy=deployment_immediacy,
378 resolutionImmediacy=resolution_immediacy,
379 )
380
381 mso.previous = mso.existing
382 if state == 'absent':
383 if mso.existing:
384 mso.sent = mso.existing = {}
385 ops.append(dict(op='remove', path=domains_path))
386 elif state == 'present':
387 mso.sanitize(payload, collate=True)
388
389 if mso.existing:
390 ops.append(dict(op='replace', path=domain_path, value=mso.sent))
391 else:
392 ops.append(dict(op='add', path=domains_path + '/-', value=mso.sent))
393
394 mso.existing = mso.proposed
395
396 if not module.check_mode:
397 mso.request(schema_path, method='PATCH', data=ops)
398
399 mso.exit_json()
400
401
402if __name__ == "__main__":
403 main()