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_bd_subnet.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_bd_subnet
17short_description: Manage BD subnets in schema templates
18description:
19- Manage BD subnets 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 to change.
32 type: str
33 required: yes
34 bd:
35 description:
36 - The name of the BD to manage.
37 type: str
38 required: yes
39 subnet:
40 description:
41 - The IP range in CIDR notation.
42 type: str
43 required: true
44 aliases: [ ip ]
45 description:
46 description:
47 - The description of this subnet.
48 type: str
49 scope:
50 description:
51 - The scope of the subnet.
52 type: str
53 choices: [ private, public ]
54 shared:
55 description:
56 - Whether this subnet is shared between VRFs.
57 type: bool
58 no_default_gateway:
59 description:
60 - Whether this subnet has a default gateway.
61 type: bool
62 state:
63 description:
64 - Use C(present) or C(absent) for adding or removing.
65 - Use C(query) for listing an object or multiple objects.
66 type: str
67 choices: [ absent, present, query ]
68 default: present
69notes:
70- Due to restrictions of the MSO REST API concurrent modifications to BD subnets can be dangerous and corrupt data.
71extends_documentation_fragment: mso
72'''
73
74EXAMPLES = r'''
75- name: Add a new subnet to a BD
76 mso_schema_template_bd_subnet:
77 host: mso_host
78 username: admin
79 password: SomeSecretPassword
80 schema: Schema 1
81 template: Template 1
82 bd: BD 1
83 subnet: 10.0.0.0/24
84 state: present
85 delegate_to: localhost
86
87- name: Remove a subset from a BD
88 mso_schema_template_bd_subnet:
89 host: mso_host
90 username: admin
91 password: SomeSecretPassword
92 schema: Schema 1
93 template: Template 1
94 bd: BD 1
95 subnet: 10.0.0.0/24
96 state: absent
97 delegate_to: localhost
98
99- name: Query a specific BD subnet
100 mso_schema_template_bd_subnet:
101 host: mso_host
102 username: admin
103 password: SomeSecretPassword
104 schema: Schema 1
105 template: Template 1
106 bd: BD 1
107 subnet: 10.0.0.0/24
108 state: query
109 delegate_to: localhost
110 register: query_result
111
112- name: Query all BD subnets
113 mso_schema_template_bd_subnet:
114 host: mso_host
115 username: admin
116 password: SomeSecretPassword
117 schema: Schema 1
118 template: Template 1
119 bd: BD 1
120 state: query
121 delegate_to: localhost
122 register: query_result
123'''
124
125RETURN = r'''
126'''
127
128from ansible.module_utils.basic import AnsibleModule
129from ansible.module_utils.network.aci.mso import MSOModule, mso_argument_spec, mso_reference_spec, mso_subnet_spec
130
131
132def main():
133 argument_spec = mso_argument_spec()
134 argument_spec.update(
135 schema=dict(type='str', required=True),
136 template=dict(type='str', required=True),
137 bd=dict(type='str', required=True),
138 state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
139 )
140 argument_spec.update(mso_subnet_spec())
141
142 module = AnsibleModule(
143 argument_spec=argument_spec,
144 supports_check_mode=True,
145 required_if=[
146 ['state', 'absent', ['subnet']],
147 ['state', 'present', ['subnet']],
148 ],
149 )
150
151 schema = module.params['schema']
152 template = module.params['template']
153 bd = module.params['bd']
154 subnet = module.params['subnet']
155 description = module.params['description']
156 scope = module.params['scope']
157 shared = module.params['shared']
158 no_default_gateway = module.params['no_default_gateway']
159 state = module.params['state']
160
161 mso = MSOModule(module)
162
163 # Get schema
164 schema_obj = mso.get_obj('schemas', displayName=schema)
165 if not schema_obj:
166 mso.fail_json(msg="Provided schema '{0}' does not exist".format(schema))
167
168 schema_path = 'schemas/{id}'.format(**schema_obj)
169
170 # Get template
171 templates = [t['name'] for t in schema_obj['templates']]
172 if template not in templates:
173 mso.fail_json(msg="Provided template '{0}' does not exist. Existing templates: {1}".format(template, ', '.join(templates)))
174 template_idx = templates.index(template)
175
176 # Get BD
177 bds = [b['name'] for b in schema_obj['templates'][template_idx]['bds']]
178 if bd not in bds:
179 mso.fail_json(msg="Provided BD '{0}' does not exist. Existing BDs: {1}".format(bd, ', '.join(bds)))
180 bd_idx = bds.index(bd)
181
182 # Get Subnet
183 subnets = [s['ip'] for s in schema_obj['templates'][template_idx]['bds'][bd_idx]['subnets']]
184 if subnet in subnets:
185 subnet_idx = subnets.index(subnet)
186 # FIXME: Changes based on index are DANGEROUS
187 subnet_path = '/templates/{0}/bds/{1}/subnets/{2}'.format(template, bd, subnet_idx)
188 mso.existing = schema_obj['templates'][template_idx]['bds'][bd_idx]['subnets'][subnet_idx]
189
190 if state == 'query':
191 if subnet is None:
192 mso.existing = schema_obj['templates'][template_idx]['bds'][bd_idx]['subnets']
193 elif not mso.existing:
194 mso.fail_json(msg="Subnet IP '{subnet}' not found".format(subnet=subnet))
195 mso.exit_json()
196
197 subnets_path = '/templates/{0}/bds/{1}/subnets'.format(template, bd)
198 ops = []
199
200 mso.previous = mso.existing
201 if state == 'absent':
202 if mso.existing:
203 mso.sent = mso.existing = {}
204 ops.append(dict(op='remove', path=subnet_path))
205
206 elif state == 'present':
207 if not mso.existing:
208 if description is None:
209 description = subnet
210 if scope is None:
211 scope = 'private'
212 if shared is None:
213 shared = False
214 if no_default_gateway is None:
215 no_default_gateway = False
216
217 payload = dict(
218 ip=subnet,
219 description=description,
220 scope=scope,
221 shared=shared,
222 noDefaultGateway=no_default_gateway,
223 )
224
225 mso.sanitize(payload, collate=True)
226
227 if mso.existing:
228 ops.append(dict(op='replace', path=subnet_path, value=mso.sent))
229 else:
230 ops.append(dict(op='add', path=subnets_path + '/-', value=mso.sent))
231
232 mso.existing = mso.proposed
233
234 if not module.check_mode:
235 mso.request(schema_path, method='PATCH', data=ops)
236
237 mso.exit_json()
238
239
240if __name__ == "__main__":
241 main()