diff options
Diffstat (limited to 'plugins')
47 files changed, 2665 insertions, 2011 deletions
diff --git a/plugins/action/__init__.py b/plugins/action/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/plugins/action/__init__.py diff --git a/plugins/action/vyos.py b/plugins/action/vyos.py new file mode 100644 index 0000000..cab2f3f --- /dev/null +++ b/plugins/action/vyos.py @@ -0,0 +1,129 @@ +# +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# 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 + +import sys +import copy + +from ansible_collections.ansible.netcommon.plugins.action.network import ( + ActionModule as ActionNetworkModule, +) +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + load_provider, +) +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( + vyos_provider_spec, +) +from ansible.utils.display import Display + +display = Display() + + +class ActionModule(ActionNetworkModule): + def run(self, tmp=None, task_vars=None): + del tmp # tmp no longer has any effect + + module_name = self._task.action.split(".")[-1] + self._config_module = True if module_name == "vyos_config" else False + persistent_connection = self._play_context.connection.split(".")[-1] + warnings = [] + + if persistent_connection == "network_cli": + provider = self._task.args.get("provider", {}) + if any(provider.values()): + display.warning( + "provider is unnecessary when using network_cli and will be ignored" + ) + del self._task.args["provider"] + elif self._play_context.connection == "local": + provider = load_provider(vyos_provider_spec, self._task.args) + pc = copy.deepcopy(self._play_context) + pc.connection = "ansible.netcommon.network_cli" + pc.network_os = "vyos.vyos.vyos" + pc.remote_addr = provider["host"] or self._play_context.remote_addr + pc.port = int(provider["port"] or self._play_context.port or 22) + pc.remote_user = ( + provider["username"] or self._play_context.connection_user + ) + pc.password = provider["password"] or self._play_context.password + pc.private_key_file = ( + provider["ssh_keyfile"] or self._play_context.private_key_file + ) + + connection = self._shared_loader_obj.connection_loader.get( + "ansible.netcommon.persistent", + pc, + sys.stdin, + task_uuid=self._task._uuid, + ) + + # TODO: Remove below code after ansible minimal is cut out + if connection is None: + pc.connection = "network_cli" + pc.network_os = "vyos" + connection = self._shared_loader_obj.connection_loader.get( + "persistent", pc, sys.stdin, task_uuid=self._task._uuid + ) + + display.vvv( + "using connection plugin %s (was local)" % pc.connection, + pc.remote_addr, + ) + + command_timeout = ( + int(provider["timeout"]) + if provider["timeout"] + else connection.get_option("persistent_command_timeout") + ) + connection.set_options( + direct={"persistent_command_timeout": command_timeout} + ) + + socket_path = connection.run() + display.vvvv("socket_path: %s" % socket_path, pc.remote_addr) + if not socket_path: + return { + "failed": True, + "msg": "unable to open shell. Please see: " + + "https://docs.ansible.com/ansible/network_debug_troubleshooting.html#unable-to-open-shell", + } + + task_vars["ansible_socket"] = socket_path + warnings.append( + [ + "connection local support for this module is deprecated and will be removed in version 2.14, use connection %s" + % pc.connection + ] + ) + else: + return { + "failed": True, + "msg": "Connection type %s is not valid for this module" + % self._play_context.connection, + } + + result = super(ActionModule, self).run(task_vars=task_vars) + if warnings: + if "warnings" in result: + result["warnings"].extend(warnings) + else: + result["warnings"] = warnings + return result diff --git a/plugins/cliconf/__init__.py b/plugins/cliconf/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/plugins/cliconf/__init__.py diff --git a/plugins/cliconf/vyos.py b/plugins/cliconf/vyos.py new file mode 100644 index 0000000..3033603 --- /dev/null +++ b/plugins/cliconf/vyos.py @@ -0,0 +1,342 @@ +# +# (c) 2017 Red Hat Inc. +# +# This file is part of Ansible +# +# 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 + +DOCUMENTATION = """ +--- +author: Ansible Networking Team +cliconf: vyos +short_description: Use vyos cliconf to run command on VyOS platform +description: + - This vyos plugin provides low level abstraction apis for + sending and receiving CLI commands from VyOS network devices. +version_added: "2.4" +""" + +import re +import json + +from ansible.errors import AnsibleConnectionFailure +from ansible.module_utils._text import to_text +from ansible.module_utils.common._collections_compat import Mapping +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import ( + NetworkConfig, +) +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + to_list, +) +from ansible.plugins.cliconf import CliconfBase + + +class Cliconf(CliconfBase): + def get_device_info(self): + device_info = {} + + device_info["network_os"] = "vyos" + reply = self.get("show version") + data = to_text(reply, errors="surrogate_or_strict").strip() + + match = re.search(r"Version:\s*(.*)", data) + if match: + device_info["network_os_version"] = match.group(1) + + match = re.search(r"HW model:\s*(\S+)", data) + if match: + device_info["network_os_model"] = match.group(1) + + reply = self.get("show host name") + device_info["network_os_hostname"] = to_text( + reply, errors="surrogate_or_strict" + ).strip() + + return device_info + + def get_config(self, flags=None, format=None): + if format: + option_values = self.get_option_values() + if format not in option_values["format"]: + raise ValueError( + "'format' value %s is invalid. Valid values of format are %s" + % (format, ", ".join(option_values["format"])) + ) + + if not flags: + flags = [] + + if format == "text": + command = "show configuration" + else: + command = "show configuration commands" + + command += " ".join(to_list(flags)) + command = command.strip() + + out = self.send_command(command) + return out + + def edit_config( + self, candidate=None, commit=True, replace=None, comment=None + ): + resp = {} + operations = self.get_device_operations() + self.check_edit_config_capability( + operations, candidate, commit, replace, comment + ) + + results = [] + requests = [] + self.send_command("configure") + for cmd in to_list(candidate): + if not isinstance(cmd, Mapping): + cmd = {"command": cmd} + + results.append(self.send_command(**cmd)) + requests.append(cmd["command"]) + out = self.get("compare") + out = to_text(out, errors="surrogate_or_strict") + diff_config = out if not out.startswith("No changes") else None + + if diff_config: + if commit: + try: + self.commit(comment) + except AnsibleConnectionFailure as e: + msg = "commit failed: %s" % e.message + self.discard_changes() + raise AnsibleConnectionFailure(msg) + else: + self.send_command("exit") + else: + self.discard_changes() + else: + self.send_command("exit") + if ( + to_text( + self._connection.get_prompt(), errors="surrogate_or_strict" + ) + .strip() + .endswith("#") + ): + self.discard_changes() + + if diff_config: + resp["diff"] = diff_config + resp["response"] = results + resp["request"] = requests + return resp + + def get( + self, + command=None, + prompt=None, + answer=None, + sendonly=False, + output=None, + newline=True, + check_all=False, + ): + if not command: + raise ValueError("must provide value of command to execute") + if output: + raise ValueError( + "'output' value %s is not supported for get" % output + ) + + return self.send_command( + command=command, + prompt=prompt, + answer=answer, + sendonly=sendonly, + newline=newline, + check_all=check_all, + ) + + def commit(self, comment=None): + if comment: + command = 'commit comment "{0}"'.format(comment) + else: + command = "commit" + self.send_command(command) + + def discard_changes(self): + self.send_command("exit discard") + + def get_diff( + self, + candidate=None, + running=None, + diff_match="line", + diff_ignore_lines=None, + path=None, + diff_replace=None, + ): + diff = {} + device_operations = self.get_device_operations() + option_values = self.get_option_values() + + if candidate is None and device_operations["supports_generate_diff"]: + raise ValueError( + "candidate configuration is required to generate diff" + ) + + if diff_match not in option_values["diff_match"]: + raise ValueError( + "'match' value %s in invalid, valid values are %s" + % (diff_match, ", ".join(option_values["diff_match"])) + ) + + if diff_replace: + raise ValueError("'replace' in diff is not supported") + + if diff_ignore_lines: + raise ValueError("'diff_ignore_lines' in diff is not supported") + + if path: + raise ValueError("'path' in diff is not supported") + + set_format = candidate.startswith("set") or candidate.startswith( + "delete" + ) + candidate_obj = NetworkConfig(indent=4, contents=candidate) + if not set_format: + config = [c.line for c in candidate_obj.items] + commands = list() + # this filters out less specific lines + for item in config: + for index, entry in enumerate(commands): + if item.startswith(entry): + del commands[index] + break + commands.append(item) + + candidate_commands = [ + "set %s" % cmd.replace(" {", "") for cmd in commands + ] + + else: + candidate_commands = str(candidate).strip().split("\n") + + if diff_match == "none": + diff["config_diff"] = list(candidate_commands) + return diff + + running_commands = [ + str(c).replace("'", "") for c in running.splitlines() + ] + + updates = list() + visited = set() + + for line in candidate_commands: + item = str(line).replace("'", "") + + if not item.startswith("set") and not item.startswith("delete"): + raise ValueError( + "line must start with either `set` or `delete`" + ) + + elif item.startswith("set") and item not in running_commands: + updates.append(line) + + elif item.startswith("delete"): + if not running_commands: + updates.append(line) + else: + item = re.sub(r"delete", "set", item) + for entry in running_commands: + if entry.startswith(item) and line not in visited: + updates.append(line) + visited.add(line) + + diff["config_diff"] = list(updates) + return diff + + def run_commands(self, commands=None, check_rc=True): + if commands is None: + raise ValueError("'commands' value is required") + + responses = list() + for cmd in to_list(commands): + if not isinstance(cmd, Mapping): + cmd = {"command": cmd} + + output = cmd.pop("output", None) + if output: + raise ValueError( + "'output' value %s is not supported for run_commands" + % output + ) + + try: + out = self.send_command(**cmd) + except AnsibleConnectionFailure as e: + if check_rc: + raise + out = getattr(e, "err", e) + + responses.append(out) + + return responses + + def get_device_operations(self): + return { + "supports_diff_replace": False, + "supports_commit": True, + "supports_rollback": False, + "supports_defaults": False, + "supports_onbox_diff": True, + "supports_commit_comment": True, + "supports_multiline_delimiter": False, + "supports_diff_match": True, + "supports_diff_ignore_lines": False, + "supports_generate_diff": False, + "supports_replace": False, + } + + def get_option_values(self): + return { + "format": ["text", "set"], + "diff_match": ["line", "none"], + "diff_replace": [], + "output": [], + } + + def get_capabilities(self): + result = super(Cliconf, self).get_capabilities() + result["rpc"] += [ + "commit", + "discard_changes", + "get_diff", + "run_commands", + ] + result["device_operations"] = self.get_device_operations() + result.update(self.get_option_values()) + return json.dumps(result) + + def set_cli_prompt_context(self): + """ + Make sure we are in the operational cli mode + :return: None + """ + if self._connection.connected: + self._update_cli_prompt_context( + config_context="#", exit_command="exit discard" + ) diff --git a/plugins/doc_fragments/__init__.py b/plugins/doc_fragments/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/plugins/doc_fragments/__init__.py diff --git a/plugins/doc_fragments/vyos.py b/plugins/doc_fragments/vyos.py new file mode 100644 index 0000000..094963f --- /dev/null +++ b/plugins/doc_fragments/vyos.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2015, Peter Sprygada <psprygada@ansible.com> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + + +class ModuleDocFragment(object): + + # Standard files documentation fragment + DOCUMENTATION = r"""options: + provider: + description: + - B(Deprecated) + - 'Starting with Ansible 2.5 we recommend using C(connection: network_cli).' + - For more information please see the L(Network Guide, ../network/getting_started/network_differences.html#multiple-communication-protocols). + - HORIZONTALLINE + - A dict object containing connection details. + type: dict + suboptions: + host: + description: + - Specifies the DNS host name or address for connecting to the remote device + over the specified transport. The value of host is used as the destination + address for the transport. + type: str + required: true + port: + description: + - Specifies the port to use when building the connection to the remote device. + type: int + default: 22 + username: + description: + - Configures the username to use to authenticate the connection to the remote + device. This value is used to authenticate the SSH session. If the value + is not specified in the task, the value of environment variable C(ANSIBLE_NET_USERNAME) + will be used instead. + type: str + password: + description: + - Specifies the password to use to authenticate the connection to the remote + device. This value is used to authenticate the SSH session. If the value + is not specified in the task, the value of environment variable C(ANSIBLE_NET_PASSWORD) + will be used instead. + type: str + timeout: + description: + - Specifies the timeout in seconds for communicating with the network device + for either connecting or sending commands. If the timeout is exceeded before + the operation is completed, the module will error. + type: int + default: 10 + ssh_keyfile: + description: + - Specifies the SSH key to use to authenticate the connection to the remote + device. This value is the path to the key used to authenticate the SSH + session. If the value is not specified in the task, the value of environment + variable C(ANSIBLE_NET_SSH_KEYFILE) will be used instead. + type: path +notes: +- For more information on using Ansible to manage network devices see the :ref:`Ansible + Network Guide <network_guide>` +""" diff --git a/plugins/module_utils/__init__.py b/plugins/module_utils/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/plugins/module_utils/__init__.py diff --git a/plugins/module_utils/network/vyos/config/interfaces/interfaces.py b/plugins/module_utils/network/vyos/config/interfaces/interfaces.py index d781fd0..deb504c 100644 --- a/plugins/module_utils/network/vyos/config/interfaces/interfaces.py +++ b/plugins/module_utils/network/vyos/config/interfaces/interfaces.py @@ -15,8 +15,10 @@ __metaclass__ = type from copy import deepcopy -from ansible.module_utils.network.common.cfg.base import ConfigBase -from ansible.module_utils.network.common.utils import ( +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( + ConfigBase, +) +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( to_list, dict_diff, remove_empties, @@ -37,7 +39,10 @@ class Interfaces(ConfigBase): The vyos_interfaces class """ - gather_subset = ["!all", "!min"] + gather_subset = [ + "!all", + "!min", + ] gather_network_resources = ["interfaces"] diff --git a/plugins/module_utils/network/vyos/config/l3_interfaces/l3_interfaces.py b/plugins/module_utils/network/vyos/config/l3_interfaces/l3_interfaces.py index fb7dbdc..a23e417 100644 --- a/plugins/module_utils/network/vyos/config/l3_interfaces/l3_interfaces.py +++ b/plugins/module_utils/network/vyos/config/l3_interfaces/l3_interfaces.py @@ -17,8 +17,13 @@ __metaclass__ = type from copy import deepcopy -from ansible.module_utils.network.common.cfg.base import ConfigBase -from ansible.module_utils.network.common.utils import to_list, remove_empties +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( + ConfigBase, +) +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + to_list, + remove_empties, +) from ansible.module_utils.six import iteritems from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import ( Facts, @@ -35,9 +40,14 @@ class L3_interfaces(ConfigBase): The vyos_l3_interfaces class """ - gather_subset = ["!all", "!min"] + gather_subset = [ + "!all", + "!min", + ] - gather_network_resources = ["l3_interfaces"] + gather_network_resources = [ + "l3_interfaces", + ] def __init__(self, module): super(L3_interfaces, self).__init__(module) diff --git a/plugins/module_utils/network/vyos/config/lag_interfaces/lag_interfaces.py b/plugins/module_utils/network/vyos/config/lag_interfaces/lag_interfaces.py index 290f3b3..2a9efd9 100644 --- a/plugins/module_utils/network/vyos/config/lag_interfaces/lag_interfaces.py +++ b/plugins/module_utils/network/vyos/config/lag_interfaces/lag_interfaces.py @@ -11,11 +11,16 @@ created from __future__ import absolute_import, division, print_function __metaclass__ = type -from ansible.module_utils.network.common.cfg.base import ConfigBase +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( + ConfigBase, +) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import ( Facts, ) -from ansible.module_utils.network.common.utils import to_list, dict_diff +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + to_list, + dict_diff, +) from ansible.module_utils.six import iteritems from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils import ( search_obj_in_list, @@ -30,9 +35,14 @@ class Lag_interfaces(ConfigBase): The vyos_lag_interfaces class """ - gather_subset = ["!all", "!min"] + gather_subset = [ + "!all", + "!min", + ] - gather_network_resources = ["lag_interfaces"] + gather_network_resources = [ + "lag_interfaces", + ] params = [ "arp_monitor", diff --git a/plugins/module_utils/network/vyos/config/lldp_global/lldp_global.py b/plugins/module_utils/network/vyos/config/lldp_global/lldp_global.py index 303d46a..010e96d 100644 --- a/plugins/module_utils/network/vyos/config/lldp_global/lldp_global.py +++ b/plugins/module_utils/network/vyos/config/lldp_global/lldp_global.py @@ -11,8 +11,13 @@ created from __future__ import absolute_import, division, print_function __metaclass__ = type -from ansible.module_utils.network.common.cfg.base import ConfigBase -from ansible.module_utils.network.common.utils import to_list, dict_diff +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( + ConfigBase, +) +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + to_list, + dict_diff, +) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import ( Facts, ) @@ -28,9 +33,14 @@ class Lldp_global(ConfigBase): The vyos_lldp_global class """ - gather_subset = ["!all", "!min"] + gather_subset = [ + "!all", + "!min", + ] - gather_network_resources = ["lldp_global"] + gather_network_resources = [ + "lldp_global", + ] params = ["enable", "address", "snmp", "legacy_protocols"] diff --git a/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py b/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py index aa0bd36..377fec9 100644 --- a/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py +++ b/plugins/module_utils/network/vyos/config/lldp_interfaces/lldp_interfaces.py @@ -16,13 +16,18 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type -from ansible.module_utils.network.common.cfg.base import ConfigBase +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import ( + ConfigBase, +) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.facts import ( Facts, ) -from ansible.module_utils.network.common.utils import to_list, dict_diff +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( + to_list, + dict_diff, +) from ansible.module_utils.six import iteritems -from ansible.module_utils.network.vyos.utils.utils import ( +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.utils import ( search_obj_in_list, search_dict_tv_in_list, key_value_in_dict, @@ -35,9 +40,14 @@ class Lldp_interfaces(ConfigBase): The vyos_lldp_interfaces class """ - gather_subset = ["!all", "!min"] + gather_subset = [ + "!all", + "!min", + ] - gather_network_resources = ["lldp_interfaces"] + gather_network_resources = [ + "lldp_interfaces", + ] params = ["enable", "location", "name"] diff --git a/plugins/module_utils/network/vyos/facts/facts.py b/plugins/module_utils/network/vyos/facts/facts.py index bb292e1..b5816c2 100644 --- a/plugins/module_utils/network/vyos/facts/facts.py +++ b/plugins/module_utils/network/vyos/facts/facts.py @@ -9,7 +9,9 @@ calls the appropriate facts gathering function from __future__ import absolute_import, division, print_function __metaclass__ = type -from ansible.module_utils.network.common.facts.facts import FactsBase +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts import ( + FactsBase, +) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.facts.interfaces.interfaces import ( InterfacesFacts, ) diff --git a/plugins/module_utils/network/vyos/facts/interfaces/interfaces.py b/plugins/module_utils/network/vyos/facts/interfaces/interfaces.py index 7b73b9b..4b24803 100644 --- a/plugins/module_utils/network/vyos/facts/interfaces/interfaces.py +++ b/plugins/module_utils/network/vyos/facts/interfaces/interfaces.py @@ -17,7 +17,9 @@ __metaclass__ = type from re import findall, M from copy import deepcopy -from ansible.module_utils.network.common import utils +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import ( + utils, +) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.interfaces.interfaces import ( InterfacesArgs, ) diff --git a/plugins/module_utils/network/vyos/facts/l3_interfaces/l3_interfaces.py b/plugins/module_utils/network/vyos/facts/l3_interfaces/l3_interfaces.py index 05973ba..babfc85 100644 --- a/plugins/module_utils/network/vyos/facts/l3_interfaces/l3_interfaces.py +++ b/plugins/module_utils/network/vyos/facts/l3_interfaces/l3_interfaces.py @@ -17,7 +17,9 @@ __metaclass__ = type import re from copy import deepcopy -from ansible.module_utils.network.common import utils +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import ( + utils, +) from ansible.module_utils.six import iteritems from ansible.module_utils.compat import ipaddress from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.l3_interfaces.l3_interfaces import ( diff --git a/plugins/module_utils/network/vyos/facts/lag_interfaces/lag_interfaces.py b/plugins/module_utils/network/vyos/facts/lag_interfaces/lag_interfaces.py index 6ae780f..9201e5c 100644 --- a/plugins/module_utils/network/vyos/facts/lag_interfaces/lag_interfaces.py +++ b/plugins/module_utils/network/vyos/facts/lag_interfaces/lag_interfaces.py @@ -15,7 +15,9 @@ __metaclass__ = type from re import findall, search, M from copy import deepcopy -from ansible.module_utils.network.common import utils +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import ( + utils, +) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.lag_interfaces.lag_interfaces import ( Lag_interfacesArgs, ) diff --git a/plugins/module_utils/network/vyos/facts/legacy/base.py b/plugins/module_utils/network/vyos/facts/legacy/base.py index dce93aa..f6b343e 100644 --- a/plugins/module_utils/network/vyos/facts/legacy/base.py +++ b/plugins/module_utils/network/vyos/facts/legacy/base.py @@ -14,7 +14,7 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type import platform import re -from ansible.module_utils.network.vyos.vyos import ( +from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import ( run_commands, get_capabilities, ) @@ -36,7 +36,9 @@ class LegacyFactsBase(object): class Default(LegacyFactsBase): - COMMANDS = ["show version"] + COMMANDS = [ + "show version", + ] def populate(self): super(Default, self).populate() @@ -70,7 +72,10 @@ class Default(LegacyFactsBase): class Config(LegacyFactsBase): - COMMANDS = ["show configuration commands", "show system commit"] + COMMANDS = [ + "show configuration commands", + "show system commit", + ] def populate(self): super(Config, self).populate() @@ -102,7 +107,10 @@ class Config(LegacyFactsBase): class Neighbors(LegacyFactsBase): - COMMANDS = ["show lldp neighbors", "show lldp neighbors detail"] + COMMANDS = [ + "show lldp neighbors", + "show lldp neighbors detail", + ] def populate(self): super(Neighbors, self).populate() diff --git a/plugins/module_utils/network/vyos/facts/lldp_global/lldp_global.py b/plugins/module_utils/network/vyos/facts/lldp_global/lldp_global.py index 8954393..3c7e2f9 100644 --- a/plugins/module_utils/network/vyos/facts/lldp_global/lldp_global.py +++ b/plugins/module_utils/network/vyos/facts/lldp_global/lldp_global.py @@ -16,7 +16,9 @@ __metaclass__ = type from re import findall, M from copy import deepcopy -from ansible.module_utils.network.common import utils +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import ( + utils, +) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.lldp_global.lldp_global import ( Lldp_globalArgs, ) diff --git a/plugins/module_utils/network/vyos/facts/lldp_interfaces/lldp_interfaces.py b/plugins/module_utils/network/vyos/facts/lldp_interfaces/lldp_interfaces.py index 72629ed..dcfbc6e 100644 --- a/plugins/module_utils/network/vyos/facts/lldp_interfaces/lldp_interfaces.py +++ b/plugins/module_utils/network/vyos/facts/lldp_interfaces/lldp_interfaces.py @@ -18,7 +18,9 @@ __metaclass__ = type from re import findall, search, M from copy import deepcopy -from ansible.module_utils.network.common import utils +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import ( + utils, +) from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.argspec.lldp_interfaces.lldp_interfaces import ( Lldp_interfacesArgs, ) diff --git a/plugins/module_utils/network/vyos/vyos.py b/plugins/module_utils/network/vyos/vyos.py index 1d2c508..908395a 100644 --- a/plugins/module_utils/network/vyos/vyos.py +++ b/plugins/module_utils/network/vyos/vyos.py @@ -46,7 +46,9 @@ vyos_provider_spec = { "timeout": dict(type="int"), } vyos_argument_spec = { - "provider": dict(type="dict", options=vyos_provider_spec) + "provider": dict( + type="dict", options=vyos_provider_spec, removed_in_version=2.14 + ), } diff --git a/plugins/modules/_vyos_interface.py b/plugins/modules/_vyos_interface.py deleted file mode 100644 index 71a98c5..0000000 --- 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 054d810..0000000 --- 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 95fbae9..0000000 --- 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 6978754..0000000 --- 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 6705d57..0000000 --- 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 81a985d..b08fb73 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 6da7352..1853849 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 7c9f3ab..24fa161 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 125b256..9eaa278 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 3459fa1..175cf3b 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 096fd1f..93df4e4 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 961ef4e..faa9629 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 113ea53..a77ecaf 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 5c9b4c1..84f3d01 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 294bec1..6810a54 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 259de8c..aa7a316 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 55b1a1a..08eb113 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 7847a58..402facf 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 70ceed8..8fe572b 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 6c2f9f7..9f81eb9 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 8271049..3d5a903 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 564a257..e0c40e7 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 30694a6..b49462b 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 5a766ee..d619524 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 4564749..a0aafb5 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, diff --git a/plugins/terminal/__init__.py b/plugins/terminal/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/plugins/terminal/__init__.py diff --git a/plugins/terminal/vyos.py b/plugins/terminal/vyos.py new file mode 100644 index 0000000..fe7712f --- /dev/null +++ b/plugins/terminal/vyos.py @@ -0,0 +1,53 @@ +# +# (c) 2016 Red Hat Inc. +# +# This file is part of Ansible +# +# 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 + +import os +import re + +from ansible.plugins.terminal import TerminalBase +from ansible.errors import AnsibleConnectionFailure + + +class TerminalModule(TerminalBase): + + terminal_stdout_re = [ + re.compile(br"[\r\n]?[\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:>|#) ?$"), + re.compile(br"\@[\w\-\.]+:\S+?[>#\$] ?$"), + ] + + terminal_stderr_re = [ + re.compile(br"\n\s*Invalid command:"), + re.compile(br"\nCommit failed"), + re.compile(br"\n\s+Set failed"), + ] + + terminal_length = os.getenv("ANSIBLE_VYOS_TERMINAL_LENGTH", 10000) + + def on_open_shell(self): + try: + for cmd in (b"set terminal length 0", b"set terminal width 512"): + self._exec_cli_command(cmd) + self._exec_cli_command( + b"set terminal length %d" % self.terminal_length + ) + except AnsibleConnectionFailure: + raise AnsibleConnectionFailure("unable to set terminal parameters") |