diff options
author | ansible-zuul[bot] <48994755+ansible-zuul[bot]@users.noreply.github.com> | 2020-01-16 18:56:16 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-16 18:56:16 +0000 |
commit | 03addce56012d4bd360e18612d2eb3af04d8f01a (patch) | |
tree | 9cf59872c2ddc7e99595db4f47c72a7ce08b6c10 /plugins/modules | |
parent | d31b74ba6c74a6e3cdebd80b9eb5272aeb9b0fb4 (diff) | |
parent | 6b6166151faa3d811ae0ec3010a89e518a26287b (diff) | |
download | vyos.vyos-03addce56012d4bd360e18612d2eb3af04d8f01a.tar.gz vyos.vyos-03addce56012d4bd360e18612d2eb3af04d8f01a.zip |
Merge pull request #59 from CaptTrews/master
Updated from network content collector
Reviewed-by: https://github.com/apps/ansible-zuul
Diffstat (limited to 'plugins/modules')
25 files changed, 1980 insertions, 1980 deletions
diff --git a/plugins/modules/_vyos_interface.py b/plugins/modules/_vyos_interface.py deleted file mode 100644 index 71a98c5d..00000000 --- a/plugins/modules/_vyos_interface.py +++ /dev/null @@ -1,468 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# (c) 2017, Ansible by Red Hat, inc -# -# This file is part of Ansible by Red Hat -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see <http://www.gnu.org/licenses/>. -# - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["deprecated"], - "supported_by": "network", -} - - -DOCUMENTATION = """ ---- -module: vyos_interface -version_added: "2.4" -author: "Ganesh Nalawade (@ganeshrn)" -short_description: Manage Interface on VyOS network devices -description: - - This module provides declarative management of Interfaces - on VyOS network devices. -deprecated: - removed_in: '2.13' - alternative: vyos_interfaces - why: Updated modules released with more functionality. -notes: - - Tested against VYOS 1.1.7 -options: - name: - description: - - Name of the Interface. - required: true - description: - description: - - Description of Interface. - enabled: - description: - - Interface link status. - type: bool - speed: - description: - - Interface link speed. - mtu: - description: - - Maximum size of transmit packet. - duplex: - description: - - Interface link status. - default: auto - choices: ['full', 'half', 'auto'] - delay: - description: - - Time in seconds to wait before checking for the operational state on remote - device. This wait is applicable for operational state argument which are - I(state) with values C(up)/C(down) and I(neighbors). - default: 10 - neighbors: - description: - - Check the operational state of given interface C(name) for LLDP neighbor. - - The following suboptions are available. - suboptions: - host: - description: - - "LLDP neighbor host for given interface C(name)." - port: - description: - - "LLDP neighbor port to which given interface C(name) is connected." - version_added: 2.5 - aggregate: - description: List of Interfaces definitions. - state: - description: - - State of the Interface configuration, C(up) means present and - operationally up and C(down) means present and operationally C(down) - default: present - choices: ['present', 'absent', 'up', 'down'] -extends_documentation_fragment: vyos -""" - -EXAMPLES = """ -- name: configure interface - vyos_interface: - name: eth0 - description: test-interface - -- name: remove interface - vyos_interface: - name: eth0 - state: absent - -- name: make interface down - vyos_interface: - name: eth0 - enabled: False - -- name: make interface up - vyos_interface: - name: eth0 - enabled: True - -- name: Configure interface speed, mtu, duplex - vyos_interface: - name: eth5 - state: present - speed: 100 - mtu: 256 - duplex: full - -- name: Set interface using aggregate - vyos_interface: - aggregate: - - { name: eth1, description: test-interface-1, speed: 100, duplex: half, mtu: 512} - - { name: eth2, description: test-interface-2, speed: 1000, duplex: full, mtu: 256} - -- name: Disable interface on aggregate - net_interface: - aggregate: - - name: eth1 - - name: eth2 - enabled: False - -- name: Delete interface using aggregate - net_interface: - aggregate: - - name: eth1 - - name: eth2 - state: absent - -- name: Check lldp neighbors intent arguments - vyos_interface: - name: eth0 - neighbors: - - port: eth0 - host: netdev - -- name: Config + intent - vyos_interface: - name: eth1 - enabled: False - state: down -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always, except for the platforms that use Netconf transport to manage the device. - type: list - sample: - - set interfaces ethernet eth0 description "test-interface" - - set interfaces ethernet eth0 speed 100 - - set interfaces ethernet eth0 mtu 256 - - set interfaces ethernet eth0 duplex full -""" -import re - -from copy import deepcopy -from time import sleep - -from ansible.module_utils._text import to_text -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.connection import exec_command -from ansible.module_utils.network.common.utils import ( - conditional, - remove_default_spec, -) -from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( - load_config, - get_config, -) -from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( - vyos_argument_spec, -) - - -def search_obj_in_list(name, lst): - for o in lst: - if o["name"] == name: - return o - - return None - - -def map_obj_to_commands(updates): - commands = list() - want, have = updates - - params = ("speed", "description", "duplex", "mtu") - for w in want: - name = w["name"] - disable = w["disable"] - state = w["state"] - - obj_in_have = search_obj_in_list(name, have) - set_interface = "set interfaces ethernet " + name - delete_interface = "delete interfaces ethernet " + name - - if state == "absent" and obj_in_have: - commands.append(delete_interface) - elif state in ("present", "up", "down"): - if obj_in_have: - for item in params: - value = w.get(item) - - if value and value != obj_in_have.get(item): - if item == "description": - value = "'" + str(value) + "'" - commands.append( - set_interface + " " + item + " " + str(value) - ) - - if disable and not obj_in_have.get("disable", False): - commands.append(set_interface + " disable") - elif not disable and obj_in_have.get("disable", False): - commands.append(delete_interface + " disable") - else: - commands.append(set_interface) - for item in params: - value = w.get(item) - if value: - if item == "description": - value = "'" + str(value) + "'" - commands.append( - set_interface + " " + item + " " + str(value) - ) - - if disable: - commands.append(set_interface + " disable") - return commands - - -def map_config_to_obj(module): - data = get_config(module, flags=["| grep interface"]) - obj = [] - for line in data.split("\n"): - if line.startswith("set interfaces ethernet"): - match = re.search(r"set interfaces ethernet (\S+)", line, re.M) - name = match.group(1) - if name: - interface = {} - for item in obj: - if item["name"] == name: - interface = item - break - - if not interface: - interface = {"name": name} - obj.append(interface) - - match = re.search(r"%s (\S+)" % name, line, re.M) - if match: - param = match.group(1) - if param == "description": - match = re.search(r"description (.+)", line, re.M) - description = match.group(1).strip("'") - interface["description"] = description - elif param == "speed": - match = re.search(r"speed (\S+)", line, re.M) - speed = match.group(1).strip("'") - interface["speed"] = speed - elif param == "mtu": - match = re.search(r"mtu (\S+)", line, re.M) - mtu = match.group(1).strip("'") - interface["mtu"] = int(mtu) - elif param == "duplex": - match = re.search(r"duplex (\S+)", line, re.M) - duplex = match.group(1).strip("'") - interface["duplex"] = duplex - elif param.strip("'") == "disable": - interface["disable"] = True - - return obj - - -def map_params_to_obj(module): - obj = [] - aggregate = module.params.get("aggregate") - if aggregate: - for item in aggregate: - for key in item: - if item.get(key) is None: - item[key] = module.params[key] - - d = item.copy() - if d["enabled"]: - d["disable"] = False - else: - d["disable"] = True - - obj.append(d) - else: - params = { - "name": module.params["name"], - "description": module.params["description"], - "speed": module.params["speed"], - "mtu": module.params["mtu"], - "duplex": module.params["duplex"], - "delay": module.params["delay"], - "state": module.params["state"], - "neighbors": module.params["neighbors"], - } - - if module.params["enabled"]: - params.update({"disable": False}) - else: - params.update({"disable": True}) - - obj.append(params) - return obj - - -def check_declarative_intent_params(module, want, result): - failed_conditions = [] - have_neighbors = None - for w in want: - want_state = w.get("state") - want_neighbors = w.get("neighbors") - - if want_state not in ("up", "down") and not want_neighbors: - continue - - if result["changed"]: - sleep(w["delay"]) - - command = "show interfaces ethernet %s" % w["name"] - rc, out, err = exec_command(module, command) - if rc != 0: - module.fail_json( - msg=to_text(err, errors="surrogate_then_replace"), - command=command, - rc=rc, - ) - - if want_state in ("up", "down"): - match = re.search(r"%s (\w+)" % "state", out, re.M) - have_state = None - if match: - have_state = match.group(1) - if have_state is None or not conditional( - want_state, have_state.strip().lower() - ): - failed_conditions.append("state " + "eq(%s)" % want_state) - - if want_neighbors: - have_host = [] - have_port = [] - if have_neighbors is None: - rc, have_neighbors, err = exec_command( - module, "show lldp neighbors detail" - ) - if rc != 0: - module.fail_json( - msg=to_text(err, errors="surrogate_then_replace"), - command=command, - rc=rc, - ) - - if have_neighbors: - lines = have_neighbors.strip().split("Interface: ") - for line in lines: - field = line.split("\n") - if field[0].split(",")[0].strip() == w["name"]: - for item in field: - if item.strip().startswith("SysName:"): - have_host.append(item.split(":")[1].strip()) - if item.strip().startswith("PortDescr:"): - have_port.append(item.split(":")[1].strip()) - for item in want_neighbors: - host = item.get("host") - port = item.get("port") - if host and host not in have_host: - failed_conditions.append("host " + host) - if port and port not in have_port: - failed_conditions.append("port " + port) - - return failed_conditions - - -def main(): - """ main entry point for module execution - """ - neighbors_spec = dict(host=dict(), port=dict()) - - element_spec = dict( - name=dict(), - description=dict(), - speed=dict(), - mtu=dict(type="int"), - duplex=dict(choices=["full", "half", "auto"]), - enabled=dict(default=True, type="bool"), - neighbors=dict(type="list", elements="dict", options=neighbors_spec), - delay=dict(default=10, type="int"), - state=dict( - default="present", choices=["present", "absent", "up", "down"] - ), - ) - - aggregate_spec = deepcopy(element_spec) - aggregate_spec["name"] = dict(required=True) - - # remove default in aggregate spec, to handle common arguments - remove_default_spec(aggregate_spec) - - argument_spec = dict( - aggregate=dict(type="list", elements="dict", options=aggregate_spec) - ) - - argument_spec.update(element_spec) - argument_spec.update(vyos_argument_spec) - - required_one_of = [["name", "aggregate"]] - mutually_exclusive = [["name", "aggregate"]] - - required_together = [["speed", "duplex"]] - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=required_one_of, - mutually_exclusive=mutually_exclusive, - required_together=required_together, - supports_check_mode=True, - ) - - warnings = list() - - result = {"changed": False} - - if warnings: - result["warnings"] = warnings - - want = map_params_to_obj(module) - have = map_config_to_obj(module) - - commands = map_obj_to_commands((want, have)) - result["commands"] = commands - - if commands: - commit = not module.check_mode - diff = load_config(module, commands, commit=commit) - if diff: - if module._diff: - result["diff"] = {"prepared": diff} - result["changed"] = True - - failed_conditions = check_declarative_intent_params(module, want, result) - - if failed_conditions: - msg = "One or more conditional statements have not been satisfied" - module.fail_json(msg=msg, failed_conditions=failed_conditions) - module.exit_json(**result) - - -if __name__ == "__main__": - main() diff --git a/plugins/modules/_vyos_l3_interface.py b/plugins/modules/_vyos_l3_interface.py deleted file mode 100644 index 054d810f..00000000 --- a/plugins/modules/_vyos_l3_interface.py +++ /dev/null @@ -1,328 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# (c) 2017, Ansible by Red Hat, inc -# -# This file is part of Ansible by Red Hat -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see <http://www.gnu.org/licenses/>. -# - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["deprecated"], - "supported_by": "network", -} - - -DOCUMENTATION = """ ---- -module: vyos_l3_interface -version_added: "2.4" -author: "Ricardo Carrillo Cruz (@rcarrillocruz)" -short_description: Manage L3 interfaces on VyOS network devices -description: - - This module provides declarative management of L3 interfaces - on VyOS network devices. -deprecated: - removed_in: '2.13' - alternative: vyos_l3_interfaces - why: Updated modules released with more functionality. -notes: - - Tested against VYOS 1.1.7 -options: - name: - description: - - Name of the L3 interface. - ipv4: - description: - - IPv4 of the L3 interface. - ipv6: - description: - - IPv6 of the L3 interface. - aggregate: - description: List of L3 interfaces definitions - state: - description: - - State of the L3 interface configuration. - default: present - choices: ['present', 'absent'] -extends_documentation_fragment: vyos -""" - -EXAMPLES = """ -- name: Set eth0 IPv4 address - vyos_l3_interface: - name: eth0 - ipv4: 192.168.0.1/24 - -- name: Remove eth0 IPv4 address - vyos_l3_interface: - name: eth0 - state: absent - -- name: Set IP addresses on aggregate - vyos_l3_interface: - aggregate: - - { name: eth1, ipv4: 192.168.2.10/24 } - - { name: eth2, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64" } - -- name: Remove IP addresses on aggregate - vyos_l3_interface: - aggregate: - - { name: eth1, ipv4: 192.168.2.10/24 } - - { name: eth2, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64" } - state: absent -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always, except for the platforms that use Netconf transport to manage the device. - type: list - sample: - - set interfaces ethernet eth0 address '192.168.0.1/24' -""" - -import socket -import re - -from copy import deepcopy - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.utils import ( - is_masklen, - validate_ip_address, -) -from ansible.module_utils.network.common.utils import remove_default_spec -from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( - load_config, - run_commands, -) -from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( - vyos_argument_spec, -) - - -def is_ipv4(value): - if value: - address = value.split("/") - if is_masklen(address[1]) and validate_ip_address(address[0]): - return True - return False - - -def is_ipv6(value): - if value: - address = value.split("/") - if 0 <= int(address[1]) <= 128: - try: - socket.inet_pton(socket.AF_INET6, address[0]) - except socket.error: - return False - return True - return False - - -def search_obj_in_list(name, lst): - for o in lst: - if o["name"] == name: - return o - - return None - - -def map_obj_to_commands(updates, module): - commands = list() - want, have = updates - - for w in want: - name = w["name"] - ipv4 = w["ipv4"] - ipv6 = w["ipv6"] - state = w["state"] - - obj_in_have = search_obj_in_list(name, have) - - if state == "absent" and obj_in_have: - if ( - not ipv4 - and not ipv6 - and (obj_in_have["ipv4"] or obj_in_have["ipv6"]) - ): - if name == "lo": - commands.append("delete interfaces loopback lo address") - else: - commands.append( - "delete interfaces ethernet " + name + " address" - ) - else: - if ipv4 and ipv4 in obj_in_have["ipv4"]: - if name == "lo": - commands.append( - "delete interfaces loopback lo address " + ipv4 - ) - else: - commands.append( - "delete interfaces ethernet " - + name - + " address " - + ipv4 - ) - if ipv6 and ipv6 in obj_in_have["ipv6"]: - if name == "lo": - commands.append( - "delete interfaces loopback lo address " + ipv6 - ) - else: - commands.append( - "delete interfaces ethernet " - + name - + " address " - + ipv6 - ) - elif state == "present" and obj_in_have: - if ipv4 and ipv4 not in obj_in_have["ipv4"]: - if name == "lo": - commands.append( - "set interfaces loopback lo address " + ipv4 - ) - else: - commands.append( - "set interfaces ethernet " + name + " address " + ipv4 - ) - - if ipv6 and ipv6 not in obj_in_have["ipv6"]: - if name == "lo": - commands.append( - "set interfaces loopback lo address " + ipv6 - ) - else: - commands.append( - "set interfaces ethernet " + name + " address " + ipv6 - ) - - return commands - - -def map_config_to_obj(module): - obj = [] - output = run_commands(module, ["show interfaces"]) - lines = re.split(r"\n[e|l]", output[0])[1:] - - if len(lines) > 0: - for line in lines: - splitted_line = line.split() - - if len(splitted_line) > 0: - ipv4 = [] - ipv6 = [] - - if splitted_line[0].lower().startswith("th"): - name = "e" + splitted_line[0].lower() - elif splitted_line[0].lower().startswith("o"): - name = "l" + splitted_line[0].lower() - - for i in splitted_line[1:]: - if ("." in i or ":" in i) and "/" in i: - value = i.split(r"\n")[0] - if is_ipv4(value): - ipv4.append(value) - elif is_ipv6(value): - ipv6.append(value) - - obj.append({"name": name, "ipv4": ipv4, "ipv6": ipv6}) - - return obj - - -def map_params_to_obj(module): - obj = [] - - aggregate = module.params.get("aggregate") - if aggregate: - for item in aggregate: - for key in item: - if item.get(key) is None: - item[key] = module.params[key] - - obj.append(item.copy()) - else: - obj.append( - { - "name": module.params["name"], - "ipv4": module.params["ipv4"], - "ipv6": module.params["ipv6"], - "state": module.params["state"], - } - ) - - return obj - - -def main(): - """ main entry point for module execution - """ - element_spec = dict( - name=dict(), - ipv4=dict(), - ipv6=dict(), - state=dict(default="present", choices=["present", "absent"]), - ) - - aggregate_spec = deepcopy(element_spec) - aggregate_spec["name"] = dict(required=True) - - # remove default in aggregate spec, to handle common arguments - remove_default_spec(aggregate_spec) - - argument_spec = dict( - aggregate=dict(type="list", elements="dict", options=aggregate_spec) - ) - - argument_spec.update(element_spec) - argument_spec.update(vyos_argument_spec) - - required_one_of = [["name", "aggregate"]] - mutually_exclusive = [["name", "aggregate"]] - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=required_one_of, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True, - ) - - warnings = list() - - result = {"changed": False} - - if warnings: - result["warnings"] = warnings - - want = map_params_to_obj(module) - have = map_config_to_obj(module) - - commands = map_obj_to_commands((want, have), module) - result["commands"] = commands - - if commands: - commit = not module.check_mode - load_config(module, commands, commit=commit) - result["changed"] = True - - module.exit_json(**result) - - -if __name__ == "__main__": - main() diff --git a/plugins/modules/_vyos_linkagg.py b/plugins/modules/_vyos_linkagg.py deleted file mode 100644 index 95fbae91..00000000 --- a/plugins/modules/_vyos_linkagg.py +++ /dev/null @@ -1,317 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# (c) 2017, Ansible by Red Hat, inc -# -# This file is part of Ansible by Red Hat -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see <http://www.gnu.org/licenses/>. -# - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["deprecated"], - "supported_by": "network", -} - - -DOCUMENTATION = """ ---- -module: vyos_linkagg -version_added: "2.4" -author: "Ricardo Carrillo Cruz (@rcarrillocruz)" -short_description: Manage link aggregation groups on VyOS network devices -description: - - This module provides declarative management of link aggregation groups - on VyOS network devices. -deprecated: - removed_in: '2.13' - alternative: vyos_lag_interfaces - why: Updated modules released with more functionality. -notes: - - Tested against VYOS 1.1.7 -options: - name: - description: - - Name of the link aggregation group. - required: true - type: str - mode: - description: - - Mode of the link aggregation group. - choices: ['802.3ad', 'active-backup', 'broadcast', - 'round-robin', 'transmit-load-balance', - 'adaptive-load-balance', 'xor-hash', 'on'] - type: str - members: - description: - - List of members of the link aggregation group. - type: list - aggregate: - description: List of link aggregation definitions. - type: list - state: - description: - - State of the link aggregation group. - default: present - choices: ['present', 'absent', 'up', 'down'] - type: str -extends_documentation_fragment: vyos -""" - -EXAMPLES = """ -- name: configure link aggregation group - vyos_linkagg: - name: bond0 - members: - - eth0 - - eth1 - -- name: remove configuration - vyos_linkagg: - name: bond0 - state: absent - -- name: Create aggregate of linkagg definitions - vyos_linkagg: - aggregate: - - { name: bond0, members: [eth1] } - - { name: bond1, members: [eth2] } - -- name: Remove aggregate of linkagg definitions - vyos_linkagg: - aggregate: - - name: bond0 - - name: bond1 - state: absent -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always, except for the platforms that use Netconf transport to manage the device. - type: list - sample: - - set interfaces bonding bond0 - - set interfaces ethernet eth0 bond-group 'bond0' - - set interfaces ethernet eth1 bond-group 'bond0' -""" -from copy import deepcopy - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.utils import remove_default_spec -from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( - load_config, - run_commands, -) -from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( - vyos_argument_spec, -) - - -def search_obj_in_list(name, lst): - for o in lst: - if o["name"] == name: - return o - - return None - - -def map_obj_to_commands(updates, module): - commands = list() - want, have = updates - - for w in want: - name = w["name"] - members = w.get("members") or [] - mode = w["mode"] - - if mode == "on": - mode = "802.3ad" - - state = w["state"] - - obj_in_have = search_obj_in_list(name, have) - - if state == "absent": - if obj_in_have: - for m in obj_in_have["members"]: - commands.append( - "delete interfaces ethernet " + m + " bond-group" - ) - - commands.append("delete interfaces bonding " + name) - else: - if not obj_in_have: - commands.append( - "set interfaces bonding " + name + " mode " + mode - ) - - for m in members: - commands.append( - "set interfaces ethernet " + m + " bond-group " + name - ) - - if state == "down": - commands.append( - "set interfaces bonding " + name + " disable" - ) - else: - if mode != obj_in_have["mode"]: - commands.append( - "set interfaces bonding " + name + " mode " + mode - ) - - missing_members = list( - set(members) - set(obj_in_have["members"]) - ) - for m in missing_members: - commands.append( - "set interfaces ethernet " + m + " bond-group " + name - ) - - if state == "down" and obj_in_have["state"] == "up": - commands.append( - "set interfaces bonding " + name + " disable" - ) - elif state == "up" and obj_in_have["state"] == "down": - commands.append( - "delete interfaces bonding " + name + " disable" - ) - - return commands - - -def map_config_to_obj(module): - obj = [] - output = run_commands(module, ["show interfaces bonding slaves"]) - lines = output[0].splitlines() - - if len(lines) > 1: - for line in lines[1:]: - splitted_line = line.split() - - name = splitted_line[0] - mode = splitted_line[1] - state = splitted_line[2] - - if len(splitted_line) > 4: - members = splitted_line[4:] - else: - members = [] - - obj.append( - { - "name": name, - "mode": mode, - "members": members, - "state": state, - } - ) - - return obj - - -def map_params_to_obj(module): - obj = [] - aggregate = module.params.get("aggregate") - if aggregate: - for item in aggregate: - for key in item: - if item.get(key) is None: - item[key] = module.params[key] - - obj.append(item.copy()) - else: - obj.append( - { - "name": module.params["name"], - "mode": module.params["mode"], - "members": module.params["members"], - "state": module.params["state"], - } - ) - - return obj - - -def main(): - """ main entry point for module execution - """ - element_spec = dict( - name=dict(), - mode=dict( - choices=[ - "802.3ad", - "active-backup", - "broadcast", - "round-robin", - "transmit-load-balance", - "adaptive-load-balance", - "xor-hash", - "on", - ], - default="802.3ad", - ), - members=dict(type="list"), - state=dict( - default="present", choices=["present", "absent", "up", "down"] - ), - ) - - aggregate_spec = deepcopy(element_spec) - aggregate_spec["name"] = dict(required=True) - - # remove default in aggregate spec, to handle common arguments - remove_default_spec(aggregate_spec) - - argument_spec = dict( - aggregate=dict(type="list", elements="dict", options=aggregate_spec) - ) - - argument_spec.update(element_spec) - argument_spec.update(vyos_argument_spec) - - required_one_of = [["name", "aggregate"]] - mutually_exclusive = [["name", "aggregate"]] - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=required_one_of, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True, - ) - - warnings = list() - - result = {"changed": False} - - if warnings: - result["warnings"] = warnings - - want = map_params_to_obj(module) - have = map_config_to_obj(module) - - commands = map_obj_to_commands((want, have), module) - result["commands"] = commands - - if commands: - commit = not module.check_mode - load_config(module, commands, commit=commit) - result["changed"] = True - - module.exit_json(**result) - - -if __name__ == "__main__": - main() diff --git a/plugins/modules/_vyos_lldp.py b/plugins/modules/_vyos_lldp.py deleted file mode 100644 index 69787543..00000000 --- a/plugins/modules/_vyos_lldp.py +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# (c) 2017, Ansible by Red Hat, inc -# -# This file is part of Ansible by Red Hat -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see <http://www.gnu.org/licenses/>. -# - -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["deprecated"], - "supported_by": "network", -} - - -DOCUMENTATION = """ ---- -module: vyos_lldp -version_added: "2.4" -author: "Ricardo Carrillo Cruz (@rcarrillocruz)" -short_description: Manage LLDP configuration on VyOS network devices -description: - - This module provides declarative management of LLDP service - on VyOS network devices. -deprecated: - removed_in: '2.13' - alternative: vyos_lldp_global - why: Updated modules released with more functionality. -notes: - - Tested against VYOS 1.1.7 -options: - interfaces: - description: - - Name of the interfaces. - type: list - state: - description: - - State of the link aggregation group. - default: present - choices: ['present', 'absent', 'enabled', 'disabled'] - type: str -extends_documentation_fragment: vyos -""" - -EXAMPLES = """ -- name: Enable LLDP service - vyos_lldp: - state: present - -- name: Disable LLDP service - vyos_lldp: - state: absent -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always, except for the platforms that use Netconf transport to manage the device. - type: list - sample: - - set service lldp -""" -from ansible.module_utils.basic import AnsibleModule -from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( - get_config, - load_config, -) -from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( - vyos_argument_spec, -) - - -def has_lldp(module): - config = get_config(module).splitlines() - - if "set service 'lldp'" in config or "set service lldp" in config: - return True - else: - return False - - -def main(): - """ main entry point for module execution - """ - argument_spec = dict( - interfaces=dict(type="list"), - state=dict( - default="present", - choices=["present", "absent", "enabled", "disabled"], - ), - ) - - argument_spec.update(vyos_argument_spec) - - module = AnsibleModule( - argument_spec=argument_spec, supports_check_mode=True - ) - - warnings = list() - - result = {"changed": False} - - if warnings: - result["warnings"] = warnings - - HAS_LLDP = has_lldp(module) - - commands = [] - - if module.params["state"] == "absent" and HAS_LLDP: - commands.append("delete service lldp") - elif module.params["state"] == "present" and not HAS_LLDP: - commands.append("set service lldp") - - result["commands"] = commands - - if commands: - commit = not module.check_mode - load_config(module, commands, commit=commit) - result["changed"] = True - - module.exit_json(**result) - - -if __name__ == "__main__": - main() diff --git a/plugins/modules/_vyos_lldp_interface.py b/plugins/modules/_vyos_lldp_interface.py deleted file mode 100644 index 6705d575..00000000 --- a/plugins/modules/_vyos_lldp_interface.py +++ /dev/null @@ -1,260 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# (c) 2017, Ansible by Red Hat, inc -# -# This file is part of Ansible by Red Hat -# -# Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Ansible. If not, see <http://www.gnu.org/licenses/>. -# - - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["deprecated"], - "supported_by": "network", -} - - -DOCUMENTATION = """ ---- -module: vyos_lldp_interface -version_added: "2.4" -author: "Ricardo Carrillo Cruz (@rcarrillocruz)" -short_description: Manage LLDP interfaces configuration on VyOS network devices -description: - - This module provides declarative management of LLDP interfaces - configuration on VyOS network devices. -deprecated: - removed_in: '2.13' - alternative: vyos_lldp_interfaces - why: Updated modules released with more functionality. -notes: - - Tested against VYOS 1.1.7 -options: - name: - description: - - Name of the interface LLDP should be configured on. - type: str - aggregate: - description: List of interfaces LLDP should be configured on. - type: list - state: - description: - - State of the LLDP configuration. - default: present - choices: ['present', 'absent', 'enabled', 'disabled'] - type: str -extends_documentation_fragment: vyos -""" - -EXAMPLES = """ -- name: Enable LLDP on eth1 - net_lldp_interface: - state: present - -- name: Enable LLDP on specific interfaces - net_lldp_interface: - interfaces: - - eth1 - - eth2 - state: present - -- name: Disable LLDP globally - net_lldp_interface: - state: disabled - -- name: Create aggregate of LLDP interface configurations - vyos_lldp_interface: - aggregate: - - name: eth1 - - name: eth2 - state: present - -- name: Delete aggregate of LLDP interface configurations - vyos_lldp_interface: - aggregate: - - name: eth1 - - name: eth2 - state: absent -""" - -RETURN = """ -commands: - description: The list of configuration mode commands to send to the device - returned: always, except for the platforms that use Netconf transport to manage the device. - type: list - sample: - - set service lldp eth1 - - set service lldp eth2 disable -""" - - -from copy import deepcopy - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.utils import remove_default_spec -from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( - get_config, - load_config, -) -from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( - vyos_argument_spec, -) - - -def search_obj_in_list(name, lst): - for o in lst: - if o["name"] == name: - return o - - return None - - -def map_obj_to_commands(updates, module): - commands = list() - want, have = updates - - for w in want: - name = w["name"] - state = w["state"] - - obj_in_have = search_obj_in_list(name, have) - - if state == "absent" and obj_in_have: - commands.append("delete service lldp interface " + name) - elif state in ("present", "enabled"): - if not obj_in_have: - commands.append("set service lldp interface " + name) - elif ( - obj_in_have - and obj_in_have["state"] == "disabled" - and state == "enabled" - ): - commands.append( - "delete service lldp interface " + name + " disable" - ) - elif state == "disabled": - if not obj_in_have: - commands.append("set service lldp interface " + name) - commands.append( - "set service lldp interface " + name + " disable" - ) - elif obj_in_have and obj_in_have["state"] != "disabled": - commands.append( - "set service lldp interface " + name + " disable" - ) - - return commands - - -def map_config_to_obj(module): - obj = [] - config = get_config(module).splitlines() - - output = [c for c in config if c.startswith("set service lldp interface")] - - for i in output: - splitted_line = i.split() - - if len(splitted_line) > 5: - new_obj = {"name": splitted_line[4]} - - if splitted_line[5] == "'disable'": - new_obj["state"] = "disabled" - else: - new_obj = {"name": splitted_line[4][1:-1]} - new_obj["state"] = "present" - - obj.append(new_obj) - - return obj - - -def map_params_to_obj(module): - obj = [] - - aggregate = module.params.get("aggregate") - if aggregate: - for item in aggregate: - for key in item: - if item.get(key) is None: - item[key] = module.params[key] - - obj.append(item.copy()) - else: - obj.append( - {"name": module.params["name"], "state": module.params["state"]} - ) - - return obj - - -def main(): - """ main entry point for module execution - """ - element_spec = dict( - name=dict(), - state=dict( - default="present", - choices=["present", "absent", "enabled", "disabled"], - ), - ) - - aggregate_spec = deepcopy(element_spec) - aggregate_spec["name"] = dict(required=True) - - # remove default in aggregate spec, to handle common arguments - remove_default_spec(aggregate_spec) - - argument_spec = dict( - aggregate=dict(type="list", elements="dict", options=aggregate_spec) - ) - - argument_spec.update(element_spec) - argument_spec.update(vyos_argument_spec) - - required_one_of = [["name", "aggregate"]] - mutually_exclusive = [["name", "aggregate"]] - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=required_one_of, - mutually_exclusive=mutually_exclusive, - supports_check_mode=True, - ) - - warnings = list() - - result = {"changed": False} - - if warnings: - result["warnings"] = warnings - - want = map_params_to_obj(module) - have = map_config_to_obj(module) - - commands = map_obj_to_commands((want, have), module) - result["commands"] = commands - - if commands: - commit = not module.check_mode - load_config(module, commands, commit=commit) - result["changed"] = True - - module.exit_json(**result) - - -if __name__ == "__main__": - main() diff --git a/plugins/modules/vyos_banner.py b/plugins/modules/vyos_banner.py index 81a985d4..b08fb73e 100644 --- a/plugins/modules/vyos_banner.py +++ b/plugins/modules/vyos_banner.py @@ -25,38 +25,37 @@ ANSIBLE_METADATA = { "supported_by": "network", } -DOCUMENTATION = """ ---- -module: vyos_banner -version_added: "2.4" -author: "Trishna Guha (@trishnaguha)" +DOCUMENTATION = """module: vyos_banner +author: Trishna Guha (@trishnaguha) short_description: Manage multiline banners on VyOS devices description: - - This will configure both pre-login and post-login banners on remote - devices running VyOS. It allows playbooks to add or remote - banner text from the active running configuration. +- This will configure both pre-login and post-login banners on remote devices running + VyOS. It allows playbooks to add or remote banner text from the active running configuration. notes: - - Tested against VyOS 1.1.8 (helium). - - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). +- Tested against VyOS 1.1.8 (helium). +- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: banner: description: - - Specifies which banner that should be - configured on the remote device. + - Specifies which banner that should be configured on the remote device. required: true - choices: ['pre-login', 'post-login'] + choices: + - pre-login + - post-login text: description: - - The banner text that should be - present in the remote device running configuration. This argument - accepts a multiline string, with no empty lines. Requires I(state=present). + - The banner text that should be present in the remote device running configuration. + This argument accepts a multiline string, with no empty lines. Requires I(state=present). state: description: - - Specifies whether or not the configuration is present in the current - devices active running configuration. + - Specifies whether or not the configuration is present in the current devices + active running configuration. default: present - choices: ['present', 'absent'] -extends_documentation_fragment: vyos + choices: + - present + - absent +extends_documentation_fragment: +- vyos.vyos.vyos """ EXAMPLES = """ diff --git a/plugins/modules/vyos_command.py b/plugins/modules/vyos_command.py index 6da7352e..18538491 100644 --- a/plugins/modules/vyos_command.py +++ b/plugins/modules/vyos_command.py @@ -23,72 +23,64 @@ ANSIBLE_METADATA = { } -DOCUMENTATION = """ ---- -module: vyos_command -version_added: "2.2" -author: "Nathaniel Case (@Qalthos)" +DOCUMENTATION = """module: vyos_command +author: Nathaniel Case (@Qalthos) short_description: Run one or more commands on VyOS devices description: - - The command module allows running one or more commands on remote - devices running VyOS. This module can also be introspected - to validate key parameters before returning successfully. If the - conditional statements are not met in the wait period, the task - fails. - - Certain C(show) commands in VyOS produce many lines of output and - use a custom pager that can cause this module to hang. If the - value of the environment variable C(ANSIBLE_VYOS_TERMINAL_LENGTH) - is not set, the default number of 10000 is used. -extends_documentation_fragment: vyos +- The command module allows running one or more commands on remote devices running + VyOS. This module can also be introspected to validate key parameters before returning + successfully. If the conditional statements are not met in the wait period, the + task fails. +- Certain C(show) commands in VyOS produce many lines of output and use a custom pager + that can cause this module to hang. If the value of the environment variable C(ANSIBLE_VYOS_TERMINAL_LENGTH) + is not set, the default number of 10000 is used. +extends_documentation_fragment: +- vyos.vyos.vyos options: commands: description: - - The ordered set of commands to execute on the remote device - running VyOS. The output from the command execution is - returned to the playbook. If the I(wait_for) argument is - provided, the module is not returned until the condition is - satisfied or the number of retries has been exceeded. + - The ordered set of commands to execute on the remote device running VyOS. The + output from the command execution is returned to the playbook. If the I(wait_for) + argument is provided, the module is not returned until the condition is satisfied + or the number of retries has been exceeded. required: true wait_for: description: - - Specifies what to evaluate from the output of the command - and what conditionals to apply. This argument will cause - the task to wait for a particular conditional to be true - before moving forward. If the conditional is not true - by the configured I(retries), the task fails. See examples. - aliases: ['waitfor'] + - Specifies what to evaluate from the output of the command and what conditionals + to apply. This argument will cause the task to wait for a particular conditional + to be true before moving forward. If the conditional is not true by the configured + I(retries), the task fails. See examples. + aliases: + - waitfor match: description: - - The I(match) argument is used in conjunction with the - I(wait_for) argument to specify the match policy. Valid - values are C(all) or C(any). If the value is set to C(all) - then all conditionals in the wait_for must be satisfied. If - the value is set to C(any) then only one of the values must be - satisfied. + - The I(match) argument is used in conjunction with the I(wait_for) argument to + specify the match policy. Valid values are C(all) or C(any). If the value is + set to C(all) then all conditionals in the wait_for must be satisfied. If the + value is set to C(any) then only one of the values must be satisfied. default: all - choices: ['any', 'all'] + choices: + - any + - all retries: description: - - Specifies the number of retries a command should be tried - before it is considered failed. The command is run on the - target device every retry and evaluated against the I(wait_for) - conditionals. + - Specifies the number of retries a command should be tried before it is considered + failed. The command is run on the target device every retry and evaluated against + the I(wait_for) conditionals. default: 10 interval: description: - - Configures the interval in seconds to wait between I(retries) - of the command. If the command does not pass the specified - conditions, the interval indicates how long to wait before - trying the command again. + - Configures the interval in seconds to wait between I(retries) of the command. + If the command does not pass the specified conditions, the interval indicates + how long to wait before trying the command again. default: 1 - notes: - - Tested against VyOS 1.1.8 (helium). - - Running C(show system boot-messages all) will cause the module to hang since - VyOS is using a custom pager setting to display the output of that command. - - If a command sent to the device requires answering a prompt, it is possible - to pass a dict containing I(command), I(answer) and I(prompt). See examples. - - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). +- Tested against VyOS 1.1.8 (helium). +- Running C(show system boot-messages all) will cause the module to hang since VyOS + is using a custom pager setting to display the output of that command. +- If a command sent to the device requires answering a prompt, it is possible to pass + a dict containing I(command), I(answer) and I(prompt). See examples. +- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). """ EXAMPLES = """ @@ -143,8 +135,10 @@ import time from ansible.module_utils._text import to_text from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.parsing import Conditional -from ansible.module_utils.network.common.utils import ( +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import ( + Conditional, +) +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( transform_commands, to_lines, ) @@ -219,7 +213,7 @@ def main(): module.fail_json(msg=msg, failed_conditions=failed_conditions) result.update( - {"stdout": responses, "stdout_lines": list(to_lines(responses))} + {"stdout": responses, "stdout_lines": list(to_lines(responses)),} ) module.exit_json(**result) diff --git a/plugins/modules/vyos_config.py b/plugins/modules/vyos_config.py index 7c9f3ab1..24fa161a 100644 --- a/plugins/modules/vyos_config.py +++ b/plugins/modules/vyos_config.py @@ -23,96 +23,89 @@ ANSIBLE_METADATA = { } -DOCUMENTATION = """ ---- -module: vyos_config -version_added: "2.2" -author: "Nathaniel Case (@Qalthos)" +DOCUMENTATION = """module: vyos_config +author: Nathaniel Case (@Qalthos) short_description: Manage VyOS configuration on remote device description: - - This module provides configuration file management of VyOS - devices. It provides arguments for managing both the - configuration file and state of the active configuration. All - configuration statements are based on `set` and `delete` commands - in the device configuration. -extends_documentation_fragment: vyos +- This module provides configuration file management of VyOS devices. It provides + arguments for managing both the configuration file and state of the active configuration. + All configuration statements are based on `set` and `delete` commands in the device + configuration. +extends_documentation_fragment: +- vyos.vyos.vyos notes: - - Tested against VyOS 1.1.8 (helium). - - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). +- Tested against VyOS 1.1.8 (helium). +- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: lines: description: - - The ordered set of configuration lines to be managed and - compared with the existing configuration on the remote - device. + - The ordered set of configuration lines to be managed and compared with the existing + configuration on the remote device. src: description: - - The C(src) argument specifies the path to the source config - file to load. The source config file can either be in - bracket format or set format. The source file can include - Jinja2 template variables. + - The C(src) argument specifies the path to the source config file to load. The + source config file can either be in bracket format or set format. The source + file can include Jinja2 template variables. match: description: - - The C(match) argument controls the method used to match - against the current active configuration. By default, the - desired config is matched against the active config and the - deltas are loaded. If the C(match) argument is set to C(none) - the active configuration is ignored and the configuration is - always loaded. + - The C(match) argument controls the method used to match against the current + active configuration. By default, the desired config is matched against the + active config and the deltas are loaded. If the C(match) argument is set to + C(none) the active configuration is ignored and the configuration is always + loaded. default: line - choices: ['line', 'none'] + choices: + - line + - none backup: description: - - The C(backup) argument will backup the current devices active - configuration to the Ansible control host prior to making any - changes. If the C(backup_options) value is not given, the - backup file will be located in the backup folder in the playbook - root directory or role root directory, if playbook is part of an - ansible role. If the directory does not exist, it is created. + - The C(backup) argument will backup the current devices active configuration + to the Ansible control host prior to making any changes. If the C(backup_options) + value is not given, the backup file will be located in the backup folder in + the playbook root directory or role root directory, if playbook is part of an + ansible role. If the directory does not exist, it is created. type: bool default: 'no' comment: description: - - Allows a commit description to be specified to be included - when the configuration is committed. If the configuration is - not changed or committed, this argument is ignored. - default: 'configured by vyos_config' + - Allows a commit description to be specified to be included when the configuration + is committed. If the configuration is not changed or committed, this argument + is ignored. + default: configured by vyos_config config: description: - - The C(config) argument specifies the base configuration to use - to compare against the desired configuration. If this value - is not specified, the module will automatically retrieve the - current active configuration from the remote device. + - The C(config) argument specifies the base configuration to use to compare against + the desired configuration. If this value is not specified, the module will + automatically retrieve the current active configuration from the remote device. save: description: - - The C(save) argument controls whether or not changes made - to the active configuration are saved to disk. This is - independent of committing the config. When set to True, the - active configuration is saved. + - The C(save) argument controls whether or not changes made to the active configuration + are saved to disk. This is independent of committing the config. When set + to True, the active configuration is saved. type: bool default: 'no' backup_options: description: - - This is a dict object containing configurable options related to backup file path. - The value of this option is read only when C(backup) is set to I(yes), if C(backup) is set - to I(no) this option will be silently ignored. + - This is a dict object containing configurable options related to backup file + path. The value of this option is read only when C(backup) is set to I(yes), + if C(backup) is set to I(no) this option will be silently ignored. suboptions: filename: description: - - The filename to be used to store the backup configuration. If the the filename - is not given it will be generated based on the hostname, current time and date - in format defined by <hostname>_config.<current-date>@<current-time> + - The filename to be used to store the backup configuration. If the the filename + is not given it will be generated based on the hostname, current time and + date in format defined by <hostname>_config.<current-date>@<current-time> dir_path: description: - - This option provides the path ending with directory name in which the backup - configuration file will be stored. If the directory does not exist it will be first - created and the filename is either the value of C(filename) or default filename - as described in C(filename) options description. If the path value is not given - in that case a I(backup) directory will be created in the current working directory - and backup configuration will be copied in C(filename) within I(backup) directory. + - This option provides the path ending with directory name in which the backup + configuration file will be stored. If the directory does not exist it will + be first created and the filename is either the value of C(filename) or + default filename as described in C(filename) options description. If the + path value is not given in that case a I(backup) directory will be created + in the current working directory and backup configuration will be copied + in C(filename) within I(backup) directory. type: path type: dict - version_added: "2.8" """ EXAMPLES = """ @@ -217,7 +210,17 @@ def get_candidate(module): def format_commands(commands): - return [line for line in commands if len(line.strip()) > 0] + """ + This function format the input commands and removes the prepend white spaces + for command lines having 'set' or 'delete' and it skips empty lines. + :param commands: + :return: list of commands + """ + return [ + line.strip() if line.split()[0] in ("set", "delete") else line + for line in commands + if len(line.strip()) > 0 + ] def diff_config(commands, config): diff --git a/plugins/modules/vyos_facts.py b/plugins/modules/vyos_facts.py index 125b2564..9eaa278d 100644 --- a/plugins/modules/vyos_facts.py +++ b/plugins/modules/vyos_facts.py @@ -15,48 +15,40 @@ ANSIBLE_METADATA = { } -DOCUMENTATION = """ ---- -module: vyos_facts -version_added: 2.2 +DOCUMENTATION = """module: vyos_facts short_description: Get facts about vyos devices. description: - - Collects facts from network devices running the vyos operating - system. This module places the facts gathered in the fact tree keyed by the - respective resource name. The facts module will always collect a - base set of facts from the device and can enable or disable - collection of additional facts. +- Collects facts from network devices running the vyos operating system. This module + places the facts gathered in the fact tree keyed by the respective resource name. The + facts module will always collect a base set of facts from the device and can enable + or disable collection of additional facts. author: - - Nathaniel Case (@qalthos) - - Nilashish Chakraborty (@Nilashishc) - - Rohit Thakur (@rohitthakur2590) -extends_documentation_fragment: vyos +- Nathaniel Case (@qalthos) +- Nilashish Chakraborty (@Nilashishc) +- Rohit Thakur (@rohitthakur2590) +extends_documentation_fragment: +- vyos.vyos.vyos notes: - - Tested against VyOS 1.1.8 (helium). - - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). +- Tested against VyOS 1.1.8 (helium). +- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: gather_subset: description: - - When supplied, this argument will restrict the facts collected - to a given subset. Possible values for this argument include - all, default, config, and neighbors. Can specify a list of - values to include a larger subset. Values can also be used - with an initial C(M(!)) to specify that a specific subset should - not be collected. + - When supplied, this argument will restrict the facts collected to a given subset. Possible + values for this argument include all, default, config, and neighbors. Can specify + a list of values to include a larger subset. Values can also be used with an + initial C(M(!)) to specify that a specific subset should not be collected. required: false - default: "!config" + default: '!config' gather_network_resources: description: - - When supplied, this argument will restrict the facts collected - to a given subset. Possible values for this argument include - all and the resources like interfaces. - Can specify a list of values to include a larger subset. Values - can also be used with an initial C(M(!)) to specify that a - specific subset should not be collected. - Valid subsets are 'all', 'interfaces', 'l3_interfaces', 'lag_interfaces', - 'lldp_global', 'lldp_interfaces'. + - When supplied, this argument will restrict the facts collected to a given subset. + Possible values for this argument include all and the resources like interfaces. + Can specify a list of values to include a larger subset. Values can also be + used with an initial C(M(!)) to specify that a specific subset should not be + collected. Valid subsets are 'all', 'interfaces', 'l3_interfaces', 'lag_interfaces', + 'lldp_global', 'lldp_interfaces'. required: false - version_added: "2.9" """ EXAMPLES = """ @@ -158,17 +150,17 @@ def main(): :returns: ansible_facts """ argument_spec = FactsArgs.argument_spec - argument_spec.update(vyos_argument_spec) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True ) - warnings = [ - "default value for `gather_subset` " - "will be changed to `min` from `!config` v2.11 onwards" - ] + warnings = [] + if module.params["gather_subset"] == "!config": + warnings.append( + "default value for `gather_subset` will be changed to `min` from `!config` v2.11 onwards" + ) result = Facts(module).get_facts() diff --git a/plugins/modules/vyos_interface.py b/plugins/modules/vyos_interface.py index 3459fa1b..175cf3b5 120000..100644 --- a/plugins/modules/vyos_interface.py +++ b/plugins/modules/vyos_interface.py @@ -1 +1,471 @@ -_vyos_interface.py
\ No newline at end of file +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# (c) 2017, Ansible by Red Hat, inc +# +# This file is part of Ansible by Red Hat +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["deprecated"], + "supported_by": "network", +} + + +DOCUMENTATION = """module: vyos_interface +author: Ganesh Nalawade (@ganeshrn) +short_description: Manage Interface on VyOS network devices +description: +- This module provides declarative management of Interfaces on VyOS network devices. +deprecated: + removed_in: '2.13' + alternative: vyos_interfaces + why: Updated modules released with more functionality. +notes: +- Tested against VYOS 1.1.7 +options: + name: + description: + - Name of the Interface. + required: true + description: + description: + - Description of Interface. + enabled: + description: + - Interface link status. + type: bool + speed: + description: + - Interface link speed. + mtu: + description: + - Maximum size of transmit packet. + duplex: + description: + - Interface link status. + default: auto + choices: + - full + - half + - auto + delay: + description: + - Time in seconds to wait before checking for the operational state on remote + device. This wait is applicable for operational state argument which are I(state) + with values C(up)/C(down) and I(neighbors). + default: 10 + neighbors: + description: + - Check the operational state of given interface C(name) for LLDP neighbor. + - The following suboptions are available. + suboptions: + host: + description: + - LLDP neighbor host for given interface C(name). + port: + description: + - LLDP neighbor port to which given interface C(name) is connected. + aggregate: + description: List of Interfaces definitions. + state: + description: + - State of the Interface configuration, C(up) means present and operationally + up and C(down) means present and operationally C(down) + default: present + choices: + - present + - absent + - up + - down +extends_documentation_fragment: +- vyos.vyos.vyos +""" + +EXAMPLES = """ +- name: configure interface + vyos_interface: + name: eth0 + description: test-interface + +- name: remove interface + vyos_interface: + name: eth0 + state: absent + +- name: make interface down + vyos_interface: + name: eth0 + enabled: False + +- name: make interface up + vyos_interface: + name: eth0 + enabled: True + +- name: Configure interface speed, mtu, duplex + vyos_interface: + name: eth5 + state: present + speed: 100 + mtu: 256 + duplex: full + +- name: Set interface using aggregate + vyos_interface: + aggregate: + - { name: eth1, description: test-interface-1, speed: 100, duplex: half, mtu: 512} + - { name: eth2, description: test-interface-2, speed: 1000, duplex: full, mtu: 256} + +- name: Disable interface on aggregate + net_interface: + aggregate: + - name: eth1 + - name: eth2 + enabled: False + +- name: Delete interface using aggregate + net_interface: + aggregate: + - name: eth1 + - name: eth2 + state: absent + +- name: Check lldp neighbors intent arguments + vyos_interface: + name: eth0 + neighbors: + - port: eth0 + host: netdev + +- name: Config + intent + vyos_interface: + name: eth1 + enabled: False + state: down +""" + +RETURN = """ +commands: + description: The list of configuration mode commands to send to the device + returned: always, except for the platforms that use Netconf transport to manage the device. + type: list + sample: + - set interfaces ethernet eth0 description "test-interface" + - set interfaces ethernet eth0 speed 100 + - set interfaces ethernet eth0 mtu 256 + - set interfaces ethernet eth0 duplex full +""" +import re + +from copy import deepcopy +from time import sleep + +from ansible.module_utils._text import to_text +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import exec_command +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + conditional, + remove_default_spec, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + load_config, + get_config, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) + + +def search_obj_in_list(name, lst): + for o in lst: + if o["name"] == name: + return o + + return None + + +def map_obj_to_commands(updates): + commands = list() + want, have = updates + + params = ("speed", "description", "duplex", "mtu") + for w in want: + name = w["name"] + disable = w["disable"] + state = w["state"] + + obj_in_have = search_obj_in_list(name, have) + set_interface = "set interfaces ethernet " + name + delete_interface = "delete interfaces ethernet " + name + + if state == "absent" and obj_in_have: + commands.append(delete_interface) + elif state in ("present", "up", "down"): + if obj_in_have: + for item in params: + value = w.get(item) + + if value and value != obj_in_have.get(item): + if item == "description": + value = "'" + str(value) + "'" + commands.append( + set_interface + " " + item + " " + str(value) + ) + + if disable and not obj_in_have.get("disable", False): + commands.append(set_interface + " disable") + elif not disable and obj_in_have.get("disable", False): + commands.append(delete_interface + " disable") + else: + commands.append(set_interface) + for item in params: + value = w.get(item) + if value: + if item == "description": + value = "'" + str(value) + "'" + commands.append( + set_interface + " " + item + " " + str(value) + ) + + if disable: + commands.append(set_interface + " disable") + return commands + + +def map_config_to_obj(module): + data = get_config(module, flags=["| grep interface"]) + obj = [] + for line in data.split("\n"): + if line.startswith("set interfaces ethernet"): + match = re.search(r"set interfaces ethernet (\S+)", line, re.M) + name = match.group(1) + if name: + interface = {} + for item in obj: + if item["name"] == name: + interface = item + break + + if not interface: + interface = {"name": name} + obj.append(interface) + + match = re.search(r"%s (\S+)" % name, line, re.M) + if match: + param = match.group(1) + if param == "description": + match = re.search(r"description (.+)", line, re.M) + description = match.group(1).strip("'") + interface["description"] = description + elif param == "speed": + match = re.search(r"speed (\S+)", line, re.M) + speed = match.group(1).strip("'") + interface["speed"] = speed + elif param == "mtu": + match = re.search(r"mtu (\S+)", line, re.M) + mtu = match.group(1).strip("'") + interface["mtu"] = int(mtu) + elif param == "duplex": + match = re.search(r"duplex (\S+)", line, re.M) + duplex = match.group(1).strip("'") + interface["duplex"] = duplex + elif param.strip("'") == "disable": + interface["disable"] = True + + return obj + + +def map_params_to_obj(module): + obj = [] + aggregate = module.params.get("aggregate") + if aggregate: + for item in aggregate: + for key in item: + if item.get(key) is None: + item[key] = module.params[key] + + d = item.copy() + if d["enabled"]: + d["disable"] = False + else: + d["disable"] = True + + obj.append(d) + else: + params = { + "name": module.params["name"], + "description": module.params["description"], + "speed": module.params["speed"], + "mtu": module.params["mtu"], + "duplex": module.params["duplex"], + "delay": module.params["delay"], + "state": module.params["state"], + "neighbors": module.params["neighbors"], + } + + if module.params["enabled"]: + params.update({"disable": False}) + else: + params.update({"disable": True}) + + obj.append(params) + return obj + + +def check_declarative_intent_params(module, want, result): + failed_conditions = [] + have_neighbors = None + for w in want: + want_state = w.get("state") + want_neighbors = w.get("neighbors") + + if want_state not in ("up", "down") and not want_neighbors: + continue + + if result["changed"]: + sleep(w["delay"]) + + command = "show interfaces ethernet %s" % w["name"] + rc, out, err = exec_command(module, command) + if rc != 0: + module.fail_json( + msg=to_text(err, errors="surrogate_then_replace"), + command=command, + rc=rc, + ) + + if want_state in ("up", "down"): + match = re.search(r"%s (\w+)" % "state", out, re.M) + have_state = None + if match: + have_state = match.group(1) + if have_state is None or not conditional( + want_state, have_state.strip().lower() + ): + failed_conditions.append("state " + "eq(%s)" % want_state) + + if want_neighbors: + have_host = [] + have_port = [] + if have_neighbors is None: + rc, have_neighbors, err = exec_command( + module, "show lldp neighbors detail" + ) + if rc != 0: + module.fail_json( + msg=to_text(err, errors="surrogate_then_replace"), + command=command, + rc=rc, + ) + + if have_neighbors: + lines = have_neighbors.strip().split("Interface: ") + for line in lines: + field = line.split("\n") + if field[0].split(",")[0].strip() == w["name"]: + for item in field: + if item.strip().startswith("SysName:"): + have_host.append(item.split(":")[1].strip()) + if item.strip().startswith("PortDescr:"): + have_port.append(item.split(":")[1].strip()) + for item in want_neighbors: + host = item.get("host") + port = item.get("port") + if host and host not in have_host: + failed_conditions.append("host " + host) + if port and port not in have_port: + failed_conditions.append("port " + port) + + return failed_conditions + + +def main(): + """ main entry point for module execution + """ + neighbors_spec = dict(host=dict(), port=dict()) + + element_spec = dict( + name=dict(), + description=dict(), + speed=dict(), + mtu=dict(type="int"), + duplex=dict(choices=["full", "half", "auto"]), + enabled=dict(default=True, type="bool"), + neighbors=dict(type="list", elements="dict", options=neighbors_spec), + delay=dict(default=10, type="int"), + state=dict( + default="present", choices=["present", "absent", "up", "down"] + ), + ) + + aggregate_spec = deepcopy(element_spec) + aggregate_spec["name"] = dict(required=True) + + # remove default in aggregate spec, to handle common arguments + remove_default_spec(aggregate_spec) + + argument_spec = dict( + aggregate=dict(type="list", elements="dict", options=aggregate_spec), + ) + + argument_spec.update(element_spec) + argument_spec.update(vyos_argument_spec) + + required_one_of = [["name", "aggregate"]] + mutually_exclusive = [["name", "aggregate"]] + + required_together = [["speed", "duplex"]] + module = AnsibleModule( + argument_spec=argument_spec, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + supports_check_mode=True, + ) + + warnings = list() + + result = {"changed": False} + + if warnings: + result["warnings"] = warnings + + want = map_params_to_obj(module) + have = map_config_to_obj(module) + + commands = map_obj_to_commands((want, have)) + result["commands"] = commands + + if commands: + commit = not module.check_mode + diff = load_config(module, commands, commit=commit) + if diff: + if module._diff: + result["diff"] = {"prepared": diff} + result["changed"] = True + + failed_conditions = check_declarative_intent_params(module, want, result) + + if failed_conditions: + msg = "One or more conditional statements have not been satisfied" + module.fail_json(msg=msg, failed_conditions=failed_conditions) + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/vyos_interfaces.py b/plugins/modules/vyos_interfaces.py index 096fd1ff..93df4e46 100644 --- a/plugins/modules/vyos_interfaces.py +++ b/plugins/modules/vyos_interfaces.py @@ -36,18 +36,15 @@ ANSIBLE_METADATA = { "supported_by": "network", } -DOCUMENTATION = """ ---- -module: vyos_interfaces -version_added: 2.9 +DOCUMENTATION = """module: vyos_interfaces short_description: Manages interface attributes of VyOS network devices. description: - - This module manages the interface attributes on VyOS network devices. - - This module supports managing base attributes of Ethernet, Bonding, - VXLAN, Loopback and Virtual Tunnel Interfaces. +- This module manages the interface attributes on VyOS network devices. +- This module supports managing base attributes of Ethernet, Bonding, VXLAN, Loopback + and Virtual Tunnel Interfaces. notes: - - Tested against VyOS 1.1.8 (helium). - - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). +- Tested against VyOS 1.1.8 (helium). +- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: Nilashish Chakraborty (@nilashishc) options: config: @@ -58,64 +55,73 @@ options: description: - Full name of the interface, e.g. eth0, eth1, bond0, vti1, vxlan2. type: str - required: True + required: true description: description: - - Interface description. + - Interface description. type: str duplex: description: - - Interface duplex mode. - - Applicable for Ethernet interfaces only. - choices: ['full', 'half', 'auto'] + - Interface duplex mode. + - Applicable for Ethernet interfaces only. + choices: + - full + - half + - auto type: str enabled: - default: True + default: true description: - - Administrative state of the interface. - - Set the value to C(true) to administratively enable - the interface or C(false) to disable it. + - Administrative state of the interface. + - Set the value to C(true) to administratively enable the interface or C(false) + to disable it. type: bool mtu: description: - - MTU for a specific interface. Refer to vendor documentation for valid values. - - Applicable for Ethernet, Bonding, VXLAN and Virtual Tunnel interfaces. + - MTU for a specific interface. Refer to vendor documentation for valid values. + - Applicable for Ethernet, Bonding, VXLAN and Virtual Tunnel interfaces. type: int speed: description: - - Interface link speed. - - Applicable for Ethernet interfaces only. + - Interface link speed. + - Applicable for Ethernet interfaces only. type: str - choices: ['auto', '10', '100', '1000', '2500', '10000'] + choices: + - auto + - '10' + - '100' + - '1000' + - '2500' + - '10000' vifs: description: - - Virtual sub-interfaces related configuration. - - 802.1Q VLAN interfaces are represented as virtual sub-interfaces in VyOS. + - Virtual sub-interfaces related configuration. + - 802.1Q VLAN interfaces are represented as virtual sub-interfaces in VyOS. type: list suboptions: vlan_id: description: - - Identifier for the virtual sub-interface. + - Identifier for the virtual sub-interface. type: int description: description: - - Virtual sub-interface description. + - Virtual sub-interface description. type: str enabled: description: - - Administrative state of the virtual sub-interface. - - Set the value to C(true) to administratively enable - the interface or C(false) to disable it. + - Administrative state of the virtual sub-interface. + - Set the value to C(true) to administratively enable the interface or + C(false) to disable it. type: bool - default: True + default: true mtu: description: - - MTU for the virtual sub-interface. - - Refer to vendor documentation for valid values. + - MTU for the virtual sub-interface. + - Refer to vendor documentation for valid values. type: int state: description: - - The state of the configuration after module completion. + - The state of the configuration after module completion. type: str choices: - merged diff --git a/plugins/modules/vyos_l3_interface.py b/plugins/modules/vyos_l3_interface.py index 961ef4e6..faa9629f 120000..100644 --- a/plugins/modules/vyos_l3_interface.py +++ b/plugins/modules/vyos_l3_interface.py @@ -1 +1,329 @@ -_vyos_l3_interface.py
\ No newline at end of file +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# (c) 2017, Ansible by Red Hat, inc +# +# This file is part of Ansible by Red Hat +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["deprecated"], + "supported_by": "network", +} + + +DOCUMENTATION = """module: vyos_l3_interface +author: Ricardo Carrillo Cruz (@rcarrillocruz) +short_description: Manage L3 interfaces on VyOS network devices +description: +- This module provides declarative management of L3 interfaces on VyOS network devices. +deprecated: + removed_in: '2.13' + alternative: vyos_l3_interfaces + why: Updated modules released with more functionality. +notes: +- Tested against VYOS 1.1.7 +options: + name: + description: + - Name of the L3 interface. + ipv4: + description: + - IPv4 of the L3 interface. + ipv6: + description: + - IPv6 of the L3 interface. + aggregate: + description: List of L3 interfaces definitions + state: + description: + - State of the L3 interface configuration. + default: present + choices: + - present + - absent +extends_documentation_fragment: +- vyos.vyos.vyos +""" + +EXAMPLES = """ +- name: Set eth0 IPv4 address + vyos_l3_interface: + name: eth0 + ipv4: 192.168.0.1/24 + +- name: Remove eth0 IPv4 address + vyos_l3_interface: + name: eth0 + state: absent + +- name: Set IP addresses on aggregate + vyos_l3_interface: + aggregate: + - { name: eth1, ipv4: 192.168.2.10/24 } + - { name: eth2, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64" } + +- name: Remove IP addresses on aggregate + vyos_l3_interface: + aggregate: + - { name: eth1, ipv4: 192.168.2.10/24 } + - { name: eth2, ipv4: 192.168.3.10/24, ipv6: "fd5d:12c9:2201:1::1/64" } + state: absent +""" + +RETURN = """ +commands: + description: The list of configuration mode commands to send to the device + returned: always, except for the platforms that use Netconf transport to manage the device. + type: list + sample: + - set interfaces ethernet eth0 address '192.168.0.1/24' +""" + +import socket +import re + +from copy import deepcopy + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + is_masklen, + validate_ip_address, +) +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + remove_default_spec, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + load_config, + run_commands, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) + + +def is_ipv4(value): + if value: + address = value.split("/") + if is_masklen(address[1]) and validate_ip_address(address[0]): + return True + return False + + +def is_ipv6(value): + if value: + address = value.split("/") + if 0 <= int(address[1]) <= 128: + try: + socket.inet_pton(socket.AF_INET6, address[0]) + except socket.error: + return False + return True + return False + + +def search_obj_in_list(name, lst): + for o in lst: + if o["name"] == name: + return o + + return None + + +def map_obj_to_commands(updates, module): + commands = list() + want, have = updates + + for w in want: + name = w["name"] + ipv4 = w["ipv4"] + ipv6 = w["ipv6"] + state = w["state"] + + obj_in_have = search_obj_in_list(name, have) + + if state == "absent" and obj_in_have: + if ( + not ipv4 + and not ipv6 + and (obj_in_have["ipv4"] or obj_in_have["ipv6"]) + ): + if name == "lo": + commands.append("delete interfaces loopback lo address") + else: + commands.append( + "delete interfaces ethernet " + name + " address" + ) + else: + if ipv4 and ipv4 in obj_in_have["ipv4"]: + if name == "lo": + commands.append( + "delete interfaces loopback lo address " + ipv4 + ) + else: + commands.append( + "delete interfaces ethernet " + + name + + " address " + + ipv4 + ) + if ipv6 and ipv6 in obj_in_have["ipv6"]: + if name == "lo": + commands.append( + "delete interfaces loopback lo address " + ipv6 + ) + else: + commands.append( + "delete interfaces ethernet " + + name + + " address " + + ipv6 + ) + elif state == "present" and obj_in_have: + if ipv4 and ipv4 not in obj_in_have["ipv4"]: + if name == "lo": + commands.append( + "set interfaces loopback lo address " + ipv4 + ) + else: + commands.append( + "set interfaces ethernet " + name + " address " + ipv4 + ) + + if ipv6 and ipv6 not in obj_in_have["ipv6"]: + if name == "lo": + commands.append( + "set interfaces loopback lo address " + ipv6 + ) + else: + commands.append( + "set interfaces ethernet " + name + " address " + ipv6 + ) + + return commands + + +def map_config_to_obj(module): + obj = [] + output = run_commands(module, ["show interfaces"]) + lines = re.split(r"\n[e|l]", output[0])[1:] + + if len(lines) > 0: + for line in lines: + splitted_line = line.split() + + if len(splitted_line) > 0: + ipv4 = [] + ipv6 = [] + + if splitted_line[0].lower().startswith("th"): + name = "e" + splitted_line[0].lower() + elif splitted_line[0].lower().startswith("o"): + name = "l" + splitted_line[0].lower() + + for i in splitted_line[1:]: + if ("." in i or ":" in i) and "/" in i: + value = i.split(r"\n")[0] + if is_ipv4(value): + ipv4.append(value) + elif is_ipv6(value): + ipv6.append(value) + + obj.append({"name": name, "ipv4": ipv4, "ipv6": ipv6}) + + return obj + + +def map_params_to_obj(module): + obj = [] + + aggregate = module.params.get("aggregate") + if aggregate: + for item in aggregate: + for key in item: + if item.get(key) is None: + item[key] = module.params[key] + + obj.append(item.copy()) + else: + obj.append( + { + "name": module.params["name"], + "ipv4": module.params["ipv4"], + "ipv6": module.params["ipv6"], + "state": module.params["state"], + } + ) + + return obj + + +def main(): + """ main entry point for module execution + """ + element_spec = dict( + name=dict(), + ipv4=dict(), + ipv6=dict(), + state=dict(default="present", choices=["present", "absent"]), + ) + + aggregate_spec = deepcopy(element_spec) + aggregate_spec["name"] = dict(required=True) + + # remove default in aggregate spec, to handle common arguments + remove_default_spec(aggregate_spec) + + argument_spec = dict( + aggregate=dict(type="list", elements="dict", options=aggregate_spec), + ) + + argument_spec.update(element_spec) + argument_spec.update(vyos_argument_spec) + + required_one_of = [["name", "aggregate"]] + mutually_exclusive = [["name", "aggregate"]] + module = AnsibleModule( + argument_spec=argument_spec, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + supports_check_mode=True, + ) + + warnings = list() + + result = {"changed": False} + + if warnings: + result["warnings"] = warnings + + want = map_params_to_obj(module) + have = map_config_to_obj(module) + + commands = map_obj_to_commands((want, have), module) + result["commands"] = commands + + if commands: + commit = not module.check_mode + load_config(module, commands, commit=commit) + result["changed"] = True + + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/vyos_l3_interfaces.py b/plugins/modules/vyos_l3_interfaces.py index 113ea536..a77ecaf7 100644 --- a/plugins/modules/vyos_l3_interfaces.py +++ b/plugins/modules/vyos_l3_interfaces.py @@ -36,15 +36,12 @@ ANSIBLE_METADATA = { "supported_by": "network", } -DOCUMENTATION = """ ---- -module: vyos_l3_interfaces -version_added: 2.9 +DOCUMENTATION = """module: vyos_l3_interfaces short_description: Manages L3 interface attributes of VyOS network devices. description: This module manages the L3 interface attributes on VyOS network devices. notes: - - Tested against VyOS 1.1.8 (helium). - - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). +- Tested against VyOS 1.1.8 (helium). +- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: Nilashish Chakraborty (@NilashishC) options: config: @@ -54,62 +51,62 @@ options: suboptions: name: description: - - Full name of the interface, e.g. eth0, eth1. + - Full name of the interface, e.g. eth0, eth1. type: str - required: True + required: true ipv4: description: - - List of IPv4 addresses of the interface. + - List of IPv4 addresses of the interface. type: list elements: dict suboptions: address: description: - - IPv4 address of the interface. + - IPv4 address of the interface. type: str ipv6: description: - - List of IPv6 addresses of the interface. + - List of IPv6 addresses of the interface. type: list elements: dict suboptions: address: description: - - IPv6 address of the interface. + - IPv6 address of the interface. type: str vifs: description: - - Virtual sub-interfaces L3 configurations. + - Virtual sub-interfaces L3 configurations. elements: dict type: list suboptions: vlan_id: description: - - Identifier for the virtual sub-interface. + - Identifier for the virtual sub-interface. type: int ipv4: description: - - List of IPv4 addresses of the virtual interface. + - List of IPv4 addresses of the virtual interface. type: list elements: dict suboptions: address: description: - - IPv4 address of the virtual interface. + - IPv4 address of the virtual interface. type: str ipv6: description: - - List of IPv6 addresses of the virtual interface. + - List of IPv6 addresses of the virtual interface. type: list elements: dict suboptions: address: description: - - IPv6 address of the virtual interface. + - IPv6 address of the virtual interface. type: str state: description: - - The state of the configuration after module completion. + - The state of the configuration after module completion. type: str choices: - merged @@ -117,7 +114,6 @@ options: - overridden - deleted default: merged - """ EXAMPLES = """ # Using merged diff --git a/plugins/modules/vyos_lag_interfaces.py b/plugins/modules/vyos_lag_interfaces.py index 5c9b4c13..84f3d018 100644 --- a/plugins/modules/vyos_lag_interfaces.py +++ b/plugins/modules/vyos_lag_interfaces.py @@ -36,15 +36,13 @@ ANSIBLE_METADATA = { "supported_by": "network", } -DOCUMENTATION = """ ---- -module: vyos_lag_interfaces -version_added: 2.9 +DOCUMENTATION = """module: vyos_lag_interfaces short_description: Manages attributes of link aggregation groups on VyOS network devices. -description: This module manages attributes of link aggregation groups on VyOS network devices. +description: This module manages attributes of link aggregation groups on VyOS network + devices. notes: - - Tested against VyOS 1.1.8 (helium). - - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). +- Tested against VyOS 1.1.8 (helium). +- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: Rohit Thakur (@rohitthakur2590) options: config: @@ -53,58 +51,58 @@ options: suboptions: name: description: - - Name of the link aggregation group (LAG) or bond. + - Name of the link aggregation group (LAG) or bond. type: str - required: True + required: true mode: description: - - LAG or bond mode. + - LAG or bond mode. type: str choices: - - 802.3ad - - active-backup - - broadcast - - round-robin - - transmit-load-balance - - adaptive-load-balance - - xor-hash + - 802.3ad + - active-backup + - broadcast + - round-robin + - transmit-load-balance + - adaptive-load-balance + - xor-hash members: description: - - List of member interfaces for the LAG (bond). + - List of member interfaces for the LAG (bond). type: list suboptions: member: description: - - Name of the member interface. + - Name of the member interface. type: str primary: description: - - Primary device interfaces for the LAG (bond). + - Primary device interfaces for the LAG (bond). type: str hash_policy: description: - - LAG or bonding transmit hash policy. + - LAG or bonding transmit hash policy. type: str choices: - - layer2 - - layer2+3 - - layer3+4 + - layer2 + - layer2+3 + - layer3+4 arp_monitor: description: - - ARP Link monitoring parameters. + - ARP Link monitoring parameters. type: dict suboptions: interval: description: - - ARP link monitoring frequency in milliseconds. + - ARP link monitoring frequency in milliseconds. type: int target: description: - - IP address to use for ARP monitoring. + - IP address to use for ARP monitoring. type: list state: description: - - The state of the configuration after module completion. + - The state of the configuration after module completion. type: str choices: - merged @@ -112,7 +110,6 @@ options: - overridden - deleted default: merged - """ EXAMPLES = """ # Using merged diff --git a/plugins/modules/vyos_linkagg.py b/plugins/modules/vyos_linkagg.py index 294bec1b..6810a540 120000..100644 --- a/plugins/modules/vyos_linkagg.py +++ b/plugins/modules/vyos_linkagg.py @@ -1 +1,327 @@ -_vyos_linkagg.py
\ No newline at end of file +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# (c) 2017, Ansible by Red Hat, inc +# +# This file is part of Ansible by Red Hat +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["deprecated"], + "supported_by": "network", +} + + +DOCUMENTATION = """module: vyos_linkagg +author: Ricardo Carrillo Cruz (@rcarrillocruz) +short_description: Manage link aggregation groups on VyOS network devices +description: +- This module provides declarative management of link aggregation groups on VyOS network + devices. +deprecated: + removed_in: '2.13' + alternative: vyos_lag_interfaces + why: Updated modules released with more functionality. +notes: +- Tested against VYOS 1.1.7 +options: + name: + description: + - Name of the link aggregation group. + required: true + type: str + mode: + description: + - Mode of the link aggregation group. + choices: + - 802.3ad + - active-backup + - broadcast + - round-robin + - transmit-load-balance + - adaptive-load-balance + - xor-hash + - 'on' + type: str + members: + description: + - List of members of the link aggregation group. + type: list + aggregate: + description: List of link aggregation definitions. + type: list + state: + description: + - State of the link aggregation group. + default: present + choices: + - present + - absent + - up + - down + type: str +extends_documentation_fragment: +- vyos.vyos.vyos +""" + +EXAMPLES = """ +- name: configure link aggregation group + vyos_linkagg: + name: bond0 + members: + - eth0 + - eth1 + +- name: remove configuration + vyos_linkagg: + name: bond0 + state: absent + +- name: Create aggregate of linkagg definitions + vyos_linkagg: + aggregate: + - { name: bond0, members: [eth1] } + - { name: bond1, members: [eth2] } + +- name: Remove aggregate of linkagg definitions + vyos_linkagg: + aggregate: + - name: bond0 + - name: bond1 + state: absent +""" + +RETURN = """ +commands: + description: The list of configuration mode commands to send to the device + returned: always, except for the platforms that use Netconf transport to manage the device. + type: list + sample: + - set interfaces bonding bond0 + - set interfaces ethernet eth0 bond-group 'bond0' + - set interfaces ethernet eth1 bond-group 'bond0' +""" +from copy import deepcopy + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + remove_default_spec, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + load_config, + run_commands, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) + + +def search_obj_in_list(name, lst): + for o in lst: + if o["name"] == name: + return o + + return None + + +def map_obj_to_commands(updates, module): + commands = list() + want, have = updates + + for w in want: + name = w["name"] + members = w.get("members") or [] + mode = w["mode"] + + if mode == "on": + mode = "802.3ad" + + state = w["state"] + + obj_in_have = search_obj_in_list(name, have) + + if state == "absent": + if obj_in_have: + for m in obj_in_have["members"]: + commands.append( + "delete interfaces ethernet " + m + " bond-group" + ) + + commands.append("delete interfaces bonding " + name) + else: + if not obj_in_have: + commands.append( + "set interfaces bonding " + name + " mode " + mode + ) + + for m in members: + commands.append( + "set interfaces ethernet " + m + " bond-group " + name + ) + + if state == "down": + commands.append( + "set interfaces bonding " + name + " disable" + ) + else: + if mode != obj_in_have["mode"]: + commands.append( + "set interfaces bonding " + name + " mode " + mode + ) + + missing_members = list( + set(members) - set(obj_in_have["members"]) + ) + for m in missing_members: + commands.append( + "set interfaces ethernet " + m + " bond-group " + name + ) + + if state == "down" and obj_in_have["state"] == "up": + commands.append( + "set interfaces bonding " + name + " disable" + ) + elif state == "up" and obj_in_have["state"] == "down": + commands.append( + "delete interfaces bonding " + name + " disable" + ) + + return commands + + +def map_config_to_obj(module): + obj = [] + output = run_commands(module, ["show interfaces bonding slaves"]) + lines = output[0].splitlines() + + if len(lines) > 1: + for line in lines[1:]: + splitted_line = line.split() + + name = splitted_line[0] + mode = splitted_line[1] + state = splitted_line[2] + + if len(splitted_line) > 4: + members = splitted_line[4:] + else: + members = [] + + obj.append( + { + "name": name, + "mode": mode, + "members": members, + "state": state, + } + ) + + return obj + + +def map_params_to_obj(module): + obj = [] + aggregate = module.params.get("aggregate") + if aggregate: + for item in aggregate: + for key in item: + if item.get(key) is None: + item[key] = module.params[key] + + obj.append(item.copy()) + else: + obj.append( + { + "name": module.params["name"], + "mode": module.params["mode"], + "members": module.params["members"], + "state": module.params["state"], + } + ) + + return obj + + +def main(): + """ main entry point for module execution + """ + element_spec = dict( + name=dict(), + mode=dict( + choices=[ + "802.3ad", + "active-backup", + "broadcast", + "round-robin", + "transmit-load-balance", + "adaptive-load-balance", + "xor-hash", + "on", + ], + default="802.3ad", + ), + members=dict(type="list"), + state=dict( + default="present", choices=["present", "absent", "up", "down"] + ), + ) + + aggregate_spec = deepcopy(element_spec) + aggregate_spec["name"] = dict(required=True) + + # remove default in aggregate spec, to handle common arguments + remove_default_spec(aggregate_spec) + + argument_spec = dict( + aggregate=dict(type="list", elements="dict", options=aggregate_spec), + ) + + argument_spec.update(element_spec) + argument_spec.update(vyos_argument_spec) + + required_one_of = [["name", "aggregate"]] + mutually_exclusive = [["name", "aggregate"]] + module = AnsibleModule( + argument_spec=argument_spec, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + supports_check_mode=True, + ) + + warnings = list() + + result = {"changed": False} + + if warnings: + result["warnings"] = warnings + + want = map_params_to_obj(module) + have = map_config_to_obj(module) + + commands = map_obj_to_commands((want, have), module) + result["commands"] = commands + + if commands: + commit = not module.check_mode + load_config(module, commands, commit=commit) + result["changed"] = True + + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/vyos_lldp.py b/plugins/modules/vyos_lldp.py index 259de8c9..aa7a3167 120000..100644 --- a/plugins/modules/vyos_lldp.py +++ b/plugins/modules/vyos_lldp.py @@ -1 +1,145 @@ -_vyos_lldp.py
\ No newline at end of file +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# (c) 2017, Ansible by Red Hat, inc +# +# This file is part of Ansible by Red Hat +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["deprecated"], + "supported_by": "network", +} + + +DOCUMENTATION = """module: vyos_lldp +author: Ricardo Carrillo Cruz (@rcarrillocruz) +short_description: Manage LLDP configuration on VyOS network devices +description: +- This module provides declarative management of LLDP service on VyOS network devices. +deprecated: + removed_in: '2.13' + alternative: vyos_lldp_global + why: Updated modules released with more functionality. +notes: +- Tested against VYOS 1.1.7 +options: + interfaces: + description: + - Name of the interfaces. + type: list + state: + description: + - State of the link aggregation group. + default: present + choices: + - present + - absent + - enabled + - disabled + type: str +extends_documentation_fragment: +- vyos.vyos.vyos +""" + +EXAMPLES = """ +- name: Enable LLDP service + vyos_lldp: + state: present + +- name: Disable LLDP service + vyos_lldp: + state: absent +""" + +RETURN = """ +commands: + description: The list of configuration mode commands to send to the device + returned: always, except for the platforms that use Netconf transport to manage the device. + type: list + sample: + - set service lldp +""" +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + get_config, + load_config, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) + + +def has_lldp(module): + config = get_config(module).splitlines() + + if "set service 'lldp'" in config or "set service lldp" in config: + return True + else: + return False + + +def main(): + """ main entry point for module execution + """ + argument_spec = dict( + interfaces=dict(type="list"), + state=dict( + default="present", + choices=["present", "absent", "enabled", "disabled"], + ), + ) + + argument_spec.update(vyos_argument_spec) + + module = AnsibleModule( + argument_spec=argument_spec, supports_check_mode=True + ) + + warnings = list() + + result = {"changed": False} + + if warnings: + result["warnings"] = warnings + + HAS_LLDP = has_lldp(module) + + commands = [] + + if module.params["state"] == "absent" and HAS_LLDP: + commands.append("delete service lldp") + elif module.params["state"] == "present" and not HAS_LLDP: + commands.append("set service lldp") + + result["commands"] = commands + + if commands: + commit = not module.check_mode + load_config(module, commands, commit=commit) + result["changed"] = True + + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/vyos_lldp_global.py b/plugins/modules/vyos_lldp_global.py index 55b1a1ab..08eb1133 100644 --- a/plugins/modules/vyos_lldp_global.py +++ b/plugins/modules/vyos_lldp_global.py @@ -36,17 +36,16 @@ ANSIBLE_METADATA = { "supported_by": "network", } -DOCUMENTATION = """ ---- -module: vyos_lldp_global -version_added: 2.9 -short_description: Manage link layer discovery protocol (LLDP) attributes on VyOS devices.. -description: This module manages link layer discovery protocol (LLDP) attributes on VyOS devices. +DOCUMENTATION = """module: vyos_lldp_global +short_description: Manage link layer discovery protocol (LLDP) attributes on VyOS + devices.. +description: This module manages link layer discovery protocol (LLDP) attributes on + VyOS devices. notes: - - Tested against VyOS 1.1.8 (helium). - - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). +- Tested against VyOS 1.1.8 (helium). +- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: - - Rohit Thakur (@rohitthakur2590) +- Rohit Thakur (@rohitthakur2590) options: config: description: The provided link layer discovery protocol (LLDP) configuration. @@ -54,28 +53,28 @@ options: suboptions: enable: description: - - This argument is a boolean value to enable or disable LLDP. + - This argument is a boolean value to enable or disable LLDP. type: bool address: description: - - This argument defines management-address. + - This argument defines management-address. type: str snmp: description: - - This argument enable the SNMP queries to LLDP database. + - This argument enable the SNMP queries to LLDP database. type: str legacy_protocols: description: - - List of the supported legacy protocols. + - List of the supported legacy protocols. type: list choices: - - cdp - - edp - - fdp - - sonmp + - cdp + - edp + - fdp + - sonmp state: description: - - The state of the configuration after module completion. + - The state of the configuration after module completion. type: str choices: - merged diff --git a/plugins/modules/vyos_lldp_interface.py b/plugins/modules/vyos_lldp_interface.py index 7847a588..402facf8 120000..100644 --- a/plugins/modules/vyos_lldp_interface.py +++ b/plugins/modules/vyos_lldp_interface.py @@ -1 +1,264 @@ -_vyos_lldp_interface.py
\ No newline at end of file +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# (c) 2017, Ansible by Red Hat, inc +# +# This file is part of Ansible by Red Hat +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. +# + + +ANSIBLE_METADATA = { + "metadata_version": "1.1", + "status": ["deprecated"], + "supported_by": "network", +} + + +DOCUMENTATION = """module: vyos_lldp_interface +author: Ricardo Carrillo Cruz (@rcarrillocruz) +short_description: Manage LLDP interfaces configuration on VyOS network devices +description: +- This module provides declarative management of LLDP interfaces configuration on + VyOS network devices. +deprecated: + removed_in: '2.13' + alternative: vyos_lldp_interfaces + why: Updated modules released with more functionality. +notes: +- Tested against VYOS 1.1.7 +options: + name: + description: + - Name of the interface LLDP should be configured on. + type: str + aggregate: + description: List of interfaces LLDP should be configured on. + type: list + state: + description: + - State of the LLDP configuration. + default: present + choices: + - present + - absent + - enabled + - disabled + type: str +extends_documentation_fragment: +- vyos.vyos.vyos +""" + +EXAMPLES = """ +- name: Enable LLDP on eth1 + net_lldp_interface: + state: present + +- name: Enable LLDP on specific interfaces + net_lldp_interface: + interfaces: + - eth1 + - eth2 + state: present + +- name: Disable LLDP globally + net_lldp_interface: + state: disabled + +- name: Create aggregate of LLDP interface configurations + vyos_lldp_interface: + aggregate: + - name: eth1 + - name: eth2 + state: present + +- name: Delete aggregate of LLDP interface configurations + vyos_lldp_interface: + aggregate: + - name: eth1 + - name: eth2 + state: absent +""" + +RETURN = """ +commands: + description: The list of configuration mode commands to send to the device + returned: always, except for the platforms that use Netconf transport to manage the device. + type: list + sample: + - set service lldp eth1 + - set service lldp eth2 disable +""" + + +from copy import deepcopy + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + remove_default_spec, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + get_config, + load_config, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_argument_spec, +) + + +def search_obj_in_list(name, lst): + for o in lst: + if o["name"] == name: + return o + + return None + + +def map_obj_to_commands(updates, module): + commands = list() + want, have = updates + + for w in want: + name = w["name"] + state = w["state"] + + obj_in_have = search_obj_in_list(name, have) + + if state == "absent" and obj_in_have: + commands.append("delete service lldp interface " + name) + elif state in ("present", "enabled"): + if not obj_in_have: + commands.append("set service lldp interface " + name) + elif ( + obj_in_have + and obj_in_have["state"] == "disabled" + and state == "enabled" + ): + commands.append( + "delete service lldp interface " + name + " disable" + ) + elif state == "disabled": + if not obj_in_have: + commands.append("set service lldp interface " + name) + commands.append( + "set service lldp interface " + name + " disable" + ) + elif obj_in_have and obj_in_have["state"] != "disabled": + commands.append( + "set service lldp interface " + name + " disable" + ) + + return commands + + +def map_config_to_obj(module): + obj = [] + config = get_config(module).splitlines() + + output = [c for c in config if c.startswith("set service lldp interface")] + + for i in output: + splitted_line = i.split() + + if len(splitted_line) > 5: + new_obj = {"name": splitted_line[4]} + + if splitted_line[5] == "'disable'": + new_obj["state"] = "disabled" + else: + new_obj = {"name": splitted_line[4][1:-1]} + new_obj["state"] = "present" + + obj.append(new_obj) + + return obj + + +def map_params_to_obj(module): + obj = [] + + aggregate = module.params.get("aggregate") + if aggregate: + for item in aggregate: + for key in item: + if item.get(key) is None: + item[key] = module.params[key] + + obj.append(item.copy()) + else: + obj.append( + {"name": module.params["name"], "state": module.params["state"]} + ) + + return obj + + +def main(): + """ main entry point for module execution + """ + element_spec = dict( + name=dict(), + state=dict( + default="present", + choices=["present", "absent", "enabled", "disabled"], + ), + ) + + aggregate_spec = deepcopy(element_spec) + aggregate_spec["name"] = dict(required=True) + + # remove default in aggregate spec, to handle common arguments + remove_default_spec(aggregate_spec) + + argument_spec = dict( + aggregate=dict(type="list", elements="dict", options=aggregate_spec), + ) + + argument_spec.update(element_spec) + argument_spec.update(vyos_argument_spec) + + required_one_of = [["name", "aggregate"]] + mutually_exclusive = [["name", "aggregate"]] + + module = AnsibleModule( + argument_spec=argument_spec, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + supports_check_mode=True, + ) + + warnings = list() + + result = {"changed": False} + + if warnings: + result["warnings"] = warnings + + want = map_params_to_obj(module) + have = map_config_to_obj(module) + + commands = map_obj_to_commands((want, have), module) + result["commands"] = commands + + if commands: + commit = not module.check_mode + load_config(module, commands, commit=commit) + result["changed"] = True + + module.exit_json(**result) + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/vyos_lldp_interfaces.py b/plugins/modules/vyos_lldp_interfaces.py index 70ceed8c..8fe572b0 100644 --- a/plugins/modules/vyos_lldp_interfaces.py +++ b/plugins/modules/vyos_lldp_interfaces.py @@ -36,17 +36,14 @@ ANSIBLE_METADATA = { "supported_by": "network", } -DOCUMENTATION = """ ---- -module: vyos_lldp_interfaces -version_added: 2.9 +DOCUMENTATION = """module: vyos_lldp_interfaces short_description: Manages attributes of lldp interfaces on VyOS devices. description: This module manages attributes of lldp interfaces on VyOS network devices. notes: - - Tested against VyOS 1.1.8 (helium). - - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). +- Tested against VyOS 1.1.8 (helium). +- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). author: - - Rohit Thakur (@rohitthakur2590) +- Rohit Thakur (@rohitthakur2590) options: config: description: A list of lldp interfaces configurations. @@ -54,43 +51,43 @@ options: suboptions: name: description: - - Name of the lldp interface. + - Name of the lldp interface. type: str - required: True + required: true enable: description: - - to disable lldp on the interface. + - to disable lldp on the interface. type: bool - default: True + default: true location: description: - - LLDP-MED location data. + - LLDP-MED location data. type: dict suboptions: civic_based: description: - - Civic-based location data. + - Civic-based location data. type: dict suboptions: ca_info: - description: LLDP-MED address info - type: list - suboptions: - ca_type: - description: LLDP-MED Civic Address type. - type: int - required: True - ca_value: - description: LLDP-MED Civic Address value. - type: str - required: True + description: LLDP-MED address info + type: list + suboptions: + ca_type: + description: LLDP-MED Civic Address type. + type: int + required: true + ca_value: + description: LLDP-MED Civic Address value. + type: str + required: true country_code: description: Country Code type: str - required: True + required: true coordinate_based: description: - - Coordinate-based location. + - Coordinate-based location. type: dict suboptions: altitude: @@ -100,23 +97,23 @@ options: description: Coordinate datum type. type: str choices: - - WGS84 - - NAD83 - - MLLW + - WGS84 + - NAD83 + - MLLW latitude: description: Latitude. type: str - required: True + required: true longitude: description: Longitude. type: str - required: True + required: true elin: description: Emergency Call Service ELIN number (between 10-25 numbers). type: str state: description: - - The state of the configuration after module completion. + - The state of the configuration after module completion. type: str choices: - merged @@ -124,7 +121,6 @@ options: - overridden - deleted default: merged - """ EXAMPLES = """ # Using merged diff --git a/plugins/modules/vyos_logging.py b/plugins/modules/vyos_logging.py index 6c2f9f7a..9f81eb9e 100644 --- a/plugins/modules/vyos_logging.py +++ b/plugins/modules/vyos_logging.py @@ -25,42 +25,45 @@ ANSIBLE_METADATA = { "supported_by": "network", } -DOCUMENTATION = """ ---- -module: vyos_logging -version_added: "2.4" -author: "Trishna Guha (@trishnaguha)" +DOCUMENTATION = """module: vyos_logging +author: Trishna Guha (@trishnaguha) short_description: Manage logging on network devices description: - - This module provides declarative management of logging - on Vyatta Vyos devices. +- This module provides declarative management of logging on Vyatta Vyos devices. notes: - - Tested against VyOS 1.1.8 (helium). - - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). +- Tested against VyOS 1.1.8 (helium). +- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: dest: description: - - Destination of the logs. - choices: ['console', 'file', 'global', 'host', 'user'] + - Destination of the logs. + choices: + - console + - file + - global + - host + - user name: description: - - If value of C(dest) is I(file) it indicates file-name, - for I(user) it indicates username and for I(host) indicates - the host name to be notified. + - If value of C(dest) is I(file) it indicates file-name, for I(user) it indicates + username and for I(host) indicates the host name to be notified. facility: description: - - Set logging facility. + - Set logging facility. level: description: - - Set logging severity levels. + - Set logging severity levels. aggregate: description: List of logging definitions. state: description: - - State of the logging configuration. + - State of the logging configuration. default: present - choices: ['present', 'absent'] -extends_documentation_fragment: vyos + choices: + - present + - absent +extends_documentation_fragment: +- vyos.vyos.vyos """ EXAMPLES = """ @@ -112,7 +115,9 @@ import re from copy import deepcopy from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.utils import remove_default_spec +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + remove_default_spec, +) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( get_config, load_config, @@ -252,7 +257,7 @@ def main(): remove_default_spec(aggregate_spec) argument_spec = dict( - aggregate=dict(type="list", elements="dict", options=aggregate_spec) + aggregate=dict(type="list", elements="dict", options=aggregate_spec), ) argument_spec.update(element_spec) diff --git a/plugins/modules/vyos_ping.py b/plugins/modules/vyos_ping.py index 82710490..3d5a9036 100644 --- a/plugins/modules/vyos_ping.py +++ b/plugins/modules/vyos_ping.py @@ -29,56 +29,56 @@ ANSIBLE_METADATA = { "supported_by": "community", } -DOCUMENTATION = """ ---- -module: vyos_ping +DOCUMENTATION = """module: vyos_ping short_description: Tests reachability using ping from VyOS network devices description: - - Tests reachability using ping from a VyOS device to a remote destination. - - Tested against VyOS 1.1.8 (helium) - - For a general purpose network module, see the M(net_ping) module. - - For Windows targets, use the M(win_ping) module instead. - - For targets running Python, use the M(ping) module instead. +- Tests reachability using ping from a VyOS device to a remote destination. +- Tested against VyOS 1.1.8 (helium) +- For a general purpose network module, see the M(net_ping) module. +- For Windows targets, use the M(win_ping) module instead. +- For targets running Python, use the M(ping) module instead. author: - - Nilashish Chakraborty (@NilashishC) -version_added: '2.8' +- Nilashish Chakraborty (@NilashishC) options: dest: description: - - The IP Address or hostname (resolvable by the device) of the remote node. + - The IP Address or hostname (resolvable by the device) of the remote node. required: true count: description: - - Number of packets to send to check reachability. + - Number of packets to send to check reachability. type: int default: 5 source: description: - - The source interface or IP Address to use while sending the ping packet(s). + - The source interface or IP Address to use while sending the ping packet(s). ttl: description: - - The time-to-live value for the ICMP packet(s). + - The time-to-live value for the ICMP packet(s). type: int size: description: - - Determines the size (in bytes) of the ping packet(s). + - Determines the size (in bytes) of the ping packet(s). type: int interval: description: - - Determines the interval (in seconds) between consecutive pings. + - Determines the interval (in seconds) between consecutive pings. type: int state: description: - - Determines if the expected result is success or fail. - choices: [ absent, present ] + - Determines if the expected result is success or fail. + choices: + - absent + - present default: present notes: - - Tested against VyOS 1.1.8 (helium). - - For a general purpose network module, see the M(net_ping) module. - - For Windows targets, use the M(win_ping) module instead. - - For targets running Python, use the M(ping) module instead. - - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). -extends_documentation_fragment: vyos +- Tested against VyOS 1.1.8 (helium). +- For a general purpose network module, see the M(net_ping) module. +- For Windows targets, use the M(win_ping) module instead. +- For targets running Python, use the M(ping) module instead. +- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). +extends_documentation_fragment: +- vyos.vyos.vyos """ EXAMPLES = """ diff --git a/plugins/modules/vyos_static_route.py b/plugins/modules/vyos_static_route.py index 564a2574..e0c40e7f 100644 --- a/plugins/modules/vyos_static_route.py +++ b/plugins/modules/vyos_static_route.py @@ -26,41 +26,40 @@ ANSIBLE_METADATA = { } -DOCUMENTATION = """ ---- -module: vyos_static_route -version_added: "2.4" -author: "Trishna Guha (@trishnaguha)" +DOCUMENTATION = """module: vyos_static_route +author: Trishna Guha (@trishnaguha) short_description: Manage static IP routes on Vyatta VyOS network devices description: - - This module provides declarative management of static - IP routes on Vyatta VyOS network devices. +- This module provides declarative management of static IP routes on Vyatta VyOS network + devices. notes: - - Tested against VyOS 1.1.8 (helium). - - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). +- Tested against VyOS 1.1.8 (helium). +- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: prefix: description: - - Network prefix of the static route. - C(mask) param should be ignored if C(prefix) is provided - with C(mask) value C(prefix/mask). + - Network prefix of the static route. C(mask) param should be ignored if C(prefix) + is provided with C(mask) value C(prefix/mask). mask: description: - - Network prefix mask of the static route. + - Network prefix mask of the static route. next_hop: description: - - Next hop IP of the static route. + - Next hop IP of the static route. admin_distance: description: - - Admin distance of the static route. + - Admin distance of the static route. aggregate: description: List of static route definitions state: description: - - State of the static route configuration. + - State of the static route configuration. default: present - choices: ['present', 'absent'] -extends_documentation_fragment: vyos + choices: + - present + - absent +extends_documentation_fragment: +- vyos.vyos.vyos """ EXAMPLES = """ @@ -110,7 +109,9 @@ import re from copy import deepcopy from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.utils import remove_default_spec +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + remove_default_spec, +) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( get_config, load_config, @@ -250,7 +251,7 @@ def main(): remove_default_spec(aggregate_spec) argument_spec = dict( - aggregate=dict(type="list", elements="dict", options=aggregate_spec) + aggregate=dict(type="list", elements="dict", options=aggregate_spec), ) argument_spec.update(element_spec) diff --git a/plugins/modules/vyos_system.py b/plugins/modules/vyos_system.py index 30694a61..b49462b6 100644 --- a/plugins/modules/vyos_system.py +++ b/plugins/modules/vyos_system.py @@ -24,41 +24,39 @@ ANSIBLE_METADATA = { } -DOCUMENTATION = """ ---- -module: "vyos_system" -version_added: "2.3" -author: "Nathaniel Case (@Qalthos)" +DOCUMENTATION = """module: vyos_system +author: Nathaniel Case (@Qalthos) short_description: Run `set system` commands on VyOS devices description: - - Runs one or more commands on remote devices running VyOS. - This module can also be introspected to validate key parameters before - returning successfully. -extends_documentation_fragment: vyos +- Runs one or more commands on remote devices running VyOS. This module can also be + introspected to validate key parameters before returning successfully. +extends_documentation_fragment: +- vyos.vyos.vyos notes: - - Tested against VyOS 1.1.8 (helium). - - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). +- Tested against VyOS 1.1.8 (helium). +- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: host_name: description: - - Configure the device hostname parameter. This option takes an ASCII string value. + - Configure the device hostname parameter. This option takes an ASCII string value. domain_name: description: - - The new domain name to apply to the device. + - The new domain name to apply to the device. name_servers: description: - - A list of name servers to use with the device. Mutually exclusive with - I(domain_search) - aliases: ['name_server'] + - A list of name servers to use with the device. Mutually exclusive with I(domain_search) + aliases: + - name_server domain_search: description: - - A list of domain names to search. Mutually exclusive with - I(name_server) + - A list of domain names to search. Mutually exclusive with I(name_server) state: description: - - Whether to apply (C(present)) or remove (C(absent)) the settings. + - Whether to apply (C(present)) or remove (C(absent)) the settings. default: present - choices: ['present', 'absent'] + choices: + - present + - absent """ RETURN = """ diff --git a/plugins/modules/vyos_user.py b/plugins/modules/vyos_user.py index 5a766eea..d6195240 100644 --- a/plugins/modules/vyos_user.py +++ b/plugins/modules/vyos_user.py @@ -25,78 +25,75 @@ ANSIBLE_METADATA = { "supported_by": "network", } -DOCUMENTATION = """ ---- -module: vyos_user -version_added: "2.4" -author: "Trishna Guha (@trishnaguha)" +DOCUMENTATION = """module: vyos_user +author: Trishna Guha (@trishnaguha) short_description: Manage the collection of local users on VyOS device description: - - This module provides declarative management of the local usernames - configured on network devices. It allows playbooks to manage - either individual usernames or the collection of usernames in the - current running config. It also supports purging usernames from the - configuration that are not explicitly defined. +- This module provides declarative management of the local usernames configured on + network devices. It allows playbooks to manage either individual usernames or the + collection of usernames in the current running config. It also supports purging + usernames from the configuration that are not explicitly defined. notes: - - Tested against VyOS 1.1.8 (helium). - - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). +- Tested against VyOS 1.1.8 (helium). +- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: aggregate: description: - - The set of username objects to be configured on the remote - VyOS device. The list entries can either be the username or - a hash of username and properties. This argument is mutually - exclusive with the C(name) argument. - aliases: ['users', 'collection'] + - The set of username objects to be configured on the remote VyOS device. The + list entries can either be the username or a hash of username and properties. + This argument is mutually exclusive with the C(name) argument. + aliases: + - users + - collection name: description: - - The username to be configured on the VyOS device. - This argument accepts a string value and is mutually exclusive - with the C(aggregate) argument. - Please note that this option is not same as C(provider username). + - The username to be configured on the VyOS device. This argument accepts a string + value and is mutually exclusive with the C(aggregate) argument. Please note + that this option is not same as C(provider username). full_name: description: - - The C(full_name) argument provides the full name of the user - account to be created on the remote device. This argument accepts - any text string value. + - The C(full_name) argument provides the full name of the user account to be created + on the remote device. This argument accepts any text string value. configured_password: description: - - The password to be configured on the VyOS device. The - password needs to be provided in clear and it will be encrypted - on the device. - Please note that this option is not same as C(provider password). + - The password to be configured on the VyOS device. The password needs to be provided + in clear and it will be encrypted on the device. Please note that this option + is not same as C(provider password). update_password: description: - - Since passwords are encrypted in the device running config, this - argument will instruct the module when to change the password. When - set to C(always), the password will always be updated in the device - and when set to C(on_create) the password will be updated only if - the username is created. + - Since passwords are encrypted in the device running config, this argument will + instruct the module when to change the password. When set to C(always), the + password will always be updated in the device and when set to C(on_create) the + password will be updated only if the username is created. default: always - choices: ['on_create', 'always'] + choices: + - on_create + - always level: description: - - The C(level) argument configures the level of the user when logged - into the system. This argument accepts string values admin or operator. - aliases: ['role'] + - The C(level) argument configures the level of the user when logged into the + system. This argument accepts string values admin or operator. + aliases: + - role purge: description: - - Instructs the module to consider the - resource definition absolute. It will remove any previously - configured usernames on the device with the exception of the - `admin` user (the current defined set of users). + - Instructs the module to consider the resource definition absolute. It will remove + any previously configured usernames on the device with the exception of the + `admin` user (the current defined set of users). type: bool default: false state: description: - - Configures the state of the username definition - as it relates to the device operational configuration. When set - to I(present), the username(s) should be configured in the device active - configuration and when set to I(absent) the username(s) should not be - in the device active configuration + - Configures the state of the username definition as it relates to the device + operational configuration. When set to I(present), the username(s) should be + configured in the device active configuration and when set to I(absent) the + username(s) should not be in the device active configuration default: present - choices: ['present', 'absent'] -extends_documentation_fragment: vyos + choices: + - present + - absent +extends_documentation_fragment: +- vyos.vyos.vyos """ EXAMPLES = """ @@ -139,7 +136,9 @@ from copy import deepcopy from functools import partial from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.utils import remove_default_spec +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + remove_default_spec, +) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( get_config, load_config, diff --git a/plugins/modules/vyos_vlan.py b/plugins/modules/vyos_vlan.py index 4564749e..a0aafb57 100644 --- a/plugins/modules/vyos_vlan.py +++ b/plugins/modules/vyos_vlan.py @@ -15,56 +15,55 @@ ANSIBLE_METADATA = { "supported_by": "network", } -DOCUMENTATION = """ ---- -module: vyos_vlan -version_added: "2.5" -author: "Trishna Guha (@trishnaguha)" +DOCUMENTATION = """module: vyos_vlan +author: Trishna Guha (@trishnaguha) short_description: Manage VLANs on VyOS network devices description: - - This module provides declarative management of VLANs - on VyOS network devices. +- This module provides declarative management of VLANs on VyOS network devices. notes: - - Tested against VyOS 1.1.8 (helium). - - This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). +- Tested against VyOS 1.1.8 (helium). +- This module works with connection C(network_cli). See L(the VyOS OS Platform Options,../network/user_guide/platform_vyos.html). options: name: description: - - Name of the VLAN. + - Name of the VLAN. address: description: - - Configure Virtual interface address. + - Configure Virtual interface address. vlan_id: description: - - ID of the VLAN. Range 0-4094. + - ID of the VLAN. Range 0-4094. required: true interfaces: description: - - List of interfaces that should be associated to the VLAN. + - List of interfaces that should be associated to the VLAN. required: true associated_interfaces: description: - - This is a intent option and checks the operational state of the for given vlan C(name) - for associated interfaces. If the value in the C(associated_interfaces) does not match with - the operational state of vlan on device it will result in failure. - version_added: "2.5" + - This is a intent option and checks the operational state of the for given vlan + C(name) for associated interfaces. If the value in the C(associated_interfaces) + does not match with the operational state of vlan on device it will result in + failure. delay: description: - - Delay the play should wait to check for declarative intent params values. + - Delay the play should wait to check for declarative intent params values. default: 10 aggregate: description: List of VLANs definitions. purge: description: - - Purge VLANs not defined in the I(aggregate) parameter. - default: no + - Purge VLANs not defined in the I(aggregate) parameter. + default: false type: bool state: description: - - State of the VLAN configuration. + - State of the VLAN configuration. default: present - choices: ['present', 'absent'] -extends_documentation_fragment: vyos + choices: + - present + - absent +extends_documentation_fragment: +- vyos.vyos.vyos """ EXAMPLES = """ @@ -125,7 +124,9 @@ import time from copy import deepcopy from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.network.common.utils import remove_default_spec +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + remove_default_spec, +) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( load_config, run_commands, |