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_vrf_region_cidr_subnet.py
Go to the documentation of this file.
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4# Copyright: (c) 2019, 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_site_vrf_region_cidr_subnet
17short_description: Manage site-local VRF regions in schema template
18description:
19- Manage site-local VRF regions in schema template 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 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 vrf:
40 description:
41 - The name of the VRF.
42 type: str
43 region:
44 description:
45 - The name of the region.
46 type: str
47 cidr:
48 description:
49 - The IP range of for the region CIDR.
50 type: str
51 subnet:
52 description:
53 - The IP subnet of this region CIDR.
54 type: str
55 aliases: [ ip ]
56 zone:
57 description:
58 - The name of the zone for the region CIDR subnet.
59 type: str
60 aliases: [ name ]
61 state:
62 description:
63 - Use C(present) or C(absent) for adding or removing.
64 - Use C(query) for listing an object or multiple objects.
65 type: str
66 choices: [ absent, present, query ]
67 default: present
68notes:
69- The ACI MultiSite PATCH API has a deficiency requiring some objects to be referenced by index.
70 This can cause silent corruption on concurrent access when changing/removing on object as
71 the wrong object may be referenced. This module is affected by this deficiency.
72seealso:
73- module: mso_schema_site_vrf_region_cidr
74- module: mso_schema_template_vrf
75extends_documentation_fragment: mso
76'''
77
78EXAMPLES = r'''
79- name: Add a new site VRF region CIDR subnet
80 mso_schema_template_vrf_region_cidr_subnet:
81 host: mso_host
82 username: admin
83 password: SomeSecretPassword
84 schema: Schema1
85 site: Site1
86 template: Template1
87 vrf: VRF1
88 region: us-west-1
89 cidr: 14.14.14.1/24
90 subnet: 14.14.14.2/24
91 zone: us-west-1a
92 state: present
93 delegate_to: localhost
94
95- name: Remove a site VRF region CIDR subnet
96 mso_schema_site_vrf_region_cidr_subnet:
97 host: mso_host
98 username: admin
99 password: SomeSecretPassword
100 schema: Schema1
101 site: Site1
102 template: Template1
103 vrf: VRF1
104 region: us-west-1
105 cidr: 14.14.14.1/24
106 subnet: 14.14.14.2/24
107 state: absent
108 delegate_to: localhost
109
110- name: Query a specific site VRF region CIDR subnet
111 mso_schema_site_vrf_region_cidr_subnet:
112 host: mso_host
113 username: admin
114 password: SomeSecretPassword
115 schema: Schema1
116 site: Site1
117 template: Template1
118 vrf: VRF1
119 region: us-west-1
120 cidr: 14.14.14.1/24
121 subnet: 14.14.14.2/24
122 state: query
123 delegate_to: localhost
124 register: query_result
125
126- name: Query all site VRF region CIDR subnet
127 mso_schema_site_vrf_region_cidr_subnet:
128 host: mso_host
129 username: admin
130 password: SomeSecretPassword
131 schema: Schema1
132 site: Site1
133 template: Template1
134 vrf: VRF1
135 region: us-west-1
136 cidr: 14.14.14.1/24
137 state: query
138 delegate_to: localhost
139 register: query_result
140'''
141
142RETURN = r'''
143'''
144
145from ansible.module_utils.basic import AnsibleModule
146from ansible.module_utils.network.aci.mso import MSOModule, mso_argument_spec
147
148
149def main():
150 argument_spec = mso_argument_spec()
151 argument_spec.update(
152 schema=dict(type='str', required=True),
153 site=dict(type='str', required=True),
154 template=dict(type='str', required=True),
155 vrf=dict(type='str', required=True),
156 region=dict(type='str', required=True),
157 cidr=dict(type='str', required=True),
158 subnet=dict(type='str', aliases=['ip']), # This parameter is not required for querying all objects
159 zone=dict(type='str', aliases=['name']),
160 state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
161 )
162
163 module = AnsibleModule(
164 argument_spec=argument_spec,
165 supports_check_mode=True,
166 required_if=[
167 ['state', 'absent', ['subnet']],
168 ['state', 'present', ['subnet', 'zone']],
169 ],
170 )
171
172 schema = module.params['schema']
173 site = module.params['site']
174 template = module.params['template']
175 vrf = module.params['vrf']
176 region = module.params['region']
177 cidr = module.params['cidr']
178 subnet = module.params['subnet']
179 zone = module.params['zone']
180 state = module.params['state']
181
182 mso = MSOModule(module)
183
184 # Get schema_id
185 schema_obj = mso.get_obj('schemas', displayName=schema)
186 if not schema_obj:
187 mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
188
189 schema_path = 'schemas/{id}'.format(**schema_obj)
190 schema_id = schema_obj['id']
191
192 # Get site
193 site_id = mso.lookup_site(site)
194
195 # Get site_idx
196 sites = [(s['siteId'], s['templateName']) for s in schema_obj['sites']]
197 if (site_id, template) not in sites:
198 mso.fail_json(msg="Provided site/template '{0}-{1}' does not exist. Existing sites/templates: {2}".format(site, template, ', '.join(sites)))
199
200 # Schema-access uses indexes
201 site_idx = sites.index((site_id, template))
202 # Path-based access uses site_id-template
203 site_template = '{0}-{1}'.format(site_id, template)
204
205 # Get VRF
206 vrf_ref = mso.vrf_ref(schema_id=schema_id, template=template, vrf=vrf)
207 vrfs = [v['vrfRef'] for v in schema_obj['sites'][site_idx]['vrfs']]
208 if vrf_ref not in vrfs:
209 mso.fail_json(msg="Provided vrf '{0}' does not exist. Existing vrfs: {1}".format(vrf, ', '.join(vrfs)))
210 vrf_idx = vrfs.index(vrf_ref)
211
212 # Get Region
213 regions = [r['name'] for r in schema_obj['sites'][site_idx]['vrfs'][vrf_idx]['regions']]
214 if region not in regions:
215 mso.fail_json(msg="Provided region '{0}' does not exist. Existing regions: {1}".format(region, ', '.join(regions)))
216 region_idx = regions.index(region)
217
218 # Get CIDR
219 cidrs = [c['ip'] for c in schema_obj['sites'][site_idx]['vrfs'][vrf_idx]['regions'][region_idx]['cidrs']]
220 if cidr not in cidrs:
221 mso.fail_json(msg="Provided CIDR IP '{0}' does not exist. Existing CIDR IPs: {1}".format(cidr, ', '.join(cidrs)))
222 cidr_idx = cidrs.index(cidr)
223
224 # Get Subnet
225 subnets = [s['ip'] for s in schema_obj['sites'][site_idx]['vrfs'][vrf_idx]['regions'][region_idx]['cidrs'][cidr_idx]['subnets']]
226 if subnet is not None and subnet in subnets:
227 subnet_idx = subnets.index(subnet)
228 # FIXME: Changes based on index are DANGEROUS
229 subnet_path = '/sites/{0}/vrfs/{1}/regions/{2}/cidrs/{3}/subnets/{4}'.format(site_template, vrf, region, cidr_idx, subnet_idx)
230 mso.existing = schema_obj['sites'][site_idx]['vrfs'][vrf_idx]['regions'][region_idx]['cidrs'][cidr_idx]['subnets'][subnet_idx]
231
232 if state == 'query':
233 if subnet is None:
234 mso.existing = schema_obj['sites'][site_idx]['vrfs'][vrf_idx]['regions'][region_idx]['cidrs'][cidr_idx]['subnets']
235 elif not mso.existing:
236 mso.fail_json(msg="Subnet IP '{subnet}' not found".format(subnet=subnet))
237 mso.exit_json()
238
239 subnets_path = '/sites/{0}/vrfs/{1}/regions/{2}/cidrs/{3}/subnets'.format(site_template, vrf, region, cidr_idx)
240 ops = []
241
242 mso.previous = mso.existing
243 if state == 'absent':
244 if mso.existing:
245 mso.sent = mso.existing = {}
246 ops.append(dict(op='remove', path=subnet_path))
247
248 elif state == 'present':
249
250 payload = dict(
251 ip=subnet,
252 zone=zone,
253 )
254
255 mso.sanitize(payload, collate=True)
256
257 if mso.existing:
258 ops.append(dict(op='replace', path=subnet_path, value=mso.sent))
259 else:
260 ops.append(dict(op='add', path=subnets_path + '/-', value=mso.sent))
261
262 mso.existing = mso.proposed
263
264 if not module.check_mode:
265 mso.request(schema_path, method='PATCH', data=ops)
266
267 mso.exit_json()
268
269
270if __name__ == "__main__":
271 main()