1#!/usr/local/bin/python3.8 2from __future__ import (absolute_import, division, print_function) 3# Copyright 2019-2020 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_system_speed_test_schedule 27short_description: Speed test schedule for each interface 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 system feature and speed_test_schedule category. 31 Examples include all parameters and values need to be adjusted to datasources before usage. 32 Tested with FOS v6.0.0 33version_added: "2.10" 34author: 35 - Link Zheng (@chillancezen) 36 - Jie Xue (@JieX19) 37 - Hongbin Lu (@fgtdev-hblu) 38 - Frank Shen (@frankshen01) 39 - Miguel Angel Munoz (@mamunozgonzalez) 40 - Nicolas Thomas (@thomnico) 41notes: 42 - Legacy fortiosapi has been deprecated, httpapi is the preferred way to run playbooks 43 44requirements: 45 - ansible>=2.9.0 46options: 47 access_token: 48 description: 49 - Token-based authentication. 50 Generated from GUI of Fortigate. 51 type: str 52 required: false 53 enable_log: 54 description: 55 - Enable/Disable logging for task. 56 type: bool 57 required: false 58 default: false 59 vdom: 60 description: 61 - Virtual domain, among those defined previously. A vdom is a 62 virtual instance of the FortiGate that can be configured and 63 used as a different unit. 64 type: str 65 default: root 66 67 state: 68 description: 69 - Indicates whether to create or remove the object. 70 type: str 71 required: true 72 choices: 73 - present 74 - absent 75 system_speed_test_schedule: 76 description: 77 - Speed test schedule for each interface. 78 default: null 79 type: dict 80 suboptions: 81 diffserv: 82 description: 83 - DSCP used for speed test. 84 type: str 85 interface: 86 description: 87 - Interface name. Source system.interface.name. 88 required: true 89 type: str 90 schedules: 91 description: 92 - Schedules for the interface. 93 type: list 94 suboptions: 95 name: 96 description: 97 - Name of a firewall recurring schedule. Source firewall.schedule.recurring.name. 98 required: true 99 type: str 100 server_name: 101 description: 102 - Speed test server name. 103 type: str 104 status: 105 description: 106 - Enable/disable scheduled speed test. 107 type: str 108 choices: 109 - disable 110 - enable 111 update_inbandwidth: 112 description: 113 - Enable/disable bypassing interface"s inbound bandwidth setting. 114 type: str 115 choices: 116 - disable 117 - enable 118 update_inbandwidth_maximum: 119 description: 120 - Maximum downloading bandwidth (kbps) to be used in a speed test. 121 type: int 122 update_inbandwidth_minimum: 123 description: 124 - Minimum downloading bandwidth (kbps) to be considered effective. 125 type: int 126 update_outbandwidth: 127 description: 128 - Enable/disable bypassing interface"s outbound bandwidth setting. 129 type: str 130 choices: 131 - disable 132 - enable 133 update_outbandwidth_maximum: 134 description: 135 - Maximum uploading bandwidth (kbps) to be used in a speed test. 136 type: int 137 update_outbandwidth_minimum: 138 description: 139 - Minimum uploading bandwidth (kbps) to be considered effective. 140 type: int 141''' 142 143EXAMPLES = ''' 144- hosts: fortigates 145 collections: 146 - fortinet.fortios 147 connection: httpapi 148 vars: 149 vdom: "root" 150 ansible_httpapi_use_ssl: yes 151 ansible_httpapi_validate_certs: no 152 ansible_httpapi_port: 443 153 tasks: 154 - name: Speed test schedule for each interface. 155 fortios_system_speed_test_schedule: 156 vdom: "{{ vdom }}" 157 state: "present" 158 access_token: "<your_own_value>" 159 system_speed_test_schedule: 160 diffserv: "<your_own_value>" 161 interface: "<your_own_value> (source system.interface.name)" 162 schedules: 163 - 164 name: "default_name_6 (source firewall.schedule.recurring.name)" 165 server_name: "<your_own_value>" 166 status: "disable" 167 update_inbandwidth: "disable" 168 update_inbandwidth_maximum: "10" 169 update_inbandwidth_minimum: "11" 170 update_outbandwidth: "disable" 171 update_outbandwidth_maximum: "13" 172 update_outbandwidth_minimum: "14" 173 174''' 175 176RETURN = ''' 177build: 178 description: Build number of the fortigate image 179 returned: always 180 type: str 181 sample: '1547' 182http_method: 183 description: Last method used to provision the content into FortiGate 184 returned: always 185 type: str 186 sample: 'PUT' 187http_status: 188 description: Last result given by FortiGate on last operation applied 189 returned: always 190 type: str 191 sample: "200" 192mkey: 193 description: Master key (id) used in the last call to FortiGate 194 returned: success 195 type: str 196 sample: "id" 197name: 198 description: Name of the table used to fulfill the request 199 returned: always 200 type: str 201 sample: "urlfilter" 202path: 203 description: Path of the table used to fulfill the request 204 returned: always 205 type: str 206 sample: "webfilter" 207revision: 208 description: Internal revision number 209 returned: always 210 type: str 211 sample: "17.0.2.10658" 212serial: 213 description: Serial number of the unit 214 returned: always 215 type: str 216 sample: "FGVMEVYYQT3AB5352" 217status: 218 description: Indication of the operation's result 219 returned: always 220 type: str 221 sample: "success" 222vdom: 223 description: Virtual domain used 224 returned: always 225 type: str 226 sample: "root" 227version: 228 description: Version of the FortiGate 229 returned: always 230 type: str 231 sample: "v5.6.3" 232 233''' 234from ansible.module_utils.basic import AnsibleModule 235from ansible.module_utils.connection import Connection 236from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import FortiOSHandler 237from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_legacy_fortiosapi 238from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import schema_to_module_spec 239from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_schema_versioning 240from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG 241from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import is_same_comparison 242from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import serialize 243 244 245def filter_system_speed_test_schedule_data(json): 246 option_list = ['diffserv', 'interface', 'schedules', 247 'server_name', 'status', 'update_inbandwidth', 248 'update_inbandwidth_maximum', 'update_inbandwidth_minimum', 'update_outbandwidth', 249 'update_outbandwidth_maximum', 'update_outbandwidth_minimum'] 250 dictionary = {} 251 252 for attribute in option_list: 253 if attribute in json and json[attribute] is not None: 254 dictionary[attribute] = json[attribute] 255 256 return dictionary 257 258 259def underscore_to_hyphen(data): 260 if isinstance(data, list): 261 for i, elem in enumerate(data): 262 data[i] = underscore_to_hyphen(elem) 263 elif isinstance(data, dict): 264 new_data = {} 265 for k, v in data.items(): 266 new_data[k.replace('_', '-')] = underscore_to_hyphen(v) 267 data = new_data 268 269 return data 270 271 272def system_speed_test_schedule(data, fos): 273 vdom = data['vdom'] 274 275 state = data['state'] 276 277 system_speed_test_schedule_data = data['system_speed_test_schedule'] 278 filtered_data = underscore_to_hyphen(filter_system_speed_test_schedule_data(system_speed_test_schedule_data)) 279 280 if state == "present" or state is True: 281 return fos.set('system', 282 'speed-test-schedule', 283 data=filtered_data, 284 vdom=vdom) 285 286 elif state == "absent": 287 return fos.delete('system', 288 'speed-test-schedule', 289 mkey=filtered_data['interface'], 290 vdom=vdom) 291 else: 292 fos._module.fail_json(msg='state must be present or absent!') 293 294 295def is_successful_status(status): 296 return status['status'] == "success" or \ 297 status['http_method'] == "DELETE" and status['http_status'] == 404 298 299 300def fortios_system(data, fos): 301 302 if data['system_speed_test_schedule']: 303 resp = system_speed_test_schedule(data, fos) 304 else: 305 fos._module.fail_json(msg='missing task body: %s' % ('system_speed_test_schedule')) 306 307 return not is_successful_status(resp), \ 308 resp['status'] == "success" and \ 309 (resp['revision_changed'] if 'revision_changed' in resp else True), \ 310 resp 311 312 313versioned_schema = { 314 "type": "list", 315 "children": { 316 "status": { 317 "type": "string", 318 "options": [ 319 { 320 "value": "disable", 321 "revisions": { 322 "v7.0.0": True 323 } 324 }, 325 { 326 "value": "enable", 327 "revisions": { 328 "v7.0.0": True 329 } 330 } 331 ], 332 "revisions": { 333 "v7.0.0": True 334 } 335 }, 336 "diffserv": { 337 "type": "string", 338 "revisions": { 339 "v7.0.0": True 340 } 341 }, 342 "server_name": { 343 "type": "string", 344 "revisions": { 345 "v7.0.0": True 346 } 347 }, 348 "update_inbandwidth_minimum": { 349 "type": "integer", 350 "revisions": { 351 "v7.0.0": True 352 } 353 }, 354 "schedules": { 355 "type": "list", 356 "children": { 357 "name": { 358 "type": "string", 359 "revisions": { 360 "v7.0.0": True 361 } 362 } 363 }, 364 "revisions": { 365 "v7.0.0": True 366 } 367 }, 368 "update_inbandwidth_maximum": { 369 "type": "integer", 370 "revisions": { 371 "v7.0.0": True 372 } 373 }, 374 "update_outbandwidth_maximum": { 375 "type": "integer", 376 "revisions": { 377 "v7.0.0": True 378 } 379 }, 380 "update_inbandwidth": { 381 "type": "string", 382 "options": [ 383 { 384 "value": "disable", 385 "revisions": { 386 "v7.0.0": True 387 } 388 }, 389 { 390 "value": "enable", 391 "revisions": { 392 "v7.0.0": True 393 } 394 } 395 ], 396 "revisions": { 397 "v7.0.0": True 398 } 399 }, 400 "update_outbandwidth": { 401 "type": "string", 402 "options": [ 403 { 404 "value": "disable", 405 "revisions": { 406 "v7.0.0": True 407 } 408 }, 409 { 410 "value": "enable", 411 "revisions": { 412 "v7.0.0": True 413 } 414 } 415 ], 416 "revisions": { 417 "v7.0.0": True 418 } 419 }, 420 "interface": { 421 "type": "string", 422 "revisions": { 423 "v7.0.0": True 424 } 425 }, 426 "update_outbandwidth_minimum": { 427 "type": "integer", 428 "revisions": { 429 "v7.0.0": True 430 } 431 } 432 }, 433 "revisions": { 434 "v7.0.0": True 435 } 436} 437 438 439def main(): 440 module_spec = schema_to_module_spec(versioned_schema) 441 mkeyname = 'interface' 442 fields = { 443 "access_token": {"required": False, "type": "str", "no_log": True}, 444 "enable_log": {"required": False, "type": bool}, 445 "vdom": {"required": False, "type": "str", "default": "root"}, 446 "state": {"required": True, "type": "str", 447 "choices": ["present", "absent"]}, 448 "system_speed_test_schedule": { 449 "required": False, "type": "dict", "default": None, 450 "options": { 451 } 452 } 453 } 454 for attribute_name in module_spec['options']: 455 fields["system_speed_test_schedule"]['options'][attribute_name] = module_spec['options'][attribute_name] 456 if mkeyname and mkeyname == attribute_name: 457 fields["system_speed_test_schedule"]['options'][attribute_name]['required'] = True 458 459 check_legacy_fortiosapi() 460 module = AnsibleModule(argument_spec=fields, 461 supports_check_mode=False) 462 463 versions_check_result = None 464 if module._socket_path: 465 connection = Connection(module._socket_path) 466 if 'access_token' in module.params: 467 connection.set_option('access_token', module.params['access_token']) 468 469 if 'enable_log' in module.params: 470 connection.set_option('enable_log', module.params['enable_log']) 471 else: 472 connection.set_option('enable_log', False) 473 fos = FortiOSHandler(connection, module, mkeyname) 474 versions_check_result = check_schema_versioning(fos, versioned_schema, "system_speed_test_schedule") 475 476 is_error, has_changed, result = fortios_system(module.params, fos) 477 478 else: 479 module.fail_json(**FAIL_SOCKET_MSG) 480 481 if versions_check_result and versions_check_result['matched'] is False: 482 module.warn("Ansible has detected version mismatch between FortOS system and your playbook, see more details by specifying option -vvv") 483 484 if not is_error: 485 if versions_check_result and versions_check_result['matched'] is False: 486 module.exit_json(changed=has_changed, version_check_warning=versions_check_result, meta=result) 487 else: 488 module.exit_json(changed=has_changed, meta=result) 489 else: 490 if versions_check_result and versions_check_result['matched'] is False: 491 module.fail_json(msg="Error in repo", version_check_warning=versions_check_result, meta=result) 492 else: 493 module.fail_json(msg="Error in repo", meta=result) 494 495 496if __name__ == '__main__': 497 main() 498