Skip to content

Commit a1548c5

Browse files
sajaganalhercot
authored andcommitted
[minor_change] Added module to manage the Commissioning and Decommissioning of the Fabric Node
1 parent 214611f commit a1548c5

3 files changed

Lines changed: 532 additions & 0 deletions

File tree

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
#!/usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
4+
# Copyright: (c) 2025, Sabari Jaganathan (@sajagana)
5+
# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
6+
7+
from __future__ import absolute_import, division, print_function
8+
9+
__metaclass__ = type
10+
11+
ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"}
12+
13+
DOCUMENTATION = r"""
14+
---
15+
module: aci_fabric_node_decommission
16+
short_description: Manage the Commissioning and Decommissioning of the Fabric Node (fabric:RsDecommissionNode)
17+
description:
18+
- Manage the Commissioning and Decommissioning of the Fabric Node on Cisco ACI fabrics.
19+
options:
20+
pod_id:
21+
description:
22+
- The Pod ID for the Fabric Node.
23+
type: int
24+
node_id:
25+
description:
26+
- The Node ID for the Fabric Node.
27+
type: int
28+
remove_from_controller:
29+
description:
30+
- Completely deletes the node configuration from the controller during decommissioning.
31+
- To register the fabric node, use M(cisco.aci.aci_fabric_node).
32+
type: bool
33+
state:
34+
description:
35+
- Use C(present) for decommissioning the Fabric Node.
36+
- Use C(absent) for commissioning the Fabric Node.
37+
- Use C(query) for listing an object or multiple objects.
38+
type: str
39+
choices: [ absent, present, query ]
40+
default: present
41+
extends_documentation_fragment:
42+
- cisco.aci.aci
43+
- cisco.aci.annotation
44+
- cisco.aci.owner
45+
46+
seealso:
47+
- name: APIC Management Information Model reference
48+
description: More information about the internal APIC class B(fabric:RsDecommissionNode).
49+
link: https://developer.cisco.com/docs/apic-mim-ref/
50+
author:
51+
- Sabari Jaganathan (@sajagana)
52+
"""
53+
54+
EXAMPLES = r"""
55+
- name: Decommission the fabric node
56+
cisco.aci.aci_fabric_node_decommission:
57+
host: apic
58+
username: admin
59+
password: SomeSecretPassword
60+
pod_id: 1
61+
node_id: 201
62+
state: present
63+
64+
- name: Query the decommissioned fabric node
65+
cisco.aci.aci_fabric_node_decommission:
66+
host: apic
67+
username: admin
68+
password: SomeSecretPassword
69+
pod_id: 1
70+
node_id: 201
71+
state: query
72+
register: query_one
73+
74+
- name: Query all decommissioned fabric nodes
75+
cisco.aci.aci_fabric_node_decommission:
76+
host: apic
77+
username: admin
78+
password: SomeSecretPassword
79+
state: query
80+
register: query_all
81+
82+
- name: Commission the fabric node
83+
cisco.aci.aci_fabric_node_decommission:
84+
host: apic
85+
username: admin
86+
password: SomeSecretPassword
87+
pod_id: 1
88+
node_id: 201
89+
state: absent
90+
"""
91+
92+
RETURN = r"""
93+
current:
94+
description: The existing configuration from the APIC after the module has finished
95+
returned: success
96+
type: list
97+
sample:
98+
[
99+
{
100+
"fvTenant": {
101+
"attributes": {
102+
"descr": "Production environment",
103+
"dn": "uni/tn-production",
104+
"name": "production",
105+
"nameAlias": "",
106+
"ownerKey": "",
107+
"ownerTag": ""
108+
}
109+
}
110+
}
111+
]
112+
error:
113+
description: The error information as returned from the APIC
114+
returned: failure
115+
type: dict
116+
sample:
117+
{
118+
"code": "122",
119+
"text": "unknown managed object class foo"
120+
}
121+
raw:
122+
description: The raw output returned by the APIC REST API (xml or json)
123+
returned: parse error
124+
type: str
125+
sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class "/></imdata>'
126+
sent:
127+
description: The actual/minimal configuration pushed to the APIC
128+
returned: info
129+
type: list
130+
sample:
131+
{
132+
"fvTenant": {
133+
"attributes": {
134+
"descr": "Production environment"
135+
}
136+
}
137+
}
138+
previous:
139+
description: The original configuration from the APIC before the module has started
140+
returned: info
141+
type: list
142+
sample:
143+
[
144+
{
145+
"fvTenant": {
146+
"attributes": {
147+
"descr": "Production",
148+
"dn": "uni/tn-production",
149+
"name": "production",
150+
"nameAlias": "",
151+
"ownerKey": "",
152+
"ownerTag": ""
153+
}
154+
}
155+
}
156+
]
157+
proposed:
158+
description: The assembled configuration from the user-provided parameters
159+
returned: info
160+
type: dict
161+
sample:
162+
{
163+
"fvTenant": {
164+
"attributes": {
165+
"descr": "Production environment",
166+
"name": "production"
167+
}
168+
}
169+
}
170+
filter_string:
171+
description: The filter string used for the request
172+
returned: failure or debug
173+
type: str
174+
sample: ?rsp-prop-include=config-only
175+
method:
176+
description: The HTTP method used for the request to the APIC
177+
returned: failure or debug
178+
type: str
179+
sample: POST
180+
response:
181+
description: The HTTP response from the APIC
182+
returned: failure or debug
183+
type: str
184+
sample: OK (30 bytes)
185+
status:
186+
description: The HTTP status from the APIC
187+
returned: failure or debug
188+
type: int
189+
sample: 200
190+
url:
191+
description: The HTTP url used for the request to the APIC
192+
returned: failure or debug
193+
type: str
194+
sample: https://10.11.12.13/api/mo/uni/tn-production.json
195+
"""
196+
197+
from ansible.module_utils.basic import AnsibleModule
198+
from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec
199+
200+
201+
def main():
202+
argument_spec = aci_argument_spec()
203+
argument_spec.update(aci_annotation_spec())
204+
argument_spec.update(aci_owner_spec())
205+
argument_spec.update(
206+
pod_id=dict(type="int"),
207+
node_id=dict(type="int"),
208+
remove_from_controller=dict(type="bool"),
209+
state=dict(type="str", default="present", choices=["absent", "present", "query"]),
210+
)
211+
212+
module = AnsibleModule(
213+
argument_spec=argument_spec,
214+
supports_check_mode=True,
215+
required_if=[
216+
["state", "present", ["pod_id", "node_id"]],
217+
["state", "absent", ["pod_id", "node_id"]],
218+
],
219+
)
220+
221+
pod_id = module.params.get("pod_id")
222+
node_id = module.params.get("node_id")
223+
remove_from_controller = module.params.get("remove_from_controller")
224+
state = module.params.get("state")
225+
226+
aci = ACIModule(module)
227+
228+
aci.construct_url(
229+
root_class=dict(
230+
aci_class="fabricOOServicePol",
231+
aci_rn="fabric/outofsvc",
232+
),
233+
subclass_1=dict(
234+
aci_class="fabricRsDecommissionNode",
235+
aci_rn="rsdecommissionNode-[topology/pod-{0}/node-{1}]".format(pod_id, node_id),
236+
target_filter={},
237+
),
238+
)
239+
240+
aci.get_existing()
241+
242+
if state == "present": # Decommission
243+
aci.payload(
244+
aci_class="fabricRsDecommissionNode",
245+
class_config=dict(
246+
tDn="topology/pod-{0}/node-{1}".format(pod_id, node_id),
247+
removeFromController="yes" if remove_from_controller else "no",
248+
),
249+
)
250+
aci.get_diff(aci_class="fabricRsDecommissionNode")
251+
aci.post_config()
252+
253+
elif state == "absent": # Commission
254+
aci.payload(
255+
aci_class="fabricRsDecommissionNode",
256+
class_config=dict(
257+
tDn="topology/pod-{0}/node-{1}".format(pod_id, node_id),
258+
status="deleted",
259+
),
260+
)
261+
262+
if aci.existing:
263+
aci.get_diff(aci_class="fabricRsDecommissionNode")
264+
aci.post_config()
265+
266+
aci.exit_json()
267+
268+
269+
if __name__ == "__main__":
270+
main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# No ACI simulator yet, so not enabled
2+
# unsupported

0 commit comments

Comments
 (0)