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