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)  

aci_bd_subnet.py
Go to the documentation of this file.
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
5
6from __future__ import absolute_import, division, print_function
7__metaclass__ = type
8
9ANSIBLE_METADATA = {'metadata_version': '1.1',
10 'status': ['preview'],
11 'supported_by': 'certified'}
12
13DOCUMENTATION = r'''
14---
15module: aci_bd_subnet
16short_description: Manage Subnets (fv:Subnet)
17description:
18- Manage Subnets on Cisco ACI fabrics.
19version_added: '2.4'
20options:
21 bd:
22 description:
23 - The name of the Bridge Domain.
24 type: str
25 aliases: [ bd_name ]
26 description:
27 description:
28 - The description for the Subnet.
29 type: str
30 aliases: [ descr ]
31 enable_vip:
32 description:
33 - Determines if the Subnet should be treated as a VIP; used when the BD is extended to multiple sites.
34 - The APIC defaults to C(no) when unset during creation.
35 type: bool
36 gateway:
37 description:
38 - The IPv4 or IPv6 gateway address for the Subnet.
39 type: str
40 aliases: [ gateway_ip ]
41 mask:
42 description:
43 - The subnet mask for the Subnet.
44 - This is the number associated with CIDR notation.
45 - For IPv4 addresses, accepted values range between C(0) and C(32).
46 - For IPv6 addresses, accepted Values range between C(0) and C(128).
47 type: int
48 aliases: [ subnet_mask ]
49 nd_prefix_policy:
50 description:
51 - The IPv6 Neighbor Discovery Prefix Policy to associate with the Subnet.
52 type: str
53 preferred:
54 description:
55 - Determines if the Subnet is preferred over all available Subnets. Only one Subnet per Address Family (IPv4/IPv6).
56 can be preferred in the Bridge Domain.
57 - The APIC defaults to C(no) when unset during creation.
58 type: bool
59 route_profile:
60 description:
61 - The Route Profile to the associate with the Subnet.
62 type: str
63 route_profile_l3_out:
64 description:
65 - The L3 Out that contains the associated Route Profile.
66 type: str
67 scope:
68 description:
69 - Determines the scope of the Subnet.
70 - The C(private) option only allows communication with hosts in the same VRF.
71 - The C(public) option allows the Subnet to be advertised outside of the ACI Fabric, and allows communication with
72 hosts in other VRFs.
73 - The shared option limits communication to hosts in either the same VRF or the shared VRF.
74 - The value is a list of options, C(private) and C(public) are mutually exclusive, but both can be used with C(shared).
75 - The APIC defaults to C(private) when unset during creation.
76 type: list
77 choices:
78 - private
79 - public
80 - shared
81 subnet_control:
82 description:
83 - Determines the Subnet's Control State.
84 - The C(querier_ip) option is used to treat the gateway_ip as an IGMP querier source IP.
85 - The C(nd_ra) option is used to treat the gateway_ip address as a Neighbor Discovery Router Advertisement Prefix.
86 - The C(no_gw) option is used to remove default gateway functionality from the gateway address.
87 - The APIC defaults to C(nd_ra) when unset during creation.
88 type: str
89 choices: [ nd_ra, no_gw, querier_ip, unspecified ]
90 subnet_name:
91 description:
92 - The name of the Subnet.
93 type: str
94 aliases: [ name ]
95 tenant:
96 description:
97 - The name of the Tenant.
98 type: str
99 aliases: [ tenant_name ]
100 state:
101 description:
102 - Use C(present) or C(absent) for adding or removing.
103 - Use C(query) for listing an object or multiple objects.
104 type: str
105 choices: [ absent, present, query ]
106 default: present
107extends_documentation_fragment: aci
108notes:
109- The C(gateway) parameter is the root key used to access the Subnet (not name), so the C(gateway)
110 is required when the state is C(absent) or C(present).
111- The C(tenant) and C(bd) used must exist before using this module in your playbook.
112 The M(aci_tenant) module and M(aci_bd) can be used for these.
113seealso:
114- module: aci_bd
115- module: aci_tenant
116- name: APIC Management Information Model reference
117 description: More information about the internal APIC class B(fv:Subnet).
118 link: https://developer.cisco.com/docs/apic-mim-ref/
119author:
120- Jacob McGill (@jmcgill298)
121'''
122
123EXAMPLES = r'''
124- name: Create a tenant
125 aci_tenant:
126 host: apic
127 username: admin
128 password: SomeSecretPassword
129 tenant: production
130 state: present
131 delegate_to: localhost
132
133- name: Create a bridge domain
134 aci_bd:
135 host: apic
136 username: admin
137 password: SomeSecretPassword
138 tenant: production
139 bd: database
140 state: present
141 delegate_to: localhost
142
143- name: Create a subnet
144 aci_bd_subnet:
145 host: apic
146 username: admin
147 password: SomeSecretPassword
148 tenant: production
149 bd: database
150 gateway: 10.1.1.1
151 mask: 24
152 state: present
153 delegate_to: localhost
154
155- name: Create a subnet with options
156 aci_bd_subnet:
157 host: apic
158 username: admin
159 password: SomeSecretPassword
160 tenant: production
161 bd: database
162 subnet_name: sql
163 gateway: 10.1.2.1
164 mask: 23
165 description: SQL Servers
166 scope: public
167 route_profile_l3_out: corp
168 route_profile: corp_route_profile
169 state: present
170 delegate_to: localhost
171
172- name: Update a subnets scope to private and shared
173 aci_bd_subnet:
174 host: apic
175 username: admin
176 password: SomeSecretPassword
177 tenant: production
178 bd: database
179 gateway: 10.1.1.1
180 mask: 24
181 scope: [private, shared]
182 state: present
183 delegate_to: localhost
184
185- name: Get all subnets
186 aci_bd_subnet:
187 host: apic
188 username: admin
189 password: SomeSecretPassword
190 state: query
191 delegate_to: localhost
192
193- name: Get all subnets of specific gateway in specified tenant
194 aci_bd_subnet:
195 host: apic
196 username: admin
197 password: SomeSecretPassword
198 tenant: production
199 gateway: 10.1.1.1
200 mask: 24
201 state: query
202 delegate_to: localhost
203 register: query_result
204
205- name: Get specific subnet
206 aci_bd_subnet:
207 host: apic
208 username: admin
209 password: SomeSecretPassword
210 tenant: production
211 bd: database
212 gateway: 10.1.1.1
213 mask: 24
214 state: query
215 delegate_to: localhost
216 register: query_result
217
218- name: Delete a subnet
219 aci_bd_subnet:
220 host: apic
221 username: admin
222 password: SomeSecretPassword
223 tenant: production
224 bd: database
225 gateway: 10.1.1.1
226 mask: 24
227 state: absent
228 delegate_to: localhost
229'''
230
231RETURN = r'''
232current:
233 description: The existing configuration from the APIC after the module has finished
234 returned: success
235 type: list
236 sample:
237 [
238 {
239 "fvTenant": {
240 "attributes": {
241 "descr": "Production environment",
242 "dn": "uni/tn-production",
243 "name": "production",
244 "nameAlias": "",
245 "ownerKey": "",
246 "ownerTag": ""
247 }
248 }
249 }
250 ]
251error:
252 description: The error information as returned from the APIC
253 returned: failure
254 type: dict
255 sample:
256 {
257 "code": "122",
258 "text": "unknown managed object class foo"
259 }
260raw:
261 description: The raw output returned by the APIC REST API (xml or json)
262 returned: parse error
263 type: str
264 sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
265sent:
266 description: The actual/minimal configuration pushed to the APIC
267 returned: info
268 type: list
269 sample:
270 {
271 "fvTenant": {
272 "attributes": {
273 "descr": "Production environment"
274 }
275 }
276 }
277previous:
278 description: The original configuration from the APIC before the module has started
279 returned: info
280 type: list
281 sample:
282 [
283 {
284 "fvTenant": {
285 "attributes": {
286 "descr": "Production",
287 "dn": "uni/tn-production",
288 "name": "production",
289 "nameAlias": "",
290 "ownerKey": "",
291 "ownerTag": ""
292 }
293 }
294 }
295 ]
296proposed:
297 description: The assembled configuration from the user-provided parameters
298 returned: info
299 type: dict
300 sample:
301 {
302 "fvTenant": {
303 "attributes": {
304 "descr": "Production environment",
305 "name": "production"
306 }
307 }
308 }
309filter_string:
310 description: The filter string used for the request
311 returned: failure or debug
312 type: str
313 sample: ?rsp-prop-include=config-only
314method:
315 description: The HTTP method used for the request to the APIC
316 returned: failure or debug
317 type: str
318 sample: POST
319response:
320 description: The HTTP response from the APIC
321 returned: failure or debug
322 type: str
323 sample: OK (30 bytes)
324status:
325 description: The HTTP status from the APIC
326 returned: failure or debug
327 type: int
328 sample: 200
329url:
330 description: The HTTP url used for the request to the APIC
331 returned: failure or debug
332 type: str
333 sample: https://10.11.12.13/api/mo/uni/tn-production.json
334'''
335
336from ansible.module_utils.basic import AnsibleModule
337from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
338
339SUBNET_CONTROL_MAPPING = dict(
340 nd_ra='nd',
341 no_gw='no-default-gateway',
342 querier_ip='querier',
343 unspecified='',
344)
345
346
347def main():
348 argument_spec = aci_argument_spec()
349 argument_spec.update(
350 bd=dict(type='str', aliases=['bd_name']), # Not required for querying all objects
351 description=dict(type='str', aliases=['descr']),
352 enable_vip=dict(type='bool'),
353 gateway=dict(type='str', aliases=['gateway_ip']), # Not required for querying all objects
354 mask=dict(type='int', aliases=['subnet_mask']), # Not required for querying all objects
355 subnet_name=dict(type='str', aliases=['name']),
356 nd_prefix_policy=dict(type='str'),
357 preferred=dict(type='bool'),
358 route_profile=dict(type='str'),
359 route_profile_l3_out=dict(type='str'),
360 scope=dict(type='list', choices=['private', 'public', 'shared']),
361 subnet_control=dict(type='str', choices=['nd_ra', 'no_gw', 'querier_ip', 'unspecified']),
362 state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
363 tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
364 )
365
366 module = AnsibleModule(
367 argument_spec=argument_spec,
368 supports_check_mode=True,
369 required_together=[['gateway', 'mask']],
370 required_if=[
371 ['state', 'present', ['bd', 'gateway', 'mask', 'tenant']],
372 ['state', 'absent', ['bd', 'gateway', 'mask', 'tenant']],
373 ],
374 )
375
376 aci = ACIModule(module)
377
378 description = module.params['description']
379 enable_vip = aci.boolean(module.params['enable_vip'])
380 tenant = module.params['tenant']
381 bd = module.params['bd']
382 gateway = module.params['gateway']
383 mask = module.params['mask']
384 if mask is not None and mask not in range(0, 129):
385 # TODO: split checks between IPv4 and IPv6 Addresses
386 module.fail_json(msg='Valid Subnet Masks are 0 to 32 for IPv4 Addresses and 0 to 128 for IPv6 addresses')
387 if gateway is not None:
388 gateway = '{0}/{1}'.format(gateway, str(mask))
389 subnet_name = module.params['subnet_name']
390 nd_prefix_policy = module.params['nd_prefix_policy']
391 preferred = aci.boolean(module.params['preferred'])
392 route_profile = module.params['route_profile']
393 route_profile_l3_out = module.params['route_profile_l3_out']
394 scope = module.params['scope']
395 if scope is not None:
396 if 'private' in scope and 'public' in scope:
397 module.fail_json(msg="Parameter 'scope' cannot be both 'private' and 'public', got: %s" % scope)
398 else:
399 scope = ','.join(sorted(scope))
400 state = module.params['state']
401 subnet_control = module.params['subnet_control']
402 if subnet_control:
403 subnet_control = SUBNET_CONTROL_MAPPING[subnet_control]
404
405 aci.construct_url(
406 root_class=dict(
407 aci_class='fvTenant',
408 aci_rn='tn-{0}'.format(tenant),
409 module_object=tenant,
410 target_filter={'name': tenant},
411 ),
412 subclass_1=dict(
413 aci_class='fvBD',
414 aci_rn='BD-{0}'.format(bd),
415 module_object=bd,
416 target_filter={'name': bd},
417 ),
418 subclass_2=dict(
419 aci_class='fvSubnet',
420 aci_rn='subnet-[{0}]'.format(gateway),
421 module_object=gateway,
422 target_filter={'ip': gateway},
423 ),
424 child_classes=['fvRsBDSubnetToProfile', 'fvRsNdPfxPol'],
425 )
426
427 aci.get_existing()
428
429 if state == 'present':
430 aci.payload(
431 aci_class='fvSubnet',
432 class_config=dict(
433 ctrl=subnet_control,
434 descr=description,
435 ip=gateway,
436 name=subnet_name,
437 preferred=preferred,
438 scope=scope,
439 virtual=enable_vip,
440 ),
441 child_configs=[
442 {'fvRsBDSubnetToProfile': {'attributes': {'tnL3extOutName': route_profile_l3_out, 'tnRtctrlProfileName': route_profile}}},
443 {'fvRsNdPfxPol': {'attributes': {'tnNdPfxPolName': nd_prefix_policy}}},
444 ],
445 )
446
447 aci.get_diff(aci_class='fvSubnet')
448
449 aci.post_config()
450
451 elif state == 'absent':
452 aci.delete_config()
453
454 aci.exit_json()
455
456
457if __name__ == "__main__":
458 main()