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_template_anp_epg.py
Go to the documentation of this file.
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4# Copyright: (c) 2018, Dag Wieers (@dagwieers) <dag@wieers.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_template_anp_epg
17short_description: Manage Endpoint Groups (EPGs) in schema templates
18description:
19- Manage EPGs in schema templates on Cisco ACI Multi-Site.
20author:
21- Dag Wieers (@dagwieers)
22version_added: '2.8'
23options:
24 schema:
25 description:
26 - The name of the schema.
27 type: str
28 required: yes
29 template:
30 description:
31 - The name of the template.
32 type: str
33 required: yes
34 anp:
35 description:
36 - The name of the ANP.
37 type: str
38 required: yes
39 epg:
40 description:
41 - The name of the EPG to manage.
42 type: str
43 aliases: [ name ]
44 display_name:
45 description:
46 - The name as displayed on the MSO web interface.
47 type: str
48# contracts:
49# description:
50# - A list of contracts associated to this ANP.
51# type: list
52 bd:
53 description:
54 - The BD associated to this ANP.
55 type: dict
56 suboptions:
57 name:
58 description:
59 - The name of the BD to associate with.
60 required: true
61 type: str
62 schema:
63 description:
64 - The schema that defines the referenced BD.
65 - If this parameter is unspecified, it defaults to the current schema.
66 type: str
67 template:
68 description:
69 - The template that defines the referenced BD.
70 type: str
71 vrf:
72 version_added: '2.9'
73 description:
74 - The VRF associated to this ANP.
75 type: dict
76 suboptions:
77 name:
78 description:
79 - The name of the VRF to associate with.
80 required: true
81 type: str
82 schema:
83 description:
84 - The schema that defines the referenced VRF.
85 - If this parameter is unspecified, it defaults to the current schema.
86 type: str
87 template:
88 description:
89 - The template that defines the referenced VRF.
90 type: str
91 subnets:
92 description:
93 - The subnets associated to this ANP.
94 type: list
95 suboptions:
96 ip:
97 description:
98 - The IP range in CIDR notation.
99 type: str
100 required: true
101 description:
102 description:
103 - The description of this subnet.
104 type: str
105 scope:
106 description:
107 - The scope of the subnet.
108 type: str
109 choices: [ private, public ]
110 shared:
111 description:
112 - Whether this subnet is shared between VRFs.
113 type: bool
114 no_default_gateway:
115 description:
116 - Whether this subnet has a default gateway.
117 type: bool
118 useg_epg:
119 description:
120 - Whether this is a USEG EPG.
121 type: bool
122# useg_epg_attributes:
123# description:
124# - A dictionary consisting of USEG attributes.
125# type: dict
126 intra_epg_isolation:
127 description:
128 - Whether intra EPG isolation is enforced.
129 - When not specified, this parameter defaults to C(unenforced).
130 type: str
131 choices: [ enforced, unenforced ]
132 intersite_multicaste_source:
133 description:
134 - Whether intersite multicast source is enabled.
135 - When not specified, this parameter defaults to C(no).
136 type: bool
137 preferred_group:
138 description:
139 - Whether this EPG is added to preferred group or not.
140 - When not specified, this parameter defaults to C(no).
141 type: bool
142 version_added: 2.9
143 state:
144 description:
145 - Use C(present) or C(absent) for adding or removing.
146 - Use C(query) for listing an object or multiple objects.
147 type: str
148 choices: [ absent, present, query ]
149 default: present
150seealso:
151- module: mso_schema_template_anp
152- module: mso_schema_template_anp_epg_subnet
153- module: mso_schema_template_bd
154- module: mso_schema_template_contract_filter
155extends_documentation_fragment: mso
156'''
157
158EXAMPLES = r'''
159- name: Add a new EPG
160 mso_schema_template_anp_epg:
161 host: mso_host
162 username: admin
163 password: SomeSecretPassword
164 schema: Schema 1
165 template: Template 1
166 anp: ANP 1
167 epg: EPG 1
168 bd:
169 name: bd1
170 vrf:
171 name: vrf1
172 state: present
173 delegate_to: localhost
174
175- name: Add a new EPG with preferred group.
176 mso_schema_template_anp_epg:
177 host: mso_host
178 username: admin
179 password: SomeSecretPassword
180 schema: Schema 1
181 template: Template 1
182 anp: ANP 1
183 epg: EPG 1
184 state: present
185 preferred_group: yes
186 delegate_to: localhost
187
188- name: Remove an EPG
189 mso_schema_template_anp_epg:
190 host: mso_host
191 username: admin
192 password: SomeSecretPassword
193 schema: Schema 1
194 template: Template 1
195 anp: ANP 1
196 epg: EPG 1
197 bd:
198 name: bd1
199 vrf:
200 name: vrf1
201 state: absent
202 delegate_to: localhost
203
204- name: Query a specific EPG
205 mso_schema_template_anp_epg:
206 host: mso_host
207 username: admin
208 password: SomeSecretPassword
209 schema: Schema 1
210 template: Template 1
211 anp: ANP 1
212 epg: EPG 1
213 bd:
214 name: bd1
215 vrf:
216 name: vrf1
217 state: query
218 delegate_to: localhost
219 register: query_result
220
221- name: Query all EPGs
222 mso_schema_template_anp_epg:
223 host: mso_host
224 username: admin
225 password: SomeSecretPassword
226 schema: Schema 1
227 template: Template 1
228 anp: ANP 1
229 epg: EPG 1
230 bd:
231 name: bd1
232 vrf:
233 name: vrf1
234 state: query
235 delegate_to: localhost
236 register: query_result
237'''
238
239RETURN = r'''
240'''
241
242from ansible.module_utils.basic import AnsibleModule
243from ansible.module_utils.network.aci.mso import MSOModule, mso_argument_spec, mso_reference_spec, mso_subnet_spec, issubset
244
245
246def main():
247 argument_spec = mso_argument_spec()
248 argument_spec.update(
249 schema=dict(type='str', required=True),
250 template=dict(type='str', required=True),
251 anp=dict(type='str', required=True),
252 epg=dict(type='str', aliases=['name']), # This parameter is not required for querying all objects
253 bd=dict(type='dict', options=mso_reference_spec()),
254 vrf=dict(type='dict', options=mso_reference_spec()),
255 display_name=dict(type='str'),
256 useg_epg=dict(type='bool'),
257 intra_epg_isolation=dict(type='str', choices=['enforced', 'unenforced']),
258 intersite_multicaste_source=dict(type='bool'),
259 subnets=dict(type='list', options=mso_subnet_spec()),
260 state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
261 preferred_group=dict(type='bool'),
262 )
263
264 module = AnsibleModule(
265 argument_spec=argument_spec,
266 supports_check_mode=True,
267 required_if=[
268 ['state', 'absent', ['epg']],
269 ['state', 'present', ['epg']],
270 ],
271 )
272
273 schema = module.params['schema']
274 template = module.params['template']
275 anp = module.params['anp']
276 epg = module.params['epg']
277 display_name = module.params['display_name']
278 bd = module.params['bd']
279 vrf = module.params['vrf']
280 useg_epg = module.params['useg_epg']
281 intra_epg_isolation = module.params['intra_epg_isolation']
282 intersite_multicaste_source = module.params['intersite_multicaste_source']
283 subnets = module.params['subnets']
284 state = module.params['state']
285 preferred_group = module.params['preferred_group']
286
287 mso = MSOModule(module)
288
289 # Get schema_id
290 schema_obj = mso.get_obj('schemas', displayName=schema)
291 if schema_obj:
292 schema_id = schema_obj['id']
293 else:
294 mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
295
296 schema_path = 'schemas/{id}'.format(**schema_obj)
297
298 # Get template
299 templates = [t['name'] for t in schema_obj['templates']]
300 if template not in templates:
301 mso.fail_json(msg="Provided template '{0}' does not exist. Existing templates: {1}".format(template, ', '.join(templates)))
302 template_idx = templates.index(template)
303
304 # Get ANP
305 anps = [a['name'] for a in schema_obj['templates'][template_idx]['anps']]
306 if anp not in anps:
307 mso.fail_json(msg="Provided anp '{0}' does not exist. Existing anps: {1}".format(anp, ', '.join(anps)))
308 anp_idx = anps.index(anp)
309
310 # Get EPG
311 epgs = [e['name'] for e in schema_obj['templates'][template_idx]['anps'][anp_idx]['epgs']]
312 if epg is not None and epg in epgs:
313 epg_idx = epgs.index(epg)
314 mso.existing = schema_obj['templates'][template_idx]['anps'][anp_idx]['epgs'][epg_idx]
315
316 if state == 'query':
317 if epg is None:
318 mso.existing = schema_obj['templates'][template_idx]['anps'][anp_idx]['epgs']
319 elif not mso.existing:
320 mso.fail_json(msg="EPG '{epg}' not found".format(epg=epg))
321 mso.exit_json()
322
323 epgs_path = '/templates/{0}/anps/{1}/epgs'.format(template, anp)
324 epg_path = '/templates/{0}/anps/{1}/epgs/{2}'.format(template, anp, epg)
325 ops = []
326
327 mso.previous = mso.existing
328 if state == 'absent':
329 if mso.existing:
330 mso.sent = mso.existing = {}
331 ops.append(dict(op='remove', path=epg_path))
332
333 elif state == 'present':
334 bd_ref = mso.make_reference(bd, 'bd', schema_id, template)
335 vrf_ref = mso.make_reference(vrf, 'vrf', schema_id, template)
336 subnets = mso.make_subnets(subnets)
337
338 if display_name is None and not mso.existing:
339 display_name = epg
340
341 payload = dict(
342 name=epg,
343 displayName=display_name,
344 uSegEpg=useg_epg,
345 intraEpg=intra_epg_isolation,
346 proxyArp=intersite_multicaste_source,
347 # FIXME: Missing functionality
348 # uSegAttrs=[],
349 contractRelationships=[],
350 subnets=subnets,
351 bdRef=bd_ref,
352 preferredGroup=preferred_group,
353 vrfRef=vrf_ref,
354 )
355
356 mso.sanitize(payload, collate=True)
357
358 if mso.existing:
359 ops.append(dict(op='replace', path=epg_path, value=mso.sent))
360 else:
361 ops.append(dict(op='add', path=epgs_path + '/-', value=mso.sent))
362
363 mso.existing = mso.proposed
364
365 if not module.check_mode:
366 mso.request(schema_path, method='PATCH', data=ops)
367
368 mso.exit_json()
369
370
371if __name__ == "__main__":
372 main()