1#!/usr/bin/python 2from __future__ import (absolute_import, division, print_function) 3# Copyright 2019 Fortinet, Inc. 4# 5# This program is free software: you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation, either version 3 of the License, or 8# (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program. If not, see <https://www.gnu.org/licenses/>. 17 18__metaclass__ = type 19 20ANSIBLE_METADATA = {'status': ['preview'], 21 'supported_by': 'community', 22 'metadata_version': '1.1'} 23 24DOCUMENTATION = ''' 25--- 26module: fortios_switch_controller_switch_interface_tag 27short_description: Configure switch object tags in Fortinet's FortiOS and FortiGate. 28description: 29 - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the 30 user to set and modify switch_controller feature and switch_interface_tag category. 31 Examples include all parameters and values need to be adjusted to datasources before usage. 32 Tested with FOS v6.0.5 33version_added: "2.9" 34author: 35 - Miguel Angel Munoz (@mamunozgonzalez) 36 - Nicolas Thomas (@thomnico) 37notes: 38 - Requires fortiosapi library developed by Fortinet 39 - Run as a local_action in your playbook 40requirements: 41 - fortiosapi>=0.9.8 42options: 43 host: 44 description: 45 - FortiOS or FortiGate IP address. 46 type: str 47 required: false 48 username: 49 description: 50 - FortiOS or FortiGate username. 51 type: str 52 required: false 53 password: 54 description: 55 - FortiOS or FortiGate password. 56 type: str 57 default: "" 58 vdom: 59 description: 60 - Virtual domain, among those defined previously. A vdom is a 61 virtual instance of the FortiGate that can be configured and 62 used as a different unit. 63 type: str 64 default: root 65 https: 66 description: 67 - Indicates if the requests towards FortiGate must use HTTPS protocol. 68 type: bool 69 default: true 70 ssl_verify: 71 description: 72 - Ensures FortiGate certificate must be verified by a proper CA. 73 type: bool 74 default: true 75 state: 76 description: 77 - Indicates whether to create or remove the object. 78 type: str 79 required: true 80 choices: 81 - present 82 - absent 83 switch_controller_switch_interface_tag: 84 description: 85 - Configure switch object tags. 86 default: null 87 type: dict 88 suboptions: 89 name: 90 description: 91 - Tag name. 92 required: true 93 type: str 94''' 95 96EXAMPLES = ''' 97- hosts: localhost 98 vars: 99 host: "192.168.122.40" 100 username: "admin" 101 password: "" 102 vdom: "root" 103 ssl_verify: "False" 104 tasks: 105 - name: Configure switch object tags. 106 fortios_switch_controller_switch_interface_tag: 107 host: "{{ host }}" 108 username: "{{ username }}" 109 password: "{{ password }}" 110 vdom: "{{ vdom }}" 111 https: "False" 112 state: "present" 113 switch_controller_switch_interface_tag: 114 name: "default_name_3" 115''' 116 117RETURN = ''' 118build: 119 description: Build number of the fortigate image 120 returned: always 121 type: str 122 sample: '1547' 123http_method: 124 description: Last method used to provision the content into FortiGate 125 returned: always 126 type: str 127 sample: 'PUT' 128http_status: 129 description: Last result given by FortiGate on last operation applied 130 returned: always 131 type: str 132 sample: "200" 133mkey: 134 description: Master key (id) used in the last call to FortiGate 135 returned: success 136 type: str 137 sample: "id" 138name: 139 description: Name of the table used to fulfill the request 140 returned: always 141 type: str 142 sample: "urlfilter" 143path: 144 description: Path of the table used to fulfill the request 145 returned: always 146 type: str 147 sample: "webfilter" 148revision: 149 description: Internal revision number 150 returned: always 151 type: str 152 sample: "17.0.2.10658" 153serial: 154 description: Serial number of the unit 155 returned: always 156 type: str 157 sample: "FGVMEVYYQT3AB5352" 158status: 159 description: Indication of the operation's result 160 returned: always 161 type: str 162 sample: "success" 163vdom: 164 description: Virtual domain used 165 returned: always 166 type: str 167 sample: "root" 168version: 169 description: Version of the FortiGate 170 returned: always 171 type: str 172 sample: "v5.6.3" 173 174''' 175 176from ansible.module_utils.basic import AnsibleModule 177from ansible.module_utils.connection import Connection 178from ansible.module_utils.network.fortios.fortios import FortiOSHandler 179from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG 180 181 182def login(data, fos): 183 host = data['host'] 184 username = data['username'] 185 password = data['password'] 186 ssl_verify = data['ssl_verify'] 187 188 fos.debug('on') 189 if 'https' in data and not data['https']: 190 fos.https('off') 191 else: 192 fos.https('on') 193 194 fos.login(host, username, password, verify=ssl_verify) 195 196 197def filter_switch_controller_switch_interface_tag_data(json): 198 option_list = ['name'] 199 dictionary = {} 200 201 for attribute in option_list: 202 if attribute in json and json[attribute] is not None: 203 dictionary[attribute] = json[attribute] 204 205 return dictionary 206 207 208def underscore_to_hyphen(data): 209 if isinstance(data, list): 210 for elem in data: 211 elem = underscore_to_hyphen(elem) 212 elif isinstance(data, dict): 213 new_data = {} 214 for k, v in data.items(): 215 new_data[k.replace('_', '-')] = underscore_to_hyphen(v) 216 data = new_data 217 218 return data 219 220 221def switch_controller_switch_interface_tag(data, fos): 222 vdom = data['vdom'] 223 state = data['state'] 224 switch_controller_switch_interface_tag_data = data['switch_controller_switch_interface_tag'] 225 filtered_data = underscore_to_hyphen(filter_switch_controller_switch_interface_tag_data(switch_controller_switch_interface_tag_data)) 226 227 if state == "present": 228 return fos.set('switch-controller', 229 'switch-interface-tag', 230 data=filtered_data, 231 vdom=vdom) 232 233 elif state == "absent": 234 return fos.delete('switch-controller', 235 'switch-interface-tag', 236 mkey=filtered_data['name'], 237 vdom=vdom) 238 239 240def is_successful_status(status): 241 return status['status'] == "success" or \ 242 status['http_method'] == "DELETE" and status['http_status'] == 404 243 244 245def fortios_switch_controller(data, fos): 246 247 if data['switch_controller_switch_interface_tag']: 248 resp = switch_controller_switch_interface_tag(data, fos) 249 250 return not is_successful_status(resp), \ 251 resp['status'] == "success", \ 252 resp 253 254 255def main(): 256 fields = { 257 "host": {"required": False, "type": "str"}, 258 "username": {"required": False, "type": "str"}, 259 "password": {"required": False, "type": "str", "default": "", "no_log": True}, 260 "vdom": {"required": False, "type": "str", "default": "root"}, 261 "https": {"required": False, "type": "bool", "default": True}, 262 "ssl_verify": {"required": False, "type": "bool", "default": True}, 263 "state": {"required": True, "type": "str", 264 "choices": ["present", "absent"]}, 265 "switch_controller_switch_interface_tag": { 266 "required": False, "type": "dict", "default": None, 267 "options": { 268 "name": {"required": True, "type": "str"} 269 270 } 271 } 272 } 273 274 module = AnsibleModule(argument_spec=fields, 275 supports_check_mode=False) 276 277 # legacy_mode refers to using fortiosapi instead of HTTPAPI 278 legacy_mode = 'host' in module.params and module.params['host'] is not None and \ 279 'username' in module.params and module.params['username'] is not None and \ 280 'password' in module.params and module.params['password'] is not None 281 282 if not legacy_mode: 283 if module._socket_path: 284 connection = Connection(module._socket_path) 285 fos = FortiOSHandler(connection) 286 287 is_error, has_changed, result = fortios_switch_controller(module.params, fos) 288 else: 289 module.fail_json(**FAIL_SOCKET_MSG) 290 else: 291 try: 292 from fortiosapi import FortiOSAPI 293 except ImportError: 294 module.fail_json(msg="fortiosapi module is required") 295 296 fos = FortiOSAPI() 297 298 login(module.params, fos) 299 is_error, has_changed, result = fortios_switch_controller(module.params, fos) 300 fos.logout() 301 302 if not is_error: 303 module.exit_json(changed=has_changed, meta=result) 304 else: 305 module.fail_json(msg="Error in repo", meta=result) 306 307 308if __name__ == '__main__': 309 main() 310