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_fabric_node.py
Go to the documentation of this file.
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4# Copyright: (c) 2017, Bruno Calogero <brunocalogero@hotmail.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': 'certified'}
13
14DOCUMENTATION = r'''
15---
16module: aci_fabric_node
17short_description: Manage Fabric Node Members (fabric:NodeIdentP)
18description:
19- Manage Fabric Node Members on Cisco ACI fabrics.
20version_added: '2.5'
21options:
22 pod_id:
23 description:
24 - The pod id of the new Fabric Node Member.
25 type: int
26 serial:
27 description:
28 - Serial Number for the new Fabric Node Member.
29 type: str
30 aliases: [ serial_number ]
31 node_id:
32 description:
33 - Node ID Number for the new Fabric Node Member.
34 type: int
35 switch:
36 description:
37 - Switch Name for the new Fabric Node Member.
38 type: str
39 aliases: [ name, switch_name ]
40 description:
41 description:
42 - Description for the new Fabric Node Member.
43 type: str
44 aliases: [ descr ]
45 role:
46 description:
47 - Role for the new Fabric Node Member.
48 type: str
49 aliases: [ role_name ]
50 choices: [ leaf, spine, unspecified ]
51 state:
52 description:
53 - Use C(present) or C(absent) for adding or removing.
54 - Use C(query) for listing an object or multiple objects.
55 type: str
56 choices: [ absent, present, query ]
57 default: present
58extends_documentation_fragment: aci
59seealso:
60- name: APIC Management Information Model reference
61 description: More information about the internal APIC class B(fabric:NodeIdentP).
62 link: https://developer.cisco.com/docs/apic-mim-ref/
63author:
64- Bruno Calogero (@brunocalogero)
65'''
66
67EXAMPLES = r'''
68- name: Add fabric node
69 aci_fabric_node:
70 host: apic
71 username: admin
72 password: SomeSecretPassword
73 serial: FDO2031124L
74 node_id: 1011
75 switch: fab4-sw1011
76 state: present
77 delegate_to: localhost
78
79- name: Remove fabric node
80 aci_fabric_node:
81 host: apic
82 username: admin
83 password: SomeSecretPassword
84 serial: FDO2031124L
85 node_id: 1011
86 state: absent
87 delegate_to: localhost
88
89- name: Query fabric nodes
90 aci_fabric_node:
91 host: apic
92 username: admin
93 password: SomeSecretPassword
94 state: query
95 delegate_to: localhost
96 register: query_result
97'''
98
99RETURN = r'''
100current:
101 description: The existing configuration from the APIC after the module has finished
102 returned: success
103 type: list
104 sample:
105 [
106 {
107 "fvTenant": {
108 "attributes": {
109 "descr": "Production environment",
110 "dn": "uni/tn-production",
111 "name": "production",
112 "nameAlias": "",
113 "ownerKey": "",
114 "ownerTag": ""
115 }
116 }
117 }
118 ]
119error:
120 description: The error information as returned from the APIC
121 returned: failure
122 type: dict
123 sample:
124 {
125 "code": "122",
126 "text": "unknown managed object class foo"
127 }
128raw:
129 description: The raw output returned by the APIC REST API (xml or json)
130 returned: parse error
131 type: str
132 sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
133sent:
134 description: The actual/minimal configuration pushed to the APIC
135 returned: info
136 type: list
137 sample:
138 {
139 "fvTenant": {
140 "attributes": {
141 "descr": "Production environment"
142 }
143 }
144 }
145previous:
146 description: The original configuration from the APIC before the module has started
147 returned: info
148 type: list
149 sample:
150 [
151 {
152 "fvTenant": {
153 "attributes": {
154 "descr": "Production",
155 "dn": "uni/tn-production",
156 "name": "production",
157 "nameAlias": "",
158 "ownerKey": "",
159 "ownerTag": ""
160 }
161 }
162 }
163 ]
164proposed:
165 description: The assembled configuration from the user-provided parameters
166 returned: info
167 type: dict
168 sample:
169 {
170 "fvTenant": {
171 "attributes": {
172 "descr": "Production environment",
173 "name": "production"
174 }
175 }
176 }
177filter_string:
178 description: The filter string used for the request
179 returned: failure or debug
180 type: str
181 sample: '?rsp-prop-include=config-only'
182method:
183 description: The HTTP method used for the request to the APIC
184 returned: failure or debug
185 type: str
186 sample: POST
187response:
188 description: The HTTP response from the APIC
189 returned: failure or debug
190 type: str
191 sample: OK (30 bytes)
192status:
193 description: The HTTP status from the APIC
194 returned: failure or debug
195 type: int
196 sample: 200
197url:
198 description: The HTTP url used for the request to the APIC
199 returned: failure or debug
200 type: str
201 sample: https://10.11.12.13/api/mo/uni/tn-production.json
202'''
203
204from ansible.module_utils.basic import AnsibleModule
205from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
206
207
208# NOTE: (This problem is also present on the APIC GUI)
209# NOTE: When specifying a C(role) the new Fabric Node Member will be created but Role on GUI will be "unknown", hence not what seems to be a module problem
210
211def main():
212 argument_spec = aci_argument_spec()
213 argument_spec.update(
214 description=dict(type='str', aliases=['descr']),
215 node_id=dict(type='int'), # Not required for querying all objects
216 pod_id=dict(type='int'),
217 role=dict(type='str', choices=['leaf', 'spine', 'unspecified'], aliases=['role_name']),
218 serial=dict(type='str', aliases=['serial_number']), # Not required for querying all objects
219 switch=dict(type='str', aliases=['name', 'switch_name']),
220 state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
221 )
222
223 module = AnsibleModule(
224 argument_spec=argument_spec,
225 supports_check_mode=True,
226 required_if=[
227 ['state', 'absent', ['node_id', 'serial']],
228 ['state', 'present', ['node_id', 'serial']],
229 ],
230 )
231
232 pod_id = module.params['pod_id']
233 serial = module.params['serial']
234 node_id = module.params['node_id']
235 switch = module.params['switch']
236 description = module.params['description']
237 role = module.params['role']
238 state = module.params['state']
239
240 aci = ACIModule(module)
241 aci.construct_url(
242 root_class=dict(
243 aci_class='fabricNodeIdentP',
244 aci_rn='controller/nodeidentpol/nodep-{0}'.format(serial),
245 module_object=serial,
246 target_filter={'serial': serial},
247 )
248 )
249
250 aci.get_existing()
251
252 if state == 'present':
253 aci.payload(
254 aci_class='fabricNodeIdentP',
255 class_config=dict(
256 descr=description,
257 name=switch,
258 nodeId=node_id,
259 podId=pod_id,
260 # NOTE: Originally we were sending 'rn', but now we need 'dn' for idempotency
261 # FIXME: Did this change with ACI version ?
262 dn='uni/controller/nodeidentpol/nodep-{0}'.format(serial),
263 # rn='nodep-{0}'.format(serial),
264 role=role,
265 serial=serial,
266 )
267 )
268
269 aci.get_diff(aci_class='fabricNodeIdentP')
270
271 aci.post_config()
272
273 elif state == 'absent':
274 aci.delete_config()
275
276 aci.exit_json(**aci.result)
277
278
279if __name__ == "__main__":
280 main()