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_wireless_controller_hotspot20_anqp_3gpp_cellular 27short_description: Configure 3GPP public land mobile network (PLMN) 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 wireless_controller_hotspot20 feature and anqp_3gpp_cellular 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 wireless_controller_hotspot20_anqp_3gpp_cellular: 84 description: 85 - Configure 3GPP public land mobile network (PLMN). 86 default: null 87 type: dict 88 suboptions: 89 mcc_mnc_list: 90 description: 91 - Mobile Country Code and Mobile Network Code configuration. 92 type: list 93 suboptions: 94 id: 95 description: 96 - ID. 97 required: true 98 type: int 99 mcc: 100 description: 101 - Mobile country code. 102 type: str 103 mnc: 104 description: 105 - Mobile network code. 106 type: str 107 name: 108 description: 109 - 3GPP PLMN name. 110 required: true 111 type: str 112''' 113 114EXAMPLES = ''' 115- hosts: localhost 116 vars: 117 host: "192.168.122.40" 118 username: "admin" 119 password: "" 120 vdom: "root" 121 ssl_verify: "False" 122 tasks: 123 - name: Configure 3GPP public land mobile network (PLMN). 124 fortios_wireless_controller_hotspot20_anqp_3gpp_cellular: 125 host: "{{ host }}" 126 username: "{{ username }}" 127 password: "{{ password }}" 128 vdom: "{{ vdom }}" 129 https: "False" 130 state: "present" 131 wireless_controller_hotspot20_anqp_3gpp_cellular: 132 mcc_mnc_list: 133 - 134 id: "4" 135 mcc: "<your_own_value>" 136 mnc: "<your_own_value>" 137 name: "default_name_7" 138''' 139 140RETURN = ''' 141build: 142 description: Build number of the fortigate image 143 returned: always 144 type: str 145 sample: '1547' 146http_method: 147 description: Last method used to provision the content into FortiGate 148 returned: always 149 type: str 150 sample: 'PUT' 151http_status: 152 description: Last result given by FortiGate on last operation applied 153 returned: always 154 type: str 155 sample: "200" 156mkey: 157 description: Master key (id) used in the last call to FortiGate 158 returned: success 159 type: str 160 sample: "id" 161name: 162 description: Name of the table used to fulfill the request 163 returned: always 164 type: str 165 sample: "urlfilter" 166path: 167 description: Path of the table used to fulfill the request 168 returned: always 169 type: str 170 sample: "webfilter" 171revision: 172 description: Internal revision number 173 returned: always 174 type: str 175 sample: "17.0.2.10658" 176serial: 177 description: Serial number of the unit 178 returned: always 179 type: str 180 sample: "FGVMEVYYQT3AB5352" 181status: 182 description: Indication of the operation's result 183 returned: always 184 type: str 185 sample: "success" 186vdom: 187 description: Virtual domain used 188 returned: always 189 type: str 190 sample: "root" 191version: 192 description: Version of the FortiGate 193 returned: always 194 type: str 195 sample: "v5.6.3" 196 197''' 198 199from ansible.module_utils.basic import AnsibleModule 200from ansible.module_utils.connection import Connection 201from ansible.module_utils.network.fortios.fortios import FortiOSHandler 202from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG 203 204 205def login(data, fos): 206 host = data['host'] 207 username = data['username'] 208 password = data['password'] 209 ssl_verify = data['ssl_verify'] 210 211 fos.debug('on') 212 if 'https' in data and not data['https']: 213 fos.https('off') 214 else: 215 fos.https('on') 216 217 fos.login(host, username, password, verify=ssl_verify) 218 219 220def filter_wireless_controller_hotspot20_anqp_3gpp_cellular_data(json): 221 option_list = ['mcc_mnc_list', 'name'] 222 dictionary = {} 223 224 for attribute in option_list: 225 if attribute in json and json[attribute] is not None: 226 dictionary[attribute] = json[attribute] 227 228 return dictionary 229 230 231def underscore_to_hyphen(data): 232 if isinstance(data, list): 233 for elem in data: 234 elem = underscore_to_hyphen(elem) 235 elif isinstance(data, dict): 236 new_data = {} 237 for k, v in data.items(): 238 new_data[k.replace('_', '-')] = underscore_to_hyphen(v) 239 data = new_data 240 241 return data 242 243 244def wireless_controller_hotspot20_anqp_3gpp_cellular(data, fos): 245 vdom = data['vdom'] 246 state = data['state'] 247 wireless_controller_hotspot20_anqp_3gpp_cellular_data = data['wireless_controller_hotspot20_anqp_3gpp_cellular'] 248 filtered_data = underscore_to_hyphen(filter_wireless_controller_hotspot20_anqp_3gpp_cellular_data(wireless_controller_hotspot20_anqp_3gpp_cellular_data)) 249 250 if state == "present": 251 return fos.set('wireless-controller.hotspot20', 252 'anqp-3gpp-cellular', 253 data=filtered_data, 254 vdom=vdom) 255 256 elif state == "absent": 257 return fos.delete('wireless-controller.hotspot20', 258 'anqp-3gpp-cellular', 259 mkey=filtered_data['name'], 260 vdom=vdom) 261 262 263def is_successful_status(status): 264 return status['status'] == "success" or \ 265 status['http_method'] == "DELETE" and status['http_status'] == 404 266 267 268def fortios_wireless_controller_hotspot20(data, fos): 269 270 if data['wireless_controller_hotspot20_anqp_3gpp_cellular']: 271 resp = wireless_controller_hotspot20_anqp_3gpp_cellular(data, fos) 272 273 return not is_successful_status(resp), \ 274 resp['status'] == "success", \ 275 resp 276 277 278def main(): 279 fields = { 280 "host": {"required": False, "type": "str"}, 281 "username": {"required": False, "type": "str"}, 282 "password": {"required": False, "type": "str", "default": "", "no_log": True}, 283 "vdom": {"required": False, "type": "str", "default": "root"}, 284 "https": {"required": False, "type": "bool", "default": True}, 285 "ssl_verify": {"required": False, "type": "bool", "default": True}, 286 "state": {"required": True, "type": "str", 287 "choices": ["present", "absent"]}, 288 "wireless_controller_hotspot20_anqp_3gpp_cellular": { 289 "required": False, "type": "dict", "default": None, 290 "options": { 291 "mcc_mnc_list": {"required": False, "type": "list", 292 "options": { 293 "id": {"required": True, "type": "int"}, 294 "mcc": {"required": False, "type": "str"}, 295 "mnc": {"required": False, "type": "str"} 296 }}, 297 "name": {"required": True, "type": "str"} 298 299 } 300 } 301 } 302 303 module = AnsibleModule(argument_spec=fields, 304 supports_check_mode=False) 305 306 # legacy_mode refers to using fortiosapi instead of HTTPAPI 307 legacy_mode = 'host' in module.params and module.params['host'] is not None and \ 308 'username' in module.params and module.params['username'] is not None and \ 309 'password' in module.params and module.params['password'] is not None 310 311 if not legacy_mode: 312 if module._socket_path: 313 connection = Connection(module._socket_path) 314 fos = FortiOSHandler(connection) 315 316 is_error, has_changed, result = fortios_wireless_controller_hotspot20(module.params, fos) 317 else: 318 module.fail_json(**FAIL_SOCKET_MSG) 319 else: 320 try: 321 from fortiosapi import FortiOSAPI 322 except ImportError: 323 module.fail_json(msg="fortiosapi module is required") 324 325 fos = FortiOSAPI() 326 327 login(module.params, fos) 328 is_error, has_changed, result = fortios_wireless_controller_hotspot20(module.params, fos) 329 fos.logout() 330 331 if not is_error: 332 module.exit_json(changed=has_changed, meta=result) 333 else: 334 module.fail_json(msg="Error in repo", meta=result) 335 336 337if __name__ == '__main__': 338 main() 339