1#!/usr/bin/python
2
3# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
4
5from __future__ import absolute_import, division, print_function
6__metaclass__ = type
7
8
9ANSIBLE_METADATA = {
10    'metadata_version': '1.1',
11    'status': ['preview'],
12    'supported_by': 'community'
13}
14
15DOCUMENTATION = '''
16---
17module: aci_firmware_group_node
18
19short_description: This modules adds and remove nodes from the firmware group
20
21version_added: "2.8"
22
23description:
24    - This module addes/deletes a node to the firmware group. This modules assigns 1 node at a time.
25
26options:
27    group:
28        description:
29            - This is the name of the firmware group
30        required: true
31    node:
32        description:
33            - The node to be added to the firmware group - the value equals the NodeID
34        required: true
35    state:
36        description:
37            - Use C(present) or C(absent) for adding or removing.
38            - Use C(query) for listing an object or multiple objects.
39        default: present
40        choices: [ absent, present, query ]
41
42extends_documentation_fragment:
43    - aci
44
45author:
46    - Steven Gerhart (@sgerhart)
47'''
48
49EXAMPLES = '''
50    - name: add firmware group node
51      aci_firmware_group_node:
52        host: "{{ inventory_hostname }}"
53        username: "{{ user }}"
54        password: "{{ pass }}"
55        validate_certs: no
56        group: testingfwgrp
57        node: 1001
58        state: present
59    - name: Remove firmware group node
60      aci_firmware_group_node:
61        host: "{{ inventory_hostname }}"
62        username: "{{ user }}"
63        password: "{{ pass }}"
64        validate_certs: no
65        group: testingfwgrp
66        node: 1001
67        state: absent
68'''
69
70RETURN = '''
71current:
72  description: The existing configuration from the APIC after the module has finished
73  returned: success
74  type: list
75  sample:
76    [
77        {
78            "fvTenant": {
79                "attributes": {
80                    "descr": "Production environment",
81                    "dn": "uni/tn-production",
82                    "name": "production",
83                    "nameAlias": "",
84                    "ownerKey": "",
85                    "ownerTag": ""
86                }
87            }
88        }
89    ]
90error:
91  description: The error information as returned from the APIC
92  returned: failure
93  type: dict
94  sample:
95    {
96        "code": "122",
97        "text": "unknown managed object class foo"
98    }
99raw:
100  description: The raw output returned by the APIC REST API (xml or json)
101  returned: parse error
102  type: str
103  sample: '<?xml version="1.0" encoding="UTF-8"?><imdata totalCount="1"><error code="122" text="unknown managed object class foo"/></imdata>'
104sent:
105  description: The actual/minimal configuration pushed to the APIC
106  returned: info
107  type: list
108  sample:
109    {
110        "fvTenant": {
111            "attributes": {
112                "descr": "Production environment"
113            }
114        }
115    }
116previous:
117  description: The original configuration from the APIC before the module has started
118  returned: info
119  type: list
120  sample:
121    [
122        {
123            "fvTenant": {
124                "attributes": {
125                    "descr": "Production",
126                    "dn": "uni/tn-production",
127                    "name": "production",
128                    "nameAlias": "",
129                    "ownerKey": "",
130                    "ownerTag": ""
131                }
132            }
133        }
134    ]
135proposed:
136  description: The assembled configuration from the user-provided parameters
137  returned: info
138  type: dict
139  sample:
140    {
141        "fvTenant": {
142            "attributes": {
143                "descr": "Production environment",
144                "name": "production"
145            }
146        }
147    }
148filter_string:
149  description: The filter string used for the request
150  returned: failure or debug
151  type: str
152  sample: ?rsp-prop-include=config-only
153method:
154  description: The HTTP method used for the request to the APIC
155  returned: failure or debug
156  type: str
157  sample: POST
158response:
159  description: The HTTP response from the APIC
160  returned: failure or debug
161  type: str
162  sample: OK (30 bytes)
163status:
164  description: The HTTP status from the APIC
165  returned: failure or debug
166  type: int
167  sample: 200
168url:
169  description: The HTTP url used for the request to the APIC
170  returned: failure or debug
171  type: str
172  sample: https://10.11.12.13/api/mo/uni/tn-production.json
173'''
174
175import json
176from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
177from ansible.module_utils.basic import AnsibleModule
178
179
180def main():
181    argument_spec = aci_argument_spec()
182    argument_spec.update(
183        group=dict(type='str', aliases=['group']),  # Not required for querying all objects
184        node=dict(type='str', aliases=['node']),
185        state=dict(type='str', default='present', choices=['absent', 'present', 'query']),
186    )
187
188    module = AnsibleModule(
189        argument_spec=argument_spec,
190        supports_check_mode=True,
191        required_if=[
192            ['state', 'absent', ['node', 'group']],
193            ['state', 'present', ['node', 'group']],
194        ],
195    )
196
197    state = module.params['state']
198    group = module.params['group']
199    node = module.params['node']
200
201    aci = ACIModule(module)
202    aci.construct_url(
203        root_class=dict(
204            aci_class='firmwareFwGrp',
205            aci_rn='fabric/fwgrp-{0}'.format(group),
206            target_filter={'name': group},
207            module_object=group,
208        ),
209        subclass_1=dict(
210            aci_class='fabricNodeBlk',
211            aci_rn='nodeblk-blk{0}-{0}'.format(node),
212            target_filter={'name': node},
213            module_object=node,
214        ),
215
216    )
217
218    aci.get_existing()
219
220    if state == 'present':
221        aci.payload(
222            aci_class='fabricNodeBlk',
223            class_config=dict(
224                from_=node,
225                to_=node,
226            ),
227
228
229        )
230
231        aci.get_diff(aci_class='fabricNodeBlk')
232
233        aci.post_config()
234
235    elif state == 'absent':
236        aci.delete_config()
237
238    aci.exit_json()
239
240
241if __name__ == "__main__":
242    main()
243