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