summaryrefslogtreecommitdiffstats
path: root/collections-debian-merged/ansible_collections/cisco/iosxr/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'collections-debian-merged/ansible_collections/cisco/iosxr/plugins')
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/action/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/action/iosxr.py162
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/cliconf/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/cliconf/iosxr.py366
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/doc_fragments/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/doc_fragments/iosxr.py73
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/filter/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acl_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acl_interfaces/acl_interfaces.py85
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acls/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acls/acls.py538
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/facts/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/facts/facts.py27
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/interfaces/interfaces.py64
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/l2_interfaces.py85
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l3_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l3_interfaces/l3_interfaces.py72
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/lacp.py69
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp_interfaces/lacp_interfaces.py77
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lag_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lag_interfaces/lag_interfaces.py88
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/lldp_global.py73
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_interfaces/lldp_interfaces.py77
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospf_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospf_interfaces/ospf_interfaces.py379
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv2/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv2/ospfv2.py795
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv3/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv3/ospfv3.py1376
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/static_routes/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/static_routes/static_routes.py103
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acl_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acl_interfaces/acl_interfaces.py126
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/acls.py518
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/interfaces.py327
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/l2_interfaces.py373
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/l3_interfaces.py397
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/lacp.py213
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp_interfaces/lacp_interfaces.py312
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lag_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lag_interfaces/lag_interfaces.py439
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/lldp_global.py221
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_interfaces/lldp_interfaces.py278
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospf_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospf_interfaces/ospf_interfaces.py240
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv2/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv2/ospfv2.py262
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py255
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/static_routes.py549
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acl_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acl_interfaces/acl_interfaces.py78
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acls/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acls/acls.py457
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/facts.py122
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/interfaces.py110
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/l2_interfaces.py134
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/l3_interfaces.py126
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp/lacp.py89
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp_interfaces/lacp_interfaces.py115
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lag_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lag_interfaces/lag_interfaces.py141
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/base.py261
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_global/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_global/lldp_global.py107
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_interfaces/lldp_interfaces.py109
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospf_interfaces/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospf_interfaces/ospf_interfaces.py137
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/ospfv2.py157
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/ospfv3.py155
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/static_routes/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/static_routes/static_routes.py191
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/iosxr.py671
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/address_family.py129
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/neighbors.py135
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/process.py126
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/module.py72
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/providers.py128
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/acl_interfaces.py61
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospf_interfaces.py1370
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv2.py2876
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv3.py2801
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/utils.py391
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_acl_interfaces.py651
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_acls.py1451
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_banner.py316
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp.py355
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_command.py213
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_config.py480
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_facts.py218
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_interface.py1057
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_interfaces.py558
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_l2_interfaces.py687
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_l3_interfaces.py671
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lacp.py392
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lacp_interfaces.py652
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lag_interfaces.py853
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lldp_global.py489
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lldp_interfaces.py724
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_logging.py1220
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_netconf.py221
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospf_interfaces.py1210
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospfv2.py2544
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospfv3.py2783
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_static_routes.py854
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_system.py943
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_user.py973
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/netconf/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/netconf/iosxr.py297
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/terminal/__init__.py0
-rw-r--r--collections-debian-merged/ansible_collections/cisco/iosxr/plugins/terminal/iosxr.py57
148 files changed, 41137 insertions, 0 deletions
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/action/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/action/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/action/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/action/iosxr.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/action/iosxr.py
new file mode 100644
index 00000000..2d5819bc
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/action/iosxr.py
@@ -0,0 +1,162 @@
+#
+# (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.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ iosxr_provider_spec,
+)
+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.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 in ["iosxr_config", "config"] else False
+ )
+ force_cli = module_name in (
+ "iosxr_netconf",
+ "iosxr_config",
+ "iosxr_command",
+ "iosxr_facts",
+ )
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if self._play_context.connection == "local":
+ provider = load_provider(iosxr_provider_spec, self._task.args)
+ pc = copy.deepcopy(self._play_context)
+ pc.network_os = "cisco.iosxr.iosxr"
+ if force_cli or provider["transport"] == "cli":
+ pc.connection = "ansible.netcommon.network_cli"
+ pc.port = int(
+ provider["port"] or self._play_context.port or 22
+ )
+ elif provider["transport"] == "netconf":
+ pc.connection = "ansible.netcommon.netconf"
+ pc.port = int(
+ provider["port"] or self._play_context.port or 830
+ )
+ else:
+ return {
+ "failed": True,
+ "msg": "Transport type %s is not valid for this module"
+ % provider["transport"],
+ }
+
+ 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
+
+ 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.network_os = "iosxr"
+ if pc.connection.split(".")[-1] == "netconf":
+ pc.connection = "netconf"
+ else:
+ pc.connection = "network_cli"
+
+ 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
+ ]
+ )
+ elif persistent_connection in ("netconf", "network_cli"):
+ if force_cli and persistent_connection != "network_cli":
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for module %s"
+ % (self._play_context.connection, module_name),
+ }
+ provider = self._task.args.get("provider", {})
+ if any(provider.values()):
+ display.warning(
+ "provider is unnecessary when using {0} and will be ignored".format(
+ self._play_context.connection
+ )
+ )
+ del self._task.args["provider"]
+ 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/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/cliconf/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/cliconf/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/cliconf/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/cliconf/iosxr.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/cliconf/iosxr.py
new file mode 100644
index 00000000..0a2d81c9
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/cliconf/iosxr.py
@@ -0,0 +1,366 @@
+#
+# (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: iosxr
+short_description: Use iosxr cliconf to run command on Cisco IOS XR platform
+description:
+- This iosxr plugin provides low level abstraction apis for sending and receiving
+ CLI commands from Cisco IOS XR network devices.
+version_added: 1.0.0
+"""
+
+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.module_utils.connection import ConnectionError
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import (
+ NetworkConfig,
+ dumps,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ to_list,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ sanitize_config,
+ mask_config_blocks_from_diff,
+)
+from ansible.plugins.cliconf import CliconfBase
+
+
+class Cliconf(CliconfBase):
+ def get_device_info(self):
+ device_info = {}
+
+ device_info["network_os"] = "iosxr"
+ reply = self.get("show version | utility head -n 20")
+ data = to_text(reply, errors="surrogate_or_strict").strip()
+
+ match = re.search(r"Version (\S+)$", data, re.M)
+ if match:
+ device_info["network_os_version"] = match.group(1)
+
+ match = re.search(r'image file is "(.+)"', data)
+ if match:
+ device_info["network_os_image"] = match.group(1)
+
+ model_search_strs = [
+ r"^[Cc]isco (.+) \(revision",
+ r"^[Cc]isco (\S+ \S+).+bytes of .*memory",
+ ]
+ for item in model_search_strs:
+ match = re.search(item, data, re.M)
+ if match:
+ device_info["network_os_model"] = match.group(1)
+ break
+
+ match = re.search(r"^(.+) uptime", data, re.M)
+ if match:
+ device_info["network_os_hostname"] = match.group(1)
+
+ return device_info
+
+ def configure(self, admin=False, exclusive=False):
+ prompt = to_text(
+ self._connection.get_prompt(), errors="surrogate_or_strict"
+ ).strip()
+ if not prompt.endswith(")#"):
+ if admin and "admin-" not in prompt:
+ self.send_command("admin")
+ if exclusive:
+ self.send_command("configure exclusive")
+ return
+ self.send_command("configure terminal")
+
+ def abort(self, admin=False):
+ prompt = to_text(
+ self._connection.get_prompt(), errors="surrogate_or_strict"
+ ).strip()
+ if prompt.endswith(")#"):
+ self.send_command("abort")
+ if admin and "admin-" in prompt:
+ self.send_command("exit")
+
+ def get_config(self, source="running", format="text", flags=None):
+ if source not in ["running"]:
+ raise ValueError(
+ "fetching configuration from %s is not supported" % source
+ )
+
+ lookup = {"running": "running-config"}
+
+ cmd = "show {0} ".format(lookup[source])
+ cmd += " ".join(to_list(flags))
+ cmd = cmd.strip()
+
+ return self.send_command(cmd)
+
+ def edit_config(
+ self,
+ candidate=None,
+ commit=True,
+ admin=False,
+ exclusive=False,
+ replace=None,
+ comment=None,
+ label=None,
+ ):
+ operations = self.get_device_operations()
+ self.check_edit_config_capability(
+ operations, candidate, commit, replace, comment
+ )
+
+ resp = {}
+ results = []
+ requests = []
+
+ self.configure(admin=admin, exclusive=exclusive)
+
+ if replace:
+ candidate = "load {0}".format(replace)
+
+ for line in to_list(candidate):
+ if not isinstance(line, Mapping):
+ line = {"command": line}
+ cmd = line["command"]
+ results.append(self.send_command(**line))
+ requests.append(cmd)
+
+ # Before any commit happend, we can get a real configuration
+ # diff from the device and make it available by the iosxr_config module.
+ # This information can be usefull either in check mode or normal mode.
+ resp["show_commit_config_diff"] = self.get("show commit changes diff")
+
+ if commit:
+ self.commit(comment=comment, label=label, replace=replace)
+ else:
+ self.discard_changes()
+
+ self.abort(admin=admin)
+
+ resp["request"] = requests
+ resp["response"] = results
+ return resp
+
+ def get_diff(
+ self,
+ candidate=None,
+ running=None,
+ diff_match="line",
+ diff_ignore_lines=None,
+ path=None,
+ diff_replace="line",
+ ):
+ 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 not in option_values["diff_replace"]:
+ raise ValueError(
+ "'replace' value %s in invalid, valid values are %s"
+ % (diff_replace, ", ".join(option_values["diff_replace"]))
+ )
+
+ # prepare candidate configuration
+ sanitized_candidate = sanitize_config(candidate)
+ candidate_obj = NetworkConfig(indent=1, comment_tokens=["!"])
+ candidate_obj.load(sanitized_candidate)
+
+ if running and diff_match != "none":
+ # running configuration
+ running = mask_config_blocks_from_diff(
+ running, candidate, "ansible"
+ )
+ running = sanitize_config(running)
+
+ running_obj = NetworkConfig(
+ indent=1,
+ contents=running,
+ ignore_lines=diff_ignore_lines,
+ comment_tokens=["!"],
+ )
+ configdiffobjs = candidate_obj.difference(
+ running_obj, path=path, match=diff_match, replace=diff_replace
+ )
+
+ else:
+ configdiffobjs = candidate_obj.items
+
+ diff["config_diff"] = (
+ dumps(configdiffobjs, "commands") if configdiffobjs else ""
+ )
+ return diff
+
+ def get(
+ self,
+ command=None,
+ prompt=None,
+ answer=None,
+ sendonly=False,
+ newline=True,
+ output=None,
+ check_all=False,
+ ):
+ 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, label=None, replace=None):
+ cmd_obj = {}
+ if replace:
+ cmd_obj["command"] = "commit replace"
+ cmd_obj[
+ "prompt"
+ ] = "This commit will replace or remove the entire running configuration"
+ cmd_obj["answer"] = "yes"
+ else:
+ if comment and label:
+ cmd_obj["command"] = "commit label {0} comment {1}".format(
+ label, comment
+ )
+ elif comment:
+ cmd_obj["command"] = "commit comment {0}".format(comment)
+ elif label:
+ cmd_obj["command"] = "commit label {0}".format(label)
+ else:
+ cmd_obj["command"] = "commit show-error"
+ # In some cases even a normal commit, i.e., !replace,
+ # throws a prompt and we need to handle it before
+ # proceeding further
+ cmd_obj["prompt"] = "(C|c)onfirm"
+ cmd_obj["answer"] = "y"
+
+ self.send_command(**cmd_obj)
+
+ 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)
+
+ if out is not None:
+ try:
+ out = to_text(out, errors="surrogate_or_strict").strip()
+ except UnicodeError:
+ raise ConnectionError(
+ message=u"Failed to decode output from %s: %s"
+ % (cmd, to_text(out))
+ )
+
+ try:
+ out = json.loads(out)
+ except ValueError:
+ pass
+
+ responses.append(out)
+ return responses
+
+ def discard_changes(self):
+ self.send_command("abort")
+
+ def get_device_operations(self):
+ return {
+ "supports_diff_replace": True,
+ "supports_commit": True,
+ "supports_rollback": False,
+ "supports_defaults": False,
+ "supports_onbox_diff": False,
+ "supports_commit_comment": True,
+ "supports_multiline_delimiter": False,
+ "supports_diff_match": True,
+ "supports_diff_ignore_lines": True,
+ "supports_generate_diff": True,
+ "supports_replace": True,
+ "supports_admin": True,
+ "supports_commit_label": True,
+ }
+
+ def get_option_values(self):
+ return {
+ "format": ["text"],
+ "diff_match": ["line", "strict", "exact", "none"],
+ "diff_replace": ["line", "block", "config"],
+ "output": [],
+ }
+
+ def get_capabilities(self):
+ result = super(Cliconf, self).get_capabilities()
+ result["rpc"] += [
+ "commit",
+ "discard_changes",
+ "get_diff",
+ "configure",
+ "exit",
+ ]
+ 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="abort"
+ )
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/doc_fragments/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/doc_fragments/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/doc_fragments/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/doc_fragments/iosxr.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/doc_fragments/iosxr.py
new file mode 100644
index 00000000..9e552ded
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/doc_fragments/iosxr.py
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+# 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
+ port:
+ description:
+ - Specifies the port to use when building the connection to the remote device.
+ type: int
+ 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
+ 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
+ transport:
+ description:
+ - Specifies the type of connection based transport.
+ type: str
+ default: cli
+ choices:
+ - cli
+ - netconf
+notes:
+- For more information on using Ansible to manage network devices see the :ref:`Ansible
+ Network Guide <network_guide>`
+- For more information on using Ansible to manage Cisco devices see the `Cisco integration
+ page <https://www.ansible.com/integrations/networks/cisco>`_.
+"""
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/filter/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/filter/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/filter/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acl_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acl_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acl_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acl_interfaces/acl_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acl_interfaces/acl_interfaces.py
new file mode 100644
index 00000000..9e847a16
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acl_interfaces/acl_interfaces.py
@@ -0,0 +1,85 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_acl_interfaces module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+class Acl_interfacesArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_acl_interfaces module
+ """
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "running_config": {"type": "str"},
+ "config": {
+ "elements": "dict",
+ "options": {
+ "access_groups": {
+ "elements": "dict",
+ "options": {
+ "acls": {
+ "elements": "dict",
+ "options": {
+ "direction": {
+ "choices": ["in", "out"],
+ "type": "str",
+ "required": True,
+ },
+ "name": {"type": "str", "required": True},
+ },
+ "type": "list",
+ },
+ "afi": {
+ "choices": ["ipv4", "ipv6"],
+ "type": "str",
+ "required": True,
+ },
+ },
+ "type": "list",
+ },
+ "name": {"type": "str", "required": True},
+ },
+ "type": "list",
+ },
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "parsed",
+ "rendered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acls/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acls/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acls/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acls/acls.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acls/acls.py
new file mode 100644
index 00000000..0b3a7afc
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acls/acls.py
@@ -0,0 +1,538 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_acls module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+class AclsArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_acls module
+ """
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "running_config": {"type": "str"},
+ "config": {
+ "elements": "dict",
+ "options": {
+ "acls": {
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "aces": {
+ "elements": "dict",
+ "mutually_exclusive": [
+ ["grant", "remark", "line"]
+ ],
+ "options": {
+ "destination": {
+ "mutually_exclusive": [
+ ["address", "any", "host", "prefix"],
+ [
+ "wildcard_bits",
+ "any",
+ "host",
+ "prefix",
+ ],
+ ],
+ "options": {
+ "host": {"type": "str"},
+ "address": {"type": "str"},
+ "any": {"type": "bool"},
+ "prefix": {"type": "str"},
+ "port_protocol": {
+ "mutually_exclusive": [
+ [
+ "eq",
+ "gt",
+ "lt",
+ "neq",
+ "range",
+ ]
+ ],
+ "options": {
+ "eq": {"type": "str"},
+ "gt": {"type": "str"},
+ "lt": {"type": "str"},
+ "neq": {"type": "str"},
+ "range": {
+ "options": {
+ "end": {"type": "str"},
+ "start": {
+ "type": "str"
+ },
+ },
+ "required_together": [
+ ["start", "end"]
+ ],
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "wildcard_bits": {"type": "str"},
+ },
+ "required_together": [
+ ["address", "wildcard_bits"]
+ ],
+ "type": "dict",
+ },
+ "dscp": {
+ "mutually_exclusive": [
+ ["eq", "gt", "lt", "neq", "range"]
+ ],
+ "type": "dict",
+ "options": {
+ "eq": {"type": "str"},
+ "gt": {"type": "str"},
+ "lt": {"type": "str"},
+ "neq": {"type": "str"},
+ "range": {
+ "options": {
+ "end": {"type": "str"},
+ "start": {"type": "str"},
+ },
+ "required_together": [
+ ["start", "end"]
+ ],
+ "type": "dict",
+ },
+ },
+ },
+ "fragments": {"type": "bool"},
+ "capture": {"type": "bool"},
+ "destopts": {"type": "bool"},
+ "authen": {"type": "bool"},
+ "routing": {"type": "bool"},
+ "hop_by_hop": {"type": "bool"},
+ "grant": {
+ "type": "str",
+ "choices": ["permit", "deny"],
+ },
+ "icmp_off": {"type": "bool"},
+ "log": {"type": "bool"},
+ "log_input": {"type": "bool"},
+ "line": {"type": "str", "aliases": ["ace"]},
+ "packet_length": {
+ "mutually_exclusive": [
+ ["eq", "lt", "neq", "range"],
+ ["eq", "gt", "neq", "range"],
+ ],
+ "options": {
+ "eq": {"type": "int"},
+ "gt": {"type": "int"},
+ "lt": {"type": "int"},
+ "neq": {"type": "int"},
+ "range": {
+ "options": {
+ "end": {"type": "int"},
+ "start": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "precedence": {"type": "str"},
+ "protocol": {"type": "str"},
+ "protocol_options": {
+ "mutually_exclusive": [
+ ["icmp", "tcp", "igmp", "icmpv6"]
+ ],
+ "options": {
+ "icmpv6": {
+ "type": "dict",
+ "options": {
+ "address_unreachable": {
+ "type": "bool"
+ },
+ "administratively_prohibited": {
+ "type": "bool"
+ },
+ "beyond_scope_of_source_address": {
+ "type": "bool"
+ },
+ "destination_unreachable": {
+ "type": "bool"
+ },
+ "echo": {"type": "bool"},
+ "echo_reply": {"type": "bool"},
+ "erroneous_header_field": {
+ "type": "bool"
+ },
+ "group_membership_query": {
+ "type": "bool"
+ },
+ "group_membership_report": {
+ "type": "bool"
+ },
+ "group_membership_termination": {
+ "type": "bool"
+ },
+ "host_unreachable": {
+ "type": "bool"
+ },
+ "nd_na": {"type": "bool"},
+ "nd_ns": {"type": "bool"},
+ "neighbor_redirect": {
+ "type": "bool"
+ },
+ "no_route_to_destination": {
+ "type": "bool"
+ },
+ "node_information_request_is_refused": {
+ "type": "bool"
+ },
+ "node_information_successful_reply": {
+ "type": "bool"
+ },
+ "packet_too_big": {
+ "type": "bool"
+ },
+ "parameter_problem": {
+ "type": "bool"
+ },
+ "port_unreachable": {
+ "type": "bool"
+ },
+ "query_subject_is_IPv4address": {
+ "type": "bool"
+ },
+ "query_subject_is_IPv6address": {
+ "type": "bool"
+ },
+ "query_subject_is_domainname": {
+ "type": "bool"
+ },
+ "reassembly_timeout": {
+ "type": "bool"
+ },
+ "redirect": {"type": "bool"},
+ "router_advertisement": {
+ "type": "bool"
+ },
+ "router_renumbering": {
+ "type": "bool"
+ },
+ "router_solicitation": {
+ "type": "bool"
+ },
+ "rr_command": {"type": "bool"},
+ "rr_result": {"type": "bool"},
+ "rr_seqnum_reset": {
+ "type": "bool"
+ },
+ "time_exceeded": {
+ "type": "bool"
+ },
+ "ttl_exceeded": {
+ "type": "bool"
+ },
+ "unknown_query_type": {
+ "type": "bool"
+ },
+ "unreachable": {
+ "type": "bool"
+ },
+ "unrecognized_next_header": {
+ "type": "bool"
+ },
+ "unrecognized_option": {
+ "type": "bool"
+ },
+ "whoareyou_reply": {
+ "type": "bool"
+ },
+ "whoareyou_request": {
+ "type": "bool"
+ },
+ },
+ },
+ "icmp": {
+ "options": {
+ "administratively_prohibited": {
+ "type": "bool"
+ },
+ "alternate_address": {
+ "type": "bool"
+ },
+ "conversion_error": {
+ "type": "bool"
+ },
+ "dod_host_prohibited": {
+ "type": "bool"
+ },
+ "dod_net_prohibited": {
+ "type": "bool"
+ },
+ "echo": {"type": "bool"},
+ "echo_reply": {"type": "bool"},
+ "general_parameter_problem": {
+ "type": "bool"
+ },
+ "host_isolated": {
+ "type": "bool"
+ },
+ "host_precedence_unreachable": {
+ "type": "bool"
+ },
+ "host_redirect": {
+ "type": "bool"
+ },
+ "host_tos_redirect": {
+ "type": "bool"
+ },
+ "host_tos_unreachable": {
+ "type": "bool"
+ },
+ "host_unknown": {
+ "type": "bool"
+ },
+ "host_unreachable": {
+ "type": "bool"
+ },
+ "information_reply": {
+ "type": "bool"
+ },
+ "information_request": {
+ "type": "bool"
+ },
+ "mask_reply": {"type": "bool"},
+ "mask_request": {
+ "type": "bool"
+ },
+ "mobile_redirect": {
+ "type": "bool"
+ },
+ "net_redirect": {
+ "type": "bool"
+ },
+ "net_tos_redirect": {
+ "type": "bool"
+ },
+ "net_tos_unreachable": {
+ "type": "bool"
+ },
+ "net_unreachable": {
+ "type": "bool"
+ },
+ "network_unknown": {
+ "type": "bool"
+ },
+ "no_room_for_option": {
+ "type": "bool"
+ },
+ "option_missing": {
+ "type": "bool"
+ },
+ "packet_too_big": {
+ "type": "bool"
+ },
+ "parameter_problem": {
+ "type": "bool"
+ },
+ "port_unreachable": {
+ "type": "bool"
+ },
+ "precedence_unreachable": {
+ "type": "bool"
+ },
+ "protocol_unreachable": {
+ "type": "bool"
+ },
+ "reassembly_timeout": {
+ "type": "bool"
+ },
+ "redirect": {"type": "bool"},
+ "router_advertisement": {
+ "type": "bool"
+ },
+ "router_solicitation": {
+ "type": "bool"
+ },
+ "source_quench": {
+ "type": "bool"
+ },
+ "source_route_failed": {
+ "type": "bool"
+ },
+ "time_exceeded": {
+ "type": "bool"
+ },
+ "timestamp_reply": {
+ "type": "bool"
+ },
+ "timestamp_request": {
+ "type": "bool"
+ },
+ "traceroute": {"type": "bool"},
+ "ttl_exceeded": {
+ "type": "bool"
+ },
+ "unreachable": {
+ "type": "bool"
+ },
+ },
+ "type": "dict",
+ },
+ "igmp": {
+ "options": {
+ "dvmrp": {"type": "bool"},
+ "host_query": {"type": "bool"},
+ "host_report": {
+ "type": "bool"
+ },
+ "mtrace": {"type": "bool"},
+ "mtrace_response": {
+ "type": "bool"
+ },
+ "pim": {"type": "bool"},
+ "trace": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "tcp": {
+ "options": {
+ "ack": {"type": "bool"},
+ "established": {
+ "type": "bool"
+ },
+ "fin": {"type": "bool"},
+ "psh": {"type": "bool"},
+ "rst": {"type": "bool"},
+ "syn": {"type": "bool"},
+ "urg": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "remark": {"type": "str"},
+ "sequence": {"type": "int"},
+ "source": {
+ "mutually_exclusive": [
+ ["address", "any", "host", "prefix"],
+ [
+ "wildcard_bits",
+ "any",
+ "host",
+ "prefix",
+ ],
+ ],
+ "options": {
+ "host": {"type": "str"},
+ "address": {"type": "str"},
+ "any": {"type": "bool"},
+ "prefix": {"type": "str"},
+ "port_protocol": {
+ "mutually_exclusive": [
+ [
+ "eq",
+ "gt",
+ "lt",
+ "neq",
+ "range",
+ ]
+ ],
+ "options": {
+ "eq": {"type": "str"},
+ "gt": {"type": "str"},
+ "lt": {"type": "str"},
+ "neq": {"type": "str"},
+ "range": {
+ "options": {
+ "end": {"type": "str"},
+ "start": {
+ "type": "str"
+ },
+ },
+ "required_together": [
+ ["start", "end"]
+ ],
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "wildcard_bits": {"type": "str"},
+ },
+ "required_together": [
+ ["address", "wildcard_bits"]
+ ],
+ "type": "dict",
+ },
+ "ttl": {
+ "mutually_exclusive": [
+ ["eq", "gt", "lt", "neq", "range"]
+ ],
+ "options": {
+ "eq": {"type": "int"},
+ "gt": {"type": "int"},
+ "lt": {"type": "int"},
+ "neq": {"type": "int"},
+ "range": {
+ "options": {
+ "end": {"type": "int"},
+ "start": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ },
+ "type": "list",
+ },
+ },
+ "type": "list",
+ },
+ "afi": {
+ "choices": ["ipv4", "ipv6"],
+ "required": True,
+ "type": "str",
+ },
+ },
+ "type": "list",
+ },
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "rendered",
+ "parsed",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/facts/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/facts/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/facts/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/facts/facts.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/facts/facts.py
new file mode 100644
index 00000000..af84f8be
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/facts/facts.py
@@ -0,0 +1,27 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The arg spec for the iosxr facts module.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+class FactsArgs(object): # pylint: disable=R0903
+ """ The arg spec for the iosxr facts module
+ """
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "gather_subset": dict(
+ default=["!config"], type="list", elements="str"
+ ),
+ "gather_network_resources": dict(type="list", elements="str"),
+ }
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/interfaces/interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/interfaces/interfaces.py
new file mode 100644
index 00000000..e119c159
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/interfaces/interfaces.py
@@ -0,0 +1,64 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the ios_interfaces module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+class InterfacesArgs(object):
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str", "required": True},
+ "description": {"type": "str"},
+ "enabled": {"default": True, "type": "bool"},
+ "speed": {"type": "int"},
+ "mtu": {"type": "int"},
+ "duplex": {"type": "str", "choices": ["full", "half"]},
+ },
+ "type": "list",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "parsed",
+ "rendered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ }
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/l2_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/l2_interfaces.py
new file mode 100644
index 00000000..fbe5e870
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/l2_interfaces.py
@@ -0,0 +1,85 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_l2_interfaces module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+class L2_InterfacesArgs(object):
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str", "required": True},
+ "native_vlan": {"type": "int"},
+ "l2transport": {"type": "bool"},
+ "l2protocol": {
+ "elements": "dict",
+ "options": {
+ "cdp": {
+ "type": "str",
+ "choices": ["drop", "forward", "tunnel"],
+ },
+ "pvst": {
+ "type": "str",
+ "choices": ["drop", "forward", "tunnel"],
+ },
+ "stp": {
+ "type": "str",
+ "choices": ["drop", "forward", "tunnel"],
+ },
+ "vtp": {
+ "type": "str",
+ "choices": ["drop", "forward", "tunnel"],
+ },
+ },
+ "type": "list",
+ },
+ "q_vlan": {"type": "list", "elements": "int"},
+ "propagate": {"type": "bool"},
+ },
+ "type": "list",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "parsed",
+ "rendered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ }
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l3_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l3_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l3_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l3_interfaces/l3_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l3_interfaces/l3_interfaces.py
new file mode 100644
index 00000000..2e63dae9
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l3_interfaces/l3_interfaces.py
@@ -0,0 +1,72 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the ios_l3_interfaces module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+class L3_InterfacesArgs(object):
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str", "required": True},
+ "ipv4": {
+ "elements": "dict",
+ "type": "list",
+ "options": {
+ "address": {"type": "str"},
+ "secondary": {"type": "bool"},
+ },
+ },
+ "ipv6": {
+ "elements": "dict",
+ "type": "list",
+ "options": {"address": {"type": "str"}},
+ },
+ },
+ "type": "list",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "parsed",
+ "rendered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ }
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/lacp.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/lacp.py
new file mode 100644
index 00000000..9b09053f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/lacp.py
@@ -0,0 +1,69 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_lacp module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+class LacpArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_lacp module
+ """
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "options": {
+ "system": {
+ "options": {
+ "mac": {
+ "type": "dict",
+ "options": {"address": {"type": "str"}},
+ },
+ "priority": {"type": "int"},
+ },
+ "type": "dict",
+ }
+ },
+ "type": "dict",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "deleted",
+ "parsed",
+ "rendered",
+ "gathered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp_interfaces/lacp_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp_interfaces/lacp_interfaces.py
new file mode 100644
index 00000000..8dfab9ff
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp_interfaces/lacp_interfaces.py
@@ -0,0 +1,77 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_lacp_interfaces module
+"""
+
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+class Lacp_interfacesArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_lacp_interfaces module
+ """
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "elements": "dict",
+ "options": {
+ "churn_logging": {
+ "choices": ["actor", "partner", "both"],
+ "type": "str",
+ },
+ "collector_max_delay": {"type": "int"},
+ "name": {"type": "str"},
+ "period": {"type": "int"},
+ "switchover_suppress_flaps": {"type": "int"},
+ "system": {
+ "options": {
+ "mac": {"type": "str"},
+ "priority": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "list",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "deleted",
+ "overridden",
+ "parsed",
+ "rendered",
+ "gathered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lag_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lag_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lag_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lag_interfaces/lag_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lag_interfaces/lag_interfaces.py
new file mode 100644
index 00000000..cf076046
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lag_interfaces/lag_interfaces.py
@@ -0,0 +1,88 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_lag_interfaces module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+class Lag_interfacesArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_lag_interfaces module
+ """
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "elements": "dict",
+ "options": {
+ "links": {
+ "options": {
+ "max_active": {"type": "int"},
+ "min_active": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "load_balancing_hash": {
+ "choices": ["dst-ip", "src-ip"],
+ "type": "str",
+ },
+ "members": {
+ "elements": "dict",
+ "options": {
+ "member": {"type": "str"},
+ "mode": {
+ "choices": ["on", "active", "passive", "inherit"],
+ "type": "str",
+ },
+ },
+ "type": "list",
+ },
+ "mode": {
+ "choices": ["on", "active", "passive"],
+ "type": "str",
+ },
+ "name": {"required": True, "type": "str"},
+ },
+ "type": "list",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "parsed",
+ "rendered",
+ "gathered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ }
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/lldp_global.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/lldp_global.py
new file mode 100644
index 00000000..97efae08
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/lldp_global.py
@@ -0,0 +1,73 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_lldp_global module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+class Lldp_globalArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_lldp module
+ """
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "options": {
+ "holdtime": {"type": "int"},
+ "reinit": {"type": "int"},
+ "subinterfaces": {"type": "bool"},
+ "timer": {"type": "int"},
+ "tlv_select": {
+ "options": {
+ "management_address": {"type": "bool"},
+ "port_description": {"type": "bool"},
+ "system_capabilities": {"type": "bool"},
+ "system_description": {"type": "bool"},
+ "system_name": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "deleted",
+ "parsed",
+ "rendered",
+ "gathered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_interfaces/lldp_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_interfaces/lldp_interfaces.py
new file mode 100644
index 00000000..0dca5800
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_interfaces/lldp_interfaces.py
@@ -0,0 +1,77 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_lldp_interfaces module
+"""
+
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+class Lldp_interfacesArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_lldp_interfaces module
+ """
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "elements": "dict",
+ "options": {
+ "destination": {
+ "type": "dict",
+ "options": {
+ "mac_address": {
+ "type": "str",
+ "choices": [
+ "ieee-nearest-bridge",
+ "ieee-nearest-non-tmpr-bridge",
+ ],
+ }
+ },
+ },
+ "name": {"type": "str"},
+ "receive": {"type": "bool"},
+ "transmit": {"type": "bool"},
+ },
+ "type": "list",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "deleted",
+ "overridden",
+ "parsed",
+ "rendered",
+ "gathered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospf_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospf_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospf_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospf_interfaces/ospf_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospf_interfaces/ospf_interfaces.py
new file mode 100644
index 00000000..8bf33fd0
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospf_interfaces/ospf_interfaces.py
@@ -0,0 +1,379 @@
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the
+# cli_rm_builder.
+#
+# Manually editing this file is not advised.
+#
+# To update the argspec make the desired changes
+# in the module docstring and re-run
+# cli_rm_builder.
+#
+#############################################
+
+"""
+The arg spec for the iosxr_ospf_interfaces module
+"""
+
+
+class Ospf_interfacesArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_ospf_interfaces module
+ """
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "running_config": {"type": "str"},
+ "config": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str", "required": True},
+ "type": {"type": "str", "required": True},
+ "address_family": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "afi": {
+ "type": "str",
+ "choices": ["ipv4", "ipv6"],
+ "required": True,
+ },
+ "processes": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "process_id": {
+ "type": "str",
+ "required": True,
+ },
+ "area": {
+ "type": "dict",
+ "options": {"area_id": {"type": "str"}},
+ },
+ },
+ },
+ "apply_group_option": {
+ "type": "dict",
+ "options": {
+ "group_name": {"type": "str"},
+ "operation": {
+ "type": "str",
+ "choices": ["add", "remove", "append"],
+ },
+ },
+ },
+ "authentication": {
+ "type": "dict",
+ "options": {
+ "message_digest": {
+ "type": "dict",
+ "options": {"keychain": {"type": "str"}},
+ },
+ "null_auth": {"type": "bool"},
+ },
+ },
+ "authentication_key": {
+ "type": "dict",
+ "options": {
+ "password": {"type": "str"},
+ "clear": {"type": "str"},
+ "encrypted": {"type": "str"},
+ },
+ },
+ "bfd": {
+ "type": "dict",
+ "options": {
+ "fast_detect": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "strict_mode": {"type": "bool"},
+ },
+ },
+ "minimum_interval": {"type": "int"},
+ "multiplier": {"type": "int"},
+ },
+ },
+ "cost": {"type": "int"},
+ "cost_fallback": {
+ "type": "dict",
+ "options": {
+ "cost": {"type": "int"},
+ "threshold": {"type": "int"},
+ },
+ },
+ "database_filter": {
+ "type": "dict",
+ "options": {"all_outgoing_lsa": {"type": "bool"}},
+ },
+ "dead_interval": {"type": "int"},
+ "demand_circuit": {"type": "bool"},
+ "fast_reroute": {
+ "type": "dict",
+ "options": {
+ "disabled": {"type": "bool"},
+ "per_link": {
+ "type": "dict",
+ "options": {
+ "information_type": {
+ "type": "str",
+ "choices": [
+ "exclude",
+ "lfa_candidate",
+ ],
+ },
+ "use_candidate_only": {"type": "bool"},
+ "interface": {
+ "type": "dict",
+ "options": {
+ "bvi": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "int"}
+ },
+ },
+ "bundle_ether": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "int"}
+ },
+ },
+ "pos_int": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "int"}
+ },
+ },
+ "fast_ethernet": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"}
+ },
+ },
+ "fiftygige": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"}
+ },
+ },
+ "fortygige": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"}
+ },
+ },
+ "fourhundredgige": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"}
+ },
+ },
+ "gigabitethernet": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"}
+ },
+ },
+ "hundredgige": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"}
+ },
+ },
+ "mgmteth": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"}
+ },
+ },
+ "multilink": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"}
+ },
+ },
+ "pw_ether": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "int"}
+ },
+ },
+ "pw_iw": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "int"}
+ },
+ },
+ "srp": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"}
+ },
+ },
+ "serial": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"}
+ },
+ },
+ "tengige": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"}
+ },
+ },
+ "twentyfivegige": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"}
+ },
+ },
+ "twohundredgige": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"}
+ },
+ },
+ "nve": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "int"}
+ },
+ },
+ "tunnel_ip": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "int"}
+ },
+ },
+ "tunnel_ipsec": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "int"}
+ },
+ },
+ "tunnel_mte": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "int"}
+ },
+ },
+ "tunnel_mpls": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"}
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "flood_reduction": {"type": "bool"},
+ "hello_interval": {"type": "int"},
+ "link_down_fast_detect": {"type": "bool"},
+ "message_digest_key": {
+ "type": "dict",
+ "options": {
+ "id": {"type": "int", "required": True},
+ "md5": {
+ "type": "dict",
+ "required": True,
+ "options": {
+ "password": {"type": "str"},
+ "clear": {"type": "bool"},
+ "encrypted": {"type": "bool"},
+ },
+ },
+ },
+ },
+ "mpls_ldp_sync": {"type": "bool"},
+ "mtu_ignore": {"type": "bool"},
+ "network": {
+ "type": "str",
+ "choices": [
+ "broadcast",
+ "non-broadcast",
+ "point-to-multipoint",
+ "point-to-point",
+ ],
+ },
+ "neighbors": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "neighbor_id": {"type": "str"},
+ "cost": {"type": "int"},
+ "db_filter_all_out": {"type": "bool"},
+ "poll_interval": {"type": "int"},
+ "priority": {"type": "int"},
+ },
+ },
+ "packet_size": {"type": "int"},
+ "passive": {"type": "bool"},
+ "prefix_suppression": {"type": "bool"},
+ "priority": {"type": "int"},
+ "retransmit_interval": {"type": "int"},
+ "security_ttl": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "hops": {"type": "int"},
+ },
+ },
+ "transmit_delay": {"type": "int"},
+ },
+ },
+ },
+ },
+ "state": {
+ "type": "str",
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "parsed",
+ "rendered",
+ ],
+ "default": "merged",
+ },
+ } # pylint: disable=C0301
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv2/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv2/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv2/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv2/ospfv2.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv2/ospfv2.py
new file mode 100644
index 00000000..fb41a1e3
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv2/ospfv2.py
@@ -0,0 +1,795 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_ospfv2 module
+"""
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+class Ospfv2Args(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_ospfv2 module
+ """
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "options": {
+ "processes": {
+ "elements": "dict",
+ "options": {
+ "address_family_unicast": {"type": "bool"},
+ "adjacency_stagger": {
+ "options": {
+ "disable": {"type": "bool"},
+ "max_adjacency": {"type": "int"},
+ "min_adjacency": {"type": "int"},
+ },
+ "required_together": [
+ ["min_adjacency", "max_adjacency"]
+ ],
+ "type": "dict",
+ },
+ "apply_weight": {
+ "mutually_exclusive": [
+ ["bandwidth", "default_weight"]
+ ],
+ "options": {
+ "bandwidth": {"type": "int"},
+ "default_weight": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "areas": {
+ "elements": "dict",
+ "options": {
+ "area_id": {"required": True, "type": "str"},
+ "authentication": {
+ "mutually_exclusive": [
+ [
+ "keychain",
+ "message_digest",
+ "no_auth",
+ ]
+ ],
+ "options": {
+ "keychain": {"type": "str"},
+ "message_digest": {
+ "options": {
+ "keychain": {"type": "str"}
+ },
+ "type": "dict",
+ },
+ "no_auth": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "authentication_key": {
+ "mutually_exclusive": [
+ ["clear", "encrypted"]
+ ],
+ "options": {
+ "clear": {"type": "str"},
+ "encrypted": {"type": "str"},
+ "password": {"type": "str"},
+ },
+ "type": "dict",
+ },
+ "bfd": {
+ "options": {
+ "fast_detect": {
+ "options": {
+ "set": {"type": "bool"},
+ "strict_mode": {
+ "type": "bool"
+ },
+ },
+ "type": "dict",
+ },
+ "minimum_interval": {"type": "int"},
+ "multiplier": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "cost": {"type": "int"},
+ "dead_interval": {"type": "int"},
+ "default_cost": {"type": "int"},
+ "hello_interval": {"type": "int"},
+ "mpls": {
+ "options": {
+ "ldp": {
+ "options": {
+ "auto_config": {
+ "type": "bool"
+ },
+ "sync": {"type": "bool"},
+ "sync_igp_shortcuts": {
+ "type": "bool"
+ },
+ },
+ "type": "dict",
+ },
+ "traffic_eng": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "mtu_ignore": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "nssa": {
+ "options": {
+ "default_information_originate": {
+ "options": {
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "no_redistribution": {"type": "bool"},
+ "no_summary": {"type": "bool"},
+ "set": {"type": "bool"},
+ "translate": {
+ "options": {
+ "type7": {
+ "options": {
+ "always": {
+ "type": "bool"
+ }
+ },
+ "type": "dict",
+ }
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "ranges": {
+ "elements": "dict",
+ "mutually_exclusive": [
+ ["advertise", "not_advertise"]
+ ],
+ "options": {
+ "address": {
+ "required": True,
+ "type": "str",
+ },
+ "advertise": {"type": "bool"},
+ "not_advertise": {"type": "bool"},
+ },
+ "type": "list",
+ },
+ "route_policy": {
+ "elements": "dict",
+ "options": {
+ "direction": {
+ "choices": ["in", "out"],
+ "type": "str",
+ },
+ "parameters": {
+ "elements": "str",
+ "type": "list",
+ },
+ },
+ "type": "list",
+ },
+ "stub": {
+ "options": {
+ "no_summary": {"type": "bool"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "transmit_delay": {"type": "int"},
+ "virtual_link": {
+ "elements": "dict",
+ "options": {
+ "authentication": {
+ "mutually_exclusive": [
+ [
+ "keychain",
+ "message_digest",
+ "no_auth",
+ ]
+ ],
+ "options": {
+ "keychain": {"type": "str"},
+ "message_digest": {
+ "options": {
+ "keychain": {
+ "type": "str"
+ }
+ },
+ "type": "dict",
+ },
+ "no_auth": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "authentication_key": {
+ "mutually_exclusive": [
+ ["clear", "encrypted"]
+ ],
+ "options": {
+ "clear": {"type": "str"},
+ "encrypted": {"type": "str"},
+ "password": {"type": "str"},
+ },
+ "type": "dict",
+ },
+ "dead_interval": {"type": "int"},
+ "hello_interval": {"type": "int"},
+ "id": {
+ "required": True,
+ "type": "str",
+ },
+ "message_digest_key": {
+ "options": {
+ "id": {
+ "required": True,
+ "type": "int",
+ },
+ "md5": {
+ "mutually_exclusive": [
+ ["clear", "encrypted"]
+ ],
+ "options": {
+ "clear": {
+ "type": "bool"
+ },
+ "encrypted": {
+ "type": "bool"
+ },
+ "password": {
+ "type": "str"
+ },
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "retransmit_interval": {"type": "int"},
+ "transmit_delay": {"type": "int"},
+ },
+ "type": "list",
+ },
+ },
+ "type": "list",
+ },
+ "authentication": {
+ "mutually_exclusive": [
+ ["keychain", "message_digest", "no_auth"]
+ ],
+ "options": {
+ "keychain": {"type": "str"},
+ "message_digest": {
+ "options": {
+ "keychain": {"type": "str"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "no_auth": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "authentication_key": {
+ "mutually_exclusive": [["clear", "encrypted"]],
+ "options": {
+ "clear": {"type": "bool"},
+ "encrypted": {"type": "bool"},
+ "password": {"type": "str"},
+ },
+ "type": "dict",
+ },
+ "auto_cost": {
+ "mutually_exclusive": [
+ ["reference_bandwidth", "disable"]
+ ],
+ "options": {
+ "disable": {"type": "bool"},
+ "reference_bandwidth": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "bfd": {
+ "options": {
+ "fast_detect": {
+ "options": {
+ "set": {"type": "bool"},
+ "strict_mode": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "minimum_interval": {"type": "int"},
+ "multiplier": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "capability": {
+ "options": {
+ "opaque": {
+ "mutually_exclusive": [["set", "disable"]],
+ "options": {
+ "disable": {"type": "bool"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "type7": {"type": "str"},
+ },
+ "type": "dict",
+ },
+ "cost": {"type": "int"},
+ "database_filter": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "dead_interval": {"type": "int"},
+ "default_information_originate": {
+ "options": {
+ "always": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "default_metric": {"type": "int"},
+ "demand_circuit": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "distance": {
+ "options": {
+ "admin_distance": {
+ "elements": "dict",
+ "options": {
+ "access_list": {"type": "str"},
+ "source": {"type": "str"},
+ "value": {"type": "int"},
+ "wildcard": {"type": "str"},
+ },
+ "required_together": [
+ ["value", "source", "wildcard"]
+ ],
+ "type": "list",
+ },
+ "ospf_distance": {
+ "options": {
+ "external": {"type": "int"},
+ "inter_area": {"type": "int"},
+ "intra_area": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "distribute_bgp_ls": {
+ "options": {
+ "instance_id": {"type": "int"},
+ "throttle": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "distribute_link_state": {
+ "options": {
+ "instance_id": {"type": "int"},
+ "throttle": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "distribute_list": {
+ "elements": "dict",
+ "mutually_exclusive": [
+ ["access_list", "route_policy"]
+ ],
+ "options": {
+ "access_list": {"type": "str"},
+ "direction": {
+ "choices": ["in", "out"],
+ "type": "str",
+ },
+ "outgoing_params": {
+ "options": {
+ "id": {"type": "str"},
+ "route_type": {
+ "choices": [
+ "bgp",
+ "connected",
+ "dagr",
+ "ospf",
+ "static",
+ ],
+ "type": "str",
+ },
+ },
+ "type": "dict",
+ },
+ "route_policy": {"type": "str"},
+ },
+ "type": "list",
+ },
+ "external_out": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "flood_reduction": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "hello_interval": {"type": "int"},
+ "ignore_lsa_mospf": {"type": "bool"},
+ "link_down_fast_detect": {"type": "bool"},
+ "log_adjacency_changes": {
+ "options": {
+ "detail": {"type": "bool"},
+ "disable": {"type": "bool"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "loopback_stub_network": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "max_lsa": {
+ "options": {
+ "ignore_count": {"type": "int"},
+ "ignore_time": {"type": "int"},
+ "reset_time": {"type": "int"},
+ "threshold": {"type": "int"},
+ "warning_only": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "max_metric": {
+ "options": {
+ "router_lsa": {
+ "options": {
+ "external_lsa": {
+ "options": {
+ "max_metric_value": {
+ "type": "int"
+ },
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "include_stub": {"type": "bool"},
+ "on_startup": {
+ "options": {
+ "set": {"type": "bool"},
+ "wait_for_bgp_asn": {
+ "type": "int"
+ },
+ "wait_period": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "set": {"type": "bool"},
+ "summary_lsa": {
+ "options": {
+ "max_metric_value": {
+ "type": "int"
+ },
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ }
+ },
+ "type": "dict",
+ },
+ "message_digest_key": {
+ "options": {
+ "id": {"required": True, "type": "int"},
+ "md5": {
+ "mutually_exclusive": [
+ ["clear", "encrypted"]
+ ],
+ "options": {
+ "clear": {"type": "bool"},
+ "encrypted": {"type": "bool"},
+ "password": {"type": "str"},
+ },
+ "required": True,
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "microloop_avoidance": {
+ "mutually_exclusive": [
+ [
+ "protected",
+ "rib_update_delay",
+ "segment_routing",
+ ]
+ ],
+ "options": {
+ "protected": {"type": "bool"},
+ "rib_update_delay": {"type": "int"},
+ "segment_routing": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "monitor_convergence": {
+ "options": {
+ "prefix_list": {"type": "str"},
+ "track_external_routes": {"type": "bool"},
+ "track_ip_frr": {"type": "bool"},
+ "track_summary_routes": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "mpls": {
+ "options": {
+ "ldp": {
+ "options": {
+ "auto_config": {"type": "bool"},
+ "sync": {"type": "bool"},
+ "sync_igp_shortcuts": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "traffic_eng": {
+ "options": {
+ "autoroute_exclude": {
+ "options": {
+ "parameters": {
+ "elements": "str",
+ "type": "list",
+ },
+ "route_policy": {
+ "type": "str"
+ },
+ },
+ "type": "dict",
+ },
+ "igp_intact": {"type": "bool"},
+ "ldp_sync_update": {"type": "bool"},
+ "multicast_intact": {"type": "bool"},
+ "router_id": {"type": "str"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "mtu_ignore": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "network": {
+ "options": {
+ "broadcast": {"type": "bool"},
+ "non_broadcast": {"type": "bool"},
+ "point_to_multipoint": {"type": "bool"},
+ "point_to_point": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "nsf": {
+ "options": {
+ "cisco": {
+ "options": {
+ "enforce_global": {"type": "bool"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "flush_delay_time": {"type": "int"},
+ "ietf": {
+ "options": {
+ "helper_disable": {"type": "bool"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "interval": {"type": "int"},
+ "lifetime": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "nsr": {"type": "bool"},
+ "packet_size": {"type": "int"},
+ "passive": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "prefix_suppression": {
+ "options": {
+ "secondary_address": {"type": "bool"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "priority": {"type": "int"},
+ "process_id": {"required": True, "type": "str"},
+ "protocol_shutdown": {
+ "options": {
+ "host_mode": {"type": "bool"},
+ "limit": {
+ "options": {
+ "high": {"type": "int"},
+ "low": {"type": "int"},
+ "medium": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "on_reload": {"type": "bool"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "redistribute": {
+ "options": {
+ "id": {"type": "str"},
+ "level": {
+ "choices": [1, 2, 12],
+ "type": "int",
+ },
+ "lsa_type_summary": {"type": "bool"},
+ "match": {"type": "str"},
+ "metric": {"type": "int"},
+ "metric_type": {
+ "choices": [1, 2],
+ "type": "int",
+ },
+ "nssa_only": {"type": "bool"},
+ "preserve_med": {"type": "bool"},
+ "route_policy": {
+ "options": {
+ "name": {"type": "str"},
+ "parameters": {
+ "elements": "str",
+ "type": "list",
+ },
+ },
+ "type": "dict",
+ },
+ "route_type": {
+ "choices": [
+ "application",
+ "bgp",
+ "connected",
+ "dagr",
+ "eigrp",
+ "isis",
+ "mobile",
+ "ospf",
+ "rip",
+ "static",
+ "subscriber",
+ ],
+ "type": "str",
+ },
+ "tag": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "retransmit_interval": {"type": "int"},
+ "router_id": {"type": "str"},
+ "security_ttl": {
+ "options": {
+ "hops": {"type": "int"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "summary_in": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "summary_prefix": {
+ "elements": "dict",
+ "options": {
+ "not_advertise": {"type": "bool"},
+ "prefix": {"required": True, "type": "str"},
+ "tag": {"type": "int"},
+ },
+ "type": "list",
+ },
+ "timers": {
+ "options": {
+ "graceful_shutdown": {
+ "options": {
+ "initial_delay": {"type": "int"},
+ "retain_routes": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "lsa": {
+ "options": {
+ "group_pacing": {"type": "int"},
+ "min_arrival": {"type": "int"},
+ "refresh": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "pacing_flood": {"type": "int"},
+ "throttle": {
+ "options": {
+ "fast_reroute": {"type": "int"},
+ "lsa_all": {
+ "options": {
+ "initial_delay": {
+ "type": "int"
+ },
+ "max_delay": {"type": "int"},
+ "min_delay": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "spf": {
+ "options": {
+ "change_delay": {
+ "type": "int"
+ },
+ "max_wait": {"type": "int"},
+ "second_delay": {
+ "type": "int"
+ },
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "transmit_delay": {"type": "int"},
+ "weight": {"type": "int"},
+ },
+ "type": "list",
+ }
+ },
+ "type": "dict",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "rendered",
+ "parsed",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv3/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv3/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv3/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv3/ospfv3.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv3/ospfv3.py
new file mode 100644
index 00000000..e9d82720
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv3/ospfv3.py
@@ -0,0 +1,1376 @@
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The arg spec for the iosxr_ospfv3 module
+"""
+
+
+class Ospfv3Args(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_ospfv3 module
+ """
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "running_config": {"type": "str"},
+ "config": {
+ "type": "dict",
+ "options": {
+ "processes": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "process_id": {"type": "str", "required": True},
+ "address_family_unicast": {"type": "bool"},
+ "authentication": {
+ "type": "dict",
+ "options": {
+ "disable": {"type": "bool", "default": False},
+ "ipsec": {
+ "type": "dict",
+ "options": {
+ "spi": {"type": "int"},
+ "algorithim_type": {
+ "type": "str",
+ "choices": ["md5", "sha1"],
+ },
+ "key": {"type": "str"},
+ "clear_key": {"type": "str"},
+ "password_key": {"type": "str"},
+ },
+ },
+ },
+ },
+ "auto_cost": {
+ "type": "dict",
+ "options": {
+ "reference_bandwidth": {"type": "int"},
+ "disable": {"type": "bool"},
+ },
+ },
+ "bfd": {
+ "type": "dict",
+ "options": {
+ "fast_detect": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "strict_mode": {"type": "bool"},
+ },
+ },
+ "minimum_interval": {"type": "int"},
+ "multiplier": {"type": "int"},
+ },
+ },
+ "areas": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "area_id": {"type": "str", "required": True},
+ "authentication": {
+ "type": "dict",
+ "options": {
+ "disable": {
+ "type": "bool",
+ "default": False,
+ },
+ "ipsec": {
+ "type": "dict",
+ "options": {
+ "spi": {"type": "int"},
+ "algorithim_type": {
+ "type": "str",
+ "choices": ["md5", "sha1"],
+ },
+ "key": {"type": "str"},
+ "clear_key": {"type": "str"},
+ "password_key": {
+ "type": "str"
+ },
+ },
+ },
+ },
+ },
+ "bfd": {
+ "type": "dict",
+ "options": {
+ "fast_detect": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "strict_mode": {
+ "type": "bool"
+ },
+ },
+ },
+ "minimum_interval": {"type": "int"},
+ "multiplier": {"type": "int"},
+ },
+ },
+ "cost": {"type": "int"},
+ "database_filter": {
+ "type": "dict",
+ "options": {
+ "all_outgoing_lsa": {"type": "bool"}
+ },
+ },
+ "dead_interval": {"type": "int"},
+ "default_cost": {"type": "int"},
+ "demand_circuit": {"type": "bool"},
+ "distrinbute_rib_prefix_list_name": {
+ "type": "str"
+ },
+ "fast_reroute": {
+ "type": "dict",
+ "options": {
+ "disabled": {"type": "bool"},
+ "per_link": {
+ "type": "dict",
+ "options": {
+ "information_type": {
+ "type": "str",
+ "choices": [
+ "exclude",
+ "lfa_candidate",
+ ],
+ },
+ "use_candidate_only": {
+ "type": "bool"
+ },
+ "interface": {
+ "type": "dict",
+ "options": {
+ "bvi": {
+ "type": "list",
+ "elements": "int",
+ },
+ "bundle_ether": {
+ "type": "list",
+ "elements": "int",
+ },
+ "pos_int": {
+ "type": "list",
+ "elements": "int",
+ },
+ "fast_ethernet": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fiftygige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fortygige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fourhundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "gigabitethernet": {
+ "type": "list",
+ "elements": "str",
+ },
+ "hundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "mgmteth": {
+ "type": "list",
+ "elements": "str",
+ },
+ "multilink": {
+ "type": "list",
+ "elements": "str",
+ },
+ "pw_ether": {
+ "type": "list",
+ "elements": "int",
+ },
+ "pw_iw": {
+ "type": "list",
+ "elements": "int",
+ },
+ "srp": {
+ "type": "list",
+ "elements": "str",
+ },
+ "serial": {
+ "type": "list",
+ "elements": "str",
+ },
+ "tengige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "twentyfivegige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "twohundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "nve": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_ip": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_ipsec": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_mte": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_mpls": {
+ "type": "int"
+ },
+ },
+ },
+ },
+ },
+ "per_prefix": {
+ "type": "dict",
+ "options": {
+ "information_type": {
+ "type": "str",
+ "choices": [
+ "exclude",
+ "lfa_candidate",
+ ],
+ },
+ "use_candidate_only": {
+ "type": "bool"
+ },
+ "interface": {
+ "type": "dict",
+ "options": {
+ "bvi": {
+ "type": "list",
+ "elements": "int",
+ },
+ "bundle_ether": {
+ "type": "list",
+ "elements": "int",
+ },
+ "pos_int": {
+ "type": "list",
+ "elements": "int",
+ },
+ "fast_ethernet": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fiftygige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fortygige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fourhundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "gigabitethernet": {
+ "type": "list",
+ "elements": "str",
+ },
+ "hundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "mgmteth": {
+ "type": "list",
+ "elements": "str",
+ },
+ "multilink": {
+ "type": "list",
+ "elements": "str",
+ },
+ "pw_ether": {
+ "type": "list",
+ "elements": "int",
+ },
+ "pw_iw": {
+ "type": "list",
+ "elements": "int",
+ },
+ "srp": {
+ "type": "list",
+ "elements": "str",
+ },
+ "serial": {
+ "type": "list",
+ "elements": "str",
+ },
+ "tengige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "twentyfivegige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "twohundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "nve": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_ip": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_ipsec": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_mte": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_mpls": {
+ "type": "int"
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "flood_reduction": {"type": "bool"},
+ "hello_interval": {"type": "int"},
+ "instance_id": {"type": "int"},
+ "mtu_ignore": {"type": "bool"},
+ "mpls_ldp_sync": {"type": "bool"},
+ "network": {
+ "type": "str",
+ "choices": [
+ "broadcast",
+ "non-broadcast",
+ "point-to-multipoint",
+ "point-to-point",
+ ],
+ },
+ "nssa": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "default_information_originate": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ },
+ },
+ "no_redistribution": {"type": "bool"},
+ "no_summary": {"type": "bool"},
+ "translate": {
+ "type": "dict",
+ "options": {
+ "type7": {
+ "type": "dict",
+ "options": {
+ "always": {
+ "type": "bool",
+ "required": True,
+ }
+ },
+ }
+ },
+ },
+ },
+ },
+ "packet_size": {"type": "int"},
+ "passive": {"type": "bool"},
+ "prefix_suppression": {"type": "bool"},
+ "priority": {"type": "int"},
+ "ranges": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "address": {
+ "type": "str",
+ "required": True,
+ },
+ "cost": {"type": "int"},
+ "advertise": {"type": "bool"},
+ "not_advertise": {"type": "bool"},
+ },
+ },
+ "retransmit_interval": {"type": "int"},
+ "stub": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "no_summary": {"type": "bool"},
+ },
+ },
+ "transmit_delay": {"type": "int"},
+ "virtual_link": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "id": {
+ "type": "str",
+ "required": True,
+ },
+ "authentication": {
+ "type": "dict",
+ "options": {
+ "disable": {
+ "type": "bool",
+ "default": False,
+ },
+ "ipsec": {
+ "type": "dict",
+ "options": {
+ "spi": {"type": "int"},
+ "algorithim_type": {
+ "type": "str",
+ "choices": [
+ "md5",
+ "sha1",
+ ],
+ },
+ "key": {"type": "str"},
+ "clear_key": {
+ "type": "str"
+ },
+ "password_key": {
+ "type": "str"
+ },
+ },
+ },
+ },
+ },
+ "dead_interval": {"type": "int"},
+ "hello_interval": {"type": "int"},
+ "retransmit_interval": {"type": "int"},
+ "transmit_delay": {"type": "int"},
+ "encryption": {
+ "type": "dict",
+ "options": {
+ "disable": {
+ "type": "bool",
+ "default": False,
+ },
+ "ipsec": {
+ "type": "dict",
+ "options": {
+ "spi": {"type": "int"},
+ "esp": {
+ "type": "dict",
+ "options": {
+ "triple_des": {
+ "type": "dict",
+ "options": {
+ "key": {
+ "type": "str"
+ },
+ "clear_key": {
+ "type": "str"
+ },
+ "password_key": {
+ "type": "str"
+ },
+ },
+ },
+ "aes": {
+ "type": "dict",
+ "options": {
+ "algorithim_type": {
+ "type": "str",
+ "choices": [
+ "192",
+ "256",
+ ],
+ },
+ "key": {
+ "type": "str"
+ },
+ "clear_key": {
+ "type": "str"
+ },
+ "password_key": {
+ "type": "str"
+ },
+ },
+ },
+ "des": {
+ "type": "dict",
+ "options": {
+ "key": {
+ "type": "str"
+ },
+ "clear_key": {
+ "type": "str"
+ },
+ "password_key": {
+ "type": "str"
+ },
+ },
+ },
+ "null_encryption": {
+ "type": "dict",
+ "options": {
+ "authentication": {
+ "type": "dict",
+ "options": {
+ "algorithim_type": {
+ "type": "str",
+ "choices": [
+ "md5",
+ "sha1",
+ ],
+ },
+ "key": {
+ "type": "str"
+ },
+ "clear_key": {
+ "type": "str"
+ },
+ "password_key": {
+ "type": "str"
+ },
+ },
+ }
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "encryption": {
+ "type": "dict",
+ "options": {
+ "disable": {
+ "type": "bool",
+ "default": False,
+ },
+ "ipsec": {
+ "type": "dict",
+ "options": {
+ "spi": {"type": "int"},
+ "esp": {
+ "type": "dict",
+ "options": {
+ "triple_des": {
+ "type": "dict",
+ "options": {
+ "key": {
+ "type": "str"
+ },
+ "clear_key": {
+ "type": "str"
+ },
+ "password_key": {
+ "type": "str"
+ },
+ },
+ },
+ "aes": {
+ "type": "dict",
+ "options": {
+ "algorithim_type": {
+ "type": "str",
+ "choices": [
+ "192",
+ "256",
+ ],
+ },
+ "key": {
+ "type": "str"
+ },
+ "clear_key": {
+ "type": "str"
+ },
+ "password_key": {
+ "type": "str"
+ },
+ },
+ },
+ "des": {
+ "type": "dict",
+ "options": {
+ "key": {
+ "type": "str"
+ },
+ "clear_key": {
+ "type": "str"
+ },
+ "password_key": {
+ "type": "str"
+ },
+ },
+ },
+ "null_encryption": {
+ "type": "dict",
+ "options": {
+ "authentication": {
+ "type": "dict",
+ "options": {
+ "algorithim_type": {
+ "type": "str",
+ "choices": [
+ "md5",
+ "sha1",
+ ],
+ },
+ "key": {
+ "type": "str"
+ },
+ "clear_key": {
+ "type": "str"
+ },
+ "password_key": {
+ "type": "str"
+ },
+ },
+ }
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "capability": {
+ "type": "dict",
+ "options": {
+ "type7": {
+ "type": "dict",
+ "options": {
+ "prefer": {"type": "bool"},
+ "translate": {"type": "bool"},
+ },
+ }
+ },
+ },
+ "cost": {"type": "int"},
+ "database_filter": {
+ "type": "dict",
+ "options": {"all_outgoing_lsa": {"type": "bool"}},
+ },
+ "dead_interval": {"type": "int"},
+ "default_information_originate": {
+ "type": "dict",
+ "options": {
+ "always": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ "set": {"type": "bool"},
+ },
+ },
+ "default_metric": {"type": "int"},
+ "demand_circuit": {"type": "bool"},
+ "distance": {
+ "type": "dict",
+ "options": {
+ "admin_distance": {"type": "int"},
+ "ospfv3_distance": {
+ "type": "dict",
+ "options": {
+ "external": {"type": "int"},
+ "inter_area": {"type": "int"},
+ "intra_area": {"type": "int"},
+ },
+ },
+ },
+ },
+ "distribute_list": {
+ "type": "dict",
+ "options": {
+ "prefix_list": {
+ "type": "list",
+ "elements": "str",
+ "options": {
+ "name": {"type": "str"},
+ "in": {"type": "bool"},
+ "out": {"type": "bool"},
+ },
+ }
+ },
+ },
+ "encryption": {
+ "type": "dict",
+ "options": {
+ "disable": {"type": "bool", "default": False},
+ "ipsec": {
+ "type": "dict",
+ "options": {
+ "spi": {"type": "int"},
+ "esp": {
+ "type": "dict",
+ "options": {
+ "triple_des": {
+ "type": "dict",
+ "options": {
+ "key": {"type": "str"},
+ "clear_key": {
+ "type": "str"
+ },
+ "password_key": {
+ "type": "str"
+ },
+ },
+ },
+ "aes": {
+ "type": "dict",
+ "options": {
+ "algorithim_type": {
+ "type": "str",
+ "choices": [
+ "192",
+ "256",
+ ],
+ },
+ "key": {"type": "str"},
+ "clear_key": {
+ "type": "str"
+ },
+ "password_key": {
+ "type": "str"
+ },
+ },
+ },
+ "des": {
+ "type": "dict",
+ "options": {
+ "key": {"type": "str"},
+ "clear_key": {
+ "type": "str"
+ },
+ "password_key": {
+ "type": "str"
+ },
+ },
+ },
+ "null_encryption": {
+ "type": "dict",
+ "options": {
+ "authentication": {
+ "type": "dict",
+ "options": {
+ "algorithim_type": {
+ "type": "str",
+ "choices": [
+ "md5",
+ "sha1",
+ ],
+ },
+ "key": {
+ "type": "str"
+ },
+ "clear_key": {
+ "type": "str"
+ },
+ "password_key": {
+ "type": "str"
+ },
+ },
+ }
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "fast_reroute": {
+ "type": "dict",
+ "options": {
+ "disabled": {"type": "bool"},
+ "per_link": {
+ "type": "dict",
+ "options": {
+ "information_type": {
+ "type": "str",
+ "choices": [
+ "exclude",
+ "lfa_candidate",
+ ],
+ },
+ "use_candidate_only": {"type": "bool"},
+ "interface": {
+ "type": "dict",
+ "options": {
+ "bvi": {
+ "type": "list",
+ "elements": "int",
+ },
+ "bundle_ether": {
+ "type": "list",
+ "elements": "int",
+ },
+ "pos_int": {
+ "type": "list",
+ "elements": "int",
+ },
+ "fast_ethernet": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fiftygige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fortygige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fourhundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "gigabitethernet": {
+ "type": "list",
+ "elements": "str",
+ },
+ "hundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "mgmteth": {
+ "type": "list",
+ "elements": "str",
+ },
+ "multilink": {
+ "type": "list",
+ "elements": "str",
+ },
+ "pw_ether": {
+ "type": "list",
+ "elements": "int",
+ },
+ "pw_iw": {
+ "type": "list",
+ "elements": "int",
+ },
+ "srp": {
+ "type": "list",
+ "elements": "str",
+ },
+ "serial": {
+ "type": "list",
+ "elements": "str",
+ },
+ "tengige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "twentyfivegige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "twohundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "nve": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_ip": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_ipsec": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_mte": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_mpls": {"type": "int"},
+ },
+ },
+ },
+ },
+ "per_prefix": {
+ "type": "dict",
+ "options": {
+ "information_type": {
+ "type": "str",
+ "choices": [
+ "exclude",
+ "lfa_candidate",
+ ],
+ },
+ "use_candidate_only": {"type": "bool"},
+ "interface": {
+ "type": "dict",
+ "options": {
+ "bvi": {
+ "type": "list",
+ "elements": "int",
+ },
+ "bundle_ether": {
+ "type": "list",
+ "elements": "int",
+ },
+ "post_int": {
+ "type": "list",
+ "elements": "int",
+ },
+ "fast_ethernet": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fiftygige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fortygige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fourhundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "gigabitethernet": {
+ "type": "list",
+ "elements": "str",
+ },
+ "hundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "mgmteth": {
+ "type": "list",
+ "elements": "str",
+ },
+ "multilink": {
+ "type": "list",
+ "elements": "str",
+ },
+ "pw_ether": {
+ "type": "list",
+ "elements": "int",
+ },
+ "pw_iw": {
+ "type": "list",
+ "elements": "int",
+ },
+ "srp": {
+ "type": "list",
+ "elements": "str",
+ },
+ "serial": {
+ "type": "list",
+ "elements": "str",
+ },
+ "tengige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "twentyfivegige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "twohundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "nve": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_ip": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_ipsec": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_mte": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_mpls": {"type": "int"},
+ },
+ },
+ },
+ },
+ },
+ },
+ "flood_reduction": {"type": "bool"},
+ "graceful_restart": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "helper_disable": {"type": "bool"},
+ "min_interval": {"type": "int"},
+ "max_interval": {"type": "int"},
+ },
+ },
+ "hello_interval": {"type": "int"},
+ "ignore_mospf_type6_lsa": {"type": "bool"},
+ "instance_id": {"type": "int"},
+ "log_adjacency_changes": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "disable": {"type": "bool"},
+ "detail": {"type": "bool"},
+ },
+ },
+ "maximum": {
+ "type": "dict",
+ "options": {
+ "interfaces": {"type": "int"},
+ "paths": {"type": "int"},
+ "redistributed_prefixes": {"type": "int"},
+ },
+ },
+ "mpls_ldp_sync": {"type": "bool"},
+ "mtu_ignore": {"type": "bool"},
+ "network": {
+ "type": "str",
+ "choices": [
+ "broadcast",
+ "non-broadcast",
+ "point-to-multipoint",
+ "point-to-point",
+ ],
+ },
+ "nsr": {"type": "bool"},
+ "packet_size": {"type": "int"},
+ "passive": {"type": "bool"},
+ "prefix_suppression": {"type": "bool"},
+ "priority": {"type": "int"},
+ "protocol_shutdown": {"type": "bool"},
+ "redistribute": {
+ "type": "dict",
+ "options": {
+ "application": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "id": {
+ "type": "str",
+ "required": True,
+ },
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ "bgp": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "id": {
+ "type": "int",
+ "required": True,
+ },
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "preserved_med": {"type": "str"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ "connected": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ "eigrp": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "id": {
+ "type": "int",
+ "required": True,
+ },
+ "set": {"type": "bool"},
+ "match": {
+ "type": "str",
+ "choices": [
+ "external",
+ "internal",
+ ],
+ },
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ "isis": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "id": {
+ "type": "str",
+ "required": True,
+ },
+ "set": {"type": "bool"},
+ "level": {
+ "type": "str",
+ "choices": [
+ "level-1",
+ "level-1-2",
+ "level-2",
+ ],
+ },
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ "mobile": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ "ospfv3": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "id": {
+ "type": "str",
+ "required": True,
+ },
+ "set": {"type": "bool"},
+ "match": {
+ "type": "dict",
+ "options": {
+ "external": {
+ "type": "int",
+ "choices": ["1", "2"],
+ },
+ "nssa_external": {
+ "type": "int",
+ "choices": ["1", "2"],
+ },
+ "internal": {"type": "bool"},
+ },
+ },
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ "static": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ "subscriber": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ },
+ },
+ "retransmit_interval": {"type": "int"},
+ "router_id": {"type": "str"},
+ "spf_prefix_priority": {
+ "type": "dict",
+ "options": {
+ "disable": {"type": "bool"},
+ "route_policy": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "value": {"type": "str"},
+ },
+ },
+ },
+ },
+ "stub_router": {
+ "type": "dict",
+ "options": {
+ "router_lsa": {
+ "type": "dict",
+ "options": {
+ "advertise_with": {
+ "type": "str",
+ "choices": [
+ "max-metric",
+ "r-bit",
+ "v6-bit",
+ ],
+ },
+ "always": {"type": "bool"},
+ "external_lsa": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ },
+ },
+ "include_stub": {"type": "bool"},
+ "on_proc_migration": {"type": "int"},
+ "on_proc_restart": {"type": "int"},
+ "on_startup": {
+ "type": "dict",
+ "options": {
+ "time": {"type": "int"},
+ "wait_for_bgp": {
+ "type": "bool"
+ },
+ },
+ },
+ "on_switchover": {"type": "int"},
+ "summary_lsa": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ },
+ },
+ },
+ }
+ },
+ },
+ "summary_prefix": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "prefix": {"type": "str", "required": True},
+ "not_advertise": {"type": "bool"},
+ "tag": {"type": "int"},
+ },
+ },
+ "timers": {
+ "type": "dict",
+ "options": {
+ "lsa_arrival": {"type": "int"},
+ "pacing": {
+ "type": "dict",
+ "options": {
+ "flood": {"type": "int"},
+ "lsa_group": {"type": "int"},
+ "retransmission": {"type": "int"},
+ },
+ },
+ "throttle": {
+ "type": "dict",
+ "options": {
+ "lsa": {
+ "type": "dict",
+ "options": {
+ "all_lsa_initial": {
+ "type": "int"
+ },
+ "all_lsa_minimum": {
+ "type": "int"
+ },
+ },
+ },
+ "spf": {
+ "type": "dict",
+ "options": {
+ "spf_initial": {"type": "int"},
+ "spf_minimum": {"type": "int"},
+ },
+ },
+ },
+ },
+ },
+ },
+ "trace": {
+ "type": "dict",
+ "options": {
+ "size": {"type": "str"},
+ "value": {"type": "int"},
+ },
+ },
+ "transmit_delay": {"type": "int"},
+ },
+ }
+ },
+ },
+ "state": {
+ "type": "str",
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "rendered",
+ "parsed",
+ ],
+ "default": "merged",
+ },
+ } # pylint: disable=C0301
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/static_routes/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/static_routes/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/static_routes/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/static_routes/static_routes.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/static_routes/static_routes.py
new file mode 100644
index 00000000..362477b5
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/static_routes/static_routes.py
@@ -0,0 +1,103 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_static_routes module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+class Static_routesArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_static_routes module
+ """
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "elements": "dict",
+ "options": {
+ "vrf": {"type": "str"},
+ "address_families": {
+ "elements": "dict",
+ "options": {
+ "afi": {
+ "choices": ["ipv4", "ipv6"],
+ "required": True,
+ "type": "str",
+ },
+ "safi": {
+ "choices": ["unicast", "multicast"],
+ "required": True,
+ "type": "str",
+ },
+ "routes": {
+ "elements": "dict",
+ "options": {
+ "dest": {"required": True, "type": "str"},
+ "next_hops": {
+ "elements": "dict",
+ "options": {
+ "admin_distance": {"type": "int"},
+ "description": {"type": "str"},
+ "dest_vrf": {"type": "str"},
+ "forward_router_address": {
+ "type": "str"
+ },
+ "interface": {"type": "str"},
+ "metric": {"type": "int"},
+ "tag": {"type": "int"},
+ "track": {"type": "str"},
+ "tunnel_id": {"type": "int"},
+ "vrflabel": {"type": "int"},
+ },
+ "type": "list",
+ },
+ },
+ "type": "list",
+ },
+ },
+ "type": "list",
+ },
+ },
+ "type": "list",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "rendered",
+ "parsed",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acl_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acl_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acl_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acl_interfaces/acl_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acl_interfaces/acl_interfaces.py
new file mode 100644
index 00000000..924abba2
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acl_interfaces/acl_interfaces.py
@@ -0,0 +1,126 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_acl_interfaces class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.acl_interfaces import (
+ Acl_interfacesTemplate,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ dict_merge,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import (
+ Facts,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.resource_module import (
+ ResourceModule,
+)
+
+
+class Acl_interfaces(ResourceModule):
+ """
+ The iosxr_acl_interfaces class
+ """
+
+ def __init__(self, module):
+ super(Acl_interfaces, self).__init__(
+ empty_fact_val={},
+ facts_module=Facts(module),
+ module=module,
+ resource="acl_interfaces",
+ tmplt=Acl_interfacesTemplate(),
+ )
+
+ def execute_module(self):
+ """ Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ if self.state not in ["parsed", "gathered"]:
+ self.gen_config()
+ self.run_commands()
+ return self.result
+
+ def gen_config(self):
+ """ Select the appropriate function based on the state provided
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ # convert list of dicts to dicts of dicts
+ wantd = {entry["name"]: entry for entry in self.want}
+ haved = {entry["name"]: entry for entry in self.have}
+
+ # turn all lists of dicts into dicts prior to merge
+ for entry in wantd, haved:
+ self._list_to_dict(entry)
+
+ # if state is merged, merge want onto have and then compare
+ if self.state == "merged":
+ wantd = dict_merge(haved, wantd)
+
+ # if state is deleted, empty out wantd and set haved to wantd
+ if self.state == "deleted":
+ haved = {k: v for k, v in haved.items() if k in wantd or not wantd}
+ wantd = {}
+
+ # remove superfluous config
+ if self.state in ["overridden", "deleted"]:
+ for k, have in haved.items():
+ if k not in wantd:
+ self._compare(want={}, have=have)
+
+ for k, want in wantd.items():
+ self._compare(want=want, have=haved.pop(k, {}))
+
+ def _compare(self, want, have):
+ begin = len(self.commands)
+ self._compare_lists(want=want, have=have)
+ if len(self.commands) != begin:
+ self.commands.insert(
+ begin, self._tmplt.render(want or have, "interface", False)
+ )
+
+ def _compare_lists(self, want, have):
+ wdict = want.get("access_groups", {})
+ hdict = have.get("access_groups", {})
+
+ for afi in ("ipv4", "ipv6"):
+ wacls = wdict.pop(afi, {}).pop("acls", {})
+ hacls = hdict.pop(afi, {}).pop("acls", {})
+
+ for key, entry in wacls.items():
+ if entry != hacls.pop(key, {}):
+ entry["afi"] = afi
+ self.addcmd(entry, "access_groups", False)
+ # remove remaining items in have for replaced
+ for entry in hacls.values():
+ entry["afi"] = afi
+ self.addcmd(entry, "access_groups", True)
+
+ def _list_to_dict(self, entry):
+ for item in entry.values():
+ for ag in item.get("access_groups", []):
+ ag["acls"] = {
+ subentry["direction"]: subentry
+ for subentry in ag.get("acls", [])
+ }
+ item["access_groups"] = {
+ subentry["afi"]: subentry
+ for subentry in item.get("access_groups", [])
+ }
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/acls.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/acls.py
new file mode 100644
index 00000000..c07b3b3e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/acls.py
@@ -0,0 +1,518 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_acls class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import (
+ ConfigBase,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ flatten_dict,
+ prefix_to_address_wildcard,
+ is_ipv4_address,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ to_list,
+ search_obj_in_list,
+ dict_diff,
+ remove_empties,
+)
+from ansible.module_utils.six import iteritems
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import (
+ Facts,
+)
+
+
+class Acls(ConfigBase):
+ """
+ The iosxr_acls class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["acls"]
+
+ def __init__(self, module):
+ super(Acls, self).__init__(module)
+
+ def get_acls_facts(self, data=None):
+ """ Get the 'facts' (the current configuration)
+
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset, self.gather_network_resources, data=data
+ )
+ acls_facts = facts["ansible_network_resources"].get("acls")
+ if not acls_facts:
+ return []
+ return acls_facts
+
+ def execute_module(self):
+ """ Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_acls_facts = self.get_acls_facts()
+ else:
+ existing_acls_facts = []
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_acls_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_acls_facts = self.get_acls_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed"
+ )
+ result["parsed"] = self.get_acls_facts(data=running_config)
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_acls_facts
+ if result["changed"]:
+ result["after"] = changed_acls_facts
+
+ elif self.state == "gathered":
+ result["gathered"] = changed_acls_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_acls_facts):
+ """ Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ have = existing_acls_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """ Select the appropriate function based on the state provided
+
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ state = self._module.params["state"]
+ commands = []
+
+ if (
+ state in ("overridden", "merged", "replaced", "rendered")
+ and not want
+ ):
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ state
+ )
+ )
+
+ if state == "overridden":
+ commands.extend(self._state_overridden(want, have))
+
+ elif state == "deleted":
+ commands.extend(self._state_deleted(want, have))
+
+ else:
+ # Instead of passing entire want and have
+ # list of dictionaries to the respective
+ # _state_* methods we are passing the want
+ # and have dictionaries per AFI
+ for item in want:
+ afi = item["afi"]
+ obj_in_have = search_obj_in_list(afi, have, key="afi") or {}
+
+ if state == "merged" or self.state == "rendered":
+ commands.extend(
+ self._state_merged(remove_empties(item), obj_in_have)
+ )
+
+ elif state == "replaced":
+ commands.extend(
+ self._state_replaced(remove_empties(item), obj_in_have)
+ )
+
+ return commands
+
+ def _state_replaced(self, want, have):
+ """ The command generator when state is replaced
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ for want_acl in want["acls"]:
+ have_acl = (
+ search_obj_in_list(want_acl["name"], have.get("acls", []))
+ or {}
+ )
+ acl_updates = []
+
+ for have_ace in have_acl.get("aces", []):
+ want_ace = (
+ search_obj_in_list(
+ have_ace["sequence"], want_acl["aces"], key="sequence"
+ )
+ or {}
+ )
+ if not want_ace:
+ acl_updates.append("no {0}".format(have_ace["sequence"]))
+
+ for want_ace in want_acl.get("aces", []):
+ have_ace = (
+ search_obj_in_list(
+ want_ace.get("sequence"),
+ have_acl.get("aces", []),
+ key="sequence",
+ )
+ or {}
+ )
+ set_cmd = self._set_commands(want_ace, have_ace)
+ if set_cmd:
+ acl_updates.append(set_cmd)
+
+ if acl_updates:
+ acl_updates.insert(
+ 0,
+ "{0} access-list {1}".format(
+ want["afi"], want_acl["name"]
+ ),
+ )
+ commands.extend(acl_updates)
+
+ return commands
+
+ def _state_overridden(self, want, have):
+ """ The command generator when state is overridden
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ # Remove extraneous AFI that are present in config but not
+ # specified in `want`
+ for have_afi in have:
+ want_afi = (
+ search_obj_in_list(have_afi["afi"], want, key="afi") or {}
+ )
+ if not want_afi:
+ for acl in have_afi.get("acls", []):
+ commands.append(
+ "no {0} access-list {1}".format(
+ have_afi["afi"], acl["name"]
+ )
+ )
+
+ # First we remove the extraneous ACLs from the AFIs that
+ # are present both in `want` and in `have` and then
+ # we call `_state_replaced` to update the ACEs within those ACLs
+ for want_afi in want:
+ want_afi = remove_empties(want_afi)
+ have_afi = (
+ search_obj_in_list(want_afi["afi"], have, key="afi") or {}
+ )
+ if have_afi:
+ for have_acl in have_afi.get("acls", []):
+ want_acl = (
+ search_obj_in_list(
+ have_acl["name"], want_afi.get("acls", [])
+ )
+ or {}
+ )
+ if not want_acl:
+ commands.append(
+ "no {0} access-list {1}".format(
+ have_afi["afi"], have_acl["name"]
+ )
+ )
+
+ commands.extend(self._state_replaced(want_afi, have_afi))
+
+ return commands
+
+ def _state_merged(self, want, have):
+ """ The command generator when state is merged
+
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+ if not have:
+ have = {}
+
+ for want_acl in want["acls"]:
+ have_acl = (
+ search_obj_in_list(want_acl["name"], have.get("acls", {}))
+ or {}
+ )
+
+ acl_updates = []
+ for want_ace in want_acl["aces"]:
+ have_ace = (
+ search_obj_in_list(
+ want_ace.get("sequence"),
+ have_acl.get("aces", []),
+ key="sequence",
+ )
+ or {}
+ )
+ set_cmd = self._set_commands(want_ace, have_ace)
+ if set_cmd:
+ acl_updates.append(set_cmd)
+
+ if acl_updates:
+ acl_updates.insert(
+ 0,
+ "{0} access-list {1}".format(
+ want["afi"], want_acl["name"]
+ ),
+ )
+ commands.extend(acl_updates)
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """ The command generator when state is deleted
+
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+
+ if not want:
+ want = [{"afi": "ipv4"}, {"afi": "ipv6"}]
+
+ for item in want:
+ item = remove_empties(item)
+ have_item = search_obj_in_list(item["afi"], have, key="afi") or {}
+ if "acls" not in item:
+ if have_item:
+ for acl in have_item["acls"]:
+ commands.append(
+ "no {0} access-list {1}".format(
+ have_item["afi"], acl["name"]
+ )
+ )
+ else:
+ for want_acl in item["acls"]:
+ have_acl = (
+ search_obj_in_list(
+ want_acl["name"], have_item.get("acls", [])
+ )
+ or {}
+ )
+ if have_acl:
+ commands.append(
+ "no {0} access-list {1}".format(
+ have_item["afi"], have_acl["name"]
+ )
+ )
+
+ return commands
+
+ def _compute_commands(self, want_ace):
+ """This command creates an ACE line from an ACE dictionary
+
+ :rtype: A string
+ :returns: An ACE generated from a structured ACE dictionary
+ """
+
+ def __compute_src_dest(dir_dict):
+ cmd = ""
+ if "any" in dir_dict:
+ cmd += "any "
+ elif "host" in dir_dict:
+ cmd += "host {0} ".format(dir_dict["host"])
+ elif "prefix" in dir_dict:
+ cmd += "{0} ".format(dir_dict["prefix"])
+ else:
+ cmd += "{0} {1} ".format(
+ dir_dict["address"], dir_dict["wildcard_bits"]
+ )
+
+ if "port_protocol" in dir_dict:
+ protocol_range = dir_dict["port_protocol"].get("range")
+ if protocol_range:
+ cmd += "range {0} {1} ".format(
+ protocol_range["start"], protocol_range["end"]
+ )
+ else:
+ for key, value in iteritems(dir_dict["port_protocol"]):
+ cmd += "{0} {1} ".format(key, value)
+
+ return cmd
+
+ def __compute_protocol_options(protocol_dict):
+ cmd = ""
+ for value in protocol_options.values():
+ for subkey, subvalue in iteritems(value):
+ if subvalue:
+ cmd += "{0} ".format(subkey.replace("_", "-"))
+ return cmd
+
+ def __compute_match_options(want_ace):
+ cmd = ""
+
+ if "precedence" in want_ace:
+ cmd += "precedence {0} ".format(want_ace["precedence"])
+
+ for x in ["dscp", "packet_length", "ttl"]:
+ if x in want_ace:
+ opt_range = want_ace[x].get("range")
+ if opt_range:
+ cmd += "{0} range {1} {2} ".format(
+ x.replace("_", "-"),
+ opt_range["start"],
+ opt_range["end"],
+ )
+ else:
+ for key, value in iteritems(want_ace[x]):
+ cmd += "{0} {1} {2} ".format(
+ x.replace("_", "-"), key, value
+ )
+
+ for x in (
+ "authen",
+ "capture",
+ "fragments",
+ "routing",
+ "log",
+ "log_input",
+ "icmp_off",
+ "destopts",
+ "hop_by_hop",
+ ):
+ if x in want_ace:
+ cmd += "{0} ".format(x.replace("_", "-"))
+
+ return cmd
+
+ cmd = ""
+ if "sequence" in want_ace:
+ cmd += "{0} ".format(want_ace["sequence"])
+
+ if "remark" in want_ace:
+ cmd += "remark {0}".format(want_ace["remark"])
+
+ elif "line" in want_ace:
+ cmd += want_ace["line"]
+
+ else:
+ cmd += "{0} ".format(want_ace["grant"])
+ if "protocol" in want_ace:
+ cmd += "{0} ".format(want_ace["protocol"])
+
+ cmd += __compute_src_dest(want_ace["source"])
+ cmd += __compute_src_dest(want_ace["destination"])
+
+ protocol_options = want_ace.get("protocol_options", {})
+ if protocol_options:
+ cmd += __compute_protocol_options(protocol_options)
+
+ cmd += __compute_match_options(want_ace)
+
+ return cmd.strip()
+
+ def _set_commands(self, want_ace, have_ace):
+ """A helped method that checks if there is
+ a delta between the `have_ace` and `want_ace`.
+ If there is a delta then it calls `_compute_commands`
+ to create the ACE line.
+
+ :rtype: A string
+ :returns: An ACE generated from a structured ACE dictionary
+ via a call to `_compute_commands`
+ """
+
+ if "line" in want_ace:
+ if want_ace["line"] != have_ace.get("line"):
+ return self._compute_commands(want_ace)
+
+ else:
+ if ("prefix" in want_ace.get("source", {})) or (
+ "prefix" in want_ace.get("destination", {})
+ ):
+ self._prepare_for_diff(want_ace)
+
+ protocol_opt_delta = {}
+ delta = dict_diff(have_ace, want_ace)
+
+ # `dict_diff` doesn't work properly for `protocol_options` diff,
+ # so we need to handle it separately
+ if want_ace.get("protocol_options", {}):
+ protocol_opt_delta = set(
+ flatten_dict(have_ace.get("protocol_options", {}))
+ ) ^ set(flatten_dict(want_ace.get("protocol_options", {})))
+
+ if delta or protocol_opt_delta:
+ want_ace = self._dict_merge(have_ace, want_ace)
+ return self._compute_commands(want_ace)
+
+ def _prepare_for_diff(self, ace):
+ """This method prepares the want ace dict
+ for diff calculation against the have ace dict.
+
+ :param ace: The want ace to prepare for diff calculation
+ """
+ # Convert prefixes to "address wildcard bits" format for IPv4 addresses
+ # Not valid for IPv6 addresses because those can only be specified as prefixes
+ # and are always rendered in running-config as prefixes too
+ for x in ["source", "destination"]:
+ prefix = ace.get(x, {}).get("prefix")
+ if prefix and is_ipv4_address(prefix):
+ del ace[x]["prefix"]
+ ace[x]["address"], ace[x][
+ "wildcard_bits"
+ ] = prefix_to_address_wildcard(prefix)
+
+ def _dict_merge(self, have_ace, want_ace):
+ for x in want_ace:
+ have_ace[x] = want_ace[x]
+ return have_ace
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/interfaces.py
new file mode 100644
index 00000000..ce3534b5
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/interfaces.py
@@ -0,0 +1,327 @@
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat Inc.
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_interfaces class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+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,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import (
+ Facts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ get_interface_type,
+ dict_to_set,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ remove_command_from_config_list,
+ add_command_to_config_list,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ filter_dict_having_none_value,
+ remove_duplicate_interface,
+)
+
+
+class Interfaces(ConfigBase):
+ """
+ The iosxr_interfaces class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["interfaces"]
+
+ params = ("description", "mtu", "speed", "duplex")
+
+ def __init__(self, module):
+ super(Interfaces, self).__init__(module)
+
+ def get_interfaces_facts(self, data=None):
+ """ Get the 'facts' (the current configuration)
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset, self.gather_network_resources, data=data
+ )
+ interfaces_facts = facts["ansible_network_resources"].get("interfaces")
+ if not interfaces_facts:
+ return []
+ return interfaces_facts
+
+ def execute_module(self):
+ """ Execute the module
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_interfaces_facts = self.get_interfaces_facts()
+ else:
+ existing_interfaces_facts = []
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_interfaces_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_interfaces_facts = self.get_interfaces_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed"
+ )
+ result["parsed"] = self.get_interfaces_facts(data=running_config)
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_interfaces_facts
+ if result["changed"]:
+ result["after"] = changed_interfaces_facts
+
+ elif self.state == "gathered":
+ result["gathered"] = changed_interfaces_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_interfaces_facts):
+ """ Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ have = existing_interfaces_facts
+ resp = self.set_state(want, have)
+
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """ Select the appropriate function based on the state provided
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ if (
+ self.state in ("overridden", "merged", "replaced", "rendered")
+ and not want
+ ):
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ self.state
+ )
+ )
+
+ if self.state == "overridden":
+ commands = self._state_overridden(want, have)
+ elif self.state == "deleted":
+ commands = self._state_deleted(want, have)
+ elif self.state in ("merged", "rendered"):
+ commands = self._state_merged(want, have)
+ elif self.state == "replaced":
+ commands = self._state_replaced(want, have)
+
+ return commands
+
+ def _state_replaced(self, want, have):
+ """ The command generator when state is replaced
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ for interface in want:
+ for each in have:
+ if (
+ each["name"] == interface["name"]
+ or interface["name"] in each["name"]
+ ):
+ break
+ else:
+ continue
+ have_dict = filter_dict_having_none_value(interface, each)
+ want = dict()
+ commands.extend(self._clear_config(want, have_dict))
+ commands.extend(self._set_config(interface, each))
+ # Remove the duplicate interface call
+ commands = remove_duplicate_interface(commands)
+
+ return commands
+
+ def _state_overridden(self, want, have):
+ """ The command generator when state is overridden
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ for each in have:
+ for interface in want:
+ if (
+ each["name"] == interface["name"]
+ or interface["name"] in each["name"]
+ ):
+ break
+ else:
+ # We didn't find a matching desired state, which means we can
+ # pretend we received an empty desired state.
+ interface = dict(name=each["name"])
+ commands.extend(self._clear_config(interface, each))
+ continue
+ have_dict = filter_dict_having_none_value(interface, each)
+ want = dict()
+ commands.extend(self._clear_config(want, have_dict))
+ commands.extend(self._set_config(interface, each))
+ # Remove the duplicate interface call
+ commands = remove_duplicate_interface(commands)
+
+ return commands
+
+ def _state_merged(self, want, have):
+ """ The command generator when state is merged
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+
+ for interface in want:
+ if self.state == "rendered":
+ commands.extend(self._set_config(interface, dict()))
+ else:
+ for each in have:
+ if (
+ each["name"] == interface["name"]
+ or interface["name"] in each["name"]
+ ):
+ break
+ else:
+ continue
+ commands.extend(self._set_config(interface, each))
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """ The command generator when state is deleted
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+
+ if want:
+ for interface in want:
+ for each in have:
+ if (
+ each["name"] == interface["name"]
+ or interface["name"] in each["name"]
+ ):
+ break
+ else:
+ continue
+ interface = dict(name=interface["name"])
+ commands.extend(self._clear_config(interface, each))
+ else:
+ for each in have:
+ want = dict()
+ commands.extend(self._clear_config(want, each))
+
+ return commands
+
+ def _set_config(self, want, have):
+ # Set the interface config based on the want and have config
+ commands = []
+ interface = "interface " + want["name"]
+
+ # Get the diff b/w want and have
+ want_dict = dict_to_set(want)
+ have_dict = dict_to_set(have)
+ diff = want_dict - have_dict
+
+ if diff:
+ diff = dict(diff)
+ for item in self.params:
+ if diff.get(item):
+ cmd = item + " " + str(want.get(item))
+ add_command_to_config_list(interface, cmd, commands)
+ if diff.get("enabled"):
+ add_command_to_config_list(interface, "no shutdown", commands)
+ elif diff.get("enabled") is False:
+ add_command_to_config_list(interface, "shutdown", commands)
+
+ return commands
+
+ def _clear_config(self, want, have):
+ # Delete the interface config based on the want and have config
+ commands = []
+
+ if want.get("name"):
+ interface_type = get_interface_type(want["name"])
+ interface = "interface " + want["name"]
+ else:
+ interface_type = get_interface_type(have["name"])
+ interface = "interface " + have["name"]
+
+ if have.get("description") and want.get("description") != have.get(
+ "description"
+ ):
+ remove_command_from_config_list(interface, "description", commands)
+ if not have.get("enabled") and want.get("enabled") != have.get(
+ "enabled"
+ ):
+ # if enable is False set enable as True which is the default behavior
+ remove_command_from_config_list(interface, "shutdown", commands)
+
+ if interface_type.lower() == "gigabitethernet":
+ if (
+ have.get("speed")
+ and have.get("speed") != "auto"
+ and want.get("speed") != have.get("speed")
+ ):
+ remove_command_from_config_list(interface, "speed", commands)
+ if (
+ have.get("duplex")
+ and have.get("duplex") != "auto"
+ and want.get("duplex") != have.get("duplex")
+ ):
+ remove_command_from_config_list(interface, "duplex", commands)
+ if have.get("mtu") and want.get("mtu") != have.get("mtu"):
+ remove_command_from_config_list(interface, "mtu", commands)
+
+ return commands
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/l2_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/l2_interfaces.py
new file mode 100644
index 00000000..a5596d18
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/l2_interfaces.py
@@ -0,0 +1,373 @@
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat Inc.
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_l2_interfaces class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+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_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import (
+ Facts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ normalize_interface,
+ dict_to_set,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ remove_command_from_config_list,
+ add_command_to_config_list,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ filter_dict_having_none_value,
+ remove_duplicate_interface,
+)
+
+
+class L2_Interfaces(ConfigBase):
+ """
+ The iosxr_interfaces class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["l2_interfaces"]
+
+ def get_l2_interfaces_facts(self, data=None):
+ """ Get the 'facts' (the current configuration)
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset, self.gather_network_resources, data=data
+ )
+ l2_interfaces_facts = facts["ansible_network_resources"].get(
+ "l2_interfaces"
+ )
+ if not l2_interfaces_facts:
+ return []
+ return l2_interfaces_facts
+
+ def execute_module(self):
+ """ Execute the module
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_l2_interfaces_facts = self.get_l2_interfaces_facts()
+ else:
+ existing_l2_interfaces_facts = []
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_l2_interfaces_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_l2_interfaces_facts = self.get_l2_interfaces_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed"
+ )
+ result["parsed"] = self.get_l2_interfaces_facts(
+ data=running_config
+ )
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_l2_interfaces_facts
+ if result["changed"]:
+ result["after"] = changed_l2_interfaces_facts
+
+ elif self.state == "gathered":
+ result["gathered"] = changed_l2_interfaces_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_l2_interfaces_facts):
+ """ Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ have = existing_l2_interfaces_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """ Select the appropriate function based on the state provided
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ if (
+ self.state in ("overridden", "merged", "replaced", "rendered")
+ and not want
+ ):
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ self.state
+ )
+ )
+
+ if self.state == "overridden":
+ commands = self._state_overridden(want, have, self._module)
+ elif self.state == "deleted":
+ commands = self._state_deleted(want, have)
+ elif self.state in ("merged", "rendered"):
+ commands = self._state_merged(want, have, self._module)
+ elif self.state == "replaced":
+ commands = self._state_replaced(want, have, self._module)
+
+ return commands
+
+ def _state_replaced(self, want, have, module):
+ """ The command generator when state is replaced
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ for interface in want:
+ interface["name"] = normalize_interface(interface["name"])
+ for each in have:
+ if (
+ each["name"] == interface["name"]
+ or interface["name"] in each["name"]
+ ):
+ break
+ else:
+ commands.extend(self._set_config(interface, {}, module))
+ continue
+ interface = remove_empties(interface)
+ have_dict = filter_dict_having_none_value(interface, each)
+ commands.extend(self._clear_config(dict(), have_dict))
+ commands.extend(self._set_config(interface, each, module))
+ # Remove the duplicate interface call
+ commands = remove_duplicate_interface(commands)
+
+ return commands
+
+ def _state_overridden(self, want, have, module):
+ """ The command generator when state is overridden
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ not_in_have = set()
+ in_have = set()
+ for each in have:
+ for interface in want:
+ interface["name"] = normalize_interface(interface["name"])
+ if each["name"] == interface["name"]:
+ in_have.add(interface["name"])
+ break
+ if interface["name"] != each["name"]:
+ not_in_have.add(interface["name"])
+ else:
+ # We didn't find a matching desired state, which means we can
+ # pretend we received an empty desired state.
+ interface = dict(name=each["name"])
+ commands.extend(self._clear_config(interface, each))
+ continue
+ interface = remove_empties(interface)
+ have_dict = filter_dict_having_none_value(interface, each)
+ commands.extend(self._clear_config(dict(), have_dict))
+ commands.extend(self._set_config(interface, each, module))
+ # Add the want interface that's not already configured in have interface
+ for each in not_in_have - in_have:
+ for every in want:
+ interface = "interface {0}".format(every["name"])
+ if each and interface not in commands:
+ commands.extend(self._set_config(every, {}, module))
+
+ # Remove the duplicate interface call
+ commands = remove_duplicate_interface(commands)
+
+ return commands
+
+ def _state_merged(self, want, have, module):
+ """ The command generator when state is merged
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+
+ for interface in want:
+ interface["name"] = normalize_interface(interface["name"])
+ interface = remove_empties(interface)
+ for each in have:
+ if (
+ each["name"] == interface["name"]
+ or interface["name"] in each["name"]
+ ):
+ break
+ else:
+ commands.extend(self._set_config(interface, {}, module))
+ continue
+ commands.extend(self._set_config(interface, each, module))
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """ The command generator when state is deleted
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+
+ if want:
+ for interface in want:
+ interface["name"] = normalize_interface(interface["name"])
+ for each in have:
+ if (
+ each["name"] == interface["name"]
+ or interface["name"] in each["name"]
+ ):
+ break
+ else:
+ continue
+ interface = dict(name=interface["name"])
+ commands.extend(self._clear_config(interface, each))
+ else:
+ for each in have:
+ want = dict()
+ commands.extend(self._clear_config(want, each))
+
+ return commands
+
+ def _set_config(self, want, have, module):
+ # Set the interface config based on the want and have config
+ commands = []
+ interface = "interface " + want["name"]
+ l2_protocol_bool = False
+ # Get the diff b/w want and have
+ want_dict = dict_to_set(want)
+ have_dict = dict_to_set(have)
+ diff = want_dict - have_dict
+
+ if diff:
+ # For merging with already configured l2protocol
+ if have.get("l2protocol") and len(have.get("l2protocol")) > 1:
+ l2_protocol_diff = []
+ for each in want.get("l2protocol"):
+ for every in have.get("l2protocol"):
+ if every == each:
+ break
+ if each not in have.get("l2protocol"):
+ l2_protocol_diff.append(each)
+ l2_protocol_bool = True
+ l2protocol = tuple(l2_protocol_diff)
+ else:
+ l2protocol = {}
+
+ diff = dict(diff)
+ wants_native = diff.get("native_vlan")
+ l2transport = diff.get("l2transport")
+ q_vlan = diff.get("q_vlan")
+ propagate = diff.get("propagate")
+ if l2_protocol_bool is False:
+ l2protocol = diff.get("l2protocol")
+
+ if wants_native:
+ cmd = "dot1q native vlan {0}".format(wants_native)
+ add_command_to_config_list(interface, cmd, commands)
+
+ if l2transport or l2protocol:
+ for each in l2protocol:
+ each = dict(each)
+ if isinstance(each, dict):
+ cmd = "l2transport l2protocol {0} {1}".format(
+ list(each.keys())[0], list(each.values())[0]
+ )
+ add_command_to_config_list(interface, cmd, commands)
+ if propagate and not have.get("propagate"):
+ cmd = "l2transport propagate remote-status"
+ add_command_to_config_list(interface, cmd, commands)
+ elif want.get("l2transport") is False and (
+ want.get("l2protocol") or want.get("propagate")
+ ):
+ module.fail_json(
+ msg="L2transport L2protocol or Propagate can only be configured when "
+ "L2transport set to True!"
+ )
+
+ if q_vlan and "." in interface:
+ q_vlans = " ".join(map(str, want.get("q_vlan")))
+ if q_vlans != have.get("q_vlan"):
+ cmd = "dot1q vlan {0}".format(q_vlans)
+ add_command_to_config_list(interface, cmd, commands)
+
+ return commands
+
+ def _clear_config(self, want, have):
+ # Delete the interface config based on the want and have config
+ commands = []
+
+ if want.get("name"):
+ interface = "interface " + want["name"]
+ else:
+ interface = "interface " + have["name"]
+ if have.get("native_vlan"):
+ remove_command_from_config_list(
+ interface, "dot1q native vlan", commands
+ )
+
+ if have.get("q_vlan"):
+ remove_command_from_config_list(
+ interface, "encapsulation dot1q", commands
+ )
+
+ if have.get("l2protocol") and (
+ want.get("l2protocol") is None or want.get("propagate") is None
+ ):
+ if "no l2transport" not in commands:
+ remove_command_from_config_list(
+ interface, "l2transport", commands
+ )
+ elif have.get("l2transport") and have.get("l2transport") != want.get(
+ "l2transport"
+ ):
+ if "no l2transport" not in commands:
+ remove_command_from_config_list(
+ interface, "l2transport", commands
+ )
+ return commands
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/l3_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/l3_interfaces.py
new file mode 100644
index 00000000..47949a77
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/l3_interfaces.py
@@ -0,0 +1,397 @@
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat Inc.
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_l3_interfaces class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+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,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import (
+ Facts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ normalize_interface,
+ dict_to_set,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ remove_command_from_config_list,
+ add_command_to_config_list,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ filter_dict_having_none_value,
+ remove_duplicate_interface,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ validate_n_expand_ipv4,
+ validate_ipv6,
+)
+
+
+class L3_Interfaces(ConfigBase):
+ """
+ The iosxr_l3_interfaces class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["l3_interfaces"]
+
+ def get_l3_interfaces_facts(self, data=None):
+ """ Get the 'facts' (the current configuration)
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset, self.gather_network_resources, data=data
+ )
+ l3_interfaces_facts = facts["ansible_network_resources"].get(
+ "l3_interfaces"
+ )
+ if not l3_interfaces_facts:
+ return []
+ return l3_interfaces_facts
+
+ def execute_module(self):
+ """ Execute the module
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_l3_interfaces_facts = self.get_l3_interfaces_facts()
+ else:
+ existing_l3_interfaces_facts = []
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_l3_interfaces_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_l3_interfaces_facts = self.get_l3_interfaces_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed"
+ )
+ result["parsed"] = self.get_l3_interfaces_facts(
+ data=running_config
+ )
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_l3_interfaces_facts
+ if result["changed"]:
+ result["after"] = changed_l3_interfaces_facts
+
+ elif self.state == "gathered":
+ result["gathered"] = changed_l3_interfaces_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_l3_interfaces_facts):
+ """ Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ have = existing_l3_interfaces_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """ Select the appropriate function based on the state provided
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ if (
+ self.state in ("overridden", "merged", "replaced", "rendered")
+ and not want
+ ):
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ self.state
+ )
+ )
+
+ if self.state == "overridden":
+ commands = self._state_overridden(want, have, self._module)
+ elif self.state == "deleted":
+ commands = self._state_deleted(want, have)
+ elif self.state in ("merged", "rendered"):
+ commands = self._state_merged(want, have, self._module)
+ elif self.state == "replaced":
+ commands = self._state_replaced(want, have, self._module)
+
+ return commands
+
+ def _state_replaced(self, want, have, module):
+ """ The command generator when state is replaced
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ for interface in want:
+ interface["name"] = normalize_interface(interface["name"])
+ for each in have:
+ if each["name"] == interface["name"]:
+ break
+ else:
+ commands.extend(self._set_config(interface, dict(), module))
+ continue
+ have_dict = filter_dict_having_none_value(interface, each)
+ commands.extend(self._clear_config(dict(), have_dict))
+ commands.extend(self._set_config(interface, each, module))
+ # Remove the duplicate interface call
+ commands = remove_duplicate_interface(commands)
+
+ return commands
+
+ def _state_overridden(self, want, have, module):
+ """ The command generator when state is overridden
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ not_in_have = set()
+ in_have = set()
+
+ for each in have:
+ for interface in want:
+ interface["name"] = normalize_interface(interface["name"])
+ if each["name"] == interface["name"]:
+ in_have.add(interface["name"])
+ break
+ if interface["name"] != each["name"]:
+ not_in_have.add(interface["name"])
+ else:
+ # We didn't find a matching desired state, which means we can
+ # pretend we received an empty desired state.
+ interface = dict(name=each["name"])
+ kwargs = {"want": interface, "have": each}
+ commands.extend(self._clear_config(**kwargs))
+ continue
+ have_dict = filter_dict_having_none_value(interface, each)
+ commands.extend(self._clear_config(dict(), have_dict))
+ commands.extend(self._set_config(interface, each, module))
+ # Add the want interface that's not already configured in have interface
+ for each in not_in_have - in_have:
+ for every in want:
+ interface = "interface {0}".format(every["name"])
+ if each and interface not in commands:
+ commands.extend(self._set_config(every, {}, module))
+ # Remove the duplicate interface call
+ commands = remove_duplicate_interface(commands)
+
+ return commands
+
+ def _state_merged(self, want, have, module):
+ """ The command generator when state is merged
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+
+ for interface in want:
+ interface["name"] = normalize_interface(interface["name"])
+ if self.state == "rendered":
+ commands.extend(self._set_config(interface, dict(), module))
+ else:
+ for each in have:
+ if each["name"] == interface["name"]:
+ break
+ else:
+ commands.extend(
+ self._set_config(interface, dict(), module)
+ )
+ continue
+ commands.extend(self._set_config(interface, each, module))
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """ The command generator when state is deleted
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+
+ if want:
+ for interface in want:
+ interface["name"] = normalize_interface(interface["name"])
+ for each in have:
+ if (
+ each["name"] == interface["name"]
+ or interface["name"] in each["name"]
+ ):
+ break
+ else:
+ continue
+ interface = dict(name=interface["name"])
+ commands.extend(self._clear_config(interface, each))
+ else:
+ for each in have:
+ want = dict()
+ commands.extend(self._clear_config(want, each))
+
+ return commands
+
+ def verify_diff_again(self, want, have):
+ """
+ Verify the IPV4 difference again as sometimes due to
+ change in order of set, set difference may result into change,
+ when there's actually no difference between want and have
+ :param want: want_dict IPV4
+ :param have: have_dict IPV4
+ :return: diff
+ """
+ diff = False
+ for each in want:
+ each_want = dict(each)
+ for every in have:
+ every_have = dict(every)
+
+ if each_want.get("address") == every_have.get("address"):
+ if len(each_want.keys()) == len(every_have.keys()) and (
+ each_want.get("secondary")
+ == every_have.get("secondary")
+ ):
+ diff = False
+ break
+ if not each_want.get("secondary") and not every_have.get(
+ "secondary"
+ ):
+ diff = False
+ break
+
+ diff = True
+ else:
+ diff = True
+ if diff:
+ break
+
+ return diff
+
+ def _set_config(self, want, have, module):
+ # Set the interface config based on the want and have config
+ commands = []
+ interface = "interface " + want["name"]
+
+ # To handle L3 IPV4 configuration
+ if want.get("ipv4"):
+ for each in want.get("ipv4"):
+ if each.get("address") != "dhcp":
+ ip_addr_want = validate_n_expand_ipv4(module, each)
+ each["address"] = ip_addr_want
+
+ # Get the diff b/w want and have
+ want_dict = dict_to_set(want)
+ have_dict = dict_to_set(have)
+
+ # To handle L3 IPV4 configuration
+ want_ipv4 = dict(want_dict).get("ipv4")
+ have_ipv4 = dict(have_dict).get("ipv4")
+ if want_ipv4:
+ if have_ipv4:
+ diff_ipv4 = set(want_ipv4) - set(dict(have_dict).get("ipv4"))
+ if diff_ipv4:
+ diff_ipv4 = (
+ diff_ipv4
+ if self.verify_diff_again(want_ipv4, have_ipv4)
+ else ()
+ )
+ else:
+ diff_ipv4 = set(want_ipv4)
+ for each in diff_ipv4:
+ ipv4_dict = dict(each)
+ if ipv4_dict.get("address") != "dhcp":
+ cmd = "ipv4 address {0}".format(ipv4_dict["address"])
+ if ipv4_dict.get("secondary"):
+ cmd += " secondary"
+ add_command_to_config_list(interface, cmd, commands)
+
+ # To handle L3 IPV6 configuration
+ want_ipv6 = dict(want_dict).get("ipv6")
+ have_ipv6 = dict(have_dict).get("ipv6")
+ if want_ipv6:
+ if have_ipv6:
+ diff_ipv6 = set(want_ipv6) - set(have_ipv6)
+ else:
+ diff_ipv6 = set(want_ipv6)
+ for each in diff_ipv6:
+ ipv6_dict = dict(each)
+ validate_ipv6(ipv6_dict.get("address"), module)
+ cmd = "ipv6 address {0}".format(ipv6_dict.get("address"))
+ add_command_to_config_list(interface, cmd, commands)
+
+ return commands
+
+ def _clear_config(self, want, have):
+ # Delete the interface config based on the want and have config
+ count = 0
+ commands = []
+ if want.get("name"):
+ interface = "interface " + want["name"]
+ else:
+ interface = "interface " + have["name"]
+
+ if have.get("ipv4") and want.get("ipv4"):
+ for each in have.get("ipv4"):
+ if each.get("secondary") and not (
+ want.get("ipv4")[count].get("secondary")
+ ):
+ cmd = "ipv4 address {0} secondary".format(
+ each.get("address")
+ )
+ remove_command_from_config_list(interface, cmd, commands)
+ count += 1
+ if have.get("ipv4") and not (want.get("ipv4")):
+ remove_command_from_config_list(
+ interface, "ipv4 address", commands
+ )
+ if have.get("ipv6") and not (want.get("ipv6")):
+ remove_command_from_config_list(
+ interface, "ipv6 address", commands
+ )
+
+ return commands
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/lacp.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/lacp.py
new file mode 100644
index 00000000..1c5d53f2
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/lacp.py
@@ -0,0 +1,213 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_lacp class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+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,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import (
+ Facts,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ dict_diff,
+)
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ remove_empties,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ flatten_dict,
+)
+
+
+class Lacp(ConfigBase):
+ """
+ The iosxr_lacp class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["lacp"]
+
+ def __init__(self, module):
+ super(Lacp, self).__init__(module)
+
+ def get_lacp_facts(self, data=None):
+ """ Get the 'facts' (the current configuration)
+
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset, self.gather_network_resources, data=data
+ )
+ lacp_facts = facts["ansible_network_resources"].get("lacp")
+ if not lacp_facts:
+ return {}
+ return lacp_facts
+
+ def execute_module(self):
+ """ Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_lacp_facts = self.get_lacp_facts()
+ else:
+ existing_lacp_facts = {}
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_lacp_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_lacp_facts = self.get_lacp_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed"
+ )
+ result["parsed"] = self.get_lacp_facts(data=running_config)
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_lacp_facts
+ if result["changed"]:
+ result["after"] = changed_lacp_facts
+
+ elif self.state == "gathered":
+ result["gathered"] = changed_lacp_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_lacp_facts):
+ """ Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params.get("config")
+ if not want:
+ want = {}
+ have = existing_lacp_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """ Select the appropriate function based on the state provided
+
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ if self.state in ("merged", "replaced", "rendered") and not want:
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ self.state
+ )
+ )
+
+ if self.state == "deleted":
+ commands = self._state_deleted(want, have)
+ elif self.state in ("merged", "rendered"):
+ commands = self._state_merged(want, have)
+ elif self.state == "replaced":
+ commands = self._state_replaced(want, have)
+
+ return commands
+
+ def _state_replaced(self, want, have):
+ """ The command generator when state is replaced
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ commands.extend(self._state_deleted(want, have))
+
+ commands.extend(self._state_merged(want, have))
+
+ return commands
+
+ def _state_merged(self, want, have):
+ """ The command generator when state is merged
+
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+
+ updates = dict_diff(have, want)
+ if self.state == "rendered":
+ updates = want
+ if updates:
+ for key, value in iteritems(
+ flatten_dict(remove_empties(updates["system"]))
+ ):
+ commands.append(
+ "lacp system {0} {1}".format(
+ key.replace("address", "mac"), value
+ )
+ )
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """ The command generator when state is deleted
+
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+
+ for x in [
+ k
+ for k in have.get("system", {})
+ if k not in remove_empties(want.get("system", {}))
+ ]:
+ commands.append("no lacp system {0}".format(x))
+
+ return commands
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp_interfaces/lacp_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp_interfaces/lacp_interfaces.py
new file mode 100644
index 00000000..83c1ee9d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp_interfaces/lacp_interfaces.py
@@ -0,0 +1,312 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_lacp_interfaces class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+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,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import (
+ Facts,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ dict_diff,
+ remove_empties,
+)
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ search_obj_in_list,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ dict_delete,
+ pad_commands,
+ flatten_dict,
+)
+
+
+class Lacp_interfaces(ConfigBase):
+ """
+ The iosxr_lacp_interfaces class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["lacp_interfaces"]
+
+ def __init__(self, module):
+ super(Lacp_interfaces, self).__init__(module)
+
+ def get_lacp_interfaces_facts(self, data=None):
+ """ Get the 'facts' (the current configuration)
+
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset, self.gather_network_resources, data=data
+ )
+ lacp_interfaces_facts = facts["ansible_network_resources"].get(
+ "lacp_interfaces"
+ )
+ if not lacp_interfaces_facts:
+ return []
+ return lacp_interfaces_facts
+
+ def execute_module(self):
+ """ Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ commands = list()
+ warnings = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_lacp_interfaces_facts = self.get_lacp_interfaces_facts()
+ else:
+ existing_lacp_interfaces_facts = []
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_lacp_interfaces_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_lacp_interfaces_facts = self.get_lacp_interfaces_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed"
+ )
+ result["parsed"] = self.get_lacp_interfaces_facts(
+ data=running_config
+ )
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_lacp_interfaces_facts
+ if result["changed"]:
+ result["after"] = changed_lacp_interfaces_facts
+ elif self.state == "gathered":
+ result["gathered"] = changed_lacp_interfaces_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_lacp_interfaces_facts):
+ """ Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ have = existing_lacp_interfaces_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """ Select the appropriate function based on the state provided
+
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ state = self._module.params["state"]
+
+ if (
+ state in ("overridden", "merged", "replaced", "rendered")
+ and not want
+ ):
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ state
+ )
+ )
+
+ if state == "overridden":
+ commands.extend(Lacp_interfaces._state_overridden(want, have))
+
+ elif state == "deleted":
+ if not want:
+ for intf in have:
+ commands.extend(
+ Lacp_interfaces._state_deleted(
+ {"name": intf["name"]}, intf
+ )
+ )
+ else:
+ for item in want:
+ obj_in_have = search_obj_in_list(item["name"], have)
+ commands.extend(
+ Lacp_interfaces._state_deleted(item, obj_in_have)
+ )
+
+ else:
+ for item in want:
+ name = item["name"]
+ obj_in_have = search_obj_in_list(name, have)
+
+ if state in ("merged", "rendered"):
+ commands.extend(
+ Lacp_interfaces._state_merged(item, obj_in_have)
+ )
+
+ elif state == "replaced":
+ commands.extend(
+ Lacp_interfaces._state_replaced(item, obj_in_have)
+ )
+
+ return commands
+
+ @staticmethod
+ def _state_replaced(want, have):
+ """ The command generator when state is replaced
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ replaced_commands = []
+ merged_commands = []
+
+ if have:
+ replaced_commands = Lacp_interfaces._state_deleted(want, have)
+
+ merged_commands = Lacp_interfaces._state_merged(want, have)
+
+ if merged_commands and replaced_commands:
+ del merged_commands[0]
+
+ commands.extend(replaced_commands)
+ commands.extend(merged_commands)
+
+ return commands
+
+ @staticmethod
+ def _state_overridden(want, have):
+ """ The command generator when state is overridden
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ for intf in have:
+ intf_in_want = search_obj_in_list(intf["name"], want)
+ if not intf_in_want:
+ commands.extend(
+ Lacp_interfaces._state_deleted(
+ {"name": intf["name"]}, intf
+ )
+ )
+
+ for intf in want:
+ intf_in_have = search_obj_in_list(intf["name"], have)
+ commands.extend(
+ Lacp_interfaces._state_replaced(intf, intf_in_have)
+ )
+
+ return commands
+
+ @staticmethod
+ def _state_merged(want, have):
+ """ The command generator when state is merged
+
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+
+ if not have:
+ have = {"name": want["name"]}
+
+ for key, value in iteritems(
+ flatten_dict(remove_empties(dict_diff(have, want)))
+ ):
+ commands.append(Lacp_interfaces._compute_commands(key, value))
+
+ if commands:
+ pad_commands(commands, want["name"])
+
+ return commands
+
+ @staticmethod
+ def _state_deleted(want, have):
+ """ The command generator when state is deleted
+
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+
+ for key, value in iteritems(
+ flatten_dict(dict_delete(have, remove_empties(want)))
+ ):
+ commands.append(
+ Lacp_interfaces._compute_commands(key, value, remove=True)
+ )
+
+ if commands:
+ pad_commands(commands, have["name"])
+
+ return commands
+
+ @staticmethod
+ def _compute_commands(key, value, remove=False):
+ if key == "churn_logging":
+ cmd = "lacp churn logging {0}".format(value)
+
+ elif key == "collector_max_delay":
+ cmd = "lacp collector-max-delay {0}".format(value)
+
+ elif key == "period":
+ cmd = "lacp period {0}".format(value)
+
+ elif key == "switchover_suppress_flaps":
+ cmd = "lacp switchover suppress-flaps {0}".format(value)
+
+ elif key == "mac":
+ cmd = "lacp system mac {0}".format(value)
+
+ elif key == "priority":
+ cmd = "lacp system priority {0}".format(value)
+
+ if remove:
+ cmd = "no " + cmd
+
+ return cmd
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lag_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lag_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lag_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lag_interfaces/lag_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lag_interfaces/lag_interfaces.py
new file mode 100644
index 00000000..a877341b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lag_interfaces/lag_interfaces.py
@@ -0,0 +1,439 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_lag_interfaces class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from copy import deepcopy
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import (
+ ConfigBase,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import (
+ Facts,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ to_list,
+ dict_diff,
+ remove_empties,
+ search_obj_in_list,
+ param_list_to_dict,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ diff_list_of_dicts,
+ pad_commands,
+ flatten_dict,
+ dict_delete,
+ normalize_interface,
+)
+
+
+class Lag_interfaces(ConfigBase):
+ """
+ The iosxr_lag_interfaces class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["lag_interfaces"]
+
+ def __init__(self, module):
+ super(Lag_interfaces, self).__init__(module)
+
+ def get_lag_interfaces_facts(self, data=None):
+ """ Get the 'facts' (the current configuration)
+
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset, self.gather_network_resources, data=data
+ )
+ lag_interfaces_facts = facts["ansible_network_resources"].get(
+ "lag_interfaces"
+ )
+ if not lag_interfaces_facts:
+ return []
+ return lag_interfaces_facts
+
+ def execute_module(self):
+ """ Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_lag_interfaces_facts = self.get_lag_interfaces_facts()
+ else:
+ existing_lag_interfaces_facts = {}
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_lag_interfaces_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_lag_interfaces_facts = self.get_lag_interfaces_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed"
+ )
+ result["parsed"] = self.get_lag_interfaces_facts(
+ data=running_config
+ )
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_lag_interfaces_facts
+ if result["changed"]:
+ result["after"] = changed_lag_interfaces_facts
+
+ elif self.state == "gathered":
+ result["gathered"] = changed_lag_interfaces_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_lag_interfaces_facts):
+ """ Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ if want:
+ for item in want:
+ item["name"] = normalize_interface(item["name"])
+ if "members" in want and want["members"]:
+ for item in want["members"]:
+ item.update(
+ {
+ "member": normalize_interface(item["member"]),
+ "mode": item["mode"],
+ }
+ )
+ have = existing_lag_interfaces_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """ Select the appropriate function based on the state provided
+
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ state = self._module.params["state"]
+ commands = []
+
+ if (
+ self.state in ("merged", "replaced", "overridden", "rendered")
+ and not want
+ ):
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ state
+ )
+ )
+
+ if state == "overridden":
+ commands.extend(self._state_overridden(want, have))
+
+ elif state == "deleted":
+ commands.extend(self._state_deleted(want, have))
+
+ else:
+ # Instead of passing entire want and have
+ # list of dictionaries to the respective
+ # _state_* methods we are passing the want
+ # and have dictionaries per interface
+ for item in want:
+ name = item["name"]
+ obj_in_have = search_obj_in_list(name, have)
+
+ if state in ("merged", "rendered"):
+ commands.extend(self._state_merged(item, obj_in_have))
+
+ elif state == "replaced":
+ commands.extend(self._state_replaced(item, obj_in_have))
+
+ return commands
+
+ def _state_replaced(self, want, have):
+ """ The command generator when state is replaced
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ if have:
+ commands.extend(self._render_bundle_del_commands(want, have))
+ commands.extend(self._render_bundle_updates(want, have))
+
+ if commands or have == {}:
+ pad_commands(commands, want["name"])
+
+ if have:
+ commands.extend(self._render_interface_del_commands(want, have))
+ commands.extend(self._render_interface_updates(want, have))
+
+ return commands
+
+ def _state_overridden(self, want, have):
+ """ The command generator when state is overridden
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ for have_intf in have:
+ intf_in_want = search_obj_in_list(have_intf["name"], want)
+ if not intf_in_want:
+ commands.extend(self._purge_attribs(have_intf))
+
+ for intf in want:
+ intf_in_have = search_obj_in_list(intf["name"], have)
+ commands.extend(self._state_replaced(intf, intf_in_have))
+
+ return commands
+
+ def _state_merged(self, want, have):
+ """ The command generator when state is merged
+
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+ commands.extend(self._render_bundle_updates(want, have))
+
+ if commands or have == {}:
+ pad_commands(commands, want["name"])
+
+ commands.extend(self._render_interface_updates(want, have))
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """ The command generator when state is deleted
+
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+
+ if not want:
+ for item in have:
+ commands.extend(self._purge_attribs(intf=item))
+ else:
+ for item in want:
+ name = item["name"]
+ obj_in_have = search_obj_in_list(name, have)
+ if not obj_in_have:
+ self._module.fail_json(
+ msg=("interface {0} does not exist".format(name))
+ )
+ commands.extend(self._purge_attribs(intf=obj_in_have))
+
+ return commands
+
+ def _render_bundle_updates(self, want, have):
+ """ The command generator for updates to bundles
+ :rtype: A list
+ :returns: the commands necessary to update bundles
+ """
+ commands = []
+ if not have:
+ have = {"name": want["name"]}
+
+ want_copy = deepcopy(want)
+ have_copy = deepcopy(have)
+
+ want_copy.pop("members", [])
+ have_copy.pop("members", [])
+
+ bundle_updates = dict_diff(have_copy, want_copy)
+
+ if bundle_updates:
+ for key, value in iteritems(
+ flatten_dict(remove_empties(bundle_updates))
+ ):
+ commands.append(self._compute_commands(key=key, value=value))
+
+ return commands
+
+ def _render_interface_updates(self, want, have):
+ """ The command generator for updates to member
+ interfaces
+ :rtype: A list
+ :returns: the commands necessary to update member
+ interfaces
+ """
+ commands = []
+
+ if not have:
+ have = {"name": want["name"]}
+
+ member_diff = diff_list_of_dicts(
+ want["members"], have.get("members", [])
+ )
+
+ for diff in member_diff:
+ diff_cmd = []
+ bundle_cmd = "bundle id {0}".format(
+ want["name"].split("Bundle-Ether")[1]
+ )
+ if diff.get("mode"):
+ bundle_cmd += " mode {0}".format(diff.get("mode"))
+ diff_cmd.append(bundle_cmd)
+ pad_commands(diff_cmd, diff["member"])
+ commands.extend(diff_cmd)
+
+ return commands
+
+ def _render_bundle_del_commands(self, want, have):
+ """ The command generator for delete commands
+ w.r.t bundles
+ :rtype: A list
+ :returns: the commands necessary to update member
+ interfaces
+ """
+ commands = []
+ if not want:
+ want = {"name": have["name"]}
+
+ want_copy = deepcopy(want)
+ have_copy = deepcopy(have)
+ want_copy.pop("members", [])
+ have_copy.pop("members", [])
+
+ to_delete = dict_delete(have_copy, remove_empties(want_copy))
+ if to_delete:
+ for key, value in iteritems(
+ flatten_dict(remove_empties(to_delete))
+ ):
+ commands.append(
+ self._compute_commands(key=key, value=value, remove=True)
+ )
+
+ return commands
+
+ def _render_interface_del_commands(self, want, have):
+ """ The command generator for delete commands
+ w.r.t member interfaces
+ :rtype: A list
+ :returns: the commands necessary to update member
+ interfaces
+ """
+ commands = []
+ if not want:
+ want = {}
+ have_members = have.get("members")
+
+ if have_members:
+ have_members = param_list_to_dict(
+ deepcopy(have_members), unique_key="member"
+ )
+ want_members = param_list_to_dict(
+ deepcopy(want).get("members", []), unique_key="member"
+ )
+
+ for key in have_members:
+ if key not in want_members:
+ member_cmd = ["no bundle id"]
+ pad_commands(member_cmd, key)
+ commands.extend(member_cmd)
+
+ return commands
+
+ def _purge_attribs(self, intf):
+ """ The command generator for purging attributes
+ :rtype: A list
+ :returns: the commands necessary to purge attributes
+ """
+ commands = []
+ have_copy = deepcopy(intf)
+ members = have_copy.pop("members", [])
+
+ to_delete = dict_delete(
+ have_copy, remove_empties({"name": have_copy["name"]})
+ )
+ if to_delete:
+ for key, value in iteritems(
+ flatten_dict(remove_empties(to_delete))
+ ):
+ commands.append(
+ self._compute_commands(key=key, value=value, remove=True)
+ )
+
+ if commands:
+ pad_commands(commands, intf["name"])
+
+ if members:
+ members = param_list_to_dict(
+ deepcopy(members), unique_key="member"
+ )
+ for key in members:
+ member_cmd = ["no bundle id"]
+ pad_commands(member_cmd, key)
+ commands.extend(member_cmd)
+
+ return commands
+
+ def _compute_commands(self, key, value, remove=False):
+ """ The method generates LAG commands based on the
+ key, value passed. When remove is set to True,
+ the command is negated.
+ :rtype: str
+ :returns: a command based on the `key`, `value` pair
+ passed and the value of `remove`
+ """
+ if key == "mode":
+ cmd = "lacp mode {0}".format(value)
+
+ elif key == "load_balancing_hash":
+ cmd = "bundle load-balancing hash {0}".format(value)
+
+ elif key == "max_active":
+ cmd = "bundle maximum-active links {0}".format(value)
+
+ elif key == "min_active":
+ cmd = "bundle minimum-active links {0}".format(value)
+
+ if remove:
+ cmd = "no {0}".format(cmd)
+
+ return cmd
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/lldp_global.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/lldp_global.py
new file mode 100644
index 00000000..af15f791
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/lldp_global.py
@@ -0,0 +1,221 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_lldp_global class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+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,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import (
+ Facts,
+)
+from ansible.module_utils.six import iteritems
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ flatten_dict,
+ dict_delete,
+)
+
+
+class Lldp_global(ConfigBase):
+ """
+ The iosxr_lldp class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["lldp_global"]
+
+ def __init__(self, module):
+ super(Lldp_global, self).__init__(module)
+
+ def get_lldp_global_facts(self, data=None):
+ """ Get the 'facts' (the current configuration)
+
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset, self.gather_network_resources, data=data
+ )
+ lldp_facts = facts["ansible_network_resources"].get("lldp_global")
+ if not lldp_facts:
+ return {}
+ return lldp_facts
+
+ def execute_module(self):
+ """ Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+ if self.state in self.ACTION_STATES:
+ existing_lldp_global_facts = self.get_lldp_global_facts()
+ else:
+ existing_lldp_global_facts = {}
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_lldp_global_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_lldp_global_facts = self.get_lldp_global_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed"
+ )
+ result["parsed"] = self.get_lldp_global_facts(data=running_config)
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_lldp_global_facts
+ if result["changed"]:
+ result["after"] = changed_lldp_global_facts
+ elif self.state == "gathered":
+ result["gathered"] = changed_lldp_global_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_lldp_global_facts):
+ """ Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ if not want and self._module.params["state"] == "deleted":
+ want = {}
+ have = existing_lldp_global_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """ Select the appropriate function based on the state provided
+
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ state = self._module.params["state"]
+ if state in ("merged", "replaced", "rendered") and not want:
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ state
+ )
+ )
+
+ if state == "deleted":
+ commands = self._state_deleted(want, have)
+ elif state in ("merged", "rendered"):
+ commands = self._state_merged(want, have)
+ elif state == "replaced":
+ commands = self._state_replaced(want, have)
+
+ return commands
+
+ def _state_replaced(self, want, have):
+ """ The command generator when state is replaced
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ commands.extend(self._state_deleted(want, have))
+
+ commands.extend(self._state_merged(want, have))
+
+ return commands
+
+ def _state_merged(self, want, have):
+ """ The command generator when state is merged
+
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+ updates = dict_diff(have, want)
+ if updates:
+ for key, value in iteritems(flatten_dict(remove_empties(updates))):
+ commands.append(self._compute_commands(key, value))
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """ The command generator when state is deleted
+
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+ for key, value in iteritems(
+ flatten_dict(dict_delete(have, remove_empties(want)))
+ ):
+ cmd = self._compute_commands(key, value, remove=True)
+ if cmd:
+ commands.append(cmd)
+
+ return commands
+
+ def _compute_commands(self, key, value=None, remove=False):
+ if key in ["holdtime", "reinit", "timer"]:
+ cmd = "lldp {0} {1}".format(key, value)
+ if remove:
+ return "no {0}".format(cmd)
+ else:
+ return cmd
+
+ elif key == "subinterfaces":
+ cmd = "lldp subinterfaces enable"
+ if value and not remove:
+ return cmd
+ elif (not value and not remove) or (value and remove):
+ return "no {0}".format(cmd)
+
+ else:
+ cmd = "lldp tlv-select {0} disable".format(key.replace("_", "-"))
+ if not value and not remove:
+ return cmd
+ elif (value and not remove) or (not value and remove):
+ return "no {0}".format(cmd)
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_interfaces/lldp_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_interfaces/lldp_interfaces.py
new file mode 100644
index 00000000..70394f10
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_interfaces/lldp_interfaces.py
@@ -0,0 +1,278 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_lldp_interfaces class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+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,
+ search_obj_in_list,
+ dict_diff,
+ remove_empties,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import (
+ Facts,
+)
+from ansible.module_utils.six import iteritems
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ dict_delete,
+ pad_commands,
+ flatten_dict,
+)
+
+
+class Lldp_interfaces(ConfigBase):
+ """
+ The iosxr_lldp_interfaces class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["lldp_interfaces"]
+
+ def __init__(self, module):
+ super(Lldp_interfaces, self).__init__(module)
+
+ def get_lldp_interfaces_facts(self, data=None):
+ """ Get the 'facts' (the current configuration)
+
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset, self.gather_network_resources, data=data
+ )
+ lldp_interfaces_facts = facts["ansible_network_resources"].get(
+ "lldp_interfaces"
+ )
+ if not lldp_interfaces_facts:
+ return []
+ return lldp_interfaces_facts
+
+ def execute_module(self):
+ """ Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_lldp_interfaces_facts = self.get_lldp_interfaces_facts()
+ else:
+ existing_lldp_interfaces_facts = []
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_lldp_interfaces_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_lldp_interfaces_facts = self.get_lldp_interfaces_facts()
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed"
+ )
+ result["parsed"] = self.get_lldp_interfaces_facts(
+ data=running_config
+ )
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_lldp_interfaces_facts
+ if result["changed"]:
+ result["after"] = changed_lldp_interfaces_facts
+ elif self.state == "gathered":
+ result["gathered"] = changed_lldp_interfaces_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_lldp_interfaces_facts):
+ """ Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ have = existing_lldp_interfaces_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """ Select the appropriate function based on the state provided
+
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ state = self._module.params["state"]
+ commands = []
+ if (
+ state in ("overridden", "merged", "replaced", "rendered")
+ and not want
+ ):
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ state
+ )
+ )
+
+ if state == "overridden":
+ commands.extend(self._state_overridden(want, have))
+
+ elif state == "deleted":
+ if not want:
+ for intf in have:
+ commands.extend(
+ self._state_deleted({"name": intf["name"]}, intf)
+ )
+ else:
+ for item in want:
+ obj_in_have = search_obj_in_list(item["name"], have)
+ commands.extend(self._state_deleted(item, obj_in_have))
+
+ else:
+ for item in want:
+ name = item["name"]
+ obj_in_have = search_obj_in_list(name, have)
+
+ if state in ("merged", "rendered"):
+ commands.extend(self._state_merged(item, obj_in_have))
+
+ elif state == "replaced":
+ commands.extend(self._state_replaced(item, obj_in_have))
+
+ return commands
+
+ def _state_replaced(self, want, have):
+ """ The command generator when state is replaced
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ replaced_commands = []
+ merged_commands = []
+
+ if have:
+ replaced_commands = self._state_deleted(want, have)
+
+ merged_commands = self._state_merged(want, have)
+
+ if merged_commands and replaced_commands:
+ del merged_commands[0]
+
+ commands.extend(replaced_commands)
+ commands.extend(merged_commands)
+
+ return commands
+
+ def _state_overridden(self, want, have):
+ """ The command generator when state is overridden
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ for intf in have:
+ intf_in_want = search_obj_in_list(intf["name"], want)
+ if not intf_in_want:
+ commands.extend(
+ self._state_deleted({"name": intf["name"]}, intf)
+ )
+
+ for intf in want:
+ intf_in_have = search_obj_in_list(intf["name"], have)
+ commands.extend(self._state_replaced(intf, intf_in_have))
+
+ return commands
+
+ def _state_merged(self, want, have):
+ """ The command generator when state is merged
+
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+ if not have:
+ have = {"name": want["name"]}
+
+ for key, value in iteritems(
+ flatten_dict(remove_empties(dict_diff(have, want)))
+ ):
+ commands.append(self._compute_commands(key, value))
+
+ if commands:
+ pad_commands(commands, want["name"])
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """ The command generator when state is deleted
+
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+
+ for key, value in iteritems(
+ flatten_dict(dict_delete(have, remove_empties(want)))
+ ):
+ commands.append(self._compute_commands(key, value, remove=True))
+
+ if commands:
+ pad_commands(commands, have["name"])
+
+ return commands
+
+ def _compute_commands(self, key, value=None, remove=False):
+ if key == "mac_address":
+ cmd = "lldp destination mac-address {0}".format(value)
+ if remove:
+ return "no {0}".format(cmd)
+ else:
+ return cmd
+
+ else:
+ cmd = "lldp {0} disable".format(key)
+ if not value and not remove:
+ return cmd
+ elif (value and not remove) or (not value and remove):
+ return "no {0}".format(cmd)
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospf_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospf_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospf_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospf_interfaces/ospf_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospf_interfaces/ospf_interfaces.py
new file mode 100644
index 00000000..343124b5
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospf_interfaces/ospf_interfaces.py
@@ -0,0 +1,240 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+"""
+The iosxr_ospf_interfaces config file.
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to its desired end-state is
+created.
+"""
+
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ dict_merge,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.resource_module import (
+ ResourceModule,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import (
+ Facts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.ospf_interfaces import (
+ Ospf_interfacesTemplate,
+)
+
+
+class Ospf_interfaces(ResourceModule):
+ """
+ The iosxr_ospf_interfaces config class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["ospf_interfaces"]
+
+ def __init__(self, module):
+ super(Ospf_interfaces, self).__init__(
+ empty_fact_val=[],
+ facts_module=Facts(module),
+ module=module,
+ resource="ospf_interfaces",
+ tmplt=Ospf_interfacesTemplate(),
+ )
+ self.parsers = [
+ "authentication.message_digest",
+ "authentication.null_auth",
+ "authentication.message_digest.keychain",
+ "authentication_key",
+ "bfd.minimum_interval",
+ "bfd.multiplier",
+ "bfd.fast_detect.set",
+ "bfd.fast_detect.disable",
+ "bfd.fast_detect.strict_mode",
+ "cost",
+ "cost_fallback",
+ "dead_interval",
+ "demand_circuit",
+ "flood_reduction",
+ "hello_interval",
+ "link_down.set",
+ "link_down.disable",
+ "message_digest_key",
+ "mpls.set_ldp",
+ "mpls.ldp_sync",
+ "mpls.ldp_sync_disable",
+ "mtu_ignore",
+ "network",
+ "packet_size",
+ "passive",
+ "prefix_suppression.disable",
+ "prefix_suppression.secondary_address",
+ "priority",
+ "retransmit_interval",
+ "security.ttl_hops",
+ "security.ttl",
+ "transmit_delay",
+ ]
+
+ def execute_module(self):
+ """ Execute the module
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ if self.state not in ["parsed", "gathered"]:
+ self.generate_commands()
+ self.run_commands()
+ return self.result
+
+ def generate_commands(self):
+ """ Generate configuration commands to send based on
+ want, have and desired state.
+ """
+ wantd = {entry["name"]: entry for entry in self.want}
+ haved = {entry["name"]: entry for entry in self.have}
+
+ # turn all lists of dicts into dicts prior to merge
+ for entry in wantd, haved:
+ self._ospf_int_list_to_dict(entry)
+
+ # if state is merged, merge want onto have and then compare
+ if self.state == "merged":
+ wantd = dict_merge(haved, wantd)
+
+ # if state is deleted, empty out wantd and set haved to wantd
+ if self.state == "deleted":
+ haved = {
+ k: v for k, v in iteritems(haved) if k in wantd or not wantd
+ }
+ have_int = []
+ if wantd == {}:
+ for k, have in iteritems(haved):
+ self._remove_ospf_int(have)
+
+ for k, have in iteritems(haved):
+ if k in wantd:
+ have_int.append(k)
+ self._remove_ospf_int(have)
+ wantd = {}
+
+ # remove superfluous config for overridden and deleted
+ if self.state == "overridden":
+ for k, have in iteritems(haved):
+ if k not in wantd:
+ self._remove_ospf_int(have)
+ if self.state != "deleted":
+ for k, want in iteritems(wantd):
+ self._compare(want=want, have=haved.pop(k, {}))
+
+ def _remove_ospf_int(self, entry):
+ int_name = entry.get("name", {})
+ int_addr = entry.get("address_family", {})
+ for k, addr in iteritems(int_addr):
+ for key, value in addr["processes"].items():
+ rem_entry = {
+ "name": int_name,
+ "afi": addr["afi"],
+ "process": value["process_id"],
+ "area": value["area"],
+ }
+ self.addcmd(rem_entry, "name", True)
+
+ def _compare(self, want, have):
+ """Leverages the base class `compare()` method and
+ populates the list of commands to be run by comparing
+ the `want` and `have` data with the `parsers` defined
+ for the Ospf_interfaces network resource.
+ """
+ self._compare_interface(want=want, have=have)
+
+ self._compare_addr_family(want=want, have=have)
+
+ def _compare_interface(self, want, have):
+ wdict = want.get("address_family", {})
+ hdict = have.get("address_family", {})
+ wname = want.get("name")
+ hname = have.get("name")
+ h_value = {}
+
+ for key, w_value in iteritems(wdict):
+ if hdict and hdict.get(key):
+ h_value = hdict[key]
+ else:
+ h_value = None
+ w = {
+ "name": wname,
+ "type": w_value["afi"],
+ "address_family": w_value,
+ }
+ if h_value is not None:
+ h = {
+ "name": hname,
+ "type": h_value["afi"],
+ "address_family": h_value,
+ }
+ else:
+ h = {}
+ self.compare(parsers="name", want=w, have=h)
+
+ def _compare_addr_family(self, want, have):
+ wdict = want.get("address_family", {})
+ hdict = have.get("address_family", {})
+ wname = want.get("name")
+ hname = have.get("name")
+ # Fetch the area info as that would be common to all the attributes per interface
+ for name, entry in iteritems(wdict):
+ w_process = {}
+ h_process = {}
+ for key, value in iteritems(entry):
+ if key == "processes":
+ for pname, pentry in iteritems(value):
+ w_process = pentry
+ for key, param in iteritems(entry):
+ w_addr = {"afi": name, key: param, "processes": w_process}
+ h_addr = {}
+ if hdict.get(name):
+ hdict_entry = hdict.get(name)
+ for item, value in iteritems(hdict_entry):
+ if item == "processes":
+ for pname, pentry in iteritems(value):
+ h_process = pentry
+ h_addr = {
+ "afi": name,
+ key: hdict[name].pop(key, {}),
+ "processes": h_process,
+ }
+ w = {"name": wname, "address_family": w_addr}
+ h = {"name": hname, "address_family": h_addr}
+ self.compare(parsers=self.parsers, want=w, have=h)
+ for name, entry in iteritems(hdict):
+ for key, param in iteritems(entry):
+ h_addr = {"afi": name, key: param}
+ w_addr = {}
+ w = {"name": wname, "address_family": w_addr}
+ h = {"name": hname, "address_family": h_addr}
+ self.compare(parsers=self.parsers, want=w, have=h)
+
+ def _ospf_int_list_to_dict(self, entry):
+ for name, family in iteritems(entry):
+ if "address_family" in family:
+ family["address_family"] = {
+ entry["afi"]: entry
+ for entry in family.get("address_family", [])
+ }
+ self._ospf_int_list_to_dict(family["address_family"])
+ for name, ospf_processes in iteritems(entry):
+ if "processes" in ospf_processes:
+ ospf_processes["processes"] = {
+ entry["process_id"]: entry
+ for entry in ospf_processes.get("processes", [])
+ }
+ self._ospf_int_list_to_dict(ospf_processes["processes"])
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv2/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv2/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv2/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv2/ospfv2.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv2/ospfv2.py
new file mode 100644
index 00000000..d593c7ac
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv2/ospfv2.py
@@ -0,0 +1,262 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_ospfv2 class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from copy import deepcopy
+from ansible.module_utils.six import iteritems
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import (
+ Facts,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.ospfv2 import (
+ Ospfv2Template,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.resource_module import (
+ ResourceModule,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ dict_merge,
+)
+
+
+class Ospfv2(ResourceModule):
+ """
+ The ios_ospfv2 class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["ospfv2"]
+
+ def __init__(self, module):
+ super(Ospfv2, self).__init__(
+ empty_fact_val={},
+ facts_module=Facts(module),
+ module=module,
+ resource="ospfv2",
+ tmplt=Ospfv2Template(),
+ )
+
+ def execute_module(self):
+ """ Execute the module
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ self.gen_config()
+ self.run_commands()
+
+ return self.result
+
+ def gen_config(self):
+ """ Select the appropriate function based on the state provided
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ if self.want:
+ wantd = {
+ (entry["process_id"], entry.get("vrf")): entry
+ for entry in self.want.get("processes", [])
+ }
+ else:
+ wantd = {}
+ if self.have:
+ haved = {
+ (entry["process_id"], entry.get("vrf")): entry
+ for entry in self.have.get("processes", [])
+ }
+ else:
+ haved = {}
+
+ # turn all lists of dicts into dicts prior to merge
+ for thing in wantd, haved:
+ for _pid, proc in iteritems(thing):
+ for area in proc.get("areas", []):
+ virtual_link = {
+ entry["id"]: entry
+ for entry in area.get("virtual_link", [])
+ }
+ if bool(virtual_link):
+ area["virtual_link"] = virtual_link
+ ranges = {
+ entry["address"]: entry
+ for entry in area.get("ranges", [])
+ }
+ if bool(ranges):
+ area["ranges"] = ranges
+
+ proc["areas"] = {
+ entry["area_id"]: entry for entry in proc.get("areas", [])
+ }
+ if proc.get("distribute_list"):
+ if "acls" in proc.get("distribute_list"):
+ proc["distribute_list"]["acls"] = {
+ entry["name"]: entry
+ for entry in proc["distribute_list"].get(
+ "acls", []
+ )
+ }
+
+ # if state is merged, merge want onto have
+ if self.state == "merged":
+ wantd = dict_merge(haved, wantd)
+
+ # if state is deleted, limit the have to anything in want
+ # set want to nothing
+ if self.state == "deleted":
+ haved = {
+ k: v for k, v in iteritems(haved) if k in wantd or not wantd
+ }
+ wantd = {}
+
+ # delete processes first so we do run into "more than one" errors
+ if self.state == "deleted":
+ haved_del = deepcopy(haved)
+ want_process = {}
+ for k, t_want in iteritems(haved_del):
+ want_process["process_id"] = t_want.get("process_id")
+ if not (len(t_want) == 2 and not t_want.get("areas")):
+ self._compare(want=want_process, have=haved_del.get(k, {}))
+ if self.state == "overridden":
+ haved_del = deepcopy(haved)
+ want = {}
+ for k, t_want in iteritems(haved_del):
+ if k not in wantd:
+ want["process_id"] = t_want.get("process_id")
+ if not (len(t_want) == 2 and not t_want.get("areas")):
+ self._compare(want=want, have=haved_del.get(k, {}))
+
+ for k, want in iteritems(wantd):
+ self._compare(want=want, have=haved.pop(k, {}))
+
+ def _compare(self, want, have):
+ parsers = [
+ "bfd",
+ "cost",
+ "weight",
+ "passive",
+ "priority",
+ "protocol",
+ "auto_cost",
+ "bandwidth",
+ "flood_reduction",
+ "default_metric",
+ "default_weight",
+ "router_id",
+ "demand_circuit",
+ "packet_size",
+ "transmit_delay",
+ "summary_in",
+ "external_out",
+ "dead_interval",
+ "hello_interval",
+ "authentication",
+ "adjacency_stagger",
+ "retransmit_interval",
+ "mtu_ignore",
+ "bfd.fast_detect",
+ "capability",
+ "capability.opaque",
+ "admin_distance",
+ "ospf_distance",
+ "address_family_unicast",
+ "loopback_stub_network",
+ "authentication.message_digest",
+ "default_information_originate",
+ "link_down_fast_detect",
+ "nsr",
+ "database_filter",
+ "log_adjacency",
+ "distribute_bgp_ls",
+ "distribute_link_state",
+ "max_lsa",
+ "max_metric",
+ "mpls_ldp",
+ "mpls_traffic_eng",
+ "microloop_avoidance",
+ "prefix_suppression",
+ "protocol_shutdown",
+ "timers.lsa",
+ "timers.graceful_shutdown",
+ "throttle.lsa_all",
+ "throttle.spf",
+ "throttle.fast_reroute",
+ "timers.pacing_flood",
+ ]
+
+ if want != have:
+ self.addcmd(want or have, "pid", False)
+ self.compare(parsers, want, have)
+ self._areas_compare(want, have)
+
+ def _areas_compare(self, want, have):
+ wareas = want.get("areas", {})
+ hareas = have.get("areas", {})
+ for name, entry in iteritems(wareas):
+ self._area_compare(want=entry, have=hareas.pop(name, {}))
+ for name, entry in iteritems(hareas):
+ self._area_compare(want={}, have=entry)
+
+ def _area_compare(self, want, have):
+ parsers = [
+ "area.authentication",
+ "area.authentication_key",
+ "area.authentication.message_digest",
+ "area.mpls_traffic_eng",
+ "area.mpls_ldp",
+ "area.bfd",
+ "area.bfd.fast_detect",
+ "area.nssa",
+ "area.nssa.default_information_originate",
+ "area.nssa.translate",
+ "area.default_cost",
+ "area.stub",
+ "area.ranges",
+ "area.cost",
+ "area.dead_interval",
+ "area.hello_interval",
+ "area.transmit_delay",
+ "area.mtu_ignore",
+ "area.packet_size",
+ "area.priority",
+ "area.weight",
+ "area.external_out",
+ "area.summary_in",
+ "area.demand_circuit",
+ "area.passive",
+ ]
+ self.compare(parsers=parsers, want=want, have=have)
+ self._areas_compare_virtual_link(want, have)
+
+ def _areas_compare_virtual_link(self, want, have):
+ wvlinks = want.get("virtual_link", {})
+ hvlinks = have.get("virtual_link", {})
+ for name, entry in iteritems(wvlinks):
+ self._area_compare_virtual_link(
+ want=entry, have=hvlinks.pop(name, {})
+ )
+ for name, entry in iteritems(hvlinks):
+ self._area_compare_virtual_link(want={}, have=entry)
+
+ def _area_compare_virtual_link(self, want, have):
+ parsers = [
+ "virtual_link.authentication",
+ "virtual_link.authentication_key",
+ "virtual_link.authentication.message_digest",
+ "virtual_link.hello_interval",
+ "virtual_link.dead_interval",
+ "virtual_link.retransmit_interval",
+ ]
+ self.compare(parsers=parsers, want=want, have=have)
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py
new file mode 100644
index 00000000..f68b1292
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py
@@ -0,0 +1,255 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from copy import deepcopy
+from ansible.module_utils.six import iteritems
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import (
+ Facts,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.ospfv3 import (
+ Ospfv3Template,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.resource_module import (
+ ResourceModule,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ dict_merge,
+)
+
+
+class Ospfv3(ResourceModule):
+ """
+ The ios_ospfv3 class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["ospfv3"]
+
+ def __init__(self, module):
+ super(Ospfv3, self).__init__(
+ empty_fact_val={},
+ facts_module=Facts(module),
+ module=module,
+ resource="ospfv3",
+ tmplt=Ospfv3Template(),
+ )
+
+ def execute_module(self):
+ """ Execute the module
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ self.gen_config()
+ self.run_commands()
+
+ return self.result
+
+ def gen_config(self):
+ """ Select the appropriate function based on the state provided
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ if self.want:
+ wantd = {
+ (entry["process_id"], entry.get("vrf")): entry
+ for entry in self.want.get("processes", [])
+ }
+ else:
+ wantd = {}
+ if self.have:
+ haved = {
+ (entry["process_id"], entry.get("vrf")): entry
+ for entry in self.have.get("processes", [])
+ }
+ else:
+ haved = {}
+
+ # turn all lists of dicts into dicts prior to merge
+ for thing in wantd, haved:
+ for _pid, proc in iteritems(thing):
+ for area in proc.get("areas", []):
+ virtual_link = {
+ entry["id"]: entry
+ for entry in area.get("virtual_link", [])
+ }
+ if bool(virtual_link):
+ area["virtual_link"] = virtual_link
+ ranges = {
+ entry["address"]: entry
+ for entry in area.get("ranges", [])
+ }
+ if bool(ranges):
+ area["ranges"] = ranges
+
+ proc["areas"] = {
+ entry["area_id"]: entry for entry in proc.get("areas", [])
+ }
+ if proc.get("distribute_list"):
+ if "acls" in proc.get("distribute_list"):
+ proc["distribute_list"]["acls"] = {
+ entry["name"]: entry
+ for entry in proc["distribute_list"].get(
+ "acls", []
+ )
+ }
+
+ # if state is merged, merge want onto have
+ if self.state == "merged":
+ wantd = dict_merge(haved, wantd)
+
+ # if state is deleted, limit the have to anything in want
+ # set want to nothing
+ if self.state == "deleted":
+ haved = {
+ k: v for k, v in iteritems(haved) if k in wantd or not wantd
+ }
+ wantd = {}
+
+ # delete processes first so we do run into "more than one" errors
+ if self.state == "deleted":
+ haved_del = deepcopy(haved)
+ want_process = {}
+ for k, t_want in iteritems(haved_del):
+ want_process["process_id"] = t_want.get("process_id")
+ if not (len(t_want) == 2 and not t_want.get("areas")):
+ self._compare(want=want_process, have=haved_del.get(k, {}))
+ if self.state == "overridden":
+ haved_del = deepcopy(haved)
+ want = {}
+ for k, t_want in iteritems(haved_del):
+ if k not in wantd:
+ want["process_id"] = t_want.get("process_id")
+ if not (len(t_want) == 2 and not t_want.get("areas")):
+ self._compare(want=want, have=haved_del.get(k, {}))
+
+ for k, want in iteritems(wantd):
+ self._compare(want=want, have=haved.pop(k, {}))
+
+ def _compare(self, want, have):
+ parsers = [
+ "bfd.minimum_interval",
+ "bfd.multiplier",
+ "cost",
+ "weight",
+ "passive",
+ "priority",
+ "protocol",
+ "auto_cost",
+ "bandwidth",
+ "flood_reduction",
+ "default_metric",
+ "default_weight",
+ "router_id",
+ "demand_circuit",
+ "packet_size",
+ "transmit_delay",
+ "dead_interval",
+ "hello_interval",
+ "authentication",
+ "retransmit_interval",
+ "mtu_ignore",
+ "bfd.fast_detect",
+ "capability",
+ "capability.opaque",
+ "admin_distance",
+ "ospf_distance",
+ "address_family_unicast",
+ "loopback_stub_network",
+ "authentication.ipsec",
+ "default_information_originate",
+ "link_down_fast_detect",
+ "nsr",
+ "database_filter",
+ "log_adjacency",
+ "distribute_bgp_ls",
+ "distribute_link_state",
+ "max_lsa",
+ "max_metric",
+ "mpls_ldp",
+ "mpls_traffic_eng",
+ "microloop_avoidance",
+ "prefix_suppression",
+ "protocol_shutdown",
+ "timers.lsa",
+ "timers.graceful_shutdown",
+ "throttle.lsa_all",
+ "throttle.spf",
+ "throttle.fast_reroute",
+ "timers.pacing_flood",
+ ]
+
+ if want != have:
+ self.addcmd(want or have, "pid", False)
+ self.compare(parsers, want, have)
+ self._areas_compare(want, have)
+
+ def _areas_compare(self, want, have):
+ wareas = want.get("areas", {})
+ hareas = have.get("areas", {})
+ for name, entry in iteritems(wareas):
+ self._area_compare(want=entry, have=hareas.pop(name, {}))
+ for name, entry in iteritems(hareas):
+ self._area_compare(want={}, have=entry)
+
+ def _area_compare(self, want, have):
+ parsers = [
+ "area.authentication",
+ "area.authentication.ipsec",
+ "area.mpls_traffic_eng",
+ "area.mpls_ldp",
+ "area.bfd.minimum_interval",
+ "area.bfd.multiplier",
+ "area.bfd.fast_detect",
+ "area.nssa",
+ "area.nssa.default_information_originate",
+ "area.nssa.translate",
+ "area.default_cost",
+ "area.stub",
+ "area.ranges",
+ "area.cost",
+ "area.dead_interval",
+ "area.hello_interval",
+ "area.transmit_delay",
+ "area.mtu_ignore",
+ "area.packet_size",
+ "area.priority",
+ "area.weight",
+ "area.external_out",
+ "area.summary_in",
+ "area.demand_circuit",
+ "area.passive",
+ ]
+ self.compare(parsers=parsers, want=want, have=have)
+ self._areas_compare_virtual_link(want, have)
+
+ def _areas_compare_virtual_link(self, want, have):
+ wvlinks = want.get("virtual_link", {})
+ hvlinks = have.get("virtual_link", {})
+ for name, entry in iteritems(wvlinks):
+ self._area_compare_virtual_link(
+ want=entry, have=hvlinks.pop(name, {})
+ )
+ for name, entry in iteritems(hvlinks):
+ self._area_compare_virtual_link(want={}, have=entry)
+
+ def _area_compare_virtual_link(self, want, have):
+ parsers = [
+ "virtual_link.authentication",
+ "virtual_link.authentication_key",
+ "virtual_link.authentication.message_digest",
+ "virtual_link.hello_interval",
+ "virtual_link.dead_interval",
+ "virtual_link.retransmit_interval",
+ ]
+ self.compare(parsers=parsers, want=want, have=have)
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/static_routes.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/static_routes.py
new file mode 100644
index 00000000..246966e4
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/static_routes.py
@@ -0,0 +1,549 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_static_routes class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+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,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import (
+ Facts,
+)
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ search_obj_in_list,
+ remove_empties,
+ dict_diff,
+ dict_merge,
+)
+
+
+class Static_routes(ConfigBase):
+ """
+ The iosxr_static_routes class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["static_routes"]
+
+ def __init__(self, module):
+ super(Static_routes, self).__init__(module)
+
+ def get_static_routes_facts(self, data=None):
+ """ Get the 'facts' (the current configuration)
+
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset, self.gather_network_resources, data=data
+ )
+ static_routes_facts = facts["ansible_network_resources"].get(
+ "static_routes"
+ )
+ if not static_routes_facts:
+ return []
+ return static_routes_facts
+
+ def execute_module(self):
+ """ Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_static_routes_facts = self.get_static_routes_facts()
+ else:
+ existing_static_routes_facts = []
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_static_routes_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_static_routes_facts = self.get_static_routes_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed"
+ )
+ result["parsed"] = self.get_static_routes_facts(
+ data=running_config
+ )
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_static_routes_facts
+ if result["changed"]:
+ result["after"] = changed_static_routes_facts
+
+ elif self.state == "gathered":
+ result["gathered"] = changed_static_routes_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_static_routes_facts):
+ """ Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ have = existing_static_routes_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """ Select the appropriate function based on the state provided
+
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ state = self._module.params["state"]
+ commands = []
+
+ if (
+ state in ("overridden", "merged", "replaced", "rendered")
+ and not want
+ ):
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ state
+ )
+ )
+
+ if state == "overridden":
+ commands.extend(self._state_overridden(want, have))
+
+ elif state == "deleted":
+ if not want:
+ if len(have) >= 1:
+ return "no router static"
+
+ else:
+ for w_item in want:
+ obj_in_have = self._find_vrf(w_item, have)
+ if obj_in_have:
+ commands.extend(
+ self._state_deleted(
+ remove_empties(w_item), obj_in_have
+ )
+ )
+
+ else:
+ for w_item in want:
+ obj_in_have = self._find_vrf(w_item, have)
+ if state == "merged" or self.state == "rendered":
+ commands.extend(
+ self._state_merged(remove_empties(w_item), obj_in_have)
+ )
+
+ elif state == "replaced":
+ commands.extend(
+ self._state_replaced(
+ remove_empties(w_item), obj_in_have
+ )
+ )
+
+ if commands:
+ commands.insert(0, "router static")
+
+ return commands
+
+ def _state_replaced(self, want, have):
+ """ The command generator when state is replaced
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ for want_afi in want.get("address_families", []):
+ have_afi = (
+ self.find_af_context(
+ want_afi, have.get("address_families", [])
+ )
+ or {}
+ )
+ update_commands = []
+ for want_route in want_afi.get("routes", []):
+ have_route = (
+ search_obj_in_list(
+ want_route["dest"],
+ have_afi.get("routes", []),
+ key="dest",
+ )
+ or {}
+ )
+
+ rotated_have_next_hops = self.rotate_next_hops(
+ have_route.get("next_hops", {})
+ )
+ rotated_want_next_hops = self.rotate_next_hops(
+ want_route.get("next_hops", {})
+ )
+
+ for key in rotated_have_next_hops.keys():
+ if key not in rotated_want_next_hops:
+ cmd = "no {0}".format(want_route["dest"])
+ for item in key:
+ if "." in item or ":" in item or "/" in item:
+ cmd += " {0}".format(item)
+ else:
+ cmd += " vrf {0}".format(item)
+ update_commands.append(cmd)
+
+ for key, value in iteritems(rotated_want_next_hops):
+ if key in rotated_have_next_hops:
+ existing = True
+ have_exit_point_attribs = rotated_have_next_hops[key]
+
+ else:
+ existing = False
+ have_exit_point_attribs = {}
+
+ updates = dict_diff(have_exit_point_attribs, value)
+
+ if updates or not existing:
+ update_commands.append(
+ self._compute_commands(
+ dest=want_route["dest"],
+ next_hop=key,
+ updates=updates,
+ )
+ )
+
+ if update_commands:
+ update_commands.insert(
+ 0,
+ "address-family {0} {1}".format(
+ want_afi["afi"], want_afi["safi"]
+ ),
+ )
+ commands.extend(update_commands)
+
+ if "vrf" in want and update_commands:
+ commands.insert(0, "vrf {0}".format(want["vrf"]))
+
+ return commands
+
+ def _state_overridden(self, want, have):
+ """ The command generator when state is overridden
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ # Iterate through all the entries, i.e., VRFs and Global entry in have
+ # and fully remove the ones that are not present in want and then call
+ # replaced
+
+ for h_item in have:
+ w_item = self._find_vrf(h_item, want)
+
+ # Delete all the top-level keys (VRFs/Global Route Entry) that are
+ # not specified in want.
+ if not w_item:
+ if "vrf" in h_item:
+ commands.append("no vrf {0}".format(h_item["vrf"]))
+ else:
+ for have_afi in h_item.get("address_families", []):
+ commands.append(
+ "no address-family {0} {1}".format(
+ have_afi["afi"], have_afi["safi"]
+ )
+ )
+
+ # For VRFs/Global Entry present in want, we also need to delete extraneous routes
+ # from them. We cannot reuse `_state_replaced` for this purpose since its scope is
+ # limited to replacing a single `dest`.
+ else:
+ del_cmds = []
+ for have_afi in h_item.get("address_families", []):
+ want_afi = (
+ self.find_af_context(
+ have_afi, w_item.get("address_families", [])
+ )
+ or {}
+ )
+ update_commands = []
+ for h_route in have_afi.get("routes", []):
+ w_route = (
+ search_obj_in_list(
+ h_route["dest"],
+ want_afi.get("routes", []),
+ key="dest",
+ )
+ or {}
+ )
+ if not w_route:
+ update_commands.append(
+ "no {0}".format(h_route["dest"])
+ )
+
+ if update_commands:
+ update_commands.insert(
+ 0,
+ "address-family {0} {1}".format(
+ want_afi["afi"], want_afi["safi"]
+ ),
+ )
+ del_cmds.extend(update_commands)
+
+ if "vrf" in want and update_commands:
+ del_cmds.insert(0, "vrf {0}".format(want["vrf"]))
+
+ commands.extend(del_cmds)
+
+ # We finally call `_state_replaced` to replace exiting `dest` entries
+ # or add new ones as specified in want.
+ for w_item in want:
+ h_item = self._find_vrf(w_item, have)
+ commands.extend(
+ self._state_replaced(remove_empties(w_item), h_item)
+ )
+
+ return commands
+
+ def _state_merged(self, want, have):
+ """ The command generator when state is merged
+
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+
+ for want_afi in want.get("address_families", []):
+ have_afi = (
+ self.find_af_context(
+ want_afi, have.get("address_families", [])
+ )
+ or {}
+ )
+
+ update_commands = []
+ for want_route in want_afi.get("routes", []):
+ have_route = (
+ search_obj_in_list(
+ want_route["dest"],
+ have_afi.get("routes", []),
+ key="dest",
+ )
+ or {}
+ )
+
+ # convert the next_hops list of dictionaries to dictionary of
+ # dictionaries with (`dest_vrf`, `forward_router_address`, `interface`) tuple
+ # being the key for each dictionary.
+ # a combination of these 3 attributes uniquely identifies a route entry.
+ # in case `dest_vrf` is not specified, `forward_router_address` and `interface`
+ # become the unique identifier
+ rotated_have_next_hops = self.rotate_next_hops(
+ have_route.get("next_hops", {})
+ )
+ rotated_want_next_hops = self.rotate_next_hops(
+ want_route.get("next_hops", {})
+ )
+
+ # for every dict in the want next_hops dictionaries, if the key
+ # is present in `rotated_have_next_hops`, we set `existing` to True,
+ # which means the the given want exit point exists and we run dict_diff
+ # on `value` which is basically all the other attributes of the exit point
+ # if the key is not present, it means that this is a new exit point
+ for key, value in iteritems(rotated_want_next_hops):
+ if key in rotated_have_next_hops:
+ existing = True
+ have_exit_point_attribs = rotated_have_next_hops[key]
+
+ else:
+ existing = False
+ have_exit_point_attribs = {}
+
+ updates = dict_diff(have_exit_point_attribs, value)
+ if updates or not existing:
+ update_commands.append(
+ self._compute_commands(
+ dest=want_route["dest"],
+ next_hop=key,
+ # dict_merge() is necessary to make sure that we
+ # don't end up overridding the entry and also to
+ # allow incremental updates
+ updates=dict_merge(
+ rotated_have_next_hops.get(key, {}),
+ updates,
+ ),
+ )
+ )
+
+ if update_commands:
+ update_commands.insert(
+ 0,
+ "address-family {0} {1}".format(
+ want_afi["afi"], want_afi["safi"]
+ ),
+ )
+ commands.extend(update_commands)
+
+ if "vrf" in want and update_commands:
+ commands.insert(0, "vrf {0}".format(want["vrf"]))
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """ The command generator when state is deleted
+
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+ if "address_families" not in want:
+ return ["no vrf {0}".format(want["vrf"])]
+
+ else:
+ for want_afi in want.get("address_families", []):
+ have_afi = (
+ self.find_af_context(
+ want_afi, have.get("address_families", [])
+ )
+ or {}
+ )
+ if have_afi:
+ commands.append(
+ "no address-family {0} {1}".format(
+ have_afi["afi"], have_afi["safi"]
+ )
+ )
+ if "vrf" in want and commands:
+ commands.insert(0, "vrf {0}".format(want["vrf"]))
+
+ return commands
+
+ def _find_vrf(self, item, entries):
+ """ This method iterates through the items
+ in `entries` and returns the object that
+ matches `item`.
+
+ :rtype: A dict
+ :returns: the obj in `entries` that matches `item`
+ """
+ obj = {}
+ afi = item.get("vrf")
+
+ if afi:
+ obj = search_obj_in_list(afi, entries, key="vrf") or {}
+ else:
+ for x in entries:
+ if "vrf" not in remove_empties(x):
+ obj = x
+ break
+ return obj
+
+ def find_af_context(self, want_af_context, have_address_families):
+ """ This method iterates through the have AFs
+ and returns the one that matches the want AF
+
+ :rtype: A dict
+ :returns: the corresponding AF in have AFs
+ that matches the want AF
+ """
+ for have_af in have_address_families:
+ if (
+ have_af["afi"] == want_af_context["afi"]
+ and have_af["safi"] == want_af_context["safi"]
+ ):
+ return have_af
+
+ def rotate_next_hops(self, next_hops):
+ """ This method iterates through the list of
+ next hops for a given destination network
+ and converts it to a dictionary of dictionaries.
+ Each dictionary has a primary key indicated by the
+ tuple of `dest_vrf`, `forward_router_address` and
+ `interface` and the value of this key is a dictionary
+ that contains all the other attributes of the next hop.
+
+ :rtype: A dict
+ :returns: A next_hops list in a dictionary of dictionaries format
+ """
+ next_hops_dict = {}
+
+ for entry in next_hops:
+ entry = entry.copy()
+ key_list = []
+
+ for x in ["dest_vrf", "forward_router_address", "interface"]:
+ if entry.get(x):
+ key_list.append(entry.pop(x))
+
+ key = tuple(key_list)
+ next_hops_dict[key] = entry
+
+ return next_hops_dict
+
+ def _compute_commands(self, dest, next_hop, updates=None):
+ """ This method computes a static route entry command
+ from the specified `dest`, `next_hop` and `updates`
+
+ :rtype: A str
+ :returns: A platform specific static routes command
+ """
+ if not updates:
+ updates = {}
+
+ command = dest
+
+ for x in next_hop:
+ if "." in x or ":" in x or "/" in x:
+ command += " {0}".format(x)
+ else:
+ command += " vrf {0}".format(x)
+
+ for key in sorted(updates):
+ if key == "admin_distance":
+ command += " {0}".format(updates[key])
+ else:
+ command += " {0} {1}".format(key, updates[key])
+
+ return command
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acl_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acl_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acl_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acl_interfaces/acl_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acl_interfaces/acl_interfaces.py
new file mode 100644
index 00000000..e9c476a3
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acl_interfaces/acl_interfaces.py
@@ -0,0 +1,78 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr acl_interfaces fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from copy import deepcopy
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.acl_interfaces import (
+ Acl_interfacesTemplate,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.acl_interfaces.acl_interfaces import (
+ Acl_interfacesArgs,
+)
+
+
+class Acl_interfacesFacts(object):
+ """ The iosxr acl_interfaces fact class
+ """
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Acl_interfacesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """ Populate the facts for acl_interfaces
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+
+ if not data:
+ data = connection.get_config(flags="interface")
+
+ config_parser = Acl_interfacesTemplate(lines=data.splitlines())
+ entry = sorted(
+ list(config_parser.parse().values()),
+ key=lambda k, sk="name": k[sk],
+ )
+ if entry:
+ for item in entry:
+ item["access_groups"] = sorted(
+ list(item["access_groups"].values()),
+ key=lambda k, sk="afi": k[sk],
+ )
+
+ ansible_facts["ansible_network_resources"].pop("acl_interfaces", None)
+ facts = {"acl_interfaces": []}
+ params = utils.validate_config(self.argument_spec, {"config": entry})
+ for cfg in params["config"]:
+ facts["acl_interfaces"].append(utils.remove_empties(cfg))
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acls/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acls/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acls/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acls/acls.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acls/acls.py
new file mode 100644
index 00000000..32375b7f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acls/acls.py
@@ -0,0 +1,457 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr acls fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from copy import deepcopy
+
+from collections import deque
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.acls.acls import (
+ AclsArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ isipaddress,
+)
+
+PROTOCOL_OPTIONS = {
+ "tcp": ("ack", "fin", "psh", "rst", "syn", "urg", "established"),
+ "igmp": (
+ "dvmrp",
+ "host_query",
+ "host_report",
+ "mtrace",
+ "mtrace_response",
+ "pim",
+ "trace",
+ "v2_leave",
+ "v2_report",
+ "v3_report",
+ ),
+ "icmp": (
+ "administratively_prohibited",
+ "alternate_address",
+ "conversion_error",
+ "dod_host_prohibited",
+ "dod_net_prohibited",
+ "echo",
+ "echo_reply",
+ "general_parameter_problem",
+ "host_isolated",
+ "host_precedence_unreachable",
+ "host_redirect",
+ "host_tos_redirect",
+ "host_tos_unreachable",
+ "host_unknown",
+ "host_unreachable",
+ "information_reply",
+ "information_request",
+ "mask_reply",
+ "mask_request",
+ "mobile_redirect",
+ "net_redirect",
+ "net_tos_redirect",
+ "net_tos_unreachable",
+ "net_unreachable",
+ "network_unknown",
+ "no_room_for_option",
+ "option_missing",
+ "packet_too_big",
+ "parameter_problem",
+ "port_unreachable",
+ "precedence_unreachable",
+ "protocol_unreachable",
+ "reassembly_timeout",
+ "redirect",
+ "router_advertisement",
+ "router_solicitation",
+ "source_quench",
+ "source_route_failed",
+ "time_exceeded",
+ "timestamp_reply",
+ "timestamp_request",
+ "traceroute",
+ "ttl_exceeded",
+ "unreachable",
+ ),
+ "icmpv6": (
+ "address_unreachable",
+ "administratively_prohibited",
+ "beyond_scope_of_source_address",
+ "destination_unreachable",
+ "echo",
+ "echo_reply",
+ "erroneous_header_field",
+ "group_membership_query",
+ "group_membership_report",
+ "group_membership_termination",
+ "host_unreachable",
+ "nd_na",
+ "nd_ns",
+ "neighbor_redirect",
+ "no_route_to_destination",
+ "node_information_request_is_refused",
+ "node_information_successful_reply",
+ "packet_too_big",
+ "parameter_problem",
+ "port_unreachable",
+ "query_subject_is_IPv4address",
+ "query_subject_is_IPv6address",
+ "query_subject_is_domainname",
+ "reassembly_timeout",
+ "redirect",
+ "router_advertisement",
+ "router_renumbering",
+ "router_solicitation",
+ "rr_command",
+ "rr_result",
+ "rr_seqnum_reset",
+ "time_exceeded",
+ "ttl_exceeded",
+ "unknown_query_type",
+ "unreachable",
+ "unrecognized_next_header",
+ "unrecognized_option",
+ "whoareyou_reply",
+ "whoareyou_request",
+ ),
+}
+
+
+class AclsFacts(object):
+ """ The iosxr acls fact class
+ """
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = AclsArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_device_data(self, connection):
+ return connection.get("show access-lists afi-all")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """ Populate the facts for acls
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+ if not data:
+ data = self.get_device_data(connection)
+
+ objs = []
+
+ acl_lines = data.splitlines()
+
+ # We iterate through the data and create a list of ACLs
+ # where each ACL is a dictionary in the following format:
+ # {'afi': 'ipv4', 'name': 'acl_1', 'aces': ['10 permit 172.16.0.0 0.0.255.255', '20 deny 192.168.34.0 0.0.0.255']}
+ if acl_lines:
+ acl, acls = {}, []
+ for line in acl_lines:
+ if line.startswith("ip"):
+ if acl:
+ acls.append(acl)
+ acl = {"aces": []}
+ acl["afi"], acl["name"] = line.split()[0], line.split()[2]
+ else:
+ acl["aces"].append(line.strip())
+ acls.append(acl)
+
+ # Here we group the ACLs based on AFI
+ # {
+ # 'ipv6': [{'aces': ['10 permit ipv6 2000::/12 any'], 'name': 'acl_2'}],
+ # 'ipv4': [{'aces': ['10 permit 172.16.0.0 0.0.255.255', '20 deny 192.168.34.0 0.0.0.255'], 'name': 'acl_1'},
+ # {'aces': ['20 deny 10.0.0.0/8 log'], 'name': 'acl_3'}]
+ # }
+
+ grouped_acls = {"ipv4": [], "ipv6": []}
+ for acl in acls:
+ acl_copy = deepcopy(acl)
+ del acl_copy["afi"]
+ grouped_acls[acl["afi"]].append(acl_copy)
+
+ # Now that we have the ACLs in a fairly structured format,
+ # we pass it on to render_config to convert it to model spec
+ for key, value in iteritems(grouped_acls):
+ obj = self.render_config(self.generated_spec, value)
+ if obj:
+ obj["afi"] = key
+ objs.append(obj)
+
+ ansible_facts["ansible_network_resources"].pop("acls", None)
+ facts = {}
+
+ facts["acls"] = []
+ params = utils.validate_config(self.argument_spec, {"config": objs})
+ for cfg in params["config"]:
+ facts["acls"].append(utils.remove_empties(cfg))
+
+ ansible_facts["ansible_network_resources"].update(facts)
+
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys
+ from spec for null values
+
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+ config["acls"] = []
+
+ for item in conf:
+ acl = {"name": item["name"]}
+ aces = item.get("aces", [])
+ if aces:
+ acl["aces"] = []
+ for ace in aces:
+ acl["aces"].append(self._render_ace(ace))
+ config["acls"].append(acl)
+
+ return utils.remove_empties(config)
+
+ def _render_ace(self, ace):
+ """
+ Parses an Access Control Entry (ACE) and converts it
+ into model spec
+
+ :param ace: An ACE in device specific format
+ :rtype: dictionary
+ :returns: The ACE in structured format
+ """
+
+ def __parse_src_dest(rendered_ace, ace_queue, direction):
+ """
+ Parses the ACE queue and populates address, wildcard_bits,
+ host or any keys in the source/destination dictionary of
+ ace dictionary, i.e., `rendered_ace`.
+
+ :param rendered_ace: The dictionary containing the ACE in structured format
+ :param ace_queue: The ACE queue
+ :param direction: Specifies whether to populate `source` or `destination`
+ dictionary
+ """
+ element = ace_queue.popleft()
+ if element == "host":
+ rendered_ace[direction] = {"host": ace_queue.popleft()}
+
+ elif element == "any":
+ rendered_ace[direction] = {"any": True}
+
+ elif "/" in element:
+ rendered_ace[direction] = {"prefix": element}
+
+ elif isipaddress(element):
+ rendered_ace[direction] = {
+ "address": element,
+ "wildcard_bits": ace_queue.popleft(),
+ }
+
+ def __parse_port_protocol(rendered_ace, ace_queue, direction):
+ """
+ Parses the ACE queue and populates `port_protocol` dictionary in the
+ ACE dictionary, i.e., `rendered_ace`.
+
+ :param rendered_ace: The dictionary containing the ACE in structured format
+ :param ace_queue: The ACE queue
+ :param direction: Specifies whether to populate `source` or `destination`
+ dictionary
+ """
+ if len(ace_queue) > 0 and ace_queue[0] in (
+ "eq",
+ "gt",
+ "lt",
+ "neq",
+ "range",
+ ):
+ element = ace_queue.popleft()
+ port_protocol = {}
+
+ if element == "range":
+ port_protocol["range"] = {
+ "start": ace_queue.popleft(),
+ "end": ace_queue.popleft(),
+ }
+ else:
+ port_protocol[element] = ace_queue.popleft()
+
+ rendered_ace[direction]["port_protocol"] = port_protocol
+
+ def __parse_protocol_options(rendered_ace, ace_queue, protocol):
+ """
+ Parses the ACE queue and populates protocol specific options
+ of the required dictionary and updates the ACE dictionary, i.e.,
+ `rendered_ace`.
+
+ :param rendered_ace: The dictionary containing the ACE in structured format
+ :param ace_queue: The ACE queue
+ :param protocol: Specifies the protocol that will be populated under
+ `protocol_options` dictionary
+ """
+ if len(ace_queue) > 0:
+ protocol_options = {protocol: {}}
+
+ for match_bit in PROTOCOL_OPTIONS.get(protocol, ()):
+ if match_bit.replace("_", "-") in ace_queue:
+ protocol_options[protocol][match_bit] = True
+ ace_queue.remove(match_bit.replace("_", "-"))
+
+ rendered_ace["protocol_options"] = protocol_options
+
+ def __parse_match_options(rendered_ace, ace_queue):
+ """
+ Parses the ACE queue and populates remaining options in the ACE dictionary,
+ i.e., `rendered_ace`
+
+ :param rendered_ace: The dictionary containing the ACE in structured format
+ :param ace_queue: The ACE queue
+ """
+ if len(ace_queue) > 0:
+ # We deepcopy the actual queue and iterate through the
+ # copied queue. However, we pop off the elements from
+ # the actual queue. Then, in every pass we update the copied
+ # queue with the current state of the original queue.
+ # This is done because a queue cannot be mutated during iteration.
+ copy_ace_queue = deepcopy(ace_queue)
+
+ for element in copy_ace_queue:
+ if element == "precedence":
+ ace_queue.popleft()
+ rendered_ace["precedence"] = ace_queue.popleft()
+
+ elif element == "dscp":
+ ace_queue.popleft()
+ dscp = {}
+ operation = ace_queue.popleft()
+
+ if operation in ("eq", "gt", "neq", "lt", "range"):
+ if operation == "range":
+ dscp["range"] = {
+ "start": ace_queue.popleft(),
+ "end": ace_queue.popleft(),
+ }
+ else:
+ dscp[operation] = ace_queue.popleft()
+ else:
+ # `dscp` can be followed by either the dscp value itself or
+ # the same thing can be represented using "dscp eq <dscp_value>".
+ # In both cases, it would show up as {'dscp': {'eq': "dscp_value"}}.
+ dscp["eq"] = operation
+
+ rendered_ace["dscp"] = dscp
+
+ elif element in ("packet-length", "ttl"):
+ ace_queue.popleft()
+ element_dict = {}
+ operation = ace_queue.popleft()
+
+ if operation == "range":
+ element_dict["range"] = {
+ "start": ace_queue.popleft(),
+ "end": ace_queue.popleft(),
+ }
+ else:
+ element_dict[operation] = ace_queue.popleft()
+
+ rendered_ace[element.replace("-", "_")] = element_dict
+
+ elif element in (
+ "log",
+ "log-input",
+ "fragments",
+ "icmp-off",
+ "capture",
+ "destopts",
+ "authen",
+ "routing",
+ "hop-by-hop",
+ ):
+ rendered_ace[element.replace("-", "_")] = True
+ ace_queue.remove(element)
+
+ copy_ace_queue = deepcopy(ace_queue)
+
+ rendered_ace = {}
+ split_ace = ace.split()
+
+ # Create a queue with each word in the ace
+ # We parse each element and pop it off the queue
+ ace_queue = deque(split_ace)
+
+ # An ACE will always have a sequence number, even if
+ # it is not explicitly provided while configuring
+ sequence = int(ace_queue.popleft())
+ rendered_ace["sequence"] = sequence
+ operation = ace_queue.popleft()
+
+ if operation == "remark":
+ rendered_ace["remark"] = " ".join(split_ace[2:])
+
+ else:
+ rendered_ace["grant"] = operation
+
+ # If the entry is a non-remark entry, the third element
+ # will always be the protocol specified. By default, it's
+ # the AFI.
+ rendered_ace["protocol"] = ace_queue.popleft()
+
+ # Populate source dictionary
+ __parse_src_dest(rendered_ace, ace_queue, direction="source")
+ # Populate port_protocol key in source dictionary
+ __parse_port_protocol(rendered_ace, ace_queue, direction="source")
+ # Populate destination dictionary
+ __parse_src_dest(rendered_ace, ace_queue, direction="destination")
+ # Populate port_protocol key in destination dictionary
+ __parse_port_protocol(
+ rendered_ace, ace_queue, direction="destination"
+ )
+ # Populate protocol_options dictionary
+ __parse_protocol_options(
+ rendered_ace, ace_queue, protocol=rendered_ace["protocol"]
+ )
+ # Populate remaining match options' dictionaries
+ __parse_match_options(rendered_ace, ace_queue)
+
+ # At this stage the queue should be empty
+ # If the queue is not empty, it means that
+ # we haven't been able to parse the entire ACE
+ # In this case, we add the whole unprocessed ACE
+ # to a key called `line` and send it back
+ if len(ace_queue) > 0:
+ rendered_ace = {
+ "sequence": sequence,
+ "line": " ".join(split_ace[1:]),
+ }
+
+ return utils.remove_empties(rendered_ace)
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/facts.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/facts.py
new file mode 100644
index 00000000..1441ef6d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/facts.py
@@ -0,0 +1,122 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The facts class for iosxr
+this file validates each subset of facts and selectively
+calls the appropriate facts gathering function
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts import (
+ FactsBase,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.legacy.base import (
+ Default,
+ Hardware,
+ Interfaces,
+ Config,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lacp.lacp import (
+ LacpFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lacp_interfaces.lacp_interfaces import (
+ Lacp_interfacesFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lldp_global.lldp_global import (
+ Lldp_globalFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lldp_interfaces.lldp_interfaces import (
+ Lldp_interfacesFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.interfaces.interfaces import (
+ InterfacesFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lag_interfaces.lag_interfaces import (
+ Lag_interfacesFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.l2_interfaces.l2_interfaces import (
+ L2_InterfacesFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.l3_interfaces.l3_interfaces import (
+ L3_InterfacesFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.acl_interfaces.acl_interfaces import (
+ Acl_interfacesFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.acls.acls import (
+ AclsFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.static_routes.static_routes import (
+ Static_routesFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.ospfv2.ospfv2 import (
+ Ospfv2Facts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.ospfv3.ospfv3 import (
+ Ospfv3Facts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.ospf_interfaces.ospf_interfaces import (
+ Ospf_interfacesFacts,
+)
+
+
+FACT_LEGACY_SUBSETS = dict(
+ default=Default, hardware=Hardware, interfaces=Interfaces, config=Config
+)
+FACT_RESOURCE_SUBSETS = dict(
+ lacp=LacpFacts,
+ lacp_interfaces=Lacp_interfacesFacts,
+ lldp_global=Lldp_globalFacts,
+ lldp_interfaces=Lldp_interfacesFacts,
+ interfaces=InterfacesFacts,
+ l2_interfaces=L2_InterfacesFacts,
+ lag_interfaces=Lag_interfacesFacts,
+ l3_interfaces=L3_InterfacesFacts,
+ acl_interfaces=Acl_interfacesFacts,
+ acls=AclsFacts,
+ static_routes=Static_routesFacts,
+ ospfv2=Ospfv2Facts,
+ ospfv3=Ospfv3Facts,
+ ospf_interfaces=Ospf_interfacesFacts,
+)
+
+
+class Facts(FactsBase):
+ """ The fact class for iosxr
+ """
+
+ VALID_LEGACY_GATHER_SUBSETS = frozenset(FACT_LEGACY_SUBSETS.keys())
+ VALID_RESOURCE_SUBSETS = frozenset(FACT_RESOURCE_SUBSETS.keys())
+
+ def __init__(self, module):
+ super(Facts, self).__init__(module)
+
+ def get_facts(
+ self, legacy_facts_type=None, resource_facts_type=None, data=None
+ ):
+ """ Collect the facts for iosxr
+
+ :param legacy_facts_type: List of legacy facts types
+ :param resource_facts_type: List of resource fact types
+ :param data: previously collected conf
+ :rtype: dict
+ :return: the facts gathered
+ """
+ if self.VALID_RESOURCE_SUBSETS:
+ self.get_network_resources_facts(
+ FACT_RESOURCE_SUBSETS, resource_facts_type, data
+ )
+
+ if self.VALID_LEGACY_GATHER_SUBSETS:
+ self.get_network_legacy_facts(
+ FACT_LEGACY_SUBSETS, legacy_facts_type
+ )
+
+ return self.ansible_facts, self._warnings
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/interfaces.py
new file mode 100644
index 00000000..bc4450fc
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/interfaces.py
@@ -0,0 +1,110 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat Inc.
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr interfaces fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from copy import deepcopy
+import re
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ get_interface_type,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.interfaces.interfaces import (
+ InterfacesArgs,
+)
+
+
+class InterfacesFacts(object):
+ """ The iosxr interfaces fact class
+ """
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = InterfacesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """ Populate the facts for interfaces
+ :param module: the module instance
+ :param connection: the device connection
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+ objs = []
+ if not data:
+ data = connection.get("show running-config interface")
+
+ # operate on a collection of resource x
+ config = ("\n" + data).split("\ninterface ")
+ for conf in config:
+ if conf:
+ obj = self.render_config(self.generated_spec, conf)
+ if obj:
+ objs.append(obj)
+
+ facts = {}
+ if objs:
+ facts["interfaces"] = []
+ params = utils.validate_config(
+ self.argument_spec, {"config": objs}
+ )
+ for cfg in params["config"]:
+ facts["interfaces"].append(utils.remove_empties(cfg))
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys from spec for null values
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+
+ config = deepcopy(spec)
+ match = re.search(r"^(\S+)", conf)
+
+ intf = match.group(1)
+ if match.group(1).lower() == "preconfigure":
+ match = re.search(r"^(\S+) (.*)", conf)
+ if match:
+ intf = match.group(2)
+
+ if get_interface_type(intf) == "unknown":
+ return {}
+ # populate the facts from the configuration
+ config["name"] = intf
+ config["description"] = utils.parse_conf_arg(conf, "description")
+ if utils.parse_conf_arg(conf, "speed"):
+ config["speed"] = int(utils.parse_conf_arg(conf, "speed"))
+ if utils.parse_conf_arg(conf, "mtu"):
+ config["mtu"] = int(utils.parse_conf_arg(conf, "mtu"))
+ config["duplex"] = utils.parse_conf_arg(conf, "duplex")
+ enabled = utils.parse_conf_cmd_arg(conf, "shutdown", False)
+ config["enabled"] = enabled if enabled is not None else True
+
+ return utils.remove_empties(config)
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/l2_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/l2_interfaces.py
new file mode 100644
index 00000000..82220d89
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/l2_interfaces.py
@@ -0,0 +1,134 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat Inc.
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr l2_interfaces fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+from copy import deepcopy
+import re
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ get_interface_type,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.l2_interfaces.l2_interfaces import (
+ L2_InterfacesArgs,
+)
+
+
+class L2_InterfacesFacts(object):
+ """ The iosxr l2_interfaces fact class
+ """
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = L2_InterfacesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """ Populate the facts for l2_interfaces
+ :param module: the module instance
+ :param connection: the device connection
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+ objs = []
+ if not data:
+ data = connection.get("show running-config interface")
+
+ # operate on a collection of resource x
+ config = ("\n" + data).split("\ninterface ")
+ for conf in config:
+ if conf:
+ obj = self.render_config(self.generated_spec, conf)
+ if obj:
+ objs.append(obj)
+ facts = {}
+ if objs:
+ facts["l2_interfaces"] = []
+ params = utils.validate_config(
+ self.argument_spec, {"config": objs}
+ )
+ for cfg in params["config"]:
+ facts["l2_interfaces"].append(utils.remove_empties(cfg))
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys from spec for null values
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+ match = re.search(r"^(\S+)", conf)
+
+ intf = match.group(1)
+
+ if match.group(1).lower() == "preconfigure":
+ match = re.search(r"^(\S+) (.*)", conf)
+ if match:
+ intf = match.group(2)
+
+ if get_interface_type(intf) == "unknown":
+ return {}
+
+ if intf.lower().startswith("gi"):
+ config["name"] = intf
+
+ # populate the facts from the configuration
+ native_vlan = re.search(r"dot1q native vlan (\d+)", conf)
+ if native_vlan:
+ config["native_vlan"] = int(native_vlan.group(1))
+
+ dot1q = utils.parse_conf_arg(conf, "encapsulation dot1q")
+ config["q_vlan"] = []
+ if dot1q:
+ config["q_vlan"].append(int(dot1q.split(" ")[0]))
+ if len(dot1q.split(" ")) > 1:
+ config["q_vlan"].append(int(dot1q.split(" ")[2]))
+
+ if utils.parse_conf_cmd_arg(conf, "l2transport", True):
+ config["l2transport"] = True
+ if utils.parse_conf_arg(conf, "propagate"):
+ config["propagate"] = True
+ config["l2protocol"] = []
+
+ cdp = utils.parse_conf_arg(conf, "l2protocol cdp")
+ pvst = utils.parse_conf_arg(conf, "l2protocol pvst")
+ stp = utils.parse_conf_arg(conf, "l2protocol stp")
+ vtp = utils.parse_conf_arg(conf, "l2protocol vtp")
+ if cdp:
+ config["l2protocol"].append({"cdp": cdp})
+ if pvst:
+ config["l2protocol"].append({"pvst": pvst})
+ if stp:
+ config["l2protocol"].append({"stp": stp})
+ if vtp:
+ config["l2protocol"].append({"vtp": vtp})
+
+ return utils.remove_empties(config)
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/l3_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/l3_interfaces.py
new file mode 100644
index 00000000..5bc589d3
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/l3_interfaces.py
@@ -0,0 +1,126 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_l3_interfaces fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+from copy import deepcopy
+import re
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ get_interface_type,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.l3_interfaces.l3_interfaces import (
+ L3_InterfacesArgs,
+)
+
+
+class L3_InterfacesFacts(object):
+ """ The iosxr_l3_interfaces fact class
+ """
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = L3_InterfacesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """ Populate the facts for interfaces
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+ objs = []
+
+ if not data:
+ data = connection.get("show running-config interface")
+ # operate on a collection of resource x
+ config = ("\n" + data).split("\ninterface ")
+ for conf in config:
+ if conf:
+ obj = self.render_config(self.generated_spec, conf)
+ if obj:
+ objs.append(obj)
+ facts = {}
+
+ if objs:
+ facts["l3_interfaces"] = []
+ params = utils.validate_config(
+ self.argument_spec, {"config": objs}
+ )
+ for cfg in params["config"]:
+ facts["l3_interfaces"].append(utils.remove_empties(cfg))
+ ansible_facts["ansible_network_resources"].update(facts)
+
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys from spec for null values
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+ match = re.search(r"^(\S+)", conf)
+
+ intf = match.group(1)
+ if match.group(1).lower() == "preconfigure":
+ match = re.search(r"^(\S+) (.*)", conf)
+ if match:
+ intf = match.group(2)
+
+ if get_interface_type(intf) == "unknown":
+ return {}
+
+ # populate the facts from the configuration
+ config["name"] = intf
+
+ # Get the configured IPV4 details
+ ipv4 = []
+ ipv4_all = re.findall(r"ipv4 address (\S+.*)", conf)
+ for each in ipv4_all:
+ each_ipv4 = dict()
+ if "secondary" in each:
+ each_ipv4["address"] = each.split(" secondary")[0]
+ each_ipv4["secondary"] = True
+ else:
+ each_ipv4["address"] = each
+ ipv4.append(each_ipv4)
+ config["ipv4"] = ipv4
+
+ # Get the configured IPV6 details
+ ipv6 = []
+ ipv6_all = re.findall(r"ipv6 address (\S+)", conf)
+ for each in ipv6_all:
+ each_ipv6 = dict()
+ each_ipv6["address"] = each
+ ipv6.append(each_ipv6)
+ config["ipv6"] = ipv6
+
+ return utils.remove_empties(config)
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp/lacp.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp/lacp.py
new file mode 100644
index 00000000..e052f116
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp/lacp.py
@@ -0,0 +1,89 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr lacp fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+from copy import deepcopy
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lacp.lacp import (
+ LacpArgs,
+)
+
+
+class LacpFacts(object):
+ """ The iosxr lacp fact class
+ """
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = LacpArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """ Populate the facts for lacp
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+ if not data:
+ data = connection.get_config(flags="lacp")
+
+ obj = {}
+ if data:
+ lacp_obj = self.render_config(self.generated_spec, data)
+ if lacp_obj:
+ obj = lacp_obj
+
+ ansible_facts["ansible_network_resources"].pop("lacp", None)
+ facts = {}
+
+ params = utils.validate_config(self.argument_spec, {"config": obj})
+ facts["lacp"] = utils.remove_empties(params["config"])
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys
+ from spec for null values
+
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+
+ system_priority = utils.parse_conf_arg(conf, "priority")
+ config["system"]["priority"] = (
+ int(system_priority) if system_priority else system_priority
+ )
+ config["system"]["mac"]["address"] = utils.parse_conf_arg(conf, "mac")
+
+ return config
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp_interfaces/lacp_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp_interfaces/lacp_interfaces.py
new file mode 100644
index 00000000..8cb5fcda
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp_interfaces/lacp_interfaces.py
@@ -0,0 +1,115 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr lacp_interfaces fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+import re
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lacp_interfaces.lacp_interfaces import (
+ Lacp_interfacesArgs,
+)
+from ansible.module_utils.six import iteritems
+
+
+class Lacp_interfacesFacts(object):
+ """ The iosxr lacp_interfaces fact class
+ """
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Lacp_interfacesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """ Populate the facts for lacp_interfaces
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+
+ if not data:
+ data = connection.get_config(flags="interface")
+ interfaces = ("\n" + data).split("\ninterface ")
+
+ objs = []
+ for interface in interfaces:
+ obj = self.render_config(self.generated_spec, interface)
+ if obj:
+ objs.append(obj)
+
+ ansible_facts["ansible_network_resources"].pop("lacp_interfaces", None)
+ facts = {}
+ if objs:
+ facts["lacp_interfaces"] = []
+ params = utils.validate_config(
+ self.argument_spec, {"config": objs}
+ )
+ for cfg in params["config"]:
+ facts["lacp_interfaces"].append(utils.remove_empties(cfg))
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys
+ from spec for null values
+
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+
+ match = re.search(
+ r"(GigabitEthernet|Bundle-Ether|TenGigE|FortyGigE|HundredGigE)(\S+)",
+ conf,
+ re.M,
+ )
+ if match:
+ config["name"] = match.group(1) + match.group(2)
+
+ temp = {
+ "churn_logging": "lacp churn logging",
+ "switchover_suppress_flaps": "lacp switchover suppress-flaps",
+ "collector_max_delay": "lacp collector-max-delay",
+ "period": "lacp period",
+ }
+
+ for key, value in iteritems(temp):
+ config[key] = utils.parse_conf_arg(conf, value)
+
+ for key in config["system"].keys():
+ config["system"][key] = utils.parse_conf_arg(
+ conf, "lacp system {0}".format(key)
+ )
+
+ return utils.remove_empties(config)
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lag_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lag_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lag_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lag_interfaces/lag_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lag_interfaces/lag_interfaces.py
new file mode 100644
index 00000000..2b911398
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lag_interfaces/lag_interfaces.py
@@ -0,0 +1,141 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr lag_interfaces fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+import re
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lag_interfaces.lag_interfaces import (
+ Lag_interfacesArgs,
+)
+
+
+class Lag_interfacesFacts(object):
+ """ The iosxr lag_interfaces fact class
+ """
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Lag_interfacesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """ Populate the facts for lag_interfaces
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+
+ if not data:
+ data = connection.get_config(flags="interface")
+ interfaces = ("\n" + data).split("\ninterface ")
+
+ objs = []
+
+ for interface in interfaces:
+ if interface.startswith("Bundle-Ether"):
+ obj = self.render_config(
+ self.generated_spec, interface, interfaces
+ )
+ if obj:
+ objs.append(obj)
+
+ ansible_facts["ansible_network_resources"].pop("lag_interfaces", None)
+ facts = {}
+
+ facts["lag_interfaces"] = []
+ params = utils.validate_config(self.argument_spec, {"config": objs})
+ for cfg in params["config"]:
+ facts["lag_interfaces"].append(utils.remove_empties(cfg))
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, spec, conf, data):
+ """
+ Render config as dictionary structure and delete keys
+ from spec for null values
+
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+ match = re.search(r"(Bundle-Ether)(\d+)", conf, re.M)
+ if match:
+ config["name"] = match.group(1) + match.group(2)
+ config["load_balancing_hash"] = utils.parse_conf_arg(
+ conf, "bundle load-balancing hash"
+ )
+ config["mode"] = utils.parse_conf_arg(conf, "lacp mode")
+ config["links"]["max_active"] = utils.parse_conf_arg(
+ conf, "bundle maximum-active links"
+ )
+ config["links"]["min_active"] = utils.parse_conf_arg(
+ conf, "bundle minimum-active links"
+ )
+ config["members"] = self.parse_members(match.group(2), data)
+
+ return utils.remove_empties(config)
+
+ def parse_members(self, bundle_id, interfaces):
+ """
+ Renders a list of member interfaces for every bundle
+ present in running-config.
+
+ :param bundle_id: The Bundle-Ether ID fetched from running-config
+ :param interfaces: Data of all interfaces present in running-config
+ :rtype: list
+ :returns: A list of member interfaces
+ """
+
+ def _parse_interface(name):
+ if name.startswith("preconfigure"):
+ return name.split()[1]
+ else:
+ return name.split()[0]
+
+ members = []
+ for interface in interfaces:
+ if not interface.startswith("Bu"):
+ match = re.search(
+ r"bundle id (\d+) mode (\S+)", interface, re.M
+ )
+ if match:
+ if bundle_id == match.group(1):
+ members.append(
+ {
+ "member": _parse_interface(interface),
+ "mode": match.group(2),
+ }
+ )
+
+ return members
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/base.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/base.py
new file mode 100644
index 00000000..463190cd
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/base.py
@@ -0,0 +1,261 @@
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+"""
+The iosxr legacy fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+import platform
+import re
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ run_commands,
+ get_capabilities,
+)
+from ansible.module_utils.six import iteritems
+from ansible.module_utils.six.moves import zip
+
+
+class FactsBase(object):
+
+ COMMANDS = frozenset()
+
+ def __init__(self, module):
+ self.module = module
+ self.facts = dict()
+ self.warnings = list()
+ self.responses = None
+
+ def populate(self):
+ self.responses = run_commands(
+ self.module, list(self.COMMANDS), check_rc=False
+ )
+
+
+class Default(FactsBase):
+ def populate(self):
+ self.facts.update(self.platform_facts())
+
+ def platform_facts(self):
+ platform_facts = {}
+
+ resp = get_capabilities(self.module)
+ device_info = resp["device_info"]
+
+ platform_facts["system"] = device_info["network_os"]
+
+ for item in ("model", "image", "version", "platform", "hostname"):
+ val = device_info.get("network_os_%s" % item)
+ if val:
+ platform_facts[item] = val
+
+ platform_facts["api"] = resp["network_api"]
+ platform_facts["python_version"] = platform.python_version()
+
+ return platform_facts
+
+
+class Hardware(FactsBase):
+
+ COMMANDS = ["dir /all", "show memory summary"]
+
+ def populate(self):
+ super(Hardware, self).populate()
+ data = self.responses[0]
+ self.facts["filesystems"] = self.parse_filesystems(data)
+
+ data = self.responses[1]
+ match = re.search(r"Physical Memory: (\d+)M total \((\d+)", data)
+ if match:
+ self.facts["memtotal_mb"] = match.group(1)
+ self.facts["memfree_mb"] = match.group(2)
+
+ def parse_filesystems(self, data):
+ return re.findall(r"^Directory of (\S+)", data, re.M)
+
+
+class Config(FactsBase):
+
+ COMMANDS = ["show running-config"]
+
+ def populate(self):
+ super(Config, self).populate()
+ self.facts["config"] = self.responses[0]
+
+
+class Interfaces(FactsBase):
+
+ COMMANDS = [
+ "show interfaces",
+ "show ipv6 interface",
+ "show lldp",
+ "show lldp neighbors detail",
+ ]
+
+ def populate(self):
+ super(Interfaces, self).populate()
+ self.facts["all_ipv4_addresses"] = list()
+ self.facts["all_ipv6_addresses"] = list()
+
+ interfaces = self.parse_interfaces(self.responses[0])
+ self.facts["interfaces"] = self.populate_interfaces(interfaces)
+
+ data = self.responses[1]
+ if len(data) > 0:
+ data = self.parse_interfaces(data)
+ self.populate_ipv6_interfaces(data)
+
+ if "LLDP is not enabled" not in self.responses[2]:
+ neighbors = self.responses[3]
+ self.facts["neighbors"] = self.parse_neighbors(neighbors)
+
+ def populate_interfaces(self, interfaces):
+ facts = dict()
+ for key, value in iteritems(interfaces):
+ intf = dict()
+ intf["description"] = self.parse_description(value)
+ intf["macaddress"] = self.parse_macaddress(value)
+
+ ipv4 = self.parse_ipv4(value)
+ intf["ipv4"] = self.parse_ipv4(value)
+ if ipv4:
+ self.add_ip_address(ipv4["address"], "ipv4")
+
+ intf["mtu"] = self.parse_mtu(value)
+ intf["bandwidth"] = self.parse_bandwidth(value)
+ intf["duplex"] = self.parse_duplex(value)
+ intf["lineprotocol"] = self.parse_lineprotocol(value)
+ intf["operstatus"] = self.parse_operstatus(value)
+ intf["type"] = self.parse_type(value)
+
+ facts[key] = intf
+ return facts
+
+ def populate_ipv6_interfaces(self, data):
+ for key, value in iteritems(data):
+ if key in ["No", "RPF"] or key.startswith("IP"):
+ continue
+ self.facts["interfaces"][key]["ipv6"] = list()
+ addresses = re.findall(r"\s+(.+), subnet", value, re.M)
+ subnets = re.findall(r", subnet is (.+)$", value, re.M)
+ for addr, subnet in zip(addresses, subnets):
+ ipv6 = dict(address=addr.strip(), subnet=subnet.strip())
+ self.add_ip_address(addr.strip(), "ipv6")
+ self.facts["interfaces"][key]["ipv6"].append(ipv6)
+
+ def add_ip_address(self, address, family):
+ if family == "ipv4":
+ self.facts["all_ipv4_addresses"].append(address)
+ else:
+ self.facts["all_ipv6_addresses"].append(address)
+
+ def parse_neighbors(self, neighbors):
+ facts = dict()
+ nbors = neighbors.split(
+ "------------------------------------------------"
+ )
+ for entry in nbors[1:]:
+ if entry == "":
+ continue
+ intf = self.parse_lldp_intf(entry)
+ if intf not in facts:
+ facts[intf] = list()
+ fact = dict()
+ fact["host"] = self.parse_lldp_host(entry)
+ fact["remote_description"] = self.parse_lldp_remote_desc(entry)
+ fact["port"] = self.parse_lldp_port(entry)
+ facts[intf].append(fact)
+ return facts
+
+ def parse_interfaces(self, data):
+ parsed = dict()
+ key = ""
+ for line in data.split("\n"):
+ if len(line) == 0:
+ continue
+ if line[0] == " ":
+ parsed[key] += "\n%s" % line
+ else:
+ match = re.match(r"^(\S+)", line)
+ if match:
+ key = match.group(1)
+ parsed[key] = line
+ return parsed
+
+ def parse_description(self, data):
+ match = re.search(r"Description: (.+)$", data, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_macaddress(self, data):
+ match = re.search(r"address is (\S+)", data)
+ if match:
+ return match.group(1)
+
+ def parse_ipv4(self, data):
+ match = re.search(r"Internet address is (\S+)/(\d+)", data)
+ if match:
+ addr = match.group(1)
+ masklen = int(match.group(2))
+ return dict(address=addr, masklen=masklen)
+
+ def parse_mtu(self, data):
+ match = re.search(r"MTU (\d+)", data)
+ if match:
+ return int(match.group(1))
+
+ def parse_bandwidth(self, data):
+ match = re.search(r"BW (\d+)", data)
+ if match:
+ return int(match.group(1))
+
+ def parse_duplex(self, data):
+ match = re.search(r"(\w+)(?: D|-d)uplex", data, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_type(self, data):
+ match = re.search(r"Hardware is (.+),", data, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_lineprotocol(self, data):
+ match = re.search(r"line protocol is (.+)\s+?$", data, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_operstatus(self, data):
+ match = re.search(r"^(?:.+) is (.+),", data, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_lldp_intf(self, data):
+ match = re.search(r"^Local Interface: (.+)$", data, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_lldp_remote_desc(self, data):
+ match = re.search(r"Port Description: (.+)$", data, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_lldp_host(self, data):
+ match = re.search(r"System Name: (.+)$", data, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_lldp_port(self, data):
+ match = re.search(r"Port id: (.+)$", data, re.M)
+ if match:
+ return match.group(1)
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_global/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_global/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_global/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_global/lldp_global.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_global/lldp_global.py
new file mode 100644
index 00000000..13d7f0cf
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_global/lldp_global.py
@@ -0,0 +1,107 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr lldp fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lldp_global.lldp_global import (
+ Lldp_globalArgs,
+)
+
+
+class Lldp_globalFacts(object):
+ """ The iosxr lldp fact class
+ """
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Lldp_globalArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """ Populate the facts for lldp
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+ if not data:
+ data = connection.get_config(flags="lldp")
+
+ obj = {}
+ if data:
+ lldp_obj = self.render_config(self.generated_spec, data)
+ if lldp_obj:
+ obj = lldp_obj
+
+ ansible_facts["ansible_network_resources"].pop("lldp_global", None)
+ facts = {}
+
+ params = utils.validate_config(self.argument_spec, {"config": obj})
+ facts["lldp_global"] = utils.remove_empties(params["config"])
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys
+ from spec for null values
+
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+
+ for key in spec.keys():
+ if key == "subinterfaces":
+ config[key] = True if "subinterfaces enable" in conf else None
+
+ elif key == "tlv_select":
+ for item in [
+ "system_name",
+ "port_description",
+ "management_address",
+ "system_description",
+ "system_capabilities",
+ ]:
+ config[key][item] = (
+ False
+ if ("{0} disable".format(item.replace("_", "-")))
+ in conf
+ else None
+ )
+
+ else:
+ value = utils.parse_conf_arg(conf, key)
+ config[key] = int(value) if value else value
+
+ return config
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_interfaces/lldp_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_interfaces/lldp_interfaces.py
new file mode 100644
index 00000000..57fbc425
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_interfaces/lldp_interfaces.py
@@ -0,0 +1,109 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr lldp_interfaces fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+import re
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lldp_interfaces.lldp_interfaces import (
+ Lldp_interfacesArgs,
+)
+
+
+class Lldp_interfacesFacts(object):
+ """ The iosxr lldp_interfaces fact class
+ """
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Lldp_interfacesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """ Populate the facts for lldp_interfaces
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+
+ if not data:
+ data = connection.get_config(flags="interface")
+ interfaces = ("\n" + data).split("\ninterface ")
+
+ objs = []
+ for interface in interfaces:
+ obj = self.render_config(self.generated_spec, interface)
+ if obj:
+ objs.append(obj)
+
+ ansible_facts["ansible_network_resources"].pop("lldp_interfaces", None)
+ facts = {}
+
+ if objs:
+ facts["lldp_interfaces"] = []
+ params = utils.validate_config(
+ self.argument_spec, {"config": objs}
+ )
+ for cfg in params["config"]:
+ facts["lldp_interfaces"].append(utils.remove_empties(cfg))
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys
+ from spec for null values
+
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+
+ match = re.search(
+ r"(GigabitEthernet|Bundle-Ether|TenGigE|FortyGigE|HundredGigE)(\S+)",
+ conf,
+ re.M,
+ )
+ if match:
+ config["name"] = match.group(1) + match.group(2)
+
+ for key in ["receive", "transmit"]:
+ config[key] = (
+ False if ("{0} disable".format(key)) in conf else None
+ )
+
+ for x in ["ieee-nearest-bridge", "ieee-nearest-non-tmpr-bridge"]:
+ if x in conf:
+ config["destination"]["mac_address"] = x
+
+ return utils.remove_empties(config)
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospf_interfaces/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospf_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospf_interfaces/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospf_interfaces/ospf_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospf_interfaces/ospf_interfaces.py
new file mode 100644
index 00000000..c21eaf0d
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospf_interfaces/ospf_interfaces.py
@@ -0,0 +1,137 @@
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+"""
+The iosxr ospf_interfaces fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from copy import deepcopy
+import re
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.ospf_interfaces import (
+ Ospf_interfacesTemplate,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.ospf_interfaces.ospf_interfaces import (
+ Ospf_interfacesArgs,
+)
+
+
+class Ospf_interfacesFacts(object):
+ """ The iosxr ospf_interfaces facts class
+ """
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Ospf_interfacesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_ospf_interfaces(self, connection, flag):
+ cmd = "show running-config router " + flag
+ return connection.get(cmd)
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """ Populate the facts for Ospf_interfaces network resource
+
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+
+ :rtype: dictionary
+ :returns: facts
+ """
+ facts = {}
+ objs = []
+ if not data:
+ data = self.get_ospf_interfaces(connection, flag="ospf")
+ data += "\n" + self.get_ospf_interfaces(connection, flag="ospfv3")
+ end_flag, end_mark, count, v_read = 0, 0, 0, False
+ areas, config_commands = [], []
+ area_str, process, curr_process = "", "", ""
+ data = data.splitlines()
+
+ for line in data:
+ if (
+ line.startswith("router")
+ and curr_process != ""
+ and curr_process != line
+ ):
+ end_mark, count, end_flag, area_str = 0, 0, 0, ""
+ if end_mark == 0 and count == 0 and line.startswith("router ospf"):
+ curr_process = line
+ process = re.sub("\n", "", line)
+ count += 1
+ config_commands.append(process)
+ else:
+ if line.startswith(" area") or line.startswith(" vrf"):
+ area_str = process + re.sub("\n", "", line)
+ config_commands.append(area_str.replace(" ", " "))
+ end_flag += 1
+ elif line.startswith(" interface"):
+ ospf_int = area_str + re.sub("\n", "", line)
+ # default output format has more spaces with default identation
+ # reset the spaces with replace
+ config_commands.append(ospf_int.replace(" ", " "))
+ v_read = True
+ elif v_read:
+ if "!" not in line:
+ command = ospf_int.replace(" ", " ") + re.sub(
+ "\n", "", line
+ )
+ config_commands.append(command.replace(" ", " "))
+ else:
+ v_read = False
+ elif end_flag > 0 and "!" not in line:
+ command = area_str + re.sub("\n", "", line)
+ config_commands.append(command.replace(" ", " "))
+ elif "!" in line:
+ end_flag = 0
+ end_mark += 1
+ if end_mark == 3:
+ end_mark, count = 0, 0
+ area_str = ""
+ else:
+ command = process + line
+ command.replace(" ", " ")
+ config_commands.append(re.sub("\n", "", command))
+ areas.append(re.sub("\n", "", command))
+ data = config_commands
+
+ ospf_interfaces_parser = Ospf_interfacesTemplate(lines=data)
+ objs = list(ospf_interfaces_parser.parse().values())
+ if objs:
+ for item in objs:
+ item["address_family"] = list(item["address_family"].values())
+ for af in item["address_family"]:
+ if af.get("processes"):
+ af["processes"] = list(af["processes"].values())
+
+ ansible_facts["ansible_network_resources"].pop("ospf_interfaces", None)
+
+ params = utils.remove_empties(
+ utils.validate_config(self.argument_spec, {"config": objs})
+ )
+
+ facts["ospf_interfaces"] = params.get("config", [])
+ ansible_facts["ansible_network_resources"].update(facts)
+
+ return ansible_facts
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/ospfv2.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/ospfv2.py
new file mode 100644
index 00000000..1da5ea8e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/ospfv2.py
@@ -0,0 +1,157 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr snmp fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from copy import deepcopy
+import re
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.ospfv2 import (
+ Ospfv2Template,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.ospfv2.ospfv2 import (
+ Ospfv2Args,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network_template import (
+ NetworkTemplate,
+)
+
+
+class Ospfv2Facts(object):
+ """ The iosxr snmp fact class
+ """
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Ospfv2Args.argument_spec
+
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_ospfv2_data(self, connection):
+ return connection.get("show running-config router ospf")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """ Populate the facts for interfaces
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+
+ if not data:
+ data = self.get_ospfv2_data(connection)
+ end_flag, end_mark, count, v_read = 0, 0, 0, False
+ areas, config_commands = [], []
+ area_str, process, curr_process = "", "", ""
+ data = data.splitlines()
+ for line in data:
+ if (
+ line.startswith("router ospf")
+ and curr_process != ""
+ and curr_process != line
+ ):
+ end_mark, count, end_flag, area_str = 0, 0, 0, ""
+ if end_mark == 0 and count == 0 and line.startswith("router ospf"):
+ curr_process = line
+ process = re.sub("\n", "", line)
+ count += 1
+ config_commands.append(process)
+ else:
+ if line.startswith(" area") or line.startswith(" vrf"):
+ area_str = process + re.sub("\n", "", line)
+ config_commands.append(area_str.replace(" ", " "))
+ end_flag += 1
+ elif line.startswith(" virtual-link"):
+ virtual_str = area_str + re.sub("\n", "", line)
+ config_commands.append(virtual_str.replace(" ", " "))
+ v_read = True
+ elif v_read:
+ if "!" not in line:
+ command = virtual_str.replace(" ", " ") + re.sub(
+ "\n", "", line
+ )
+ config_commands.append(command.replace(" ", " "))
+ else:
+ v_read = False
+ elif end_flag > 0 and "!" not in line:
+ command = area_str + re.sub("\n", "", line)
+ config_commands.append(command.replace(" ", " "))
+ elif "!" in line:
+ end_flag = 0
+ end_mark += 1
+ if end_mark == 3:
+ end_mark, count = 0, 0
+ area_str = ""
+ else:
+ command = process + line
+ command.replace(" ", " ")
+ config_commands.append(re.sub("\n", "", command))
+ areas.append(re.sub("\n", "", command))
+ data = config_commands
+ ipv4 = {"processes": []}
+ rmmod = NetworkTemplate(lines=data, tmplt=Ospfv2Template())
+ current = rmmod.parse()
+
+ # convert some of the dicts to lists
+ for key, sortv in [("processes", "process_id")]:
+ if key in current and current[key]:
+ current[key] = current[key].values()
+ current[key] = sorted(
+ current[key], key=lambda k, sk=sortv: k[sk]
+ )
+
+ for process in current.get("processes", []):
+ if "areas" in process:
+ process["areas"] = list(process["areas"].values())
+ process["areas"] = sorted(
+ process["areas"], key=lambda k, sk="area_id": k[sk]
+ )
+ for area in process["areas"]:
+ if "ranges" in area:
+ area["ranges"] = sorted(
+ area["ranges"], key=lambda k, s="ranges": k[s]
+ )
+ if "virtual_link" in area:
+ area["virtual_link"] = list(
+ area["virtual_link"].values()
+ )
+ area["virtual_link"] = sorted(
+ area["virtual_link"], key=lambda k, sk="id": k[sk]
+ )
+ ipv4["processes"].append(process)
+
+ ansible_facts["ansible_network_resources"].pop("ospfv2", None)
+ facts = {}
+ if current:
+ params = utils.validate_config(
+ self.argument_spec, {"config": ipv4}
+ )
+ params = utils.remove_empties(params)
+
+ facts["ospfv2"] = params["config"]
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/ospfv3.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/ospfv3.py
new file mode 100644
index 00000000..8e54e3f4
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/ospfv3.py
@@ -0,0 +1,155 @@
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from copy import deepcopy
+import re
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.ospfv3 import (
+ Ospfv3Template,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.ospfv3.ospfv3 import (
+ Ospfv3Args,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network_template import (
+ NetworkTemplate,
+)
+
+
+class Ospfv3Facts(object):
+ """ The iosxr snmp fact class
+ """
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Ospfv3Args.argument_spec
+
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_ospfv3_data(self, connection):
+ return connection.get("show running-config router ospfv3")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """ Populate the facts for interfaces
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+
+ if not data:
+ data = self.get_ospfv3_data(connection)
+ end_flag, end_mark, count, v_read = 0, 0, 0, False
+ areas, config_commands = [], []
+ area_str, process, curr_process = "", "", ""
+ data = data.splitlines()
+ for line in data:
+ if (
+ line.startswith("router ospfv3")
+ and curr_process != ""
+ and curr_process != line
+ ):
+ end_mark, count, end_flag, area_str = 0, 0, 0, ""
+ if (
+ end_mark == 0
+ and count == 0
+ and line.startswith("router ospfv3")
+ ):
+ curr_process = line
+ process = re.sub("\n", "", line)
+ count += 1
+ config_commands.append(process)
+ else:
+ if line.startswith(" area") or line.startswith(" vrf"):
+ area_str = process + re.sub("\n", "", line)
+ config_commands.append(area_str.replace(" ", " "))
+ end_flag += 1
+ elif line.startswith(" virtual-link"):
+ virtual_str = area_str + re.sub("\n", "", line)
+ config_commands.append(virtual_str.replace(" ", " "))
+ v_read = True
+ elif v_read:
+ if "!" not in line:
+ command = virtual_str.replace(" ", " ") + re.sub(
+ "\n", "", line
+ )
+ config_commands.append(command.replace(" ", " "))
+ else:
+ v_read = False
+ elif end_flag > 0 and "!" not in line:
+ command = area_str + re.sub("\n", "", line)
+ config_commands.append(command.replace(" ", " "))
+ elif "!" in line:
+ end_flag = 0
+ end_mark += 1
+ if end_mark == 3:
+ end_mark, count = 0, 0
+ area_str = ""
+ else:
+ command = process + line
+ command.replace(" ", " ")
+ config_commands.append(re.sub("\n", "", command))
+ areas.append(re.sub("\n", "", command))
+ data = config_commands
+ ipv4 = {"processes": []}
+ rmmod = NetworkTemplate(lines=data, tmplt=Ospfv3Template())
+ current = rmmod.parse()
+
+ # convert some of the dicts to lists
+ for key, sortv in [("processes", "process_id")]:
+ if key in current and current[key]:
+ current[key] = current[key].values()
+ current[key] = sorted(
+ current[key], key=lambda k, sk=sortv: k[sk]
+ )
+
+ for process in current.get("processes", []):
+ if "areas" in process:
+ process["areas"] = list(process["areas"].values())
+ process["areas"] = sorted(
+ process["areas"], key=lambda k, sk="area_id": k[sk]
+ )
+ for area in process["areas"]:
+ if "ranges" in area:
+ area["ranges"] = sorted(
+ area["ranges"], key=lambda k, s="ranges": k[s]
+ )
+ if "virtual_link" in area:
+ area["virtual_link"] = list(
+ area["virtual_link"].values()
+ )
+ area["virtual_link"] = sorted(
+ area["virtual_link"], key=lambda k, sk="id": k[sk]
+ )
+ ipv4["processes"].append(process)
+
+ ansible_facts["ansible_network_resources"].pop("ospfv3", None)
+ facts = {}
+ if current:
+ params = utils.validate_config(
+ self.argument_spec, {"config": ipv4}
+ )
+ params = utils.remove_empties(params)
+
+ facts["ospfv3"] = params["config"]
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/static_routes/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/static_routes/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/static_routes/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/static_routes/static_routes.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/static_routes/static_routes.py
new file mode 100644
index 00000000..7df0e8bc
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/static_routes/static_routes.py
@@ -0,0 +1,191 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr static_routes fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+import re
+from copy import deepcopy
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import (
+ utils,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.static_routes.static_routes import (
+ Static_routesArgs,
+)
+
+
+class Static_routesFacts(object):
+ """ The iosxr static_routes fact class
+ """
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Static_routesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_device_data(self, connection):
+ return connection.get_config(flags="router static")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """ Populate the facts for static_routes
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+ if not data:
+ data = self.get_device_data(connection)
+
+ objs = []
+
+ if "No such configuration" not in data:
+ for entry in re.compile(r"(\s) vrf").split(data):
+ obj = self.render_config(self.generated_spec, entry)
+ if obj:
+ objs.append(obj)
+
+ ansible_facts["ansible_network_resources"].pop("static_routes", None)
+ facts = {}
+
+ facts["static_routes"] = []
+ params = utils.validate_config(self.argument_spec, {"config": objs})
+ for cfg in params["config"]:
+ facts["static_routes"].append(utils.remove_empties(cfg))
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys
+ from spec for null values
+
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+ entry_list = conf.split(" address-family")
+ config["address_families"] = []
+
+ if "router static" not in entry_list[0]:
+ config["vrf"] = entry_list[0].replace("!", "").strip()
+
+ for item in entry_list[1:]:
+ routes = []
+ address_family = {"routes": []}
+ address_family["afi"], address_family["safi"] = self.parse_af(item)
+
+ destinations = re.findall(r"((?:\S+)/(?:\d+)) (?:.*)", item, re.M)
+ for dest in set(destinations):
+ route = {"next_hops": []}
+ route["dest"] = dest
+
+ regex = r"%s .+$" % dest
+ cfg = re.findall(regex, item, re.M)
+
+ for route_entry in cfg:
+ exit_point = {}
+ exit_point["forward_router_address"] = self.parse_faddr(
+ route_entry
+ )
+ exit_point["interface"] = self.parse_intf(route_entry)
+ exit_point["admin_distance"] = self.parse_admin_distance(
+ route_entry
+ )
+
+ for x in [
+ "tag",
+ "tunnel-id",
+ "metric",
+ "description",
+ "track",
+ "vrflabel",
+ "dest_vrf",
+ ]:
+ exit_point[x.replace("-", "_")] = self.parse_attrib(
+ route_entry, x.replace("dest_vrf", "vrf")
+ )
+
+ route["next_hops"].append(exit_point)
+
+ routes.append(route)
+ address_family["routes"] = sorted(
+ routes, key=lambda i: i["dest"]
+ )
+ config["address_families"].append(address_family)
+
+ return utils.remove_empties(config)
+
+ def parse_af(self, item):
+ match = re.search(r"(?:\s*)(\w+)(?:\s*)(\w+)", item, re.M)
+ if match:
+ return match.group(1), match.group(2)
+
+ def parse_faddr(self, item):
+ for x in item.split(" "):
+ if (":" in x or "." in x) and "/" not in x:
+ return x
+
+ def parse_intf(self, item):
+ match = re.search(r" ((\w+)((?:\d)/(?:\d)/(?:\d)/(?:\d+)))", item)
+ if match:
+ return match.group(1)
+
+ def parse_attrib(self, item, attrib):
+ match = re.search(r" %s (\S+)" % attrib, item)
+ if match:
+ val = match.group(1).strip("'")
+ if attrib in ["tunnel-id", "vrflabel", "tag", "metric"]:
+ val = int(val)
+ return val
+
+ def parse_admin_distance(self, item):
+ split_item = item.split(" ")
+ for item in [
+ "vrf",
+ "metric",
+ "tunnel-id",
+ "vrflabel",
+ "track",
+ "tag",
+ "description",
+ ]:
+ try:
+ del split_item[split_item.index(item) + 1]
+ del split_item[split_item.index(item)]
+ except ValueError:
+ continue
+ try:
+ return [
+ i
+ for i in split_item
+ if "." not in i
+ and ":" not in i
+ and ord(i[0]) > 48
+ and ord(i[0]) < 57
+ ][0]
+ except IndexError:
+ return None
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/iosxr.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/iosxr.py
new file mode 100644
index 00000000..771aec74
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/iosxr.py
@@ -0,0 +1,671 @@
+# This code is part of Ansible, but is an independent component.
+# This particular file snippet, and this file snippet only, is BSD licensed.
+# Modules you write using this snippet, which is embedded dynamically by Ansible
+# still belong to the author of the module, and may assign their own license
+# to the complete work.
+#
+# Copyright (c) 2015 Peter Sprygada, <psprygada@ansible.com>
+# Copyright (c) 2017 Red Hat Inc.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+import json
+import re
+from difflib import Differ
+
+from ansible.module_utils._text import to_text, to_bytes
+from ansible.module_utils.basic import env_fallback
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ to_list,
+)
+from ansible.module_utils.connection import Connection, ConnectionError
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.netconf import (
+ NetconfConnection,
+)
+
+try:
+ from ncclient.xml_ import to_xml
+
+ HAS_NCCLIENT = True
+except ImportError:
+ HAS_NCCLIENT = False
+
+try:
+ from lxml import etree
+
+ HAS_XML = True
+except ImportError:
+ HAS_XML = False
+
+_EDIT_OPS = frozenset(["merge", "create", "replace", "delete"])
+
+BASE_1_0 = "{urn:ietf:params:xml:ns:netconf:base:1.0}"
+
+NS_DICT = {
+ "BASE_NSMAP": {"xc": "urn:ietf:params:xml:ns:netconf:base:1.0"},
+ "BANNERS_NSMAP": {
+ None: "http://cisco.com/ns/yang/Cisco-IOS-XR-infra-infra-cfg"
+ },
+ "INTERFACES_NSMAP": {None: "http://openconfig.net/yang/interfaces"},
+ "INSTALL_NSMAP": {
+ None: "http://cisco.com/ns/yang/Cisco-IOS-XR-installmgr-admin-oper"
+ },
+ "HOST-NAMES_NSMAP": {
+ None: "http://cisco.com/ns/yang/Cisco-IOS-XR-shellutil-cfg"
+ },
+ "M:TYPE_NSMAP": {"idx": "urn:ietf:params:xml:ns:yang:iana-if-type"},
+ "ETHERNET_NSMAP": {None: "http://openconfig.net/yang/interfaces/ethernet"},
+ "CETHERNET_NSMAP": {
+ None: "http://cisco.com/ns/yang/Cisco-IOS-XR-drivers-media-eth-cfg"
+ },
+ "INTERFACE-CONFIGURATIONS_NSMAP": {
+ None: "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"
+ },
+ "INFRA-STATISTICS_NSMAP": {
+ None: "http://cisco.com/ns/yang/Cisco-IOS-XR-infra-statsd-oper"
+ },
+ "INTERFACE-PROPERTIES_NSMAP": {
+ None: "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-oper"
+ },
+ "IP-DOMAIN_NSMAP": {
+ None: "http://cisco.com/ns/yang/Cisco-IOS-XR-ip-domain-cfg"
+ },
+ "SYSLOG_NSMAP": {
+ None: "http://cisco.com/ns/yang/Cisco-IOS-XR-infra-syslog-cfg"
+ },
+ "AAA_NSMAP": {None: "http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-lib-cfg"},
+ "AAA_LOCALD_NSMAP": {
+ None: "http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-locald-cfg"
+ },
+}
+
+iosxr_provider_spec = {
+ "host": dict(),
+ "port": dict(type="int"),
+ "username": dict(fallback=(env_fallback, ["ANSIBLE_NET_USERNAME"])),
+ "password": dict(
+ fallback=(env_fallback, ["ANSIBLE_NET_PASSWORD"]), no_log=True
+ ),
+ "ssh_keyfile": dict(
+ fallback=(env_fallback, ["ANSIBLE_NET_SSH_KEYFILE"]), type="path"
+ ),
+ "timeout": dict(type="int"),
+ "transport": dict(type="str", default="cli", choices=["cli", "netconf"]),
+}
+
+iosxr_argument_spec = {
+ "provider": dict(
+ type="dict",
+ options=iosxr_provider_spec,
+ removed_at_date="2022-06-01",
+ removed_from_collection="cisco.iosxr",
+ )
+}
+
+command_spec = {
+ "command": dict(),
+ "prompt": dict(default=None),
+ "answer": dict(default=None),
+}
+
+CONFIG_MISPLACED_CHILDREN = [re.compile(r"^end-\s*(.+)$")]
+
+# Objects defined in Route-policy Language guide of IOS_XR.
+# Reconfiguring these objects replace existing configurations.
+# Hence these objects should be played direcly from candidate
+# configurations
+CONFIG_BLOCKS_FORCED_IN_DIFF = [
+ {"start": re.compile(r"^route-policy"), "end": re.compile(r"end-policy$")},
+ {"start": re.compile(r"^prefix-set"), "end": re.compile(r"end-set$")},
+ {"start": re.compile(r"^as-path-set"), "end": re.compile(r"end-set$")},
+ {"start": re.compile(r"^community-set"), "end": re.compile(r"end-set$")},
+ {"start": re.compile(r"^rd-set"), "end": re.compile(r"end-set$")},
+ {
+ "start": re.compile(r"^extcommunity-set"),
+ "end": re.compile(r"end-set$"),
+ },
+]
+
+
+def get_provider_argspec():
+ return iosxr_provider_spec
+
+
+def get_connection(module):
+ if hasattr(module, "connection"):
+ return module.connection
+
+ capabilities = get_capabilities(module)
+ network_api = capabilities.get("network_api")
+ if network_api == "cliconf":
+ module.connection = Connection(module._socket_path)
+ elif network_api == "netconf":
+ module.connection = NetconfConnection(module._socket_path)
+ else:
+ module.fail_json(
+ msg="Invalid connection type {0!s}".format(network_api)
+ )
+
+ return module.connection
+
+
+def get_capabilities(module):
+ if hasattr(module, "capabilities"):
+ return module.capabilities
+ try:
+ capabilities = Connection(module._socket_path).get_capabilities()
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+ module.capabilities = json.loads(capabilities)
+
+ return module.capabilities
+
+
+def build_xml_subtree(container_ele, xmap, param=None, opcode=None):
+ sub_root = container_ele
+ meta_subtree = list()
+
+ for key, meta in xmap.items():
+ candidates = meta.get("xpath", "").split("/")
+ if container_ele.tag == candidates[-2]:
+ parent = container_ele
+ elif sub_root.tag == candidates[-2]:
+ parent = sub_root
+ else:
+ parent = sub_root.find(
+ ".//"
+ + meta.get("xpath", "")
+ .split(sub_root.tag + "/", 1)[1]
+ .rsplit("/", 1)[0]
+ )
+
+ if (
+ opcode in ("delete", "merge")
+ and meta.get("operation", "unknown") == "edit"
+ ) or meta.get("operation", None) is None:
+
+ if meta.get("tag", False) is True:
+ if parent.tag == container_ele.tag:
+ if meta.get("ns", False) is True:
+ child = etree.Element(
+ candidates[-1],
+ nsmap=NS_DICT[key.upper() + "_NSMAP"],
+ )
+ else:
+ child = etree.Element(candidates[-1])
+ meta_subtree.append(child)
+ sub_root = child
+ else:
+ if meta.get("ns", False) is True:
+ child = etree.SubElement(
+ parent,
+ candidates[-1],
+ nsmap=NS_DICT[key.upper() + "_NSMAP"],
+ )
+ else:
+ child = etree.SubElement(parent, candidates[-1])
+
+ if meta.get("attrib", None) is not None and opcode in (
+ "delete",
+ "merge",
+ ):
+ child.set(BASE_1_0 + meta.get("attrib"), opcode)
+
+ continue
+
+ text = None
+ param_key = key.split(":")
+ if param_key[0] == "a":
+ if (
+ param is not None
+ and param.get(param_key[1], None) is not None
+ ):
+ text = param.get(param_key[1])
+ elif param_key[0] == "m":
+ if meta.get("value", None) is not None:
+ text = meta.get("value")
+
+ if text:
+ if meta.get("ns", False) is True:
+ child = etree.SubElement(
+ parent,
+ candidates[-1],
+ nsmap=NS_DICT[key.upper() + "_NSMAP"],
+ )
+ else:
+ child = etree.SubElement(parent, candidates[-1])
+ child.text = text
+
+ if meta.get("attrib", None) is not None and opcode in (
+ "delete",
+ "merge",
+ ):
+ child.set(BASE_1_0 + meta.get("attrib"), opcode)
+
+ if len(meta_subtree) > 1:
+ for item in meta_subtree:
+ container_ele.append(item)
+
+ if sub_root == container_ele:
+ return None
+ else:
+ return sub_root
+
+
+def build_xml(container, xmap=None, params=None, opcode=None):
+ """
+ Builds netconf xml rpc document from meta-data
+
+ Args:
+ container: the YANG container within the namespace
+ xmap: meta-data map to build xml tree
+ params: Input params that feed xml tree values
+ opcode: operation to be performed (merge, delete etc.)
+
+ Example:
+ Module inputs:
+ banner_params = [{'banner':'motd', 'text':'Ansible banner example', 'state':'present'}]
+
+ Meta-data definition:
+ bannermap = collections.OrderedDict()
+ bannermap.update([
+ ('banner', {'xpath' : 'banners/banner', 'tag' : True, 'attrib' : "operation"}),
+ ('a:banner', {'xpath' : 'banner/banner-name'}),
+ ('a:text', {'xpath' : 'banner/banner-text', 'operation' : 'edit'})
+ ])
+
+ Fields:
+ key: exact match to the key in arg_spec for a parameter
+ (prefixes --> a: value fetched from arg_spec, m: value fetched from meta-data)
+ xpath: xpath of the element (based on YANG model)
+ tag: True if no text on the element
+ attrib: attribute to be embedded in the element (e.g. xc:operation="merge")
+ operation: if edit --> includes the element in edit_config() query else ignores for get() queries
+ value: if key is prefixed with "m:", value is required in meta-data
+
+ Output:
+ <config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <banners xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-infra-infra-cfg">
+ <banner xc:operation="merge">
+ <banner-name>motd</banner-name>
+ <banner-text>Ansible banner example</banner-text>
+ </banner>
+ </banners>
+ </config>
+ :returns: xml rpc document as a string
+ """
+ if opcode == "filter":
+ root = etree.Element("filter", type="subtree")
+ elif opcode in ("delete", "merge"):
+ root = etree.Element("config", nsmap=NS_DICT["BASE_NSMAP"])
+
+ container_ele = etree.SubElement(
+ root, container, nsmap=NS_DICT[container.upper() + "_NSMAP"]
+ )
+
+ if xmap is not None:
+ if params is None:
+ build_xml_subtree(container_ele, xmap, opcode=opcode)
+ else:
+ subtree_list = list()
+ for param in to_list(params):
+ subtree_ele = build_xml_subtree(
+ container_ele, xmap, param=param, opcode=opcode
+ )
+ if subtree_ele is not None:
+ subtree_list.append(subtree_ele)
+
+ for item in subtree_list:
+ container_ele.append(item)
+
+ return etree.tostring(root, encoding="unicode")
+
+
+def etree_find(root, node):
+ try:
+ root = etree.fromstring(to_bytes(root))
+ except (ValueError, etree.XMLSyntaxError):
+ pass
+
+ return root.find(".//%s" % node.strip())
+
+
+def etree_findall(root, node):
+ try:
+ root = etree.fromstring(to_bytes(root))
+ except (ValueError, etree.XMLSyntaxError):
+ pass
+
+ return root.findall(".//%s" % node.strip())
+
+
+def is_cliconf(module):
+ capabilities = get_capabilities(module)
+ return capabilities.get("network_api") == "cliconf"
+
+
+def is_netconf(module):
+ capabilities = get_capabilities(module)
+ network_api = capabilities.get("network_api")
+ if network_api == "netconf":
+ if not HAS_NCCLIENT:
+ module.fail_json(msg="ncclient is not installed")
+ if not HAS_XML:
+ module.fail_json(msg="lxml is not installed")
+ return True
+
+ return False
+
+
+def get_config_diff(module, running=None, candidate=None):
+ conn = get_connection(module)
+
+ if is_cliconf(module):
+ try:
+ response = conn.get("show commit changes diff")
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+ return response
+ elif is_netconf(module):
+ if running and candidate:
+ # ignore rpc-reply root node and diff from data element onwards
+ running_data_ele = etree.fromstring(
+ to_bytes(running.strip())
+ ).getchildren()[0]
+ candidate_data_ele = etree.fromstring(
+ to_bytes(candidate.strip())
+ ).getchildren()[0]
+
+ running_data = to_text(etree.tostring(running_data_ele)).strip()
+ candidate_data = to_text(
+ etree.tostring(candidate_data_ele)
+ ).strip()
+ if running_data != candidate_data:
+ d = Differ()
+ diff = list(
+ d.compare(
+ running_data.splitlines(), candidate_data.splitlines()
+ )
+ )
+ return "\n".join(diff).strip()
+
+ return None
+
+
+def discard_config(module):
+ conn = get_connection(module)
+ try:
+ if is_netconf(module):
+ conn.discard_changes(remove_ns=True)
+ else:
+ conn.discard_changes()
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+
+
+def commit_config(
+ module,
+ comment=None,
+ confirmed=False,
+ confirm_timeout=None,
+ persist=False,
+ check=False,
+ label=None,
+):
+ conn = get_connection(module)
+ reply = None
+ try:
+ if is_netconf(module):
+ if check:
+ reply = conn.validate(remove_ns=True)
+ else:
+ reply = conn.commit(
+ confirmed=confirmed,
+ timeout=confirm_timeout,
+ persist=persist,
+ remove_ns=True,
+ )
+ elif is_cliconf(module):
+ if check:
+ module.fail_json(
+ msg="Validate configuration is not supported with network_cli connection type"
+ )
+ else:
+ reply = conn.commit(comment=comment, label=label)
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+
+ return reply
+
+
+def get_oper(module, filter=None):
+ conn = get_connection(module)
+
+ if filter is not None:
+ try:
+ if is_netconf(module):
+ response = conn.get(filter=filter, remove_ns=True)
+ else:
+ response = conn.get(filter)
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+ else:
+ return None
+
+ return to_bytes(
+ etree.tostring(response), errors="surrogate_then_replace"
+ ).strip()
+
+
+def get_config(module, config_filter=None, source="running"):
+ conn = get_connection(module)
+
+ # Note: Does not cache config in favour of latest config on every get operation.
+ try:
+ if is_netconf(module):
+ out = to_xml(
+ conn.get_config(
+ source=source, filter=config_filter, remove_ns=True
+ )
+ )
+ elif is_cliconf(module):
+ out = conn.get_config(source=source, flags=config_filter)
+ cfg = out.strip()
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+ return cfg
+
+
+def check_existing_commit_labels(conn, label):
+ out = conn.get(
+ command="show configuration history detail | include %s" % label
+ )
+ label_exist = re.search(label, out, re.M)
+ if label_exist:
+ return True
+ else:
+ return False
+
+
+def load_config(
+ module,
+ command_filter,
+ commit=False,
+ replace=False,
+ comment=None,
+ admin=False,
+ exclusive=False,
+ running=None,
+ nc_get_filter=None,
+ label=None,
+):
+
+ conn = get_connection(module)
+
+ diff = None
+ if is_netconf(module):
+ # FIXME: check for platform behaviour and restore this
+ # conn.lock(target = 'candidate')
+ # conn.discard_changes()
+
+ try:
+ for filter in to_list(command_filter):
+ conn.edit_config(config=filter, remove_ns=True)
+
+ candidate = get_config(
+ module, source="candidate", config_filter=nc_get_filter
+ )
+ diff = get_config_diff(module, running, candidate)
+
+ if commit and diff:
+ commit_config(module)
+ else:
+ discard_config(module)
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+ finally:
+ # conn.unlock(target = 'candidate')
+ pass
+
+ elif is_cliconf(module):
+ try:
+ if label:
+ old_label = check_existing_commit_labels(conn, label)
+ if old_label:
+ module.fail_json(
+ msg="commit label {%s} is already used for"
+ " an earlier commit, please choose a different label"
+ " and rerun task" % label
+ )
+
+ response = conn.edit_config(
+ candidate=command_filter,
+ commit=commit,
+ admin=admin,
+ exclusive=exclusive,
+ replace=replace,
+ comment=comment,
+ label=label,
+ )
+ if module._diff:
+ diff = response.get("diff")
+
+ # Overwrite the default diff by the IOS XR commit diff.
+ # See plugins/cliconf/iosxr.py for this key set: show_commit_config_diff
+ diff = response.get("show_commit_config_diff")
+
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+
+ return diff
+
+
+def run_commands(module, commands, check_rc=True):
+ connection = get_connection(module)
+ try:
+ return connection.run_commands(commands=commands, check_rc=check_rc)
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc))
+
+
+def copy_file(module, src, dst, proto="scp"):
+ conn = get_connection(module)
+ try:
+ conn.copy_file(source=src, destination=dst, proto=proto)
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+
+
+def get_file(module, src, dst, proto="scp"):
+ conn = get_connection(module)
+ try:
+ conn.get_file(source=src, destination=dst, proto=proto)
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+
+
+# A list of commands like {end-set, end-policy, ...} are part of configuration
+# block like { prefix-set, as-path-set , ... } but they are not indented properly
+# to be included with their parent. sanitize_config will add indentation to
+# end-* commands so they are included with their parents
+def sanitize_config(config, force_diff_prefix=None):
+ conf_lines = config.split("\n")
+ for regex in CONFIG_MISPLACED_CHILDREN:
+ for index, line in enumerate(conf_lines):
+ m = regex.search(line)
+ if m and m.group(0):
+ if force_diff_prefix:
+ conf_lines[index] = " " + m.group(0) + force_diff_prefix
+ else:
+ conf_lines[index] = " " + m.group(0)
+ conf = ("\n").join(conf_lines)
+ return conf
+
+
+def mask_config_blocks_from_diff(config, candidate, force_diff_prefix):
+ conf_lines = config.split("\n")
+ candidate_lines = candidate.split("\n")
+
+ for regex in CONFIG_BLOCKS_FORCED_IN_DIFF:
+ block_index_start_end = []
+ for index, line in enumerate(candidate_lines):
+ startre = regex["start"].search(line)
+ if startre and startre.group(0):
+ start_index = index
+ else:
+ endre = regex["end"].search(line)
+ if endre and endre.group(0):
+ end_index = index
+ new_block = True
+ for prev_start, prev_end in block_index_start_end:
+ if start_index == prev_start:
+ # This might be end-set of another regex
+ # otherwise we would be having new start
+ new_block = False
+ break
+ if new_block and start_index:
+ block_index_start_end.append((start_index, end_index))
+
+ for start, end in block_index_start_end:
+ diff = False
+ if candidate_lines[start] in conf_lines:
+ run_conf_start_index = conf_lines.index(candidate_lines[start])
+ else:
+ diff = False
+ continue
+ for i in range(start, end + 1):
+ if conf_lines[run_conf_start_index] == candidate_lines[i]:
+ run_conf_start_index = run_conf_start_index + 1
+ else:
+ diff = True
+ break
+ if diff:
+ run_conf_start_index = conf_lines.index(candidate_lines[start])
+ for i in range(start, end + 1):
+ conf_lines[run_conf_start_index] = (
+ conf_lines[run_conf_start_index] + force_diff_prefix
+ )
+ run_conf_start_index = run_conf_start_index + 1
+
+ conf = ("\n").join(conf_lines)
+ return conf
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/address_family.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/address_family.py
new file mode 100644
index 00000000..fd9c9bf2
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/address_family.py
@@ -0,0 +1,129 @@
+#
+# (c) 2019, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+import re
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ to_list,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers.providers import (
+ CliProvider,
+)
+
+
+class AddressFamily(CliProvider):
+ def render(self, config=None):
+ commands = list()
+ safe_list = list()
+
+ router_context = "router bgp %s" % self.get_value("config.bgp_as")
+ context_config = None
+
+ for item in self.get_value("config.address_family"):
+ context = "address-family %s %s" % (item["afi"], item["safi"])
+ context_commands = list()
+
+ if config:
+ context_path = [router_context, context]
+ context_config = self.get_config_context(
+ config, context_path, indent=1
+ )
+
+ for key, value in iteritems(item):
+ if value is not None:
+ meth = getattr(self, "_render_%s" % key, None)
+ if meth:
+ resp = meth(item, context_config)
+ if resp:
+ context_commands.extend(to_list(resp))
+
+ if context_commands:
+ commands.append(context)
+ commands.extend(context_commands)
+ commands.append("exit")
+
+ safe_list.append(context)
+
+ if config:
+ resp = self._negate_config(config, safe_list)
+ commands.extend(resp)
+
+ return commands
+
+ def _negate_config(self, config, safe_list=None):
+ commands = list()
+ matches = re.findall(r"(address-family .+)$", config, re.M)
+ for item in set(matches).difference(safe_list):
+ commands.append("no %s" % item)
+ return commands
+
+ def _render_networks(self, item, config=None):
+ commands = list()
+ safe_list = list()
+
+ for entry in item["networks"]:
+ network = entry["prefix"]
+ if entry["masklen"]:
+ network = "%s/%s" % (entry["prefix"], entry["masklen"])
+ safe_list.append(network)
+
+ cmd = "network %s" % network
+
+ if entry["route_map"]:
+ cmd += " route-policy %s" % entry["route_map"]
+
+ if not config or cmd not in config:
+ commands.append(cmd)
+
+ if config and self.params["operation"] == "replace":
+ matches = re.findall(r"network (\S+)", config, re.M)
+ for entry in set(matches).difference(safe_list):
+ commands.append("no network %s" % entry)
+
+ return commands
+
+ def _render_redistribute(self, item, config=None):
+ commands = list()
+ safe_list = list()
+
+ for entry in item["redistribute"]:
+ option = entry["protocol"]
+
+ cmd = "redistribute %s" % entry["protocol"]
+
+ if entry["id"] and entry["protocol"] in (
+ "ospf",
+ "eigrp",
+ "isis",
+ "ospfv3",
+ ):
+ cmd += " %s" % entry["id"]
+ option += " %s" % entry["id"]
+
+ if entry["metric"]:
+ cmd += " metric %s" % entry["metric"]
+
+ if entry["route_map"]:
+ cmd += " route-policy %s" % entry["route_map"]
+
+ if not config or cmd not in config:
+ commands.append(cmd)
+
+ safe_list.append(option)
+
+ if self.params["operation"] == "replace":
+ if config:
+ matches = re.findall(
+ r"redistribute (\S+)(?:\s*)(\d*)", config, re.M
+ )
+ for i in range(0, len(matches)):
+ matches[i] = " ".join(matches[i]).strip()
+ for entry in set(matches).difference(safe_list):
+ commands.append("no redistribute %s" % entry)
+
+ return commands
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/neighbors.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/neighbors.py
new file mode 100644
index 00000000..1ea870f7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/neighbors.py
@@ -0,0 +1,135 @@
+#
+# (c) 2019, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+import re
+import socket
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ to_list,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers.providers import (
+ CliProvider,
+)
+
+
+class Neighbors(CliProvider):
+ def render(self, config=None):
+ commands = list()
+ safe_list = list()
+
+ router_context = "router bgp %s" % self.get_value("config.bgp_as")
+ context_config = None
+
+ for item in self.get_value("config.neighbors"):
+ context_commands = list()
+
+ neighbor = item["neighbor"]
+
+ try:
+ socket.inet_aton(neighbor)
+ context = "neighbor %s" % neighbor
+ except socket.error:
+ context = "neighbor-group %s" % neighbor
+
+ if config:
+ context_path = [router_context, context]
+ context_config = self.get_config_context(
+ config, context_path, indent=1
+ )
+
+ for key, value in iteritems(item):
+ if value is not None:
+ meth = getattr(self, "_render_%s" % key, None)
+ if meth:
+ resp = meth(item, context_config)
+ if resp:
+ context_commands.extend(to_list(resp))
+
+ if context_commands:
+ commands.append(context)
+ commands.extend(context_commands)
+ commands.append("exit")
+
+ safe_list.append(context)
+
+ if config and safe_list:
+ commands.extend(self._negate_config(config, safe_list))
+
+ return commands
+
+ def _negate_config(self, config, safe_list=None):
+ commands = list()
+ matches = re.findall(r"(neighbor \S+)", config, re.M)
+ for item in set(matches).difference(safe_list):
+ commands.append("no %s" % item)
+ return commands
+
+ def _render_remote_as(self, item, config=None):
+ cmd = "remote-as %s" % item["remote_as"]
+ if not config or cmd not in config:
+ return cmd
+
+ def _render_description(self, item, config=None):
+ cmd = "description %s" % item["description"]
+ if not config or cmd not in config:
+ return cmd
+
+ def _render_enabled(self, item, config=None):
+ cmd = "shutdown"
+ if item["enabled"] is True:
+ cmd = "no %s" % cmd
+ if not config or cmd not in config:
+ return cmd
+
+ def _render_update_source(self, item, config=None):
+ cmd = "update-source %s" % item["update_source"].replace(" ", "")
+ if not config or cmd not in config:
+ return cmd
+
+ def _render_password(self, item, config=None):
+ cmd = "password %s" % item["password"]
+ if not config or cmd not in config:
+ return cmd
+
+ def _render_ebgp_multihop(self, item, config=None):
+ cmd = "ebgp-multihop %s" % item["ebgp_multihop"]
+ if not config or cmd not in config:
+ return cmd
+
+ def _render_tcp_mss(self, item, config=None):
+ cmd = "tcp mss %s" % item["tcp_mss"]
+ if not config or cmd not in config:
+ return cmd
+
+ def _render_advertisement_interval(self, item, config=None):
+ cmd = "advertisement-interval %s" % item["advertisement_interval"]
+ if not config or cmd not in config:
+ return cmd
+
+ def _render_neighbor_group(self, item, config=None):
+ cmd = "use neighbor-group %s" % item["neighbor_group"]
+ if not config or cmd not in config:
+ return cmd
+
+ def _render_timers(self, item, config):
+ """generate bgp timer related configuration
+ """
+ keepalive = item["timers"]["keepalive"]
+ holdtime = item["timers"]["holdtime"]
+ min_neighbor_holdtime = item["timers"]["min_neighbor_holdtime"]
+
+ if keepalive and holdtime:
+ cmd = "timers %s %s" % (keepalive, holdtime)
+ if min_neighbor_holdtime:
+ cmd += " %s" % min_neighbor_holdtime
+ if not config or cmd not in config:
+ return cmd
+ else:
+ raise ValueError(
+ "required both options for timers: keepalive and holdtime"
+ )
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/process.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/process.py
new file mode 100644
index 00000000..8b0aec3a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/process.py
@@ -0,0 +1,126 @@
+#
+# (c) 2019, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+import re
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ to_list,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers.providers import (
+ register_provider,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers.providers import (
+ CliProvider,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers.cli.config.bgp.neighbors import (
+ Neighbors,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers.cli.config.bgp.address_family import (
+ AddressFamily,
+)
+
+REDISTRIBUTE_PROTOCOLS = frozenset(
+ [
+ "ospf",
+ "ospfv3",
+ "eigrp",
+ "isis",
+ "static",
+ "connected",
+ "lisp",
+ "mobile",
+ "rip",
+ "subscriber",
+ ]
+)
+
+
+@register_provider("iosxr", "iosxr_bgp")
+class Provider(CliProvider):
+ def render(self, config=None):
+ commands = list()
+
+ existing_as = None
+ if config:
+ match = re.search(r"router bgp (\d+)", config, re.M)
+ if match:
+ existing_as = match.group(1)
+
+ operation = self.params["operation"]
+
+ context = None
+
+ if self.params["config"]:
+ context = "router bgp %s" % self.get_value("config.bgp_as")
+
+ if operation == "delete":
+ if existing_as:
+ commands.append("no router bgp %s" % existing_as)
+ elif context:
+ commands.append("no %s" % context)
+
+ else:
+ if operation == "replace":
+ if existing_as and int(existing_as) != self.get_value(
+ "config.bgp_as"
+ ):
+ # The negate command has to be committed before new BGP AS is used.
+ self.connection.edit_config(
+ "no router bgp %s" % existing_as
+ )
+ config = None
+
+ elif operation == "override":
+ if existing_as:
+ # The negate command has to be committed before new BGP AS is used.
+ self.connection.edit_config(
+ "no router bgp %s" % existing_as
+ )
+ config = None
+
+ context_commands = list()
+
+ for key, value in iteritems(self.get_value("config")):
+ if value is not None:
+ meth = getattr(self, "_render_%s" % key, None)
+ if meth:
+ resp = meth(config)
+ if resp:
+ context_commands.extend(to_list(resp))
+
+ if context and context_commands:
+ commands.append(context)
+ commands.extend(context_commands)
+ commands.append("exit")
+
+ return commands
+
+ def _render_router_id(self, config=None):
+ cmd = "bgp router-id %s" % self.get_value("config.router_id")
+ if not config or cmd not in config:
+ return cmd
+
+ def _render_log_neighbor_changes(self, config=None):
+ cmd = "bgp log neighbor changes"
+ log_neighbor_changes = self.get_value("config.log_neighbor_changes")
+ if log_neighbor_changes is True:
+ if not config or cmd not in config:
+ return "%s detail" % cmd
+ elif log_neighbor_changes is False:
+ if config and cmd in config:
+ return "%s disable" % cmd
+
+ def _render_neighbors(self, config):
+ """ generate bgp neighbor configuration
+ """
+ return Neighbors(self.params).render(config)
+
+ def _render_address_family(self, config):
+ """ generate address-family configuration
+ """
+ return AddressFamily(self.params).render(config)
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/module.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/module.py
new file mode 100644
index 00000000..4786b80c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/module.py
@@ -0,0 +1,72 @@
+#
+# (c) 2019, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import Connection
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers import (
+ providers,
+)
+from ansible.module_utils._text import to_text
+
+
+class NetworkModule(AnsibleModule):
+
+ fail_on_missing_provider = True
+
+ def __init__(self, connection=None, *args, **kwargs):
+ super(NetworkModule, self).__init__(*args, **kwargs)
+
+ if connection is None:
+ connection = Connection(self._socket_path)
+
+ self.connection = connection
+
+ @property
+ def provider(self):
+ if not hasattr(self, "_provider"):
+ capabilities = self.from_json(self.connection.get_capabilities())
+
+ network_os = capabilities["device_info"]["network_os"]
+ network_api = capabilities["network_api"]
+
+ if network_api == "cliconf":
+ connection_type = "network_cli"
+
+ cls = providers.get(
+ network_os, self._name.split(".")[-1], connection_type
+ )
+
+ if not cls:
+ msg = (
+ "unable to find suitable provider for network os %s"
+ % network_os
+ )
+ if self.fail_on_missing_provider:
+ self.fail_json(msg=msg)
+ else:
+ self.warn(msg)
+
+ obj = cls(self.params, self.connection, self.check_mode)
+
+ setattr(self, "_provider", obj)
+
+ return getattr(self, "_provider")
+
+ def get_facts(self, subset=None):
+ try:
+ self.provider.get_facts(subset)
+ except Exception as exc:
+ self.fail_json(msg=to_text(exc))
+
+ def edit_config(self, config_filter=None):
+ current_config = self.connection.get_config(flags=config_filter)
+ try:
+ commands = self.provider.edit_config(current_config)
+ changed = bool(commands)
+ return {"commands": commands, "changed": changed}
+ except Exception as exc:
+ self.fail_json(msg=to_text(exc))
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/providers.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/providers.py
new file mode 100644
index 00000000..485eb383
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/providers.py
@@ -0,0 +1,128 @@
+#
+# (c) 2019, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+import json
+
+from threading import RLock
+
+from ansible.module_utils.six import itervalues
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ to_list,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import (
+ NetworkConfig,
+)
+
+
+_registered_providers = {}
+_provider_lock = RLock()
+
+
+def register_provider(network_os, module_name):
+ def wrapper(cls):
+ _provider_lock.acquire()
+ try:
+ if network_os not in _registered_providers:
+ _registered_providers[network_os] = {}
+ for ct in cls.supported_connections:
+ if ct not in _registered_providers[network_os]:
+ _registered_providers[network_os][ct] = {}
+ for item in to_list(module_name):
+ for entry in itervalues(_registered_providers[network_os]):
+ entry[item] = cls
+ finally:
+ _provider_lock.release()
+ return cls
+
+ return wrapper
+
+
+def get(network_os, module_name, connection_type):
+ network_os_providers = _registered_providers.get(network_os)
+ if network_os_providers is None:
+ raise ValueError("unable to find a suitable provider for this module")
+ if connection_type not in network_os_providers:
+ raise ValueError("provider does not support this connection type")
+ elif module_name not in network_os_providers[connection_type]:
+ raise ValueError("could not find a suitable provider for this module")
+ return network_os_providers[connection_type][module_name]
+
+
+class ProviderBase(object):
+
+ supported_connections = ()
+
+ def __init__(self, params, connection=None, check_mode=False):
+ self.params = params
+ self.connection = connection
+ self.check_mode = check_mode
+
+ @property
+ def capabilities(self):
+ if not hasattr(self, "_capabilities"):
+ resp = self.from_json(self.connection.get_capabilities())
+ setattr(self, "_capabilities", resp)
+ return getattr(self, "_capabilities")
+
+ def get_value(self, path):
+ params = self.params.copy()
+ for key in path.split("."):
+ params = params[key]
+ return params
+
+ def get_facts(self, subset=None):
+ raise NotImplementedError(self.__class__.__name__)
+
+ def edit_config(self):
+ raise NotImplementedError(self.__class__.__name__)
+
+
+class CliProvider(ProviderBase):
+
+ supported_connections = ("network_cli",)
+
+ @property
+ def capabilities(self):
+ if not hasattr(self, "_capabilities"):
+ resp = self.from_json(self.connection.get_capabilities())
+ setattr(self, "_capabilities", resp)
+ return getattr(self, "_capabilities")
+
+ def get_config_context(self, config, path, indent=1):
+ if config is not None:
+ netcfg = NetworkConfig(indent=indent, contents=config)
+ try:
+ config = netcfg.get_block_config(to_list(path))
+ except ValueError:
+ config = None
+ return config
+
+ def render(self, config=None):
+ raise NotImplementedError(self.__class__.__name__)
+
+ def cli(self, command):
+ try:
+ if not hasattr(self, "_command_output"):
+ setattr(self, "_command_output", {})
+ return self._command_output[command]
+ except KeyError:
+ out = self.connection.get(command)
+ try:
+ out = json.loads(out)
+ except ValueError:
+ pass
+ self._command_output[command] = out
+ return out
+
+ def get_facts(self, subset=None):
+ return self.populate()
+
+ def edit_config(self, config=None):
+ commands = self.render(config)
+ if commands and self.check_mode is False:
+ self.connection.edit_config(commands)
+ return commands
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/acl_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/acl_interfaces.py
new file mode 100644
index 00000000..7f07a123
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/acl_interfaces.py
@@ -0,0 +1,61 @@
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import re
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network_template import (
+ NetworkTemplate,
+)
+
+
+class Acl_interfacesTemplate(NetworkTemplate):
+ def __init__(self, lines=None):
+ super(Acl_interfacesTemplate, self).__init__(lines=lines, tmplt=self)
+
+ # fmt: off
+ PARSERS = [
+ {
+ 'name': 'interface',
+ 'getval': re.compile(r'''
+ ^interface
+ \s(preconfigure)*\s*
+ (?P<name>\S+)$''', re.VERBOSE),
+ 'setval': 'interface {{ name }}',
+ 'result': {
+ '{{ name }}': {
+ 'name': '{{ name }}',
+ 'access_groups': {},
+ },
+ },
+ 'shared': True
+ },
+ {
+ "name": "access_groups",
+ "getval": re.compile(
+ r"""
+ \s+(?P<afi>ipv4|ipv6)
+ \saccess-group\s(?P<acl_name>\S+)
+ \s(?P<direction>\S+)$
+ """,
+ re.VERBOSE,
+ ),
+ "setval": "{{ afi }} access-group {{ name }} {{ 'egress' if direction == 'out' else 'ingress' }}",
+ "result": {
+ "{{ name }}": {
+ "access_groups": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "acls": [
+ {
+ "name": "{{ acl_name }}",
+ "direction": "{{ 'in' if direction == 'ingress' else 'out' }}",
+ },
+ ],
+ }
+ }
+ }
+ }
+ },
+ ]
+ # fmt: on
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospf_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospf_interfaces.py
new file mode 100644
index 00000000..3cd153d7
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospf_interfaces.py
@@ -0,0 +1,1370 @@
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+import re
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network_template import (
+ NetworkTemplate,
+)
+
+
+def get_ospf_type(afi):
+ return "ospf" if afi == "ipv4" else "ospfv3"
+
+
+def get_interface_type(name):
+ return (
+ "GigabitEthernet" if name.startswith("GigabitEthernet") else "Loopback"
+ )
+
+
+def _compute_command(cfg):
+ ospf_type = get_ospf_type(cfg["address_family"]["afi"])
+ type = get_interface_type(cfg["name"])
+ area = cfg["address_family"]["processes"]["area"]
+ pid = cfg["address_family"]["processes"]["process_id"]
+ cmd = "router {0} {1} area {2} interface {3} {4}".format(
+ ospf_type, pid, area["area_id"], type, cfg["name"].split(type)[1]
+ )
+ return cmd
+
+
+def _tmplt_ospf_int_delete(config_data):
+ ospf_type = get_ospf_type(config_data["afi"])
+ type = get_interface_type(config_data["name"])
+ area = config_data["area"]
+ command = "router {0} {1} area {2} interface {3} {4}".format(
+ ospf_type,
+ config_data["process"],
+ area["area_id"],
+ type,
+ config_data["name"].split(type)[1],
+ )
+ return command
+
+
+def _tmplt_ospf_config(config_data):
+ command = _compute_command(config_data)
+ return command
+
+
+def _tmplt_ospf_authentication_md_config(config_data):
+ command = _compute_command(config_data)
+ auth = config_data["address_family"]["authentication"]
+ if auth["message_digest"].get("keychain"):
+ command += (
+ " authentication message-digest keychain "
+ + auth["message_digest"]["keychain"]
+ )
+ return command
+
+
+def _tmplt_ospf_authentication_md_set(config_data):
+ command = _compute_command(config_data)
+ auth = config_data["address_family"]["authentication"]
+ if auth.get("message_digest") and auth["message_digest"].get("keychain"):
+ command += " authentication message-digest"
+ elif auth.get("null_auth"):
+ command += " authentication null"
+ return command
+
+
+def _tmplt_ospf_authentication_key(config_data):
+ command = _compute_command(config_data)
+ auth = config_data["address_family"]["authentication_key"]
+ if auth.get("password"):
+ command += " authentication-key " + auth["password"]
+ elif auth.get("encrypted"):
+ command += " authentication-key encrypted " + auth["encrypted"]
+ elif auth.get("clear"):
+ command += " authentication-key clear " + auth["clear"]
+ return command
+
+
+def _tmplt_ospf_int_bfd_min_int(config_data):
+ command = _compute_command(config_data)
+ bfd = config_data["address_family"]["bfd"]
+ if bfd.get("minimum_interval"):
+ command += " bfd minimum-interval " + str(bfd["minimum_interval"])
+ return command
+
+
+def _tmplt_ospf_int_bfd_mult(config_data):
+ command = _compute_command(config_data)
+ bfd = config_data["address_family"]["bfd"]
+ if bfd.get("multiplier"):
+ command += " bfd multiplier " + str(bfd["multiplier"])
+ return command
+
+
+def _tmplt_ospf_int_bfd_fd(config_data):
+ command = _compute_command(config_data)
+ bfd = config_data["address_family"]["bfd"]
+ if bfd.get("fast_detect") and bfd["fast_detect"].get("set"):
+ command += " bfd fast-detect"
+ elif bfd.get("fast_detect") and bfd["fast_detect"].get("disable"):
+ command += " bfd fast-detect disable"
+ elif bfd.get("fast_detect") and bfd["fast_detect"].get("strict_mode"):
+ command += " bfd fast-detect strict-mode"
+ return command
+
+
+def _tmplt_ospf_cost_config(config_data):
+ command = _compute_command(config_data)
+ command += " cost " + str(config_data["address_family"]["cost"])
+ return command
+
+
+def _tmplt_ospf_cost_fallback_config(config_data):
+ command = _compute_command(config_data)
+ fallback = config_data["address_family"]["cost_fallback"]
+ command += (
+ " cost-fallback "
+ + str(fallback["cost"])
+ + " threshold "
+ + str(fallback["threshold"])
+ )
+ return command
+
+
+def _tmplt_ospf_dead_int_config(config_data):
+ command = _compute_command(config_data)
+ command += " dead-interval " + str(
+ config_data["address_family"]["dead_interval"]
+ )
+ return command
+
+
+def _tmplt_ospf_demand_config(config_data):
+ command = _compute_command(config_data)
+ if config_data["address_family"]["demand_circuit"]:
+ command += " demand-circuit enable"
+ else:
+ command += " demand-circuit disable"
+ return command
+
+
+class Ospf_interfacesTemplate(NetworkTemplate):
+ def __init__(self, lines=None):
+ super(Ospf_interfacesTemplate, self).__init__(lines=lines, tmplt=self)
+
+ # fmt: off
+ PARSERS = [
+ {
+ "name": "name",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ $''',
+ re.VERBOSE),
+ "remval": _tmplt_ospf_int_delete,
+ "setval": _tmplt_ospf_config,
+ "compval": "name",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ },
+ },
+ },
+ "shared": True,
+ },
+ {
+ "name": "authentication.message_digest",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sauthentication(?P<authentication>)
+ \s(?P<opt>message-digest)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_authentication_md_set,
+ "compval": "address_family.authentication.message_digest",
+ "result": {
+ "{{ name }}": {
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "authentication": {
+ "set": "{{ True if authentication is defined and opt is undefined }}",
+ "message_digest": {
+ "set": "{{ True if opt == 'message-digest' else None }}",
+ },
+ }
+ },
+ }
+ }
+ }
+ },
+ {
+ "name": "authentication.message_digest.keychain",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sauthentication(?P<authentication>)
+ \s(?P<message_digest>message-digest)
+ \skeychain\s(?P<keychain>\S+)$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_authentication_md_config,
+ "compval": "address_family.authentication.message_digest.keychain",
+ "result": {
+ "{{ name }}": {
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "authentication": {
+ "message_digest": {
+ "keychain": "{{ keychain }}",
+ },
+ }
+ },
+ }
+ }
+ }
+ },
+ {
+ "name": "authentication.null_auth",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sauthentication(?P<authentication>)
+ \s(?P<opt>null)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_authentication_md_set,
+ "compval": "address_family.authentication.null_auth",
+ "result": {
+ "{{ name }}": {
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "authentication": {
+ "set": "{{ True if authentication is defined and opt is undefined }}",
+ "null_auth": "{{ True if opt == 'null' else None }}",
+ }
+ },
+ }
+ }
+ }
+ },
+ {
+ "name": "authentication_key",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sauthentication-key
+ (\sencrypted\s(?P<encrypted>\S+))?
+ (\s(?P<key>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_authentication_key,
+ "compval": "address_family.authentication_key",
+ "result": {
+ "{{ name }}": {
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "authentication_key": {
+ "encrypted": "{{ encrypted }}",
+ }
+ },
+ }
+ }
+ }
+ },
+ {
+ "name": "bfd.minimum_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sbfd(?P<bfd>)
+ \sminimum-interval\s(?P<minimum_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_int_bfd_min_int,
+ "compval": "address_family.bfd.minimum_interval",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+
+ }
+ },
+ "bfd": {
+ "minimum_interval": "{{ minimum_interval|int }}",
+ },
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "bfd.multiplier",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sbfd(?P<bfd>)
+ \smultiplier\s(?P<multiplier>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_int_bfd_mult,
+ "compval": "address_family.bfd.multiplier",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+
+ }
+ },
+ "bfd": {
+ "multiplier": "{{ multiplier|int }}",
+ },
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "bfd.fast_detect.set",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sbfd(?P<bfd>)
+ \sfast-detect(?P<fast_detect>)
+ (\s(?P<opt>(disable|strict-mode)))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_int_bfd_fd,
+ "compval": "address_family.bfd.fast_detect.set",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+
+ }
+ },
+ "bfd": {
+ "fast_detect": {
+ "set": "{{ True if opt != 'disable' and opt != 'strict-mode' and fast_detect is defined else None }}",
+ },
+ },
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "bfd.fast_detect.disable",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sbfd(?P<bfd>)
+ \sfast-detect(?P<fast_detect>)
+ (\s(?P<opt>(disable|strict-mode)))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_int_bfd_fd,
+ "compval": "address_family.bfd.fast_detect.disable",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+
+ }
+ },
+ "bfd": {
+ "fast_detect": {
+ "disable": "{{ True if opt == 'disable' else None }}"
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd.fast_detect.strict_mode",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sbfd(?P<bfd>)
+ \sfast-detect(?P<fast_detect>)
+ \s(?P<opt>strict-mode)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_int_bfd_fd,
+ "compval": "address_family.bfd.fast_detect.strict_mode",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "bfd": {
+ "fast_detect": {
+ "strict_mode": "{{ True if opt == 'strict-mode' else None }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \scost\s(?P<cost>\S+)$""",
+ re.VERBOSE),
+ "setval": _tmplt_ospf_cost_config,
+ "compval": "address_family.cost",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "cost": "{{ cost }}"
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "cost_fallback",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \scost-fallback\s(?P<cost>\S+)
+ \sthreshold\s(?P<threshold>\S+)
+ $""",
+ re.VERBOSE),
+ "setval": _tmplt_ospf_cost_fallback_config,
+ "compval": "address_family.cost_fallback",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "cost_fallback": {
+ "cost": "{{ cost }}",
+ "threshold": "{{ threshold }}"
+ }
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "dead_interval",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sdead-interval\s(?P<dead_interval>\S+)
+ $''',
+ re.VERBOSE),
+ "setval": _tmplt_ospf_dead_int_config,
+ "compval": "address_family.dead_interval",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "dead_interval": "{{ dead_interval }}"
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "demand_circuit",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sdemand-circuit\s(?P<demand_circuit>\S+)
+ $''',
+ re.VERBOSE),
+ "setval": _tmplt_ospf_demand_config,
+ "compval": "address_family.demand_circuit",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "demand_circuit": "{{ True if demand_circuit == 'enable' else False if demand_circuit == 'disable' else None }}"
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "flood_reduction",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sflood-reduction\s(?P<flood_reduction>\S+)
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "flood-reduction {{ 'enable' if flood_reduction == True else 'disable' }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "flood_reduction": "{{ True if flood_reduction == 'enable' else False if flood_reduction == 'disable' else None }}"
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "hello_interval",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \shello-interval\s(?P<dead_interval>\S+)
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "hello-interval {{ hello_interval }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "hello_interval": "{{ hello_interval }}"
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "link_down.set",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \s(?P<link_down>link-down)
+ (\s(?P<disable>disable))?
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "link-down",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "link_down": {
+ "set": "{{ True if link_down is defined and disable is undefined else None}}"
+ }
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "link_down.disable",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \s(?P<link_down>link-down)
+ \s(?P<disable>disable)
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "link-down disable",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "link_down": {
+ "disable": "{{ True if disable is defined else None }}"
+ }
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "message_digest_key",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \smessage-digest-key
+ \s(?P<id>\d+)
+ \smd5
+ \s(?P<encryption>\d)
+ \s(?P<key>\S+)$""",
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface "
+ "{{ type }} {{ name }} #message-digest-key {{ message_digest_key.id }} "
+ "md5 encrypted {{ message_digest_key.encrypted}}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "message_digest_key": {
+ "id": "{{ id }}",
+ "encrypted": "{{ encryption }}",
+ }
+ },
+ }
+ }
+ }
+ },
+ {
+ "name": "mpls.set_ldp",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \s(?P<mpls>mpls)
+ \s(?P<ldp>set_ldp)
+ (\s(?P<sync>sync))?
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "mpls ldp",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "mpls": {
+ "set_ldp": "{{ True if set_ldp is defined and sync is undefined else None}}"
+ }
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "mpls.ldp_sync",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \s(?P<mpls>mpls)
+ \s(?P<ldp>ldp)
+ \s(?P<sync>sync)
+ (\s(?P<disable>disable))?
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "mpls ldp sync",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "mpls": {
+ "ldp_sync": "{{ True if sync is defined and disable is undefined else None}}"
+ }
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "mpls.ldp_sync_disable",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \s(?P<mpls>mpls)
+ \s(?P<ldp>ldp)
+ \s(?P<sync>sync)
+ \s(?P<disable>disable)
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "mpls ldp sync disable",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "mpls": {
+ "ldp_sync": "{{ False if disable is defined }}"
+ }
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "mtu_ignore",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \smtu-ignore\s(?P<mtu_ignore>\S+)
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "mtu_ignore {{ 'enable' if mtu_ignore == 'True' else 'disable' if mtu_ignore == 'False' }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "mtu_ignore": "{{ True if mtu_ignore == 'enable' else False if mtu_ignore == 'disable' else None }}"
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "network",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \snetwork\s(?P<network>\S+)
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "network {{ network }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "network": "{{ network }}"
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "packet_size",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \spacket-size\s(?P<packet_size>\S+)
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "packet-size {{ packet_size }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "packet_size": "{{ packet_size }}"
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "passive",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \spassive\s(?P<passive>\S+)
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "passive {{ 'enable' if passive == 'True' else 'disable' if passive == 'False' }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "passive": "{{ True if passive == 'enable' else False if passive == 'disable' else None }}"
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "prefix_suppression.disable",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sprefix-suppression\s(?P<prefix_suppression>\S+)
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "prefix-suppression {{ prefix_suppression }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "prefix_suppression": {
+ "disable": "{{ True if prefix_suppression == 'disable' else None }}"
+ }
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "prefix_suppression.secondary_address",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \s(?P<prefix_suppression>prefix-suppression)
+ \s(?P<secondary_address>secondary-address)
+ (\s(?P<disable>disable))?
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "prefix-suppression secondary-address {{ disable if secondary_address is False }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "prefix_suppression": {
+ "secondary_address": "{{ True if secondary_address is defined and "
+ "disable is undefined else False if disable is defined else None }}"
+ },
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "priority",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \spriority\s(?P<priority>\d+)
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "priority {{ priority }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "priority": "{{ priority|int }}"
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "retransmit_interval",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sretransmit-interval\s(?P<retransmit_interval>\d+)
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "retransmit-interval {{ retransmit_interval }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "retransmit_interval": "{{ retransmit_interval|int }}"
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "security.ttl_hops",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \s(?P<security>security)
+ \s(?P<ttl>ttl)
+ \shops\s(?P<hops>\d+)
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "security ttl hops {{ hops }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "security_ttl": {
+ "hops": "{{ hops|int }}"
+ },
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "security.ttl",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \s(?P<security>security)
+ \s(?P<ttl>ttl)
+ (\s(?P<hops>hops))?
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "security ttl",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "security_ttl": {
+ "set": "{{ True if ttl is defined and hops is undefined }}"
+ },
+ },
+ },
+ },
+ }
+ },
+ {
+ "name": "transmit_delay",
+ "getval": re.compile(r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \stransmit-delay\s(?P<transmit_delay>\d+)
+ $''',
+ re.VERBOSE),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "transmit-delay {{ transmit_delay }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ }
+ },
+ "transmit_delay": "{{ transmit_delay|int }}"
+ },
+ },
+ },
+ }
+ },
+ ]
+ # fmt: on
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv2.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv2.py
new file mode 100644
index 00000000..83527d03
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv2.py
@@ -0,0 +1,2876 @@
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+import re
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network_template import (
+ NetworkTemplate,
+)
+from ansible.module_utils.six import iteritems
+
+
+def _tmplt_ospf_default_information(config_data):
+ if "default_information_originate" in config_data:
+ command = "default-information originate"
+ if "always" in config_data["default_information_originate"]:
+ command += " always"
+ if "metric" in config_data["default_information_originate"]:
+ command += " metric {metric}".format(
+ **config_data["default_information_originate"]
+ )
+ if "metric_type" in config_data["default_information_originate"]:
+ command += " metric-type {metric_type}".format(
+ **config_data["default_information_originate"]
+ )
+ if "route_policy" in config_data["default_information_originate"]:
+ command += " route-policy {route_policy}".format(
+ **config_data["default_information_originate"]
+ )
+ return command
+
+
+def _tmplt_ospf_auto_cost(config_data):
+ if "auto_cost" in config_data:
+ command = "auto-cost"
+ if "disable" in config_data["auto_cost"]:
+ command += " disable"
+ if "reference_bandwidth" in config_data["auto_cost"]:
+ command += " reference-bandwidth {reference_bandwidth}".format(
+ **config_data["auto_cost"]
+ )
+ return command
+
+
+def _tmplt_ospf_bfd(config_data):
+ if "bfd" in config_data:
+ command = "bfd"
+ if "minimum_interval" in config_data["bfd"]:
+ command += " minimum-interval {minimum_interval}".format(
+ **config_data["bfd"]
+ )
+
+ if "multiplier" in config_data["bfd"]:
+ command += " multiplier {multiplier}".format(**config_data["bfd"])
+
+ return command
+
+
+def _tmplt_ospf_security(config_data):
+ if "security_ttl" in config_data:
+ command = "security_ttl"
+ if "set" in config_data["security_ttl"]:
+ command += " ttl"
+ elif config_data["security_ttl"].get("hops"):
+ command += " ttl hops {0}".format(
+ config_data["security_ttl"].get("hops")
+ )
+ return command
+
+
+def _tmplt_ospf_log_adjacency(config_data):
+ if "log_adjacency_changes" in config_data:
+ command = "log adjacency"
+ if "set" in config_data["log_adjacency_changes"]:
+ command += " changes"
+ elif config_data["log_adjacency_changes"].get("disable"):
+ command += " disable"
+ elif config_data["log_adjacency_changes"].get("details"):
+ command += " details"
+ return command
+
+
+def _tmplt_ospf_log_max_lsa(config_data):
+ if "max_lsa" in config_data:
+ command = "max-lsa"
+ if "threshold" in config_data["max_lsa"]:
+ command += " {0}".format(config_data["max_lsa"].get("threshold"))
+ if "warning_only" in config_data["max_lsa"]:
+ command += " warning-only {0}".format(
+ config_data["max_lsa"].get("warning_only")
+ )
+ if "ignore_time" in config_data["max_lsa"]:
+ command += " ignore-time {0}".format(
+ config_data["max_lsa"].get("ignore_time")
+ )
+ if "ignore_count" in config_data["max_lsa"]:
+ command += " ignore-count {0}".format(
+ config_data["max_lsa"].get("ignore_count")
+ )
+ if "reset_time" in config_data["max_lsa"]:
+ command += " reset-time {0}".format(
+ config_data["max_lsa"].get("reset_time")
+ )
+ return command
+
+
+def _tmplt_ospf_max_metric(config_data):
+ if "max_metric" in config_data:
+ command = "max-metric"
+ if "router_lsa" in config_data["max_metric"]:
+ command += " router-lsa"
+ if "external_lsa" in config_data["max_metric"]:
+ command += " external-lsa {external_lsa}".format(
+ **config_data["max_metric"]
+ )
+ if "include_stub" in config_data["max_metric"]:
+ command += " include-stub"
+ if "on_startup" in config_data["max_metric"]:
+ if "time" in config_data["max_metric"]["on_startup"]:
+ command += " on-startup {time}".format(
+ **config_data["max_metric"]["on_startup"]
+ )
+ elif "wait_for_bgp" in config_data["max_metric"]["on_startup"]:
+ command += " on-startup wait-for-bgp"
+ if "summary_lsa" in config_data["max_metric"]:
+ command += " summary-lsa {summary_lsa}".format(
+ **config_data["max_metric"]
+ )
+ return command
+
+
+def _tmplt_ospf_distance_admin(config_data):
+ if "admin_distance" in config_data:
+ command = "distance"
+ if config_data["admin_distance"].get("value"):
+ command += " {0}".format(
+ config_data["admin_distance"].get("value")
+ )
+ if config_data["admin_distance"].get("source"):
+ command += " {0}".format(
+ config_data["admin_distance"].get("source")
+ )
+ if config_data["admin_distance"].get("wildcard"):
+ command += " {0}".format(
+ config_data["admin_distance"].get("wildcard")
+ )
+ if config_data["admin_distance"].get("access_list"):
+ command += " {0}".format(
+ config_data["admin_distance"].get("access_list")
+ )
+ return command
+
+
+def _tmplt_ospf_distance_ospf(config_data):
+ if "ospf_distance" in config_data:
+ command = "distance ospf"
+ if config_data["ospf_distance"].get("external"):
+ command += " external {0}".format(
+ config_data["ospf_distance"].get("external")
+ )
+ if config_data["ospf_distance"].get("inter_area"):
+ command += " inter-area {0}".format(
+ config_data["ospf_distance"].get("inter_area")
+ )
+ if config_data["ospf_distance"].get("intra_area"):
+ command += " intra-area {0}".format(
+ config_data["ospf_distance"].get("intra_area")
+ )
+ return command
+
+
+def _tmplt_ospf_nsr(config_data):
+ if "nsr" in config_data:
+ command = "nsr"
+ if "set" in config_data["nsr"]:
+ command += " nsr"
+ elif config_data["nsr"].get("disable"):
+ command += " nsr {0}".format("disable")
+ return command
+
+
+def _tmplt_ospf_protocol(config_data):
+ if "protocol_shutdown" in config_data:
+ command = "protocol"
+ if "set" in config_data["protocol_shutdown"]:
+ command += " shutdown"
+ elif config_data["shutdown"].get("host_mode"):
+ command += " shutdown host-mode"
+ elif config_data["shutdown"].get("on_reload"):
+ command += " shutdown on-reload"
+ return command
+
+
+def _tmplt_microloop_avoidance(config_data):
+ if "microloop_avoidance" in config_data:
+ command = "microloop avoidance"
+ if "protected" in config_data["microloop_avoidance"]:
+ command += " protected"
+ if "segment_routing" in config_data["microloop_avoidance"]:
+ command += " segment_routing"
+ if "rib_update_delay" in config_data["microloop_avoidance"]:
+ command += " rin-update-delay {0}".config_data[
+ "microloop_avoidance"
+ ].get("rib_update_delay")
+ return command
+
+
+def _tmplt_ospf_bfd_fast_detect(config_data):
+ if "bfd" in config_data:
+ command = "bfd"
+ if "fast_detect" in config_data["bfd"]:
+ fast_detect = config_data["bfd"].get("fast_detect")
+ command += " fast-detect"
+ if "strict_mode" in fast_detect:
+ command += " strict-mode"
+ return command
+
+
+def _tmplt_ospf_mpls_traffic_eng(config_data):
+ if "traffic_eng" in config_data:
+ command = "mpls traffic-eng"
+ if "igp_intact" in config_data["traffic_eng"]:
+ command += " igp-intact"
+ if "ldp_sync_update" in config_data["traffic_eng"]:
+ command += " ldp_sync_update"
+ if "multicast_intact" in config_data["traffic_eng"]:
+ command += " multicast_intact"
+ if "auto_route_exclude" in config_data["traffic_eng"]:
+ policy = config_data["traffic_eng"].get("autoroute_exclude")
+ command += " autoroute-exlude route-policy {0}".format(
+ policy.get("route_policy")
+ )
+ return command
+
+
+def _tmplt_ospf_authentication_md(config_data):
+ command = []
+ if "authentication" in config_data:
+ if config_data["authentication"].get("message_digest"):
+ command = "authentication message-digest"
+ md = config_data["authentication"].get("message_digest")
+ if md.get("keychain"):
+ command += " keychain " + md.get("keychain")
+ return command
+
+
+def _tmplt_ospf_authentication(config_data):
+ command = []
+ if "authentication" in config_data:
+ if config_data["authentication"].get("keychain"):
+ command = "authentication keychain " + config_data[
+ "authentication"
+ ].get("keychain")
+ elif config_data["authentication"].get("no_auth"):
+ command = "authentication null"
+ return command
+
+
+def _tmplt_ospf_adjacency_stagger(config_data):
+ if "adjacency_stagger" in config_data:
+ command = "adjacency stagger".format(**config_data)
+ if config_data["adjacency_stagger"].get(
+ "min_adjacency"
+ ) and config_data["adjacency_stagger"].get("min_adjacency"):
+ command += " {0} {1}".format(
+ config_data["adjacency_stagger"].get("min_adjacency"),
+ config_data["adjacency_stagger"].get("max_adjacency"),
+ )
+ elif config_data["adjacency_stagger"].get("disable"):
+ command += " disable"
+ return command
+
+
+def _tmplt_ospf_adjacency_distribute_bgp_state(config_data):
+ if "distribute_link_list" in config_data:
+ command = "distribute link-state"
+ if config_data["distribute_link_list"].get("instance_id"):
+ command += " instance-id {0}".format(
+ config_data["distribute_link_list"].get("instance_id")
+ )
+ elif config_data["distribute_link_list"].get("throttle"):
+ command += " throttle {0}".format(
+ config_data["distribute_link_list"].get("throttle")
+ )
+ return command
+ elif "distribute_bgp_ls" in config_data:
+ command = "distribute bgp-ls"
+ if config_data["distribute_bgp_ls"].get("instance_id"):
+ command += " instance-id {0}".format(
+ config_data["distribute_bgp_ls"].get("instance_id")
+ )
+ elif config_data["distribute_bgp_ls"].get("throttle"):
+ command += " throttle {0}".format(
+ config_data["distribute_bgp_ls"].get("throttle")
+ )
+ return command
+
+
+def _tmplt_ospf_capability_opaque(config_data):
+ if "capability" in config_data:
+ if "opaque" in config_data["capability"]:
+ command = "capability opaque"
+ opaque = config_data["capability"].get("opaque")
+ if "disable" in opaque:
+ command += "capability opaque disable"
+ return command
+
+
+def _tmplt_ospf_authentication_key(config_data):
+ if "authentication_key" in config_data:
+ command = "authentication-key".format(**config_data)
+ if config_data["authentication_key"].get("password"):
+ command += " {0}".format(
+ config_data["authentication_key"].get("password")
+ )
+ return command
+
+
+def _tmplt_ospf_area_authentication(config_data):
+ if "authentication" in config_data:
+ command = "area {area_id} authentication".format(**config_data)
+ if config_data["authentication"].get("keychain"):
+ command += " keychain " + config_data["authentication"].get(
+ "keychain"
+ )
+ elif config_data["authentication"].get("no_auth"):
+ command += " null"
+ return command
+
+
+def _tmplt_ospf_area_authentication_md(config_data):
+ if "authentication" in config_data:
+ command = "area {area_id} authentication".format(**config_data)
+ if "message_digest" in config_data["authentication"]:
+ command = "authentication message-digest"
+ md = config_data["authentication"].get("message_digest")
+ if md.get("keychain"):
+ command += " keychain " + md.get("keychain")
+ return command
+
+
+def _tmplt_ospf_area_authentication_key(config_data):
+ if "authentication_key" in config_data:
+ command = "area {area_id} authentication-key".format(**config_data)
+ if config_data["authentication_key"].get("password"):
+ command += " {0}".format(
+ config_data["authentication_key"].get("password")
+ )
+ return command
+
+
+def _tmplt_ospf_area_mpls_ldp(config_data):
+ commands = []
+ if "mpls" in config_data:
+ command = "area {area_id} mpls".format(**config_data)
+ if config_data["mpls"].get("ldp"):
+ ldp = config_data["mpls"].get("ldp")
+ if "auto_config" in ldp:
+ command += " auto-config"
+ commands.append(command)
+ if "sync" in ldp:
+ command += " sync"
+ commands.append(command)
+ if "sync_igp_shortcuts" in ldp:
+ command += " sync-igp-shortcuts"
+ commands.append(command)
+ return commands
+
+
+def _tmplt_ospf_area_bfd(config_data):
+ if "bfd" in config_data:
+ command = "area {area_id} bfd".format(**config_data)
+ if "minimum_interval" in config_data["bfd"]:
+ command += " minimum-interval {minimum_interval}".format(
+ **config_data["bfd"]
+ )
+
+ if "multiplier" in config_data["bfd"]:
+ command += " multiplier {multiplier}".format(**config_data["bfd"])
+
+ return command
+
+
+def _tmplt_ospf_area_bfd_fast_detect(config_data):
+ if "bfd" in config_data:
+ command = "area {area_id} bfd".format(**config_data)
+ if "fast_detect" in config_data["bfd"]:
+ fast_detect = config_data["bfd"].get("fast_detect")
+ command += " fast-detect"
+ if "strict_mode" in fast_detect:
+ command += " strict-mode"
+ return command
+
+
+def _tmplt_ospf_mpls_ldp(config_data):
+ commands = []
+ if "mpls" in config_data:
+ command = "mpls".format(**config_data)
+ if config_data["mpls"].get("ldp"):
+ ldp = config_data["mpls"].get("ldp")
+ if "auto_config" in ldp:
+ command += " auto-config"
+ commands.append(command)
+ if "sync" in ldp:
+ command += " sync"
+ commands.append(command)
+ if "sync_igp_shortcuts" in ldp:
+ command += " sync-igp-shortcuts"
+ commands.append(command)
+ return commands
+
+
+def _tmplt_ospf_area_nssa(config_data):
+ if "nssa" in config_data:
+ command = "area {area_id} nssa".format(**config_data)
+ if config_data["nssa"].get("no_redistribution"):
+ command += " no-redistribution"
+ if config_data["nssa"].get("no_summary"):
+ command += " no-summary"
+ return command
+
+
+def _tmplt_ospf_area_nssa_def_info_origin(config_data):
+ if "nssa" in config_data:
+ command = "area {area_id} nssa".format(**config_data)
+ if "default_information_originate" in config_data["nssa"]:
+ command += " default-information-originate"
+ def_info_origin = config_data["nssa"].get(
+ "default_information_originate"
+ )
+ if "metric" in def_info_origin:
+ command += " metric {metric}".format(
+ **config_data["nssa"]["default_information_originate"]
+ )
+ if "metric_type" in def_info_origin:
+ command += " metric-type {metric_type}".format(
+ **config_data["nssa"]["default_information_originate"]
+ )
+ return command
+
+
+def _tmplt_ospf_area_nssa_translate(config_data):
+ if "nssa" in config_data:
+ command = "area {area_id} nssa".format(**config_data)
+ if config_data["nssa"].get("translate"):
+ command += " translate"
+ translate = config_data["nssa"].get("translate")
+ if "type7" in translate:
+ command += " type7"
+ if translate["type7"].get("always"):
+ command += " always"
+ return command
+
+
+def _tmplt_ospf_area_vlink_authentication(config_data):
+ if "authentication" in config_data:
+ command = "area {area_id} virtual-link {id} authentication".format(
+ **config_data
+ )
+ if config_data["authentication"].get("keychain"):
+ command += " keychain " + config_data["authentication"].get(
+ "keychain"
+ )
+ elif config_data["authentication"].get("no_auth"):
+ command += " null"
+ return command
+
+
+def _tmplt_ospf_area_vlink_authentication_md(config_data):
+ if "authentication" in config_data:
+ command = "area {area_id} virtual-link {id} authentication".format(
+ **config_data
+ )
+ if config_data["authentication"].get("message_digest"):
+ command = "authentication message-digest"
+ md = config_data["authentication"].get("message_digest")
+ if md.get("keychain"):
+ command += " keychain " + md.get("keychain")
+ return command
+
+
+def _tmplt_ospf_area_vlink_authentication_key(config_data):
+ if "authentication_key" in config_data:
+ command = "area {area_id} virtual-link {id} authentication-key".format(
+ **config_data
+ )
+ if config_data["authentication_key"].get("password"):
+ command += " {0}".format(
+ config_data["authentication_key"].get("password")
+ )
+ return command
+
+
+def _tmplt_ospf_area_stub(config_data):
+ if "stub" in config_data:
+ command = "area {area_id} stub".format(**config_data)
+ if config_data["stub"].get("no_summary"):
+ command += " no-summary"
+ return command
+
+
+def _tmplt_ospf_area_ranges(config_data):
+ if "ranges" in config_data:
+ commands = []
+ for k, v in iteritems(config_data["ranges"]):
+ cmd = "area {area_id} range".format(**config_data)
+ temp_cmd = " {address}".format(**v)
+ if "advertise" in v:
+ temp_cmd += " advertise"
+ elif "not_advertise" in v:
+ temp_cmd += " not-advertise"
+ cmd += temp_cmd
+ commands.append(cmd)
+ return commands
+
+
+def _tmplt_prefix_suppression(config_data):
+ if "prefix_suppression" in config_data:
+ if "set" in config_data["prefix_suppression"]:
+ command = "prefix-suppression"
+ if "secondary_address" in config_data["prefix_suppression"]:
+ command = "prefix-suppression secondary-address"
+ return command
+
+
+def _tmplt_protocol_shutdown(config_data):
+ if "protocol_shutdown" in config_data:
+ if "set" in config_data["protocol_shutdown"]:
+ command = "protocol-shutdown"
+ if "host_mode" in config_data["protocol_shutdown"]:
+ command = "protocol-shutdown host-mode"
+ if "on_reload" in config_data["protocol_shutdown"]:
+ command = "protocol-shutdown on-reload"
+ return command
+
+
+def _tmplt_timers_lsa(config_data):
+ if "timers" in config_data:
+ command = "timers lsa"
+ if "group_pacing" in config_data["timers"]["lsa"]:
+ command += " group-pacing {group_pacing}".format(
+ **config_data["timers"]["lsa"]
+ )
+ if "min_arrival" in config_data["timers"]["lsa"]:
+ command += " min-arrival {min_arrival}".format(
+ **config_data["timers"]["lsa"]
+ )
+ if "refresh" in config_data["timers"]["lsa"]:
+ command += " refresh {refresh}".format(
+ **config_data["timers"]["lsa"]
+ )
+ return command
+
+
+def _tmplt_timers_graceful_shutdown(config_data):
+ if "timers" in config_data:
+ command = "timers graceful-shutdown"
+ if "initial_delay" in config_data["timers"]["graceful-shutdown"]:
+ command += " initial delay {initial_delay}".format(
+ **config_data["timers"]["graceful-shutdown"]
+ )
+ if "retain_routes" in config_data["timers"]["graceful-shutdown"]:
+ command += " retain routes {retain_routes}".format(
+ **config_data["timers"]["graceful-shutdown"]
+ )
+ return command
+
+
+class Ospfv2Template(NetworkTemplate):
+ def __init__(self, lines=None):
+ super(Ospfv2Template, self).__init__(lines=lines, tmplt=self)
+
+ # fmt: off
+ PARSERS = [
+ {
+ "name": "pid",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "router ospf {{ process_id }}",
+ "result": {
+ "processes": {"{{ pid }}": {"process_id": "{{ pid }}"}}
+ },
+ "shared": True,
+ },
+ {
+ "name": "cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \scost(?P<cost>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "cost {{ cost }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "cost": "{{ cost|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "default_metric",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdefault-metric(?P<default_metric>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "default-metric {{ default_metric }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "default_metric": "{{ default_metric|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "packet_size",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \spacket-size(?P<packet_size>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "packet-size {{ packet_size }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "packet_size": "{{ packet_size|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "dead_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdead-interval(?P<dead_interval>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "dead-interval {{ dead_interval }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "dead_interval": "{{ dead_interval|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "hello_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \shello-interval(?P<hello_interval>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "hello-interval {{ hello_interval }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "hello_interval": "{{ hello_interval|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "priority",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \spriority(?P<priority>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "priority {{ priority }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "priority": "{{ priority|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "weight",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sweight(?P<weight>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "weight {{ weight }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "weight": "{{ weight|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "retransmit_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sretransmit-interval(?P<retransmit_interval>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "retransmit-interval {{ retransmit_interval }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "retransmit_interval": "{{ retransmit_interval|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "transmit_delay",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \stransmit-delay(?P<transmit_delay>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "transmit-delay {{ transmit_delay }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "transmit_delay": "{{ transmit_delay|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "passive",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \spassive\s(?P<passive>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "passive {{ passive }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "passive": "{{ passive }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "process.database_filter",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdatabase-filter
+ \sall
+ \sout\s(?P<database_filter>\s\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "process.database_filter",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "database_filter": "{{ database_filter }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "demand_circuit",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdemand-circuit\s(?P<demand_circuit>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "demand-circuit {{ demand_circuit }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "demand_circuit": "{{ demand_circuit }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "external_out",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sexternal-out\s(?P<external_out>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "external-out {{ external_out }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "external_out": "{{ external_out }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "router_id",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \srouter-id\s(?P<router_id>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "router-id {{ router_id }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "router_id": "{{ router_id }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "summary_in",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \ssummary-in\s(?P<summary_in>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "summary-in {{ summary_in }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "summary_in": "{{ summary_in }}",
+ }
+ }
+ },
+ },
+
+ {
+ "name": "mtu_ignore",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \smtu-ignore\s(?P<mtu_ignore>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "mtu-ignore {{ mtu_ignore }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "mtu_ignore": "{{ mtu_ignore }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "flood_reduction",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sflood-reduction\s(?P<flood_reduction>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "flood-reduction {{ flood_reduction }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "flood_reduction": "{{ flood_reduction }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "loopback_stub_network",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sloopback(?P<loopback>)
+ \sstub-network\s(?P<stub_network>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "loopback stub-network {{ stub_network }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "loopback_stub_network": "{{ loopback_stub_network }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "address_family_unicast",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \saddress-family(?P<address_family>)
+ \sipv4(?P<ipv4>)
+ \sunicast(?P<unicast>)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "address_family_unicast",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "address_family_unicast": "{{ True if unicast is defined }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "default_weight",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sapply-weight(?P<apply_weight>)
+ \sdefault-weight(?P<default_weight>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "apply-weight default-weight {{ default_weight }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "apply_weight": {
+ "default_weight": "{{ default_weight|int }}",
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "bandwidth",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sapply-weight(?P<apply_weight>)
+ \sbandwidth(?P<bandwidth>\s\d+)?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "apply-weight bandwidth {{ bandwidth }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "apply_weight": {
+ "bandwidth": "{{ bandwidth|int }}",
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "adjacency_stagger",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sadjacency(?P<adjacency>)
+ \sstagger(?P<stagger>)
+ (\s(?P<min_adjacency>\d+))?
+ (\s(?P<max_adjacency>\d+))?
+ (\sdisable(?P<disable>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_adjacency_stagger,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "adjacency_stagger": {
+ "min_adjacency": "{{ min_adjacency|int }}",
+ "max_adjacency": "{{ max_adjacency }}",
+ "disable": "{{ True if disable is defined }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "authentication",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sauthentication(?P<auth>)
+ (\skeychain\s(?P<keychain>\S+)*)?
+ (\snull(?P<no_auth>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_authentication,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "authentication": {
+ "no_auth": "{{ True if no_auth is defined }}",
+ "keychain": "{{ keychain }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "authentication.message_digest",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sauthentication(?P<auth>)
+ \smessage-digest(?P<md>)
+ \skeychain\s(?P<md_key>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_authentication_md,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "authentication": {
+ "message_digest": {
+ "keychain": "{{ md_key }}",
+ "set": "{{ True if md is defined and md_key is undefined }}",
+ }
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "default_information_originate",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdefault-information(?P<default_information>)
+ (\soriginate(?P<originate>))?
+ (\salways(?P<always>))?
+ (\smetric\s(?P<metric>\d+))?
+ (\smetric-type\s(?P<metric_type>\d+))?
+ (\sroute_policy\s(?P<route_policy>)\S+)?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_default_information,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "default_information_originate": {
+ "always": "{{ True if always is defined }}",
+ "metric": "{{ metric|int }}",
+ "metric_type": "{{ metric_type|int }}",
+ "route_policy": "{{ route_policy }}",
+ "set": "{{ True if default_information is defined and always is undefined and metric "
+ "is undefined and metric_type is undefined and route_policy is undefined }}"
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "auto_cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sauto-cost(?P<auto_cost>)
+ (\sreference-bandwidth\s(?P<reference_bandwidth>\d+))?
+ (\sdisable(?P<disable>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_auto_cost,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "auto_cost": {
+ "disable": "{{ True if disable is defined }}",
+ "reference_bandwidth": "{{ reference_bandwidth|int }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "bfd",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sbfd(?P<bfd>)
+ (\sminimum-interval\s(?P<minimum_interval>\d+))?
+ (\smultiplier\s(?P<multiplier>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_bfd,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "bfd": {
+ "minimum_interval": "{{ minimum_interval|int }}",
+ "multiplier": "{{ multiplier|int }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "bfd.fast_detect",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sbfd(?P<bfd>)
+ \sfast-detect(?P<fast_detect>)
+ (\s(?P<disable>disable))?
+ (\s(?P<strict_mode>strict-mode))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_bfd_fast_detect,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "bfd": {
+ "fast_detect": {
+ "set": "{{ True if disable is undefined and strict_mode is undefined }}",
+ "strict_mode": "{{ True if strict_mode is defined }}",
+ },
+ },
+ }
+ },
+ },
+ },
+ {
+ "name": "security",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \ssecurity(?P<security>)
+ \sttl(?P<ttl>)?
+ (\shops\s(?P<hops>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_security,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "security_ttl": {
+ "set": "{{ True if ttl is defined and hops is undefined }}",
+ "hops": "{{ hops }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "nsr",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \snsr(?P<nsr>)
+ \sdisable(?P<disable>)?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_nsr,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "nsr": {
+ "set": "{{ True if nsr is defined and disable is undefined }}",
+ "disable": "{{ True if disable is defined }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "protocol",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sprotocol(?P<protocol>)
+ \s(shutdown(?P<shutdown>))
+ (\shost-mode(?P<host_mode>))?
+ (\son-reload\s(?P<on_reload>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_protocol,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "protocol_shutdown": {
+ "set": "{{ True if shutdown is defined and host-mode is undefined and on_reload is undefined }}",
+ "host_mode": "{{ True if host_mode is defined }}",
+ "on_reload": "{{ True if on_reload is defined }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "capability",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \scapability(?P<capability>)
+ (\stype7\s(?P<type7>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "capability type7 {{ type7 }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "capability": {
+ "type7": "{{ type7 }}"
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "capability.opaque",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \scapability(?P<capability>)?
+ \sopaque(?P<opaque>)
+ (\sdisable(?P<disable>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_capability_opaque,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "capability": {
+ "opaque": {
+ "disable": "{{ True if disable is defined }}",
+ "set": "{{ True if opaque is defined and disable is undefined }}",
+ },
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "admin_distance",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdistance\s(?P<value>d+)
+ \s(?P<source>\S+)
+ \s(?P<wildcard>\S+)
+ (\s(?P<access_list>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_distance_admin,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "distance": {
+ "admin_distance": {
+ "value": "{{ value|int }}",
+ "source": "{{ source }}",
+ "wildcard": "{{ wildcard }}",
+ "access_list": "{{ access_list }}",
+ }
+ },
+ }
+ }
+ },
+ },
+
+ {
+ "name": "ospf_distance",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdistance(?P<value>)
+ \sospf(?P<ospf>)
+ (\sexternal\s(?P<external>\d+))?
+ (\sinter-area\s(?P<inter_area>\d+))?
+ (\sintra-area\s(?P<intra_area>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_distance_ospf,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "distance": {
+ "ospf_distance": {
+ "external": "{{ external|int }}",
+ "inter_area": "{{ inter_area|int }}",
+ "intra_area": "{{ intra_area|int }}",
+ }
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "authentication_key",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sauthentication-key(?P<auth_key>)
+ (\s(?P<password>\S+))?
+ (\sclear\s(?P<clear>)\S+)?
+ (\sencrypted(?P<encrypted>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_authentication_key,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "authentication_key": {
+ "clear": "{{ clear }}",
+ "encrypted": "{{ encrypted}}",
+ "password": "{{ password if clear is undefined and encrypted is undefined }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "area.default_cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sdefault-cost\s(?P<default_cost>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} default-cost {{ default_cost }}",
+ "compval": "default_cost",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "default_cost": "{{ default_cost|int }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.dead_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sdead-interval\s(?P<dead_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} dead-interval {{ dead_interval }}",
+ "compval": "dead_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "dead_interval": "{{ dead_interval|int }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.hello_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \shello-interval\s(?P<hello_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} hello-interval {{ hello_interval }}",
+ "compval": "hello_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "hello_interval": "{{ hello_interval|int }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.transmit_delay",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \stransmit-delay\s(?P<transmit_delay>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} transmit-delay {{ transmit_delay }}",
+ "compval": "transmit_delay",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "transmit_delay": "{{ transmit_delay|int }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \scost\s(?P<cost>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} cost {{ cost }}",
+ "compval": "cost",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "cost": "{{ cost|int }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.priority",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \spriority\s(?P<priority>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} priority {{ priority }}",
+ "compval": "priority",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "priority": "{{ priority|int }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.weight",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sweight\s(?P<weight>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} weight {{ weight }}",
+ "compval": "weight",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "weight": "{{ weight|int }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.packet_size",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \spacket-size\s(?P<packet_size>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} packet-size {{ packet_size }}",
+ "compval": "packet_size",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "packet_size": "{{ packet_size|int }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.summary_in",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \ssummary-in\s(?P<summary_in>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} summary-in {{ summary_in }}",
+ "compval": "summary_in",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "summary_in": "{{ summary_in }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.demand_circuit",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sdemand-circuit\s(?P<demand_circuit>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} demand-circuit {{ demand_circuit }}",
+ "compval": "demand_circuit",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "demand_circuit": "{{ demand_circuit }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.passive",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \spassive\s(?P<passive>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} passive {{ passive }}",
+ "compval": "passive",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "passive": "{{ passive }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.external_out",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sexternal-out\s(?P<external_out>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} external-out {{ external_out }}",
+ "compval": "passive",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "external_out": "{{ external_out }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.mtu_ignore",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \smtu-ignore\s(?P<mtu_ignore>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} mtu-ignore {{ mtu_ignore }}",
+ "compval": "mtu_ignore",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "mtu_ignore": "{{ mtu_ignore }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.authentication",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sauthentication(?P<auth>)
+ (\skeychain\s(?P<keychain>\S+))?
+ (\snull(?P<no_auth>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_authentication,
+ "compval": "authentication",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "authentication": {
+ "no_auth": "{{ True if no_auth is defined }}",
+ "keychain": "{{ keychain }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.authentication_key",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sauthentication-key(?P<auth_key>)
+ (\s(?P<password>\S+))?
+ (\sclear\s(?P<clear>)\S+)?
+ (\sencrypted(?P<encrypted>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_authentication_key,
+ "compval": "authentication_key",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "authentication_key": {
+ "clear": "{{ clear }}",
+ "encrypted": "{{ encrypted}}",
+ "password": "{{ password if clear is undefined and encrypted is undefined }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.authentication.message_digest",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sauthentication(?P<auth>)
+ \smessage-digest(?P<md>)
+ \skeychain(?P<md_key>\s\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_authentication_md,
+ "compval": "authentication.message_digest",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "authentication": {
+ "message_digest": {
+ "keychain": "{{ md_key }}",
+ }
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.mpls_traffic_eng",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \smpls(?P<mpls>)
+ \straffic-end(?P<traffic_eng>)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} mpls traffic-eng",
+ "compval": "mpls_traffic_eng",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "mpls": {
+ "traffic_eng": "{{ True if traffic_eng is defined }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.mpls_ldp",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \smpls(?P<mpls>)
+ (\sauto-config(?P<auto_config>))?
+ (\ssync(?P<sync>))?
+ (\ssync-igp-shortcuts(?P<syn_igp_shortcuts>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_mpls_ldp,
+ "compval": "mpls_ldp",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "mpls": {
+ "ldp": {
+ "auto_config": "{{ True if auto_config is defined }}",
+ "sync": "{{ True if sync is defined }}",
+ "sync_igp_shortcuts": "{{ True if sync_igp_shortcuts is defined }}",
+
+ }
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.bfd",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sbfd(?P<bfd>)
+ (\sminimum-interval\s(?P<minimum_interval>\d+))?
+ (\smultiplier\s(?P<multiplier>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_bfd,
+ "compval": "bfd",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "bfd": {
+ "minimum_interval": "{{ minimum_interval|int }}",
+ "multiplier": "{{ multiplier|int }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.bfd.fast_detect",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sbfd(?P<bfd>)
+ \sarea(?P<area_id>)
+ \sfast-detect(?P<fast_detect>)
+ (\s(?P<disable>disable))?
+ (\s(?P<strict_mode>strict-mode))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_bfd_fast_detect,
+ "compval": "bfd.fast_detect",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "bfd": {
+ "fast_detect": {
+ "set": "{{ True if disable is undefined and strict_mode is undefined }}",
+ "strict_mode": "{{ True if strict_mode is defined }}",
+ },
+ },
+ }
+ }
+ }
+ },
+ },
+ },
+ {
+ "name": "area.stub",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sstub(?P<nssa>)
+ (\sno-summary(?P<no_sum>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_stub,
+ "compval": "stub",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "area_id": "{{ area_id }}",
+ "stub": {
+ "set": "{{ True if stub is defined and no_summary is undefined }}",
+ "no_summary": "{{ True if no_summary is defined }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.nssa",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \snssa(?P<nssa>)
+ (\sno-redistribution(?P<no_redis>))?
+ (\sno-summary(?P<no_sum>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_nssa,
+ "compval": "nssa",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "area_id": "{{ area_id }}",
+ "nssa": {
+ "set": "{{ True if nssa is defined and no_summary is undefined and no_redis is undefined }}",
+ "no_summary": "{{ True if no_summary is defined }}",
+ "no_redistribution": "{{ True if no_redis is defined }}"
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.nssa.default_information_originate",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \snssa(?P<nssa>)
+ (\sno-redistribution(?P<no_redis>))?
+ (\sdefault-information-originate(?P<def_info_origin>))?
+ (\smetric\s(?P<metric>\d+))?
+ (\smetric-type\s(?P<metric_type>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_nssa_def_info_origin,
+ "compval": "nssa.default_information_originate",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "nssa": {
+ "default_information_originate": {
+ "metric": "{{ metric|int }}",
+ "metric_type": "{{ metric_type|int }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ },
+ {
+ "name": "area.ranges",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \srange(?P<range>)
+ \s(?P<address>\S+)
+ (\sadvertise(?P<advertise>))
+ (\snot-advertise(?P<not_advertise>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_ranges,
+ "compval": "ranges",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "ranges": [
+ {
+ "address": "{{ address }}",
+ "advertise": "{{ True if advertise is defined }}",
+ "not_advertise": "{{ True if not_advertise is defined }}",
+ }
+ ],
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.nssa.translate",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \snssa(?P<nssa>)
+ \stranslate(?P<translate>)
+ \stype7(?P<type7>)
+ \salways\s(?P<always>)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_nssa_translate,
+ "compval": "nssa.translate",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "area_id": "{{ area_id }}",
+ "nssa": {
+ "translate": {
+ "type7": {
+ "always": "{{ True if always is defined }}"
+ }
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "virtual_link.hello_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \shello-interval\s(?P<hello_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} virtual-link {{ id }} hello-interval {{ hello_interval }}",
+ "compval": "hello_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}":
+ {
+ "id": "{{ id }}",
+ "hello_interval": "{{ hello_interval|int }}"
+ }
+
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "virtual_link.dead_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \sdead-interval\s(?P<dead_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} virtual-link {{ id }} dead-interval {{ dead_interval }}",
+ "compval": "dead_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}": {
+ "id": "{{ id }}",
+ "dead_interval": "{{ dead_interval|int }}"
+ }
+
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "virtual_link.retransmit_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \sretransmit-interval\s(?P<retransmit_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} virtual-link {{ id }} retransmit-interval {{ retransmit_interval }}",
+ "compval": "retransmit_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}": {
+ "id": "{{ id }}",
+ "retransmit_interval": "{{ retransmit_interval|int }}"
+ }
+ }
+
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "virtual_link.authentication",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \savirtual-link\s(?P<id>\S+)
+ \sauthentication(?P<auth>)
+ (\skeychain\s(?P<keychain>\S+))?
+ (\snull(?P<no_auth>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_vlink_authentication,
+ "compval": "authentication",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "authentication": {
+ "no_auth": "{{ True if no_auth is defined }}",
+ "keychain": "{{ keychain }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "virtual_link.authentication_key",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \sauthentication-key(?P<auth_key>)
+ (\s(?P<password>\S+))?
+ (\sclear\s(?P<clear>)\S+)?
+ (\sencrypted(?P<encrypted>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_vlink_authentication_key,
+ "compval": "authentication_key",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}": {
+ "authentication_key": {
+ "clear": "{{ clear }}",
+ "encrypted": "{{ encrypted}}",
+ "password": "{{ password if clear is undefined and encrypted is undefined }}",
+ },
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "virtual_link.authentication.message_digest",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \sauthentication(?P<auth>)
+ \smessage-digest(?P<md>)
+ \skeychain(?P<md_key>\s\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_vlink_authentication_md,
+ "compval": "authentication.message_digest",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}": {
+ "authentication": {
+ "message_digest": {
+ "keychain": "{{ md_key }}",
+ }
+ },
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "link_down_fast_detect",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \slink-down
+ \sfast-detect(?P<fast_detect>)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "link-down fast-detect",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "link_down_fast_detect": "{{ True if fast_detect is defined }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "nsr",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \snsr
+ \sdisable(?P<disable>)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "nsr disable",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "disable": "{{ True if disable is defined }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "database_filter",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdatabase-filter
+ \sall
+ \sout\s(?P<outing>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "database-filter all out {{ outing }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "outing": "{{ outing }}"
+ }
+ }
+ },
+ },
+ {
+ "name": "distribute_link_state",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdistribute(?P<distribute>)
+ \slink-state(?P<link_state>)
+ (\sinstance-id(?P<inst_id>\d+))?
+ (\sthrottle(?P<throttle>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_adjacency_distribute_bgp_state,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "distribute_link_list": {
+ "instance_id": "{{ inst_id|int }}",
+ "throttle": "{{ throttle }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "distribute_bgp_ls",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdistribute(?P<distribute>)
+ \sbgp-ls(?P<bgp_ls>)
+ (\sinstance-id(?P<inst_id>\d+))?
+ (\sthrottle(?P<throttle>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_adjacency_distribute_bgp_state,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "distribute_bgp_ls": {
+ "instance_id": "{{ inst_id|int }}",
+ "throttle": "{{ throttle }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "log_adjacency",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \slog(?P<security>)
+ \sadjacency(?P<adjacency>)?
+ (\schanges(?P<changes>))?
+ (\sdisable(?P<disable>))?
+ (\sdetails(?P<details>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_log_adjacency,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "log_adjacency_changes": {
+ "set": "{{ True changes id defined and disable is undefined and detail is undefined }}",
+ "disable": "{{ True if disable is defined }}",
+ "details": "{{ True if details is defined }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "max_lsa",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ (\smax-lsa\s(?P<threshold>\d+))?
+ (\swarning-only\s(?P<warning_only>\d+)?
+ (\signore-time\s(?P<ignore_time>\d+))?
+ (\signore-count\s(?P<ignore_count>\d+))?
+ (\sreset-time\s(?P<reset_time>)\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_log_max_lsa,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "max_lsa": {
+ "threshold": "{{ threshold|int }}",
+ "warning_only": "{{ warning_only|int }}",
+ "ignore_time": "{{ ignore_time|int }}",
+ "ignore_count": "{{ ignore_count|int }}",
+ "reset_time": "{{ reset_time|int }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "max_metric",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \smax-metric
+ \s*(?P<router_lsa>)
+ (\s*external-lsa(?P<external_lsa>))?
+ (\s(?P<max_metric_value>\d+))?
+ \s*(?P<include_stub>include-stub)*
+ \s*(?P<on_startup>on-startup)*
+ \s*(?P<wait_period>\d+)*
+ \s*(wait-for\sbgp)*
+ \s*(?P<bgp_asn>\d+)*
+ \s*(?P<summary_lsa>summary-lsa)*
+ \s*(?P<sum_lsa_max_metric_value>\d+)*
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_max_metric,
+ "remval": "max-metric router-lsa",
+ "result": {
+ "processes": {
+ '{{ "pid" }}': {
+ "max_metric": {
+ "router_lsa": {
+ "set": "{{ True if router_lsa is defined and external_lsa is undefined else None }}",
+ "external_lsa": {
+ "set": "{{ True if external_lsa is defined and max_metric_value is undefined else None }}",
+ "max_metric_value": "{{ max_metric_value }}",
+ },
+ "include_stub": "{{ not not include_stub }}",
+ "on_startup": {
+ "set": "{{ True if on_startup is defined and (wait_period and bgp_asn) is undefined else None }}",
+ "wait_period": "{{ wait_period }}",
+ "wait_for_bgp_asn": "{{ bgp_asn }}",
+ },
+ "summary_lsa": {
+ "set": "{{ True if summary_lsa is defined and sum_lsa_max_metric_value is undefined else None }}",
+ "max_metric_value": "{{ sum_lsa_max_metric_value }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "mpls_ldp",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \smpls(?P<mpls>)
+ (\sauto-config(?P<auto_config>))?
+ (\ssync(?P<sync>))?
+ (\ssync-igp-shortcuts(?P<syn_igp_shortcuts>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_mpls_ldp,
+ "compval": "mpls_ldp",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "mpls": {
+ "ldp": {
+ "auto_config": "{{ True if auto_config is defined }}",
+ "sync": "{{ True if sync is defined }}",
+ "sync_igp_shortcuts": "{{ True if sync_igp_shortcuts is defined }}",
+ }
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "microloop_avoidance",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \smicroloop(?P<microloop>)
+ \savoidance(?P<avoidance>)
+ (\s(?P<protected>protected))?
+ (\s(?P<segment_routing>segment-routing))?
+ (\srib-update-delay\s(?P<rib_update_delay>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_microloop_avoidance,
+ "compval": "microloop_avoidance",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "microloop_avoidance": {
+ "protected": "{{ True if protected is defined }}",
+ "segment_routing": "{{ True if segment_routing is defined }}",
+ "rib_update_delay": "{{ rib_update_delay }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "mpls_traffic_eng",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \smpls(?P<mpls>)
+ \straffic-end(?P<traffic_eng>)
+ (\sautoroute-exclude(?P<autoroute>))?
+ (\sroute-policy(?P<route_policy>\S+))?
+ (\s(?P<igp_intact>igp_intact))?
+ (\s(?P<ldp_sync_update>ldp-sync-update))?
+ (\s(?P<multicast_intact>multicast-intact))?
+ (\srouter-id\s(?P<router_id>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_mpls_traffic_eng,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "mpls": {
+ "autoroute_exclude": {
+ "route_policy": "{{ route_policy }}"
+ },
+ "igp_intact": "{{ True if igp_intact is defined }}",
+ "ldp_sync_update": "{{ True if ldp_sync_update is defined }}",
+ "multicast_intact": "{{ True if multicast_intact is defined }}",
+ "router_id": "{{ router_id }}"
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "prefix_suppression",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sprefix-suppression(?P<prefix_suppression>)
+ (\s(?P<secondary_address>secondary-address))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_prefix_suppression,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "prefix_suppression": {
+ "set": "{{ True if prefix_suppression is defined and secondary_address is undefined }}",
+ "secondary_address": "{{ True if secondary_address is defined }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "protocol_shutdown",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sprotocol-shutdown(?P<protocol_shutdown>)
+ (\s(?P<host_mode>host-mode))?
+ (\s(?P<on_reload>on-reload))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_protocol_shutdown,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "protocol_shutdown": {
+ "set": "{{ True if protocol_shutdown is defined and host_mode is undefined and on_reload is undefined }}",
+ "host_mode": "{{ True if host_mode is defined }}",
+ "on_reload": "{{ True if on_reload is defined }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "timers.lsa",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \stimers
+ \slsa
+ (\sgroup-pacing\s(?P<group_pacing>\d+))?
+ (\smin-arrival\s(?P<min_arrival>\d+))?
+ (\srefresh\s(?P<refresh>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_timers_lsa,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "lsa": {
+ "group_pacing": "{{ group_pacing|int }}",
+ "min_arrival": "{{ min_arrival|int }}",
+ "refresh": "{{ refresh|int }}",
+ },
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "timers.graceful_shutdown",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \stimers
+ \sgraceful_shutdown
+ (\sinitial delay\s(?P<initial_delay>\d+))?
+ (\sretain routes\s(?P<retain_routes>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_timers_graceful_shutdown,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "graceful_shutdown": {
+ "initial_delay": "{{ initial_delay|int }}",
+ "retain_routes": "{{ retain_routes|int }}",
+ },
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "throttle.spf",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \stimers
+ \sthrottle
+ \sspf
+ (\s(?P<change_delay>\d+))
+ (\s(?P<second_delay>\d+))
+ (\s(?P<max_wait>\d+))
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "timers throttle spf {{ throttle.spf.change_delay }} {{ throttle.spf.second_delay }} {{ throttle.spf.max_wait }}",
+ "compval": "throttle.lsa_all",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "throttle": {
+ "lsa_all": {
+ "initial_delay": "{{ initial_delay }}",
+ "min_delay": "{{ min_delay }}",
+ "max_delay": "{{ max_delay }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "throttle.lsa_all",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \stimers
+ \sthrottle
+ \slsa
+ \sall
+ (\s(?P<initial_delay>\d+))
+ (\s(?P<min_delay>\d+))
+ (\s(?P<max_delay>\d+))
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "timers throttle lsa all {{ throttle.lsa_all.initial_delay }} {{ throttle.lsa_all.min_delay }} {{ throttle.lsa_all.max_delay }}",
+ "compval": "throttle.lsa_all",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "throttle": {
+ "lsa_all": {
+ "initial_delay": "{{ initial_delay }}",
+ "min_delay": "{{ min_delay }}",
+ "max_delay": "{{ max_delay }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "throttle.fast_reroute",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \stimers
+ \sthrottle
+ \sfast-reroute\s(?P<fast_reroute>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "timers throttle fast-reroute {{ fast_reroute }}",
+ "compval": "throttle.fast_reroute",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "throttle": {
+ "fast_reroute": "{{ fast_reroute }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "timers.pacing_flood",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \stimers
+ \spacing
+ \sflood\s(?P<pacing_flood>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "timers pacing flood {{ pacing_flood }}",
+ "compval": "timers.pacing_flood",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "pacing_flood": "{{ pacing_flood }}",
+
+ }
+ }
+ }
+ },
+ },
+ ]
+ # fmt: on
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv3.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv3.py
new file mode 100644
index 00000000..d458615e
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv3.py
@@ -0,0 +1,2801 @@
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+import re
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network_template import (
+ NetworkTemplate,
+)
+from ansible.module_utils.six import iteritems
+
+
+def _tmplt_ospf_default_information(config_data):
+ if "default_information_originate" in config_data:
+ command = "default-information originate"
+ if "always" in config_data["default_information_originate"]:
+ command += " always"
+ if "metric" in config_data["default_information_originate"]:
+ command += " metric {metric}".format(
+ **config_data["default_information_originate"]
+ )
+ if "metric_type" in config_data["default_information_originate"]:
+ command += " metric-type {metric_type}".format(
+ **config_data["default_information_originate"]
+ )
+ if "route_policy" in config_data["default_information_originate"]:
+ command += " route-policy {route_policy}".format(
+ **config_data["default_information_originate"]
+ )
+ return command
+
+
+def _tmplt_ospf_auto_cost(config_data):
+ if "auto_cost" in config_data:
+ command = "auto-cost"
+ if "disable" in config_data["auto_cost"]:
+ command += " disable"
+ if "reference_bandwidth" in config_data["auto_cost"]:
+ command += " reference-bandwidth {reference_bandwidth}".format(
+ **config_data["auto_cost"]
+ )
+ return command
+
+
+def _tmplt_ospfv3_bfd_minimum_interval(config_data):
+ if "bfd" in config_data:
+ if "minimum_interval" in config_data["bfd"]:
+ command = "bfd minimum-interval {minimum_interval}".format(
+ **config_data["bfd"]
+ )
+ return command
+
+
+def _tmplt_ospfv3_bfd_multiplier(config_data):
+ if "bfd" in config_data:
+ if "multiplier" in config_data["bfd"]:
+ command = "bfd multiplier {multiplier}".format(
+ **config_data["bfd"]
+ )
+ return command
+
+
+def _tmplt_ospf_security(config_data):
+ if "security_ttl" in config_data:
+ command = "security_ttl"
+ if "set" in config_data["security_ttl"]:
+ command += " ttl"
+ elif config_data["security_ttl"].get("hops"):
+ command += " ttl hops {0}".format(
+ config_data["security_ttl"].get("hops")
+ )
+ return command
+
+
+def _tmplt_ospf_log_adjacency(config_data):
+ if "log_adjacency_changes" in config_data:
+ command = "log adjacency"
+ if "set" in config_data["log_adjacency_changes"]:
+ command += " changes"
+ elif config_data["log_adjacency_changes"].get("disable"):
+ command += " disable"
+ elif config_data["log_adjacency_changes"].get("details"):
+ command += " details"
+ return command
+
+
+def _tmplt_ospf_log_max_lsa(config_data):
+ if "max_lsa" in config_data:
+ command = "max-lsa"
+ if "threshold" in config_data["max_lsa"]:
+ command += " {0}".format(config_data["max_lsa"].get("threshold"))
+ if "warning_only" in config_data["max_lsa"]:
+ command += " warning-only {0}".format(
+ config_data["max_lsa"].get("warning_only")
+ )
+ if "ignore_time" in config_data["max_lsa"]:
+ command += " ignore-time {0}".format(
+ config_data["max_lsa"].get("ignore_time")
+ )
+ if "ignore_count" in config_data["max_lsa"]:
+ command += " ignore-count {0}".format(
+ config_data["max_lsa"].get("ignore_count")
+ )
+ if "reset_time" in config_data["max_lsa"]:
+ command += " reset-time {0}".format(
+ config_data["max_lsa"].get("reset_time")
+ )
+ return command
+
+
+def _tmplt_ospf_max_metric(config_data):
+ if "max_metric" in config_data:
+ command = "max-metric"
+ if "router_lsa" in config_data["max_metric"]:
+ command += " router-lsa"
+ if "external_lsa" in config_data["max_metric"]:
+ command += " external-lsa {external_lsa}".format(
+ **config_data["max_metric"]
+ )
+ if "include_stub" in config_data["max_metric"]:
+ command += " include-stub"
+ if "on_startup" in config_data["max_metric"]:
+ if "time" in config_data["max_metric"]["on_startup"]:
+ command += " on-startup {time}".format(
+ **config_data["max_metric"]["on_startup"]
+ )
+ elif "wait_for_bgp" in config_data["max_metric"]["on_startup"]:
+ command += " on-startup wait-for-bgp"
+ if "summary_lsa" in config_data["max_metric"]:
+ command += " summary-lsa {summary_lsa}".format(
+ **config_data["max_metric"]
+ )
+ return command
+
+
+def _tmplt_ospf_distance_admin(config_data):
+ if "admin_distance" in config_data:
+ command = "distance"
+ if config_data["admin_distance"].get("value"):
+ command += " {0}".format(
+ config_data["admin_distance"].get("value")
+ )
+ if config_data["admin_distance"].get("source"):
+ command += " {0}".format(
+ config_data["admin_distance"].get("source")
+ )
+ if config_data["admin_distance"].get("wildcard"):
+ command += " {0}".format(
+ config_data["admin_distance"].get("wildcard")
+ )
+ if config_data["admin_distance"].get("access_list"):
+ command += " {0}".format(
+ config_data["admin_distance"].get("access_list")
+ )
+ return command
+
+
+def _tmplt_ospf_distance_ospf(config_data):
+ if "ospf_distance" in config_data:
+ command = "distance ospf"
+ if config_data["ospf_distance"].get("external"):
+ command += " external {0}".format(
+ config_data["ospf_distance"].get("external")
+ )
+ if config_data["ospf_distance"].get("inter_area"):
+ command += " inter-area {0}".format(
+ config_data["ospf_distance"].get("inter_area")
+ )
+ if config_data["ospf_distance"].get("intra_area"):
+ command += " intra-area {0}".format(
+ config_data["ospf_distance"].get("intra_area")
+ )
+ return command
+
+
+def _tmplt_ospf_nsr(config_data):
+ if "nsr" in config_data:
+ command = "nsr"
+ if "set" in config_data["nsr"]:
+ command += " nsr"
+ elif config_data["nsr"].get("disable"):
+ command += " nsr {0}".format("disable")
+ return command
+
+
+def _tmplt_ospf_protocol(config_data):
+ if "protocol_shutdown" in config_data:
+ command = "protocol"
+ if "set" in config_data["protocol_shutdown"]:
+ command += " shutdown"
+ elif config_data["shutdown"].get("host_mode"):
+ command += " shutdown host-mode"
+ elif config_data["shutdown"].get("on_reload"):
+ command += " shutdown on-reload"
+ return command
+
+
+def _tmplt_microloop_avoidance(config_data):
+ if "microloop_avoidance" in config_data:
+ command = "microloop avoidance"
+ if "protected" in config_data["microloop_avoidance"]:
+ command += " protected"
+ if "segment_routing" in config_data["microloop_avoidance"]:
+ command += " segment_routing"
+ if "rib_update_delay" in config_data["microloop_avoidance"]:
+ command += " rin-update-delay {0}".config_data[
+ "microloop_avoidance"
+ ].get("rib_update_delay")
+ return command
+
+
+def _tmplt_ospf_bfd_fast_detect(config_data):
+ if "bfd" in config_data:
+ if "fast_detect" in config_data["bfd"]:
+ command = "bfd"
+ fast_detect = config_data["bfd"].get("fast_detect")
+ command += " fast-detect"
+ if "strict_mode" in fast_detect:
+ command += " strict-mode"
+ return command
+
+
+def _tmplt_ospf_mpls_traffic_eng(config_data):
+ if "traffic_eng" in config_data:
+ command = "mpls traffic-eng"
+ if "igp_intact" in config_data["traffic_eng"]:
+ command += " igp-intact"
+ if "ldp_sync_update" in config_data["traffic_eng"]:
+ command += " ldp_sync_update"
+ if "multicast_intact" in config_data["traffic_eng"]:
+ command += " multicast_intact"
+ if "auto_route_exclude" in config_data["traffic_eng"]:
+ policy = config_data["traffic_eng"].get("autoroute_exclude")
+ command += " autoroute-exlude route-policy {0}".format(
+ policy.get("route_policy")
+ )
+ return command
+
+
+def _tmplt_ospf_authentication_ipsec(config_data):
+ if "authentication" in config_data:
+ if config_data["authentication"].get("ipsec"):
+ command = "authentication ipsec"
+ md = config_data["authentication"].get("ipsec")
+ if md.get("spi"):
+ command += " spi " + str(md.get("spi"))
+ if md.get("algorithim_type"):
+ command += " " + md.get("algorithim_type")
+ if md.get("clear_key"):
+ command += " clear " + md.get("clear_key")
+ elif md.get("password_key"):
+ command += " password " + md.get("password_key")
+ elif md.get("key"):
+ command += " " + md.get("key")
+ return command
+
+
+def _tmplt_ospfv3_demand_circuit(config_data):
+ if "demand_circuit" in config_data:
+ command = "demand-circuit"
+ return command
+
+
+def _tmplt_ospfv3_passive(config_data):
+ if "passive" in config_data:
+ command = "passive"
+ return command
+
+
+def _tmplt_ospfv3_demand_mtu_ignore(config_data):
+ if "mtu_ignore" in config_data:
+ command = "mtu-ignore"
+ return command
+
+
+def _tmplt_ospfv3_authentication(config_data):
+ if "authentication" in config_data:
+ if config_data["authentication"].get("disable"):
+ command = "authentication disable"
+ return command
+
+
+def _tmplt_ospf_adjacency_distribute_bgp_state(config_data):
+ if "distribute_link_list" in config_data:
+ command = "distribute link-state"
+ if config_data["distribute_link_list"].get("instance_id"):
+ command += " instance-id {0}".format(
+ config_data["distribute_link_list"].get("instance_id")
+ )
+ elif config_data["distribute_link_list"].get("throttle"):
+ command += " throttle {0}".format(
+ config_data["distribute_link_list"].get("throttle")
+ )
+ return command
+ elif "distribute_bgp_ls" in config_data:
+ command = "distribute bgp-ls"
+ if config_data["distribute_bgp_ls"].get("instance_id"):
+ command += " instance-id {0}".format(
+ config_data["distribute_bgp_ls"].get("instance_id")
+ )
+ elif config_data["distribute_bgp_ls"].get("throttle"):
+ command += " throttle {0}".format(
+ config_data["distribute_bgp_ls"].get("throttle")
+ )
+ return command
+
+
+def _tmplt_ospf_capability_opaque(config_data):
+ if "capability" in config_data:
+ if "opaque" in config_data["capability"]:
+ command = "capability opaque"
+ opaque = config_data["capability"].get("opaque")
+ if "disable" in opaque:
+ command += "capability opaque disable"
+ return command
+
+
+def _tmplt_ospfv3_area_authentication(config_data):
+ if "authentication" in config_data:
+ if config_data["authentication"].get("disable"):
+ command = "area {area_id} ".format(**config_data)
+ command += "authentication disable"
+ return command
+
+
+def _tmplt_ospfv3_area_authentication_ipsec(config_data):
+ if "authentication" in config_data:
+ command = "area {area_id} ".format(**config_data)
+ if config_data["authentication"].get("ipsec"):
+ command += "authentication ipsec"
+ md = config_data["authentication"].get("ipsec")
+ if md.get("spi"):
+ command += " spi " + str(md.get("spi"))
+ if md.get("algorithim_type"):
+ command += " " + md.get("algorithim_type")
+ if md.get("clear_key"):
+ command += " clear " + md.get("clear_key")
+ elif md.get("password_key"):
+ command += " password " + md.get("password_key")
+ elif md.get("key"):
+ command += " " + md.get("key")
+ return command
+
+
+def _tmplt_ospf_area_mpls_ldp(config_data):
+ commands = []
+ if "mpls" in config_data:
+ command = "area {area_id} mpls".format(**config_data)
+ if config_data["mpls"].get("ldp"):
+ ldp = config_data["mpls"].get("ldp")
+ if "auto_config" in ldp:
+ command += " auto-config"
+ commands.append(command)
+ if "sync" in ldp:
+ command += " sync"
+ commands.append(command)
+ if "sync_igp_shortcuts" in ldp:
+ command += " sync-igp-shortcuts"
+ commands.append(command)
+ return commands
+
+
+def _tmplt_ospfv3_area_bfd_minimum_interval(config_data):
+ if "bfd" in config_data:
+ if "minimum_interval" in config_data["bfd"]:
+ command = "area {area_id} ".format(**config_data)
+ command += " bfd minimum-interval {minimum_interval}".format(
+ **config_data["bfd"]
+ )
+ return command
+
+
+def _tmplt_ospfv3_area_bfd_multiplier(config_data):
+ if "bfd" in config_data:
+ if "multiplier" in config_data["bfd"]:
+ command = "area {area_id} ".format(**config_data)
+ command += "bfd multiplier {multiplier}".format(
+ **config_data["bfd"]
+ )
+ return command
+
+
+def _tmplt_ospfv3_area_bfd_fast_detect(config_data):
+ if "bfd" in config_data:
+ if "fast_detect" in config_data["bfd"]:
+ command = "area {area_id} ".format(**config_data)
+ fast_detect = config_data["bfd"].get("fast_detect")
+ command += "bfd fast-detect"
+ if "strict_mode" in fast_detect:
+ command += " strict-mode"
+ return command
+
+
+def _tmplt_ospf_mpls_ldp(config_data):
+ commands = []
+ if "mpls" in config_data:
+ command = "mpls".format(**config_data)
+ if config_data["mpls"].get("ldp"):
+ ldp = config_data["mpls"].get("ldp")
+ if "auto_config" in ldp:
+ command += " auto-config"
+ commands.append(command)
+ if "sync" in ldp:
+ command += " sync"
+ commands.append(command)
+ if "sync_igp_shortcuts" in ldp:
+ command += " sync-igp-shortcuts"
+ commands.append(command)
+ return commands
+
+
+def _tmplt_ospf_area_nssa(config_data):
+ if "nssa" in config_data:
+ command = "area {area_id} nssa".format(**config_data)
+ if config_data["nssa"].get("no_redistribution"):
+ command += " no-redistribution"
+ if config_data["nssa"].get("no_summary"):
+ command += " no-summary"
+ return command
+
+
+def _tmplt_ospf_area_nssa_def_info_origin(config_data):
+ if "nssa" in config_data:
+ command = "area {area_id} nssa".format(**config_data)
+ if "default_information_originate" in config_data["nssa"]:
+ command += " default-information-originate"
+ def_info_origin = config_data["nssa"].get(
+ "default_information_originate"
+ )
+ if "metric" in def_info_origin:
+ command += " metric {metric}".format(
+ **config_data["nssa"]["default_information_originate"]
+ )
+ if "metric_type" in def_info_origin:
+ command += " metric-type {metric_type}".format(
+ **config_data["nssa"]["default_information_originate"]
+ )
+ return command
+
+
+def _tmplt_ospf_area_nssa_translate(config_data):
+ if "nssa" in config_data:
+ command = "area {area_id} nssa".format(**config_data)
+ if config_data["nssa"].get("translate"):
+ command += " translate"
+ translate = config_data["nssa"].get("translate")
+ if "type7" in translate:
+ command += " type7"
+ if translate["type7"].get("always"):
+ command += " always"
+ return command
+
+
+def _tmplt_ospf_area_vlink_authentication(config_data):
+ if "authentication" in config_data:
+ command = "area {area_id} virtual-link {id} authentication".format(
+ **config_data
+ )
+ if config_data["authentication"].get("keychain"):
+ command += " keychain " + config_data["authentication"].get(
+ "keychain"
+ )
+ elif config_data["authentication"].get("no_auth"):
+ command += " null"
+ return command
+
+
+def _tmplt_ospf_area_vlink_authentication_md(config_data):
+ if "authentication" in config_data:
+ command = "area {area_id} virtual-link {id} authentication".format(
+ **config_data
+ )
+ if config_data["authentication"].get("message_digest"):
+ command = "authentication message-digest"
+ md = config_data["authentication"].get("message_digest")
+ if md.get("keychain"):
+ command += " keychain " + md.get("keychain")
+ return command
+
+
+def _tmplt_ospf_area_vlink_authentication_key(config_data):
+ if "authentication_key" in config_data:
+ command = "area {area_id} virtual-link {id} authentication-key".format(
+ **config_data
+ )
+ if config_data["authentication_key"].get("password"):
+ command += " {0}".format(
+ config_data["authentication_key"].get("password")
+ )
+ return command
+
+
+def _tmplt_ospf_area_stub(config_data):
+ if "stub" in config_data:
+ command = "area {area_id} stub".format(**config_data)
+ if config_data["stub"].get("no_summary"):
+ command += " no-summary"
+ return command
+
+
+def _tmplt_ospf_area_ranges(config_data):
+ if "ranges" in config_data:
+ commands = []
+ for k, v in iteritems(config_data["ranges"]):
+ cmd = "area {area_id} range".format(**config_data)
+ temp_cmd = " {address}".format(**v)
+ if "advertise" in v:
+ temp_cmd += " advertise"
+ elif "not_advertise" in v:
+ temp_cmd += " not-advertise"
+ cmd += temp_cmd
+ commands.append(cmd)
+ return commands
+
+
+def _tmplt_prefix_suppression(config_data):
+ if "prefix_suppression" in config_data:
+ if "set" in config_data["prefix_suppression"]:
+ command = "prefix-suppression"
+ if "secondary_address" in config_data["prefix_suppression"]:
+ command = "prefix-suppression secondary-address"
+ return command
+
+
+def _tmplt_protocol_shutdown(config_data):
+ if "protocol_shutdown" in config_data:
+ if "set" in config_data["protocol_shutdown"]:
+ command = "protocol-shutdown"
+ if "host_mode" in config_data["protocol_shutdown"]:
+ command = "protocol-shutdown host-mode"
+ if "on_reload" in config_data["protocol_shutdown"]:
+ command = "protocol-shutdown on-reload"
+ return command
+
+
+def _tmplt_timers_lsa(config_data):
+ if "timers" in config_data:
+ command = "timers lsa"
+ if "group_pacing" in config_data["timers"]["lsa"]:
+ command += " group-pacing {group_pacing}".format(
+ **config_data["timers"]["lsa"]
+ )
+ if "min_arrival" in config_data["timers"]["lsa"]:
+ command += " min-arrival {min_arrival}".format(
+ **config_data["timers"]["lsa"]
+ )
+ if "refresh" in config_data["timers"]["lsa"]:
+ command += " refresh {refresh}".format(
+ **config_data["timers"]["lsa"]
+ )
+ return command
+
+
+def _tmplt_timers_graceful_shutdown(config_data):
+ if "timers" in config_data:
+ command = "timers graceful-shutdown"
+ if "initial_delay" in config_data["timers"]["graceful-shutdown"]:
+ command += " initial delay {initial_delay}".format(
+ **config_data["timers"]["graceful-shutdown"]
+ )
+ if "retain_routes" in config_data["timers"]["graceful-shutdown"]:
+ command += " retain routes {retain_routes}".format(
+ **config_data["timers"]["graceful-shutdown"]
+ )
+ return command
+
+
+class Ospfv3Template(NetworkTemplate):
+ def __init__(self, lines=None):
+ super(Ospfv3Template, self).__init__(lines=lines, tmplt=self)
+
+ # fmt: off
+ PARSERS = [
+ {
+ "name": "pid",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "router ospfv3 {{ process_id }}",
+ "result": {
+ "processes": {"{{ pid }}": {"process_id": "{{ pid }}"}}
+ },
+ "shared": True,
+ },
+ {
+ "name": "cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \scost(?P<cost>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "cost {{ cost }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "cost": "{{ cost|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "default_metric",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdefault-metric(?P<default_metric>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "default-metric {{ default_metric }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "default_metric": "{{ default_metric|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "packet_size",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \spacket-size(?P<packet_size>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "packet-size {{ packet_size }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "packet_size": "{{ packet_size|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "dead_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdead-interval(?P<dead_interval>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "dead-interval {{ dead_interval }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "dead_interval": "{{ dead_interval|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "hello_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \shello-interval(?P<hello_interval>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "hello-interval {{ hello_interval }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "hello_interval": "{{ hello_interval|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "priority",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \spriority(?P<priority>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "priority {{ priority }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "priority": "{{ priority|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "weight",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sweight(?P<weight>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "weight {{ weight }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "weight": "{{ weight|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "retransmit_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sretransmit-interval(?P<retransmit_interval>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "retransmit-interval {{ retransmit_interval }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "retransmit_interval": "{{ retransmit_interval|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "transmit_delay",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \stransmit-delay(?P<transmit_delay>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "transmit-delay {{ transmit_delay }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "transmit_delay": "{{ transmit_delay|int }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "passive",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ (\spassive(?P<passive>))?
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": _tmplt_ospfv3_passive,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "passive": "{{ True if passive is defined }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "process.database_filter",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdatabase-filter
+ \sall
+ \sout\s(?P<database_filter>\s\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "process.database_filter",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "database_filter": "{{ database_filter }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "demand_circuit",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ (\sdemand-circuit(?P<demand_circuit>))?
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": _tmplt_ospfv3_demand_circuit,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "demand_circuit": "{{ True if demand_circuit is defined }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "router_id",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \srouter-id\s(?P<router_id>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "router-id {{ router_id }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "router_id": "{{ router_id }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "mtu_ignore",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ (\smtu-ignore(?P<mtu_ignore>))?
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": _tmplt_ospfv3_demand_mtu_ignore,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "mtu_ignore": "{{ True if mtu_ignore is defined }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "flood_reduction",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sflood-reduction\s(?P<flood_reduction>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "flood-reduction {{ True if flood_reduction is defined }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "flood_reduction": "{{ flood_reduction }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "loopback_stub_network",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sloopback(?P<loopback>)
+ \sstub-network\s(?P<stub_network>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "loopback stub-network {{ stub_network }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "loopback_stub_network": "{{ loopback_stub_network }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "address_family_unicast",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \saddress-family(?P<address_family>)
+ \sipv4(?P<ipv4>)
+ \sunicast(?P<unicast>)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "address_family_unicast",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "address_family_unicast": "{{ True if unicast is defined }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "default_weight",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sapply-weight(?P<apply_weight>)
+ \sdefault-weight(?P<default_weight>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "apply-weight default-weight {{ default_weight }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "apply_weight": {
+ "default_weight": "{{ default_weight|int }}",
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "bandwidth",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sapply-weight(?P<apply_weight>)
+ \sbandwidth(?P<bandwidth>\s\d+)?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "apply-weight bandwidth {{ bandwidth }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "apply_weight": {
+ "bandwidth": "{{ bandwidth|int }}",
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "authentication",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sauthentication(?P<auth>)
+ (\sdisable(?P<disable>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospfv3_authentication,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "authentication": {
+ "disable": "{{ True if disable is defined }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "authentication.ipsec",
+ "getval": re.compile(
+ r"""^router
+ \sospfv3\s(?P<pid>\S+)
+ \sauthentication(?P<auth>)
+ \sipsec(?P<ipsec>)
+ \sspi\s(?P<spi>\d+)
+ (\s(?P<algo_type>\S+))?
+ (\spassword\s(?P<password_key>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_authentication_ipsec,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "authentication": {
+ "ipsec": {
+ "spi": "{{ spi }}",
+ "algorithim_type": "{{ algo_type }}",
+ "clear_key": "{{ clear_key }}",
+ "password_key": "{{ password_key }}",
+ "key": "{{ key }}",
+ }
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "default_information_originate",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdefault-information(?P<default_information>)
+ (\soriginate(?P<originate>))?
+ (\salways(?P<always>))?
+ (\smetric\s(?P<metric>\d+))?
+ (\smetric-type\s(?P<metric_type>\d+))?
+ (\sroute_policy\s(?P<route_policy>)\S+)?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_default_information,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "default_information_originate": {
+ "always": "{{ True if always is defined }}",
+ "metric": "{{ metric|int }}",
+ "metric_type": "{{ metric_type|int }}",
+ "route_policy": "{{ route_policy }}",
+ "set": "{{ True if default_information is defined and always is undefined and metric "
+ "is undefined and metric_type is undefined and route_policy is undefined }}"
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "auto_cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sauto-cost(?P<auto_cost>)
+ (\sreference-bandwidth\s(?P<reference_bandwidth>\d+))?
+ (\sdisable(?P<disable>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_auto_cost,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "auto_cost": {
+ "disable": "{{ True if disable is defined }}",
+ "reference_bandwidth": "{{ reference_bandwidth|int }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "bfd.minimum_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sbfd(?P<bfd>)
+ \sminimum-interval\s(?P<minimum_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospfv3_bfd_minimum_interval,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "bfd": {
+ "minimum_interval": "{{ minimum_interval|int }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "bfd.multiplier",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sbfd(?P<bfd>)
+ \smultiplier\s(?P<multiplier>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospfv3_bfd_multiplier,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "bfd": {
+ "multiplier": "{{ multiplier|int }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "bfd.fast_detect",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sbfd(?P<bfd>)
+ \sfast-detect(?P<fast_detect>)
+ (\s(?P<disable>disable))?
+ (\s(?P<strict_mode>strict-mode))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_bfd_fast_detect,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "bfd": {
+ "fast_detect": {
+ "set": "{{ True if disable is undefined and strict_mode is undefined }}",
+ "strict_mode": "{{ True if strict_mode is defined }}",
+ },
+ },
+ }
+ },
+ },
+ },
+ {
+ "name": "security",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \ssecurity(?P<security>)
+ \sttl(?P<ttl>)?
+ (\shops\s(?P<hops>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_security,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "security_ttl": {
+ "set": "{{ True if ttl is defined and hops is undefined }}",
+ "hops": "{{ hops }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "nsr",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \snsr(?P<nsr>)
+ \sdisable(?P<disable>)?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_nsr,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "nsr": {
+ "set": "{{ True if nsr is defined and disable is undefined }}",
+ "disable": "{{ True if disable is defined }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "protocol",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sprotocol(?P<protocol>)
+ \s(shutdown(?P<shutdown>))
+ (\shost-mode(?P<host_mode>))?
+ (\son-reload\s(?P<on_reload>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_protocol,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "protocol_shutdown": {
+ "set": "{{ True if shutdown is defined and host-mode is undefined and on_reload is undefined }}",
+ "host_mode": "{{ True if host_mode is defined }}",
+ "on_reload": "{{ True if on_reload is defined }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "capability",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \scapability(?P<capability>)
+ (\stype7\s(?P<type7>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "capability type7 {{ type7 }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "capability": {
+ "type7": "{{ type7 }}"
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "capability.opaque",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \scapability(?P<capability>)?
+ \sopaque(?P<opaque>)
+ (\sdisable(?P<disable>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_capability_opaque,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "capability": {
+ "opaque": {
+ "disable": "{{ True if disable is defined }}",
+ "set": "{{ True if opaque is defined and disable is undefined }}",
+ },
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "admin_distance",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdistance\s(?P<value>d+)
+ \s(?P<source>\S+)
+ \s(?P<wildcard>\S+)
+ (\s(?P<access_list>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_distance_admin,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "distance": {
+ "admin_distance": {
+ "value": "{{ value|int }}",
+ "source": "{{ source }}",
+ "wildcard": "{{ wildcard }}",
+ "access_list": "{{ access_list }}",
+ }
+ },
+ }
+ }
+ },
+ },
+
+ {
+ "name": "ospf_distance",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdistance(?P<value>)
+ \sospfv3(?P<ospf>)
+ (\sexternal\s(?P<external>\d+))?
+ (\sinter-area\s(?P<inter_area>\d+))?
+ (\sintra-area\s(?P<intra_area>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_distance_ospf,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "distance": {
+ "ospf_distance": {
+ "external": "{{ external|int }}",
+ "inter_area": "{{ inter_area|int }}",
+ "intra_area": "{{ intra_area|int }}",
+ }
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "area.default_cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sdefault-cost\s(?P<default_cost>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} default-cost {{ default_cost }}",
+ "compval": "default_cost",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "default_cost": "{{ default_cost|int }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.dead_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sdead-interval\s(?P<dead_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} dead-interval {{ dead_interval }}",
+ "compval": "dead_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "dead_interval": "{{ dead_interval|int }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.hello_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \shello-interval\s(?P<hello_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} hello-interval {{ hello_interval }}",
+ "compval": "hello_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "hello_interval": "{{ hello_interval|int }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.transmit_delay",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \stransmit-delay\s(?P<transmit_delay>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} transmit-delay {{ transmit_delay }}",
+ "compval": "transmit_delay",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "transmit_delay": "{{ transmit_delay|int }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \scost\s(?P<cost>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} cost {{ cost }}",
+ "compval": "cost",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "cost": "{{ cost|int }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.priority",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \spriority\s(?P<priority>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} priority {{ priority }}",
+ "compval": "priority",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "priority": "{{ priority|int }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.weight",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sweight\s(?P<weight>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} weight {{ weight }}",
+ "compval": "weight",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "weight": "{{ weight|int }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.packet_size",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \spacket-size\s(?P<packet_size>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} packet-size {{ packet_size }}",
+ "compval": "packet_size",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "packet_size": "{{ packet_size|int }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.summary_in",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \ssummary-in\s(?P<summary_in>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} summary-in {{ summary_in }}",
+ "compval": "summary_in",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "summary_in": "{{ summary_in }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.demand_circuit",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sdemand-circuit\s(?P<demand_circuit>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} demand-circuit {{ demand_circuit }}",
+ "compval": "demand_circuit",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "demand_circuit": "{{ demand_circuit }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.passive",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \spassive\s(?P<passive>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} passive {{ passive }}",
+ "compval": "passive",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "passive": "{{ passive }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.external_out",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sexternal-out\s(?P<external_out>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} external-out {{ external_out }}",
+ "compval": "passive",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "external_out": "{{ external_out }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.mtu_ignore",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \smtu-ignore\s(?P<mtu_ignore>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} mtu-ignore {{ mtu_ignore }}",
+ "compval": "mtu_ignore",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "mtu_ignore": "{{ mtu_ignore }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.authentication",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sauthentication(?P<auth>)
+ (\sdisable(?P<disable>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospfv3_area_authentication,
+ "compval": "authentication",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "authentication": {
+ "disable": "{{ True if disable is defined }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.authentication.ipsec",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sauthentication(?P<auth_key>)
+ \sipsec(?P<ipsec>)
+ \sspi\s(?P<spi>\d+)
+ (\s(?P<algo_type>\S+))?
+ (\spassword\s(?P<password_key>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospfv3_area_authentication_ipsec,
+ "compval": "authentication.ipsec",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "authentication": {
+ "ipsec": {
+ "spi": "{{ spi }}",
+ "algorithim_type": "{{ algo_type }}",
+ "clear_key": "{{ clear_key }}",
+ "password_key": "{{ password_key }}",
+ "key": "{{ key }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ },
+ {
+ "name": "area.mpls_traffic_eng",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \smpls(?P<mpls>)
+ \straffic-end(?P<traffic_eng>)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} mpls traffic-eng",
+ "compval": "mpls_traffic_eng",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "mpls": {
+ "traffic_eng": "{{ True if traffic_eng is defined }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.mpls_ldp",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \smpls(?P<mpls>)
+ (\sauto-config(?P<auto_config>))?
+ (\ssync(?P<sync>))?
+ (\ssync-igp-shortcuts(?P<syn_igp_shortcuts>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_mpls_ldp,
+ "compval": "mpls_ldp",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "mpls": {
+ "ldp": {
+ "auto_config": "{{ True if auto_config is defined }}",
+ "sync": "{{ True if sync is defined }}",
+ "sync_igp_shortcuts": "{{ True if sync_igp_shortcuts is defined }}",
+
+ }
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.bfd.minimum_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sbfd(?P<bfd>)
+ \sminimum-interval\s(?P<minimum_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospfv3_area_bfd_minimum_interval,
+ "compval": "bfd.minimum_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "bfd": {
+ "minimum_interval": "{{ minimum_interval|int }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.bfd.multiplier",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sbfd(?P<bfd>)
+ \smultiplier\s(?P<multiplier>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospfv3_area_bfd_multiplier,
+ "compval": "bfd.multiplier",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "bfd": {
+ "multiplier": "{{ multiplier|int }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.bfd.fast_detect",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sbfd(?P<bfd>)
+ \sarea(?P<area_id>)
+ \sfast-detect(?P<fast_detect>)
+ (\s(?P<disable>disable))?
+ (\s(?P<strict_mode>strict-mode))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospfv3_area_bfd_fast_detect,
+ "compval": "bfd.fast_detect",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "bfd": {
+ "fast_detect": {
+ "set": "{{ True if disable is undefined and strict_mode is undefined }}",
+ "strict_mode": "{{ True if strict_mode is defined }}",
+ },
+ },
+ }
+ }
+ }
+ },
+ },
+ },
+ {
+ "name": "area.stub",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sstub(?P<nssa>)
+ (\sno-summary(?P<no_sum>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_stub,
+ "compval": "stub",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "area_id": "{{ area_id }}",
+ "stub": {
+ "set": "{{ True if stub is defined and no_summary is undefined }}",
+ "no_summary": "{{ True if no_summary is defined }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.nssa",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \snssa(?P<nssa>)
+ (\sno-redistribution(?P<no_redis>))?
+ (\sno-summary(?P<no_sum>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_nssa,
+ "compval": "nssa",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "area_id": "{{ area_id }}",
+ "nssa": {
+ "set": "{{ True if nssa is defined and no_summary is undefined and no_redis is undefined }}",
+ "no_summary": "{{ True if no_summary is defined }}",
+ "no_redistribution": "{{ True if no_redis is defined }}"
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.nssa.default_information_originate",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \snssa(?P<nssa>)
+ (\sno-redistribution(?P<no_redis>))?
+ (\sdefault-information-originate(?P<def_info_origin>))?
+ (\smetric\s(?P<metric>\d+))?
+ (\smetric-type\s(?P<metric_type>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_nssa_def_info_origin,
+ "compval": "nssa.default_information_originate",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "nssa": {
+ "default_information_originate": {
+ "metric": "{{ metric|int }}",
+ "metric_type": "{{ metric_type|int }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ },
+ {
+ "name": "area.ranges",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \srange(?P<range>)
+ \s(?P<address>\S+)
+ (\sadvertise(?P<advertise>))
+ (\snot-advertise(?P<not_advertise>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_ranges,
+ "compval": "ranges",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "ranges": [
+ {
+ "address": "{{ address }}",
+ "advertise": "{{ True if advertise is defined }}",
+ "not_advertise": "{{ True if not_advertise is defined }}",
+ }
+ ],
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "area.nssa.translate",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \snssa(?P<nssa>)
+ \stranslate(?P<translate>)
+ \stype7(?P<type7>)
+ \salways\s(?P<always>)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_nssa_translate,
+ "compval": "nssa.translate",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "area_id": "{{ area_id }}",
+ "nssa": {
+ "translate": {
+ "type7": {
+ "always": "{{ True if always is defined }}"
+ }
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "virtual_link.hello_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \shello-interval\s(?P<hello_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} virtual-link {{ id }} hello-interval {{ hello_interval }}",
+ "compval": "hello_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}":
+ {
+ "id": "{{ id }}",
+ "hello_interval": "{{ hello_interval|int }}"
+ }
+
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "virtual_link.dead_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \sdead-interval\s(?P<dead_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} virtual-link {{ id }} dead-interval {{ dead_interval }}",
+ "compval": "dead_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}": {
+ "id": "{{ id }}",
+ "dead_interval": "{{ dead_interval|int }}"
+ }
+
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "virtual_link.retransmit_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \sretransmit-interval\s(?P<retransmit_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} virtual-link {{ id }} retransmit-interval {{ retransmit_interval }}",
+ "compval": "retransmit_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}": {
+ "id": "{{ id }}",
+ "retransmit_interval": "{{ retransmit_interval|int }}"
+ }
+ }
+
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ "name": "virtual_link.authentication",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \savirtual-link\s(?P<id>\S+)
+ \sauthentication(?P<auth>)
+ (\skeychain\s(?P<keychain>\S+))?
+ (\snull(?P<no_auth>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_vlink_authentication,
+ "compval": "authentication",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "authentication": {
+ "no_auth": "{{ True if no_auth is defined }}",
+ "keychain": "{{ keychain }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "virtual_link.authentication_key",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \sauthentication-key(?P<auth_key>)
+ (\s(?P<password>\S+))?
+ (\sclear\s(?P<clear>)\S+)?
+ (\sencrypted(?P<encrypted>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_vlink_authentication_key,
+ "compval": "authentication_key",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}": {
+ "authentication_key": {
+ "clear": "{{ clear }}",
+ "encrypted": "{{ encrypted}}",
+ "password": "{{ password if clear is undefined and encrypted is undefined }}",
+ },
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "virtual_link.authentication.message_digest",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \sauthentication(?P<auth>)
+ \smessage-digest(?P<md>)
+ \skeychain(?P<md_key>\s\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_vlink_authentication_md,
+ "compval": "authentication.message_digest",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}": {
+ "authentication": {
+ "message_digest": {
+ "keychain": "{{ md_key }}",
+ }
+ },
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "link_down_fast_detect",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \slink-down
+ \sfast-detect(?P<fast_detect>)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "link-down fast-detect",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "link_down_fast_detect": "{{ True if fast_detect is defined }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "nsr",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \snsr
+ \sdisable(?P<disable>)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "nsr disable",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "disable": "{{ True if disable is defined }}",
+ }
+ }
+ },
+ },
+ {
+ "name": "database_filter",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdatabase-filter
+ \sall
+ \sout\s(?P<outing>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "database-filter all out {{ outing }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "outing": "{{ outing }}"
+ }
+ }
+ },
+ },
+ {
+ "name": "distribute_link_state",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdistribute(?P<distribute>)
+ \slink-state(?P<link_state>)
+ (\sinstance-id(?P<inst_id>\d+))?
+ (\sthrottle(?P<throttle>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_adjacency_distribute_bgp_state,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "distribute_link_list": {
+ "instance_id": "{{ inst_id|int }}",
+ "throttle": "{{ throttle }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "distribute_bgp_ls",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdistribute(?P<distribute>)
+ \sbgp-ls(?P<bgp_ls>)
+ (\sinstance-id(?P<inst_id>\d+))?
+ (\sthrottle(?P<throttle>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_adjacency_distribute_bgp_state,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "distribute_bgp_ls": {
+ "instance_id": "{{ inst_id|int }}",
+ "throttle": "{{ throttle }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "log_adjacency",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \slog(?P<security>)
+ \sadjacency(?P<adjacency>)?
+ (\schanges(?P<changes>))?
+ (\sdisable(?P<disable>))?
+ (\sdetails(?P<details>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_log_adjacency,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "log_adjacency_changes": {
+ "set": "{{ True changes id defined and disable is undefined and detail is undefined }}",
+ "disable": "{{ True if disable is defined }}",
+ "details": "{{ True if details is defined }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "max_lsa",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ (\smax-lsa\s(?P<threshold>\d+))?
+ (\swarning-only\s(?P<warning_only>\d+)?
+ (\signore-time\s(?P<ignore_time>\d+))?
+ (\signore-count\s(?P<ignore_count>\d+))?
+ (\sreset-time\s(?P<reset_time>)\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_log_max_lsa,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "max_lsa": {
+ "threshold": "{{ threshold|int }}",
+ "warning_only": "{{ warning_only|int }}",
+ "ignore_time": "{{ ignore_time|int }}",
+ "ignore_count": "{{ ignore_count|int }}",
+ "reset_time": "{{ reset_time|int }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "max_metric",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \smax-metric
+ \s*(?P<router_lsa>)
+ (\s*external-lsa(?P<external_lsa>))?
+ (\s(?P<max_metric_value>\d+))?
+ \s*(?P<include_stub>include-stub)*
+ \s*(?P<on_startup>on-startup)*
+ \s*(?P<wait_period>\d+)*
+ \s*(wait-for\sbgp)*
+ \s*(?P<bgp_asn>\d+)*
+ \s*(?P<summary_lsa>summary-lsa)*
+ \s*(?P<sum_lsa_max_metric_value>\d+)*
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_max_metric,
+ "remval": "max-metric router-lsa",
+ "result": {
+ "processes": {
+ '{{ "pid" }}': {
+ "max_metric": {
+ "router_lsa": {
+ "set": "{{ True if router_lsa is defined and external_lsa is undefined else None }}",
+ "external_lsa": {
+ "set": "{{ True if external_lsa is defined and max_metric_value is undefined else None }}",
+ "max_metric_value": "{{ max_metric_value }}",
+ },
+ "include_stub": "{{ not not include_stub }}",
+ "on_startup": {
+ "set": "{{ True if on_startup is defined and (wait_period and bgp_asn) is undefined else None }}",
+ "wait_period": "{{ wait_period }}",
+ "wait_for_bgp_asn": "{{ bgp_asn }}",
+ },
+ "summary_lsa": {
+ "set": "{{ True if summary_lsa is defined and sum_lsa_max_metric_value is undefined else None }}",
+ "max_metric_value": "{{ sum_lsa_max_metric_value }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "mpls_ldp",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \smpls(?P<mpls>)
+ (\sauto-config(?P<auto_config>))?
+ (\ssync(?P<sync>))?
+ (\ssync-igp-shortcuts(?P<syn_igp_shortcuts>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_mpls_ldp,
+ "compval": "mpls_ldp",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "mpls": {
+ "ldp": {
+ "auto_config": "{{ True if auto_config is defined }}",
+ "sync": "{{ True if sync is defined }}",
+ "sync_igp_shortcuts": "{{ True if sync_igp_shortcuts is defined }}",
+ }
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "microloop_avoidance",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \smicroloop(?P<microloop>)
+ \savoidance(?P<avoidance>)
+ (\s(?P<protected>protected))?
+ (\s(?P<segment_routing>segment-routing))?
+ (\srib-update-delay\s(?P<rib_update_delay>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_microloop_avoidance,
+ "compval": "microloop_avoidance",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "microloop_avoidance": {
+ "protected": "{{ True if protected is defined }}",
+ "segment_routing": "{{ True if segment_routing is defined }}",
+ "rib_update_delay": "{{ rib_update_delay }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "mpls_traffic_eng",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \smpls(?P<mpls>)
+ \straffic-end(?P<traffic_eng>)
+ (\sautoroute-exclude(?P<autoroute>))?
+ (\sroute-policy(?P<route_policy>\S+))?
+ (\s(?P<igp_intact>igp_intact))?
+ (\s(?P<ldp_sync_update>ldp-sync-update))?
+ (\s(?P<multicast_intact>multicast-intact))?
+ (\srouter-id\s(?P<router_id>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_mpls_traffic_eng,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "mpls": {
+ "autoroute_exclude": {
+ "route_policy": "{{ route_policy }}"
+ },
+ "igp_intact": "{{ True if igp_intact is defined }}",
+ "ldp_sync_update": "{{ True if ldp_sync_update is defined }}",
+ "multicast_intact": "{{ True if multicast_intact is defined }}",
+ "router_id": "{{ router_id }}"
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "prefix_suppression",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sprefix-suppression(?P<prefix_suppression>)
+ (\s(?P<secondary_address>secondary-address))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_prefix_suppression,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "prefix_suppression": {
+ "set": "{{ True if prefix_suppression is defined and secondary_address is undefined }}",
+ "secondary_address": "{{ True if secondary_address is defined }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "protocol_shutdown",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sprotocol-shutdown(?P<protocol_shutdown>)
+ (\s(?P<host_mode>host-mode))?
+ (\s(?P<on_reload>on-reload))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_protocol_shutdown,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "protocol_shutdown": {
+ "set": "{{ True if protocol_shutdown is defined and host_mode is undefined and on_reload is undefined }}",
+ "host_mode": "{{ True if host_mode is defined }}",
+ "on_reload": "{{ True if on_reload is defined }}",
+ },
+ }
+ }
+ },
+ },
+ {
+ "name": "timers.lsa",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \stimers
+ \slsa
+ (\sgroup-pacing\s(?P<group_pacing>\d+))?
+ (\smin-arrival\s(?P<min_arrival>\d+))?
+ (\srefresh\s(?P<refresh>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_timers_lsa,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "lsa": {
+ "group_pacing": "{{ group_pacing|int }}",
+ "min_arrival": "{{ min_arrival|int }}",
+ "refresh": "{{ refresh|int }}",
+ },
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "timers.graceful_shutdown",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \stimers
+ \sgraceful_shutdown
+ (\sinitial delay\s(?P<initial_delay>\d+))?
+ (\sretain routes\s(?P<retain_routes>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_timers_graceful_shutdown,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "graceful_shutdown": {
+ "initial_delay": "{{ initial_delay|int }}",
+ "retain_routes": "{{ retain_routes|int }}",
+ },
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "throttle.spf",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \stimers
+ \sthrottle
+ \sspf
+ (\s(?P<change_delay>\d+))
+ (\s(?P<second_delay>\d+))
+ (\s(?P<max_wait>\d+))
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "timers throttle spf {{ throttle.spf.change_delay }} {{ throttle.spf.second_delay }} {{ throttle.spf.max_wait }}",
+ "compval": "throttle.lsa_all",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "throttle": {
+ "lsa_all": {
+ "initial_delay": "{{ initial_delay }}",
+ "min_delay": "{{ min_delay }}",
+ "max_delay": "{{ max_delay }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "throttle.lsa_all",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \stimers
+ \sthrottle
+ \slsa
+ \sall
+ (\s(?P<initial_delay>\d+))
+ (\s(?P<min_delay>\d+))
+ (\s(?P<max_delay>\d+))
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "timers throttle lsa all {{ throttle.lsa_all.initial_delay }} {{ throttle.lsa_all.min_delay }} {{ throttle.lsa_all.max_delay }}",
+ "compval": "throttle.lsa_all",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "throttle": {
+ "lsa_all": {
+ "initial_delay": "{{ initial_delay }}",
+ "min_delay": "{{ min_delay }}",
+ "max_delay": "{{ max_delay }}",
+ },
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "throttle.fast_reroute",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \stimers
+ \sthrottle
+ \sfast-reroute\s(?P<fast_reroute>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "timers throttle fast-reroute {{ fast_reroute }}",
+ "compval": "throttle.fast_reroute",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "throttle": {
+ "fast_reroute": "{{ fast_reroute }}",
+ }
+ }
+ }
+ }
+ },
+ },
+ {
+ "name": "timers.pacing_flood",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \stimers
+ \spacing
+ \sflood\s(?P<pacing_flood>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "timers pacing flood {{ pacing_flood }}",
+ "compval": "timers.pacing_flood",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "pacing_flood": "{{ pacing_flood }}",
+
+ }
+ }
+ }
+ },
+ },
+ ]
+ # fmt: on
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/utils.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/utils.py
new file mode 100644
index 00000000..059c8167
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/utils.py
@@ -0,0 +1,391 @@
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# utils
+
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+from ansible.module_utils._text import to_text
+from ansible_collections.ansible.netcommon.plugins.module_utils.compat import (
+ ipaddress,
+)
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ dict_diff,
+ is_masklen,
+ to_netmask,
+ search_obj_in_list,
+)
+
+
+def remove_command_from_config_list(interface, cmd, commands):
+ # To delete the passed config
+ if interface not in commands:
+ commands.insert(0, interface)
+ commands.append("no %s" % cmd)
+ return commands
+
+
+def add_command_to_config_list(interface, cmd, commands):
+ # To set the passed config
+ if interface not in commands:
+ commands.insert(0, interface)
+ commands.append(cmd)
+
+
+def dict_to_set(sample_dict):
+ # Generate a set with passed dictionary for comparison
+ test_dict = {}
+ if isinstance(sample_dict, dict):
+ for k, v in iteritems(sample_dict):
+ if v is not None:
+ if isinstance(v, list):
+ if isinstance(v[0], dict):
+ li = []
+ for each in v:
+ for key, value in iteritems(each):
+ if isinstance(value, list):
+ each[key] = tuple(value)
+ li.append(tuple(iteritems(each)))
+ v = tuple(li)
+ else:
+ v = tuple(v)
+ elif isinstance(v, dict):
+ li = []
+ for key, value in iteritems(v):
+ if isinstance(value, list):
+ v[key] = tuple(value)
+ li.extend(tuple(iteritems(v)))
+ v = tuple(li)
+ test_dict.update({k: v})
+ return_set = set(tuple(iteritems(test_dict)))
+ else:
+ return_set = set(sample_dict)
+ return return_set
+
+
+def filter_dict_having_none_value(want, have):
+ # Generate dict with have dict value which is None in want dict
+ test_dict = dict()
+ test_key_dict = dict()
+ name = want.get("name")
+ if name:
+ test_dict["name"] = name
+ diff_ip = False
+ want_ip = ""
+ for k, v in iteritems(want):
+ if isinstance(v, dict):
+ for key, value in iteritems(v):
+ if value is None and k in have and key in have.get(k):
+ dict_val = have.get(k).get(key)
+ test_key_dict.update({key: dict_val})
+ test_dict.update({k: test_key_dict})
+ if isinstance(v, list) and isinstance(v[0], dict):
+ for key, value in iteritems(v[0]):
+ if value is None and k in have and key in have.get(k):
+ dict_val = have.get(k).get(key)
+ test_key_dict.update({key: dict_val})
+ test_dict.update({k: test_key_dict})
+ # below conditions checks are added to check if
+ # secondary IP is configured, if yes then delete
+ # the already configured IP if want and have IP
+ # is different else if it's same no need to delete
+ for each in v:
+ if each.get("secondary"):
+ want_ip = each.get("address").split("/")
+ have_ip = have.get("ipv4")
+ for each in have_ip:
+ if len(want_ip) > 1 and each.get("secondary"):
+ have_ip = each.get("address").split(" ")[0]
+ if have_ip != want_ip[0]:
+ diff_ip = True
+ if each.get("secondary") and diff_ip is True:
+ test_key_dict.update({"secondary": True})
+ test_dict.update({"ipv4": test_key_dict})
+ # Checks if want doesn't have secondary IP but have has secondary IP set
+ elif have.get("ipv4"):
+ if [
+ True
+ for each_have in have.get("ipv4")
+ if "secondary" in each_have
+ ]:
+ test_dict.update({"ipv4": {"secondary": True}})
+ if k == "l2protocol":
+ diff = True
+ h_proto = have.get("l2protocol")
+ w_proto = want.get("l2protocol")
+ if h_proto:
+ if w_proto:
+ for h in h_proto:
+ for w in w_proto:
+ if h == w:
+ diff = False
+ if not diff:
+ break
+ else:
+ diff = True
+ if diff:
+ test_dict.update({k: v})
+ if v is None:
+ val = have.get(k)
+ test_dict.update({k: val})
+ return test_dict
+
+
+def remove_duplicate_interface(commands):
+ # Remove duplicate interface from commands
+ set_cmd = []
+ for each in commands:
+ if "interface" in each:
+ if each not in set_cmd:
+ set_cmd.append(each)
+ else:
+ set_cmd.append(each)
+
+ return set_cmd
+
+
+def flatten_dict(x):
+ result = {}
+ if not isinstance(x, dict):
+ return result
+
+ for key, value in iteritems(x):
+ if isinstance(value, dict):
+ result.update(flatten_dict(value))
+ else:
+ result[key] = value
+
+ return result
+
+
+def dict_delete(base, comparable):
+ """
+
+ This function generates a dict containing key, value pairs for keys
+ that are present in the `base` dict but not present in the `comparable`
+ dict.
+
+ :param base: dict object to base the diff on
+ :param comparable: dict object to compare against base
+
+ :returns: new dict object with key, value pairs that needs to be deleted.
+
+ """
+ to_delete = dict()
+
+ for key in base:
+ if isinstance(base[key], dict):
+ sub_diff = dict_delete(base[key], comparable.get(key, {}))
+ if sub_diff:
+ to_delete[key] = sub_diff
+ else:
+ if key not in comparable:
+ to_delete[key] = base[key]
+
+ return to_delete
+
+
+def pad_commands(commands, interface):
+ commands.insert(0, "interface {0}".format(interface))
+
+
+def diff_list_of_dicts(w, h, key="member"):
+ """
+ Returns a list containing diff between
+ two list of dictionaries
+ """
+ if not w:
+ w = []
+ if not h:
+ h = []
+
+ diff = []
+ for w_item in w:
+ h_item = search_obj_in_list(w_item[key], h, key=key) or {}
+ d = dict_diff(h_item, w_item)
+ if d:
+ if key not in d.keys():
+ d[key] = w_item[key]
+ diff.append(d)
+
+ return diff
+
+
+def validate_ipv4(value, module):
+ if value:
+ address = value.split("/")
+ if len(address) != 2:
+ module.fail_json(
+ msg="address format is <ipv4 address>/<mask>, got invalid format {0}".format(
+ value
+ )
+ )
+
+ if not is_masklen(address[1]):
+ module.fail_json(
+ msg="invalid value for mask: {0}, mask should be in range 0-32".format(
+ address[1]
+ )
+ )
+
+
+def validate_ipv6(value, module):
+ if value:
+ address = value.split("/")
+ if len(address) != 2:
+ module.fail_json(
+ msg="address format is <ipv6 address>/<mask>, got invalid format {0}".format(
+ value
+ )
+ )
+ else:
+ if not 0 <= int(address[1]) <= 128:
+ module.fail_json(
+ msg="invalid value for mask: {0}, mask should be in range 0-128".format(
+ address[1]
+ )
+ )
+
+
+def validate_n_expand_ipv4(module, want):
+ # Check if input IPV4 is valid IP and expand IPV4 with its subnet mask
+ ip_addr_want = want.get("address")
+ if len(ip_addr_want.split(" ")) > 1:
+ return ip_addr_want
+ validate_ipv4(ip_addr_want, module)
+ ip = ip_addr_want.split("/")
+ if len(ip) == 2:
+ ip_addr_want = "{0} {1}".format(ip[0], to_netmask(ip[1]))
+
+ return ip_addr_want
+
+
+def normalize_interface(name):
+ """Return the normalized interface name
+ """
+ if not name:
+ return
+
+ def _get_number(name):
+ digits = ""
+ for char in name:
+ if char.isdigit() or char in "/.":
+ digits += char
+ return digits
+
+ if name.lower().startswith("gi"):
+ if_type = "GigabitEthernet"
+ elif name.lower().startswith("fa"):
+ if_type = "FastEthernet"
+ elif name.lower().startswith("fo"):
+ if_type = "FortyGigE"
+ elif name.lower().startswith("te"):
+ if_type = "TenGigE"
+ elif name.lower().startswith("twe"):
+ if_type = "TwentyFiveGigE"
+ elif name.lower().startswith("hu"):
+ if_type = "HundredGigE"
+ elif name.lower().startswith("vl"):
+ if_type = "Vlan"
+ elif name.lower().startswith("lo"):
+ if_type = "Loopback"
+ elif name.lower().startswith("be"):
+ if_type = "Bundle-Ether"
+ elif name.lower().startswith("bp"):
+ if_type = "Bundle-POS"
+ else:
+ if_type = None
+
+ number_list = name.split(" ")
+ if len(number_list) == 2:
+ number = number_list[-1].strip()
+ else:
+ number = _get_number(name)
+
+ if if_type:
+ proper_interface = if_type + number
+ else:
+ proper_interface = name
+
+ return proper_interface
+
+
+def get_interface_type(interface):
+ """Gets the type of interface
+ """
+
+ if interface.upper().startswith("GI"):
+ return "GigabitEthernet"
+ elif interface.upper().startswith("FA"):
+ return "FastEthernet"
+ elif interface.upper().startswith("FO"):
+ return "FortyGigE"
+ elif interface.upper().startswith("ET"):
+ return "Ethernet"
+ elif interface.upper().startswith("LO"):
+ return "Loopback"
+ elif interface.upper().startswith("BE"):
+ return "Bundle-Ether"
+ elif interface.upper().startswith("NV"):
+ return "nve"
+ elif interface.upper().startswith("TWE"):
+ return "TwentyFiveGigE"
+ elif interface.upper().startswith("HU"):
+ return "HundredGigE"
+ elif interface.upper().startswith("PRE"):
+ return "preconfigure"
+ else:
+ return "unknown"
+
+
+def isipaddress(data):
+ """
+ Checks if the passed string is
+ a valid IPv4 or IPv6 address
+ """
+ isipaddress = True
+
+ try:
+ ipaddress.ip_address(data)
+ except ValueError:
+ isipaddress = False
+
+ return isipaddress
+
+
+def is_ipv4_address(data):
+ """
+ Checks if the passed string is
+ a valid IPv4 address
+ """
+ if "/" in data:
+ data = data.split("/")[0]
+
+ if not isipaddress(to_text(data)):
+ raise ValueError("{0} is not a valid IP address".format(data))
+
+ return ipaddress.ip_address(to_text(data)).version == 4
+
+
+def prefix_to_address_wildcard(prefix):
+ """ Converts a IPv4 prefix into address and
+ wildcard mask
+
+ :returns: IPv4 address and wildcard mask
+ """
+ wildcard = []
+
+ subnet = to_text(ipaddress.IPv4Network(to_text(prefix)).netmask)
+
+ for x in subnet.split("."):
+ component = 255 - int(x)
+ wildcard.append(str(component))
+
+ wildcard = ".".join(wildcard)
+
+ return prefix.split("/")[0], wildcard
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_acl_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_acl_interfaces.py
new file mode 100644
index 00000000..378b845c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_acl_interfaces.py
@@ -0,0 +1,651 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_acl_interfaces
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_acl_interfaces
+short_description: ACL interfaces resource module
+description:
+- This module manages adding and removing Access Control Lists (ACLs) from interfaces
+ on devices running IOS-XR software.
+version_added: 1.0.0
+author: Nilashish Chakraborty (@NilashishC)
+options:
+ config:
+ description: A dictionary of ACL options for interfaces.
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Name/Identifier for the interface
+ type: str
+ required: true
+ access_groups:
+ type: list
+ elements: dict
+ description:
+ - Specifies ACLs attached to the interfaces.
+ suboptions:
+ afi:
+ description:
+ - Specifies the AFI for the ACL(s) to be configured on this interface.
+ type: str
+ choices:
+ - ipv4
+ - ipv6
+ required: true
+ acls:
+ type: list
+ description:
+ - Specifies the ACLs for the provided AFI.
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Specifies the name of the IPv4/IPv6 ACL for the interface.
+ type: str
+ required: true
+ direction:
+ description:
+ - Specifies the direction of packets that the ACL will be applied
+ on.
+ type: str
+ choices:
+ - in
+ - out
+ required: true
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config interface).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state the configuration should be left in.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - gathered
+ - parsed
+ - rendered
+ default: merged
+
+"""
+EXAMPLES = """
+# Using merged
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:22:32.911 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+
+- name: Merge the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_acl_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/0
+ access_groups:
+ - afi: ipv4
+ acls:
+ - name: acl_1
+ direction: in
+ - name: acl_2
+ direction: out
+ - afi: ipv6
+ acls:
+ - name: acl6_1
+ direction: in
+ - name: acl6_2
+ direction: out
+
+ - name: GigabitEthernet0/0/0/1
+ access_groups:
+ - afi: ipv4
+ acls:
+ - name: acl_1
+ direction: out
+ state: merged
+
+# After state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:27:49.378 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 egress
+# !
+
+# Using merged to update interface ACL configuration
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:27:49.378 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 egress
+# !
+#
+
+- name: Update acl_interfaces configuration using merged
+ cisco.iosxr.iosxr_acl_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ access_groups:
+ - afi: ipv4
+ acls:
+ - name: acl_2
+ direction: out
+ - name: acl_1
+ direction: in
+ state: merged
+
+# After state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:27:49.378 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# !
+#
+
+# Using replaced
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:34:56.689 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 egress
+# !
+
+- name: Replace device configurations of listed interface with provided configurations
+ cisco.iosxr.iosxr_acl_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/0
+ access_groups:
+ - afi: ipv6
+ acls:
+ - name: acl6_3
+ direction: in
+ state: replaced
+
+# After state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:34:56.689 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv6 access-group acl6_3 ingress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 egress
+# !
+#
+
+# Using overridden
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:34:56.689 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 egress
+# !
+#
+
+- name: Overridde all interface ACL configuration with provided configuration
+ cisco.iosxr.iosxr_acl_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ access_groups:
+ - afi: ipv4
+ acls:
+ - name: acl_2
+ direction: in
+ - afi: ipv6
+ acls:
+ - name: acl6_3
+ direction: out
+ state: overridden
+
+# After state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:34:56.689 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_2 ingress
+# ipv6 access-group acl6_3 egress
+# !
+#
+
+# Using 'deleted' to delete all ACL attributes of a single interface
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:34:56.689 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 egress
+# !
+#
+
+- name: Delete all ACL attributes of GigabitEthernet0/0/0/1
+ cisco.iosxr.iosxr_acl_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ state: deleted
+
+# After state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:34:56.689 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+#
+
+# Using 'deleted' to remove all ACLs attached to all the interfaces in the device
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:34:56.689 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 egress
+# !
+#
+
+- name: Delete all ACL interfaces configuration from the device
+ cisco.iosxr.iosxr_acl_interfaces:
+ state: deleted
+
+# After state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:34:56.689 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+#
+
+# Using parsed
+
+# parsed.cfg
+# ------------
+#
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 egress
+# !
+
+# - name: Convert ACL interfaces config to argspec without connecting to the appliance
+# cisco.iosxr.iosxr_acl_interfaces:
+# running_config: "{{ lookup('file', './parsed.cfg') }}"
+# state: parsed
+
+
+# Task Output (redacted)
+# -----------------------
+
+# "parsed": [
+# {
+# "name": "MgmtEth0/RP0/CPU0/0"
+# },
+# {
+# "access_groups": [
+# {
+# "acls": [
+# {
+# "direction": "in",
+# "name": "acl_1"
+# },
+# {
+# "direction": "out",
+# "name": "acl_2"
+# }
+# ],
+# "afi": "ipv4"
+# },
+# {
+# "acls": [
+# {
+# "direction": "in",
+# "name": "acl6_1"
+# },
+# {
+# "direction": "out",
+# "name": "acl6_2"
+# }
+# ],
+# "afi": "ipv6"
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0"
+# },
+# {
+# "access_groups": [
+# {
+# "acls": [
+# {
+# "direction": "out",
+# "name": "acl_1"
+# }
+# ],
+# "afi": "ipv4"
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/1"
+# }
+# ]
+# }
+
+
+# Using gathered
+
+- name: Gather ACL interfaces facts using gathered state
+ cisco.iosxr.iosxr_acl_interfaces:
+ state: gathered
+
+
+# Task Output (redacted)
+# -----------------------
+#
+# "gathered": [
+# {
+# "name": "MgmtEth0/RP0/CPU0/0"
+# },
+# {
+# "access_groups": [
+# {
+# "acls": [
+# {
+# "direction": "in",
+# "name": "acl_1"
+# },
+# {
+# "direction": "out",
+# "name": "acl_2"
+# }
+# ],
+# "afi": "ipv4"
+# }
+# "name": "GigabitEthernet0/0/0/0"
+# },
+# {
+# "access_groups": [
+# {
+# "acls": [
+# {
+# "direction": "in",
+# "name": "acl6_1"
+# }
+# ],
+# "afi": "ipv6"
+# }
+# "name": "GigabitEthernet0/0/0/1"
+# }
+# ]
+
+
+# Using rendered
+
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_acl_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/0
+ access_groups:
+ - afi: ipv4
+ acls:
+ - name: acl_1
+ direction: in
+ - name: acl_2
+ direction: out
+ state: rendered
+
+# Task Output (redacted)
+# -----------------------
+
+# "rendered": [
+# "interface GigabitEthernet0/0/0/0",
+# "ipv4 access-group acl_1 ingress",
+# "ipv4 access-group acl_2 egress"
+# ]
+"""
+RETURN = """
+before:
+ description: The configuration prior to the model invocation.
+ returned: always
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The resulting configuration model invocation.
+ returned: when changed
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample:
+ - "interface GigabitEthernet0/0/0/1"
+ - "ipv4 access-group acl_1 ingress"
+ - "ipv4 access-group acl_2 egress"
+ - "ipv6 access-group acl6_1 ingress"
+ - "interface GigabitEthernet0/0/0/2"
+ - "no ipv4 access-group acl_3 ingress"
+ - "ipv4 access-group acl_4 egress"
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.acl_interfaces.acl_interfaces import (
+ Acl_interfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.acl_interfaces.acl_interfaces import (
+ Acl_interfaces,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+ mutually_exclusive = [("config", "running_config")]
+
+ module = AnsibleModule(
+ argument_spec=Acl_interfacesArgs.argument_spec,
+ required_if=required_if,
+ mutually_exclusive=mutually_exclusive,
+ supports_check_mode=True,
+ )
+
+ result = Acl_interfaces(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_acls.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_acls.py
new file mode 100644
index 00000000..ef31676c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_acls.py
@@ -0,0 +1,1451 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_acls
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_acls
+short_description: ACLs resource module
+description:
+- This module manages Access Control Lists (ACLs) on devices running IOS-XR.
+version_added: 1.0.0
+author: Nilashish Chakraborty (@NilashishC)
+options:
+ config:
+ description: A list of dictionaries specifying ACL configurations.
+ type: list
+ elements: dict
+ suboptions:
+ afi:
+ description:
+ - The Address Family Indicator (AFI) for the Access Control Lists (ACL).
+ type: str
+ required: true
+ choices:
+ - ipv4
+ - ipv6
+ acls:
+ description:
+ - A list of Access Control Lists (ACLs).
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - The name of the Access Control List (ACL).
+ type: str
+ aces:
+ description:
+ - List of Access Control Entries (ACEs) for this Access Control List (ACL).
+ type: list
+ elements: dict
+ suboptions:
+ sequence:
+ description:
+ - Sequence number for the Access Control Entry (ACE).
+ type: int
+ grant:
+ description:
+ - Forward or drop packets matching the Access Control Entry (ACE).
+ type: str
+ choices:
+ - permit
+ - deny
+ remark:
+ description:
+ - Comments or a description for the access list.
+ type: str
+ line:
+ description:
+ - An ACE excluding the sequence number.
+ - This key is mutually exclusive with all the other attributes except
+ 'sequence'.
+ - When used with other attributes, the value of this key will get
+ precedence and the other keys will be ignored.
+ - This should only be used when an attribute doesn't exist in the
+ argspec but is valid for the device.
+ - For fact gathering, any ACE that is not fully parsed, will show
+ up as a value of this attribute, excluding the sequence number,
+ which will be populated as value of the sequence key.
+ type: str
+ aliases:
+ - ace
+ source:
+ description:
+ - Specifies the packet source.
+ type: dict
+ suboptions:
+ host:
+ description:
+ - The host IP address to match.
+ type: str
+ address:
+ description:
+ - The source IP address to match.
+ type: str
+ wildcard_bits:
+ description:
+ - The Wildcard bits to apply to source address.
+ type: str
+ any:
+ description:
+ - Match any source address.
+ type: bool
+ prefix:
+ description:
+ - Source network prefix.
+ type: str
+ port_protocol:
+ description:
+ - Specify the source port or protocol.
+ type: dict
+ suboptions:
+ eq:
+ description:
+ - Match only packets on a given port number.
+ type: str
+ gt:
+ description:
+ - Match only packets with a greater port number.
+ type: str
+ lt:
+ description:
+ - Match only packets with a lower port number.
+ type: str
+ neq:
+ description:
+ - Match only packets not on a given port number.
+ type: str
+ range:
+ description:
+ - Match only packets in the range of port numbers
+ type: dict
+ suboptions:
+ start:
+ description:
+ - Specify the start of the port range
+ type: str
+ end:
+ description:
+ - Specify the end of the port range
+ type: str
+ destination:
+ description:
+ - Specifies the packet destination.
+ type: dict
+ suboptions:
+ host:
+ description:
+ - The host IP address to match.
+ type: str
+ address:
+ description:
+ - The destination IP address to match.
+ type: str
+ wildcard_bits:
+ description:
+ - The Wildcard bits to apply to destination address.
+ type: str
+ any:
+ description:
+ - Match any destination address.
+ type: bool
+ prefix:
+ description:
+ - Destination network prefix.
+ type: str
+ port_protocol:
+ description:
+ - Specify the source port or protocol.
+ type: dict
+ suboptions:
+ eq:
+ description:
+ - Match only packets on a given port number.
+ type: str
+ gt:
+ description:
+ - Match only packets with a greater port number.
+ type: str
+ lt:
+ description:
+ - Match only packets with a lower port number.
+ type: str
+ neq:
+ description:
+ - Match only packets not on a given port number.
+ type: str
+ range:
+ description:
+ - Match only packets in the range of port numbers
+ type: dict
+ suboptions:
+ start:
+ description:
+ - Specify the start of the port range
+ type: str
+ end:
+ description:
+ - Specify the end of the port range
+ type: str
+ protocol:
+ description:
+ - Specify the protocol to match.
+ - Refer to vendor documentation for valid values.
+ type: str
+ protocol_options:
+ description:
+ - Additional suboptions for the protocol.
+ type: dict
+ suboptions:
+ icmpv6:
+ description: Internet Control Message Protocol settings for IPv6.
+ type: dict
+ suboptions:
+ address_unreachable:
+ description: Address Unreachable
+ type: bool
+ administratively_prohibited:
+ description: Administratively Prohibited
+ type: bool
+ beyond_scope_of_source_address:
+ description: Administratively Prohibited
+ type: bool
+ destination_unreachable:
+ description: Destination Unreachable
+ type: bool
+ echo:
+ description: Echo
+ type: bool
+ echo_reply:
+ description: Echo Reply
+ type: bool
+ erroneous_header_field:
+ description: Erroneous Header Field
+ type: bool
+ group_membership_query:
+ description: Group Membership Query
+ type: bool
+ group_membership_report:
+ description: Group Membership Report
+ type: bool
+ group_membership_termination:
+ description: Group Membership Termination
+ type: bool
+ host_unreachable:
+ description: Host Unreachable
+ type: bool
+ nd_na:
+ description: Neighbor Discovery - Neighbor Advertisement
+ type: bool
+ nd_ns:
+ description: Neighbor Discovery - Neighbor Solicitation
+ type: bool
+ neighbor_redirect:
+ description: Neighbor Redirect
+ type: bool
+ no_route_to_destination:
+ description: No Route To Destination
+ type: bool
+ node_information_request_is_refused:
+ description: Node Information Request Is Refused
+ type: bool
+ node_information_successful_reply:
+ description: Node Information Successful Reply
+ type: bool
+ packet_too_big:
+ description: Packet Too Big
+ type: bool
+ parameter_problem:
+ description: Parameter Problem
+ type: bool
+ port_unreachable:
+ description: Port Unreachable
+ type: bool
+ query_subject_is_IPv4address:
+ description: Query Subject Is IPv4 address
+ type: bool
+ query_subject_is_IPv6address:
+ description: Query Subject Is IPv6 address
+ type: bool
+ query_subject_is_domainname:
+ description: Query Subject Is Domain name
+ type: bool
+ reassembly_timeout:
+ description: Reassembly Timeout
+ type: bool
+ redirect:
+ description: Redirect
+ type: bool
+ router_advertisement:
+ description: Router Advertisement
+ type: bool
+ router_renumbering:
+ description: Router Renumbering
+ type: bool
+ router_solicitation:
+ description: Router Solicitation
+ type: bool
+ rr_command:
+ description: RR Command
+ type: bool
+ rr_result:
+ description: RR Result
+ type: bool
+ rr_seqnum_reset:
+ description: RR Seqnum Reset
+ type: bool
+ time_exceeded:
+ description: Time Exceeded
+ type: bool
+ ttl_exceeded:
+ description: TTL Exceeded
+ type: bool
+ unknown_query_type:
+ description: Unknown Query Type
+ type: bool
+ unreachable:
+ description: Unreachable
+ type: bool
+ unrecognized_next_header:
+ description: Unrecognized Next Header
+ type: bool
+ unrecognized_option:
+ description: Unrecognized Option
+ type: bool
+ whoareyou_reply:
+ description: Whoareyou Reply
+ type: bool
+ whoareyou_request:
+ description: Whoareyou Request
+ type: bool
+ icmp:
+ description: Internet Control Message Protocol settings.
+ type: dict
+ suboptions:
+ administratively_prohibited:
+ description: Administratively prohibited
+ type: bool
+ alternate_address:
+ description: Alternate address
+ type: bool
+ conversion_error:
+ description: Datagram conversion
+ type: bool
+ dod_host_prohibited:
+ description: Host prohibited
+ type: bool
+ dod_net_prohibited:
+ description: Net prohibited
+ type: bool
+ echo:
+ description: Echo (ping)
+ type: bool
+ echo_reply:
+ description: Echo reply
+ type: bool
+ general_parameter_problem:
+ description: Parameter problem
+ type: bool
+ host_isolated:
+ description: Host isolated
+ type: bool
+ host_precedence_unreachable:
+ description: Host unreachable for precedence
+ type: bool
+ host_redirect:
+ description: Host redirect
+ type: bool
+ host_tos_redirect:
+ description: Host redirect for TOS
+ type: bool
+ host_tos_unreachable:
+ description: Host unreachable for TOS
+ type: bool
+ host_unknown:
+ description: Host unknown
+ type: bool
+ host_unreachable:
+ description: Host unreachable
+ type: bool
+ information_reply:
+ description: Information replies
+ type: bool
+ information_request:
+ description: Information requests
+ type: bool
+ mask_reply:
+ description: Mask replies
+ type: bool
+ mask_request:
+ description: Mask requests
+ type: bool
+ mobile_redirect:
+ description: Mobile host redirect
+ type: bool
+ net_redirect:
+ description: Network redirect
+ type: bool
+ net_tos_redirect:
+ description: Net redirect for TOS
+ type: bool
+ net_tos_unreachable:
+ description: Network unreachable for TOS
+ type: bool
+ net_unreachable:
+ description: Net unreachable
+ type: bool
+ network_unknown:
+ description: Network unknown
+ type: bool
+ no_room_for_option:
+ description: Parameter required but no room
+ type: bool
+ option_missing:
+ description: Parameter required but not present
+ type: bool
+ packet_too_big:
+ description: Fragmentation needed and DF set
+ type: bool
+ parameter_problem:
+ description: All parameter problems
+ type: bool
+ port_unreachable:
+ description: Port unreachable
+ type: bool
+ precedence_unreachable:
+ description: Precedence cutoff
+ type: bool
+ protocol_unreachable:
+ description: Protocol unreachable
+ type: bool
+ reassembly_timeout:
+ description: Reassembly timeout
+ type: bool
+ redirect:
+ description: All redirects
+ type: bool
+ router_advertisement:
+ description: Router discovery advertisements
+ type: bool
+ router_solicitation:
+ description: Router discovery solicitations
+ type: bool
+ source_quench:
+ description: Source quenches
+ type: bool
+ source_route_failed:
+ description: Source route failed
+ type: bool
+ time_exceeded:
+ description: All time exceededs
+ type: bool
+ timestamp_reply:
+ description: Timestamp replies
+ type: bool
+ timestamp_request:
+ description: Timestamp requests
+ type: bool
+ traceroute:
+ description: Traceroute
+ type: bool
+ ttl_exceeded:
+ description: TTL exceeded
+ type: bool
+ unreachable:
+ description: All unreachables
+ type: bool
+ tcp:
+ description: Match TCP packet flags
+ type: dict
+ suboptions:
+ ack:
+ description: Match on the ACK bit
+ type: bool
+ established:
+ description: Match established connections
+ type: bool
+ fin:
+ description: Match on the FIN bit
+ type: bool
+ psh:
+ description: Match on the PSH bit
+ type: bool
+ rst:
+ description: Match on the RST bit
+ type: bool
+ syn:
+ description: Match on the SYN bit
+ type: bool
+ urg:
+ description: Match on the URG bit
+ type: bool
+ igmp:
+ description: Internet Group Management Protocol (IGMP) settings.
+ type: dict
+ suboptions:
+ dvmrp:
+ description: Match Distance Vector Multicast Routing Protocol
+ type: bool
+ host_query:
+ description: Match Host Query
+ type: bool
+ host_report:
+ description: Match Host Report
+ type: bool
+ pim:
+ description: Match Protocol Independent Multicast
+ type: bool
+ trace:
+ description: Multicast trace
+ type: bool
+ mtrace:
+ description: Match mtrace
+ type: bool
+ mtrace_response:
+ description: Match mtrace response
+ type: bool
+ dscp:
+ description:
+ - Match packets with given DSCP value.
+ type: dict
+ suboptions:
+ eq:
+ description: Match only packets on a given dscp value
+ type: str
+ gt:
+ description: Match only packets with a greater dscp value
+ type: str
+ lt:
+ description: Match only packets with a lower dscp value
+ type: str
+ neq:
+ description: Match only packets not on a given dscp value
+ type: str
+ range:
+ description: Match only packets in the range of dscp values
+ type: dict
+ suboptions:
+ start:
+ description: Start of the dscp range
+ type: str
+ end:
+ description: End of the dscp range
+ type: str
+ fragments:
+ description:
+ - Check non-intial fragments.
+ type: bool
+ packet_length:
+ description:
+ - Match packets given packet length.
+ type: dict
+ suboptions:
+ eq:
+ description: Match only packets on a given packet length
+ type: int
+ gt:
+ description: Match only packets with a greater packet length
+ type: int
+ lt:
+ description: Match only packets with a lower packet length
+ type: int
+ neq:
+ description: Match only packets not on a given packet length
+ type: int
+ range:
+ description: Match only packets in the range of packet lengths
+ type: dict
+ suboptions:
+ start:
+ description: Start of the packet length range
+ type: int
+ end:
+ description: End of the packet length range
+ type: int
+ precedence:
+ description: Match packets with given precedence value
+ type: str
+ ttl:
+ description: Match against specified TTL value.
+ type: dict
+ suboptions:
+ eq:
+ description: Match only packets with exact TTL value.
+ type: int
+ gt:
+ description: Match only packets with a greater TTL value.
+ type: int
+ lt:
+ description: Match only packets with a lower TTL value.
+ type: int
+ neq:
+ description: Match only packets that won't have the given TTL
+ value.
+ type: int
+ range:
+ description: Match only packets in the range of given TTL values.
+ type: dict
+ suboptions:
+ start:
+ description: Start of the TTL range.
+ type: int
+ end:
+ description: End of the TTL range.
+ type: int
+ log:
+ description:
+ - Enable/disable log matches against this entry.
+ type: bool
+ log_input:
+ description:
+ - Enable/disable log matches against this entry, including input interface.
+ type: bool
+ icmp_off:
+ description:
+ - Enable/disable the ICMP message for this entry.
+ type: bool
+ capture:
+ description:
+ - Capture matched packet.
+ type: bool
+ destopts:
+ description:
+ - Match if destination opts header is present.
+ type: bool
+ authen:
+ description:
+ - Match if authentication header is present.
+ type: bool
+ routing:
+ description:
+ - Match if routing header is present.
+ type: bool
+ hop_by_hop:
+ description:
+ - Match if hop-by-hop opts header is present.
+ type: bool
+ running_config:
+ description:
+ - The module, by default, will connect to the remote device and retrieve the current
+ running-config to use as a base for comparing against the contents of source.
+ There are times when it is not desirable to have the task get the current running-config
+ for every task in a playbook. The I(running_config) argument allows the implementer
+ to pass in the configuration to use as the base config for comparison. This
+ value of this option should be the output received from device by executing
+ command B(show running-config router static).
+ type: str
+ state:
+ description:
+ - The state the configuration should be left in.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - gathered
+ - rendered
+ - parsed
+ default: merged
+
+"""
+EXAMPLES = """
+# Using merged to add new ACLs
+
+# Before state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:07:45.767 UTC
+# RP/0/RP0/CPU0:ios#
+
+- name: Merge the provided configuration with the exisiting running configuration
+ cisco.iosxr.iosxr_acls:
+ config:
+ - afi: ipv6
+ acls:
+ - name: acl6_1
+ aces:
+ - sequence: 10
+ grant: deny
+ protocol: tcp
+ source:
+ prefix: 2001:db8:1234::/48
+ port_protocol:
+ range:
+ start: ftp
+ end: telnet
+ destination:
+ any: true
+ protocol_options:
+ tcp:
+ syn: true
+ ttl:
+ range:
+ start: 180
+ end: 250
+ routing: true
+ authen: true
+ log: true
+
+ - sequence: 20
+ grant: permit
+ protocol: icmpv6
+ source:
+ any: true
+ destination:
+ any: true
+ protocol_options:
+ icmpv6:
+ router_advertisement: true
+ precedence: network
+ destopts: true
+
+ - afi: ipv4
+ acls:
+ - name: acl_1
+ aces:
+ - sequence: 16
+ remark: TEST_ACL_1_REMARK
+
+ - sequence: 21
+ grant: permit
+ protocol: tcp
+ source:
+ host: 192.0.2.10
+ port_protocol:
+ range:
+ start: pop3
+ end: 121
+ destination:
+ address: 198.51.100.0
+ wildcard_bits: 0.0.0.15
+ protocol_options:
+ tcp:
+ rst: true
+
+ - sequence: 23
+ grant: deny
+ protocol: icmp
+ source:
+ any: true
+ destination:
+ prefix: 198.51.100.0/28
+ protocol_options:
+ icmp:
+ reassembly_timeout: true
+ dscp:
+ lt: af12
+
+ - name: acl_2
+ aces:
+ - sequence: 10
+ remark: TEST_ACL_2_REMARK
+ state: merged
+
+# After state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+# 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+# Using merged to update existing ACLs
+
+# Before state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+# 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+- name: Update existing ACEs
+ cisco.iosxr.iosxr_acls:
+ config:
+ - afi: ipv4
+ acls:
+ - name: acl_1
+ aces:
+ - sequence: 21
+ source:
+ prefix: 198.51.100.32/28
+ port_protocol:
+ range:
+ start: pop3
+ end: 121
+ protocol_options:
+ tcp:
+ syn: true
+
+ - sequence: 23
+ protocol_options:
+ icmp:
+ router_advertisement: true
+ dscp:
+ eq: af23
+
+# After state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:47:18.711 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp 198.51.100.32 0.0.0.15 range pop3 121 198.51.100.0 0.0.0.15 syn
+# 23 deny icmp any 198.51.100.0 0.0.0.15 router-advertisement dscp eq af23
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+# Using replaced to replace a whole ACL
+
+# Before state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+# 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+- name: Replace device configurations of listed ACL with provided configurations
+ cisco.iosxr.iosxr_acls:
+ config:
+ - afi: ipv4
+ acls:
+ - name: acl_2
+ aces:
+ - sequence: 11
+ grant: permit
+ protocol: igmp
+ source:
+ host: 198.51.100.130
+ destination:
+ any: true
+ ttl:
+ eq: 100
+
+ - sequence: 12
+ grant: deny
+ source:
+ any: true
+ destination:
+ any: true
+ protocol: icmp
+ state: replaced
+
+# After state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 06:19:51.496 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp 198.51.100.32 0.0.0.15 range pop3 121 198.51.100.0 0.0.0.15 syn
+# 23 deny icmp any 198.51.100.0 0.0.0.15 router-advertisement dscp eq af23
+# ipv4 access-list acl_2
+# 11 permit igmp host 198.51.100.130 any ttl eq 100
+# 12 deny icmp any any
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+# Using overridden to override all ACLs in the device
+
+# Before state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+# 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+- name: Overridde all ACLs configuration with provided configuration
+ cisco.iosxr.iosxr_acls:
+ config:
+ - afi: ipv4
+ acls:
+ - name: acl_1
+ aces:
+ - sequence: 10
+ grant: permit
+ source:
+ any: true
+ destination:
+ any: true
+ protocol: tcp
+
+ - name: acl_2
+ aces:
+ - sequence: 20
+ grant: permit
+ source:
+ any: true
+ destination:
+ any: true
+ protocol: igmp
+ state: overridden
+
+# After state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 06:31:22.178 UTC
+# ipv4 access-list acl_1
+# 10 permit tcp any any
+# ipv4 access-list acl_2
+# 20 permit igmp any any
+
+# Using deleted to delete an entire ACL
+
+# Before state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+# 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+- name: Delete a single ACL
+ cisco.iosxr.iosxr_acls:
+ config:
+ - afi: ipv6
+ acls:
+ - name: acl6_1
+ state: deleted
+
+# After state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+# 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+
+# Using deleted to delete all ACLs under one AFI
+
+# Before state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+# 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+- name: Delete all ACLs under one AFI
+ cisco.iosxr.iosxr_acls:
+ config:
+ - afi: ipv4
+ state: deleted
+
+# After state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+# Using deleted to delete all ACLs from the device
+
+# Before state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+# 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+- name: Delete all ACLs from the device
+ cisco.iosxr.iosxr_acls:
+ state: deleted
+
+# After state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:07:45.767 UTC
+# RP/0/RP0/CPU0:ios#
+
+# Using gathered to gather ACL facts from the device
+
+- name: Gather ACL interfaces facts using gathered state
+ cisco.iosxr.iosxr_acls:
+ state: gathered
+
+# Task Output (redacted)
+# -----------------------
+#
+
+# "gathered": [
+# {
+# "acls": [
+# {
+# "aces": [
+# {
+# "remark": "TEST_ACL_1_REMARK",
+# "sequence": 16
+# },
+# {
+# "destination": {
+# "address": "198.51.100.0",
+# "wildcard_bits": "0.0.0.15"
+# },
+# "grant": "permit",
+# "protocol": "tcp",
+# "protocol_options": {
+# "tcp": {
+# "rst": true
+# }
+# },
+# "sequence": 21,
+# "source": {
+# "host": "192.0.2.10",
+# "port_protocol": {
+# "range": {
+# "end": "121",
+# "start": "pop3"
+# }
+# }
+# }
+# },
+# {
+# "destination": {
+# "address": "198.51.100.0",
+# "wildcard_bits": "0.0.0.15"
+# },
+# "dscp": {
+# "lt": "af12"
+# },
+# "grant": "deny",
+# "protocol": "icmp",
+# "protocol_options": {
+# "icmp": {
+# "reassembly_timeout": true
+# }
+# },
+# "sequence": 23,
+# "source": {
+# "any": true
+# }
+# }
+# ],
+# "name": "acl_1"
+# },
+# {
+# "aces": [
+# {
+# "remark": "TEST_ACL_2_REMARK",
+# "sequence": 10
+# }
+# ],
+# "name": "acl_2"
+# }
+# ],
+# "afi": "ipv4"
+# },
+# {
+# "acls": [
+# {
+# "aces": [
+# {
+# "authen": true,
+# "destination": {
+# "any": true
+# },
+# "grant": "deny",
+# "log": true,
+# "protocol": "tcp",
+# "protocol_options": {
+# "tcp": {
+# "syn": true
+# }
+# },
+# "routing": true,
+# "sequence": 10,
+# "source": {
+# "port_protocol": {
+# "range": {
+# "end": "telnet",
+# "start": "ftp"
+# }
+# },
+# "prefix": "2001:db8:1234::/48"
+# },
+# "ttl": {
+# "range": {
+# "end": 250,
+# "start": 180
+# }
+# }
+# },
+# {
+# "destination": {
+# "any": true
+# },
+# "destopts": true,
+# "grant": "permit",
+# "precedence": "network",
+# "protocol": "icmpv6",
+# "protocol_options": {
+# "icmpv6": {
+# "router_advertisement": true
+# }
+# },
+# "sequence": 20,
+# "source": {
+# "any": true
+# }
+# }
+# ],
+# "name": "acl6_1"
+# }
+# ],
+# "afi": "ipv6"
+# }
+# ]
+
+# Using rendered
+
+- name: Render platform specific commands (without connecting to the device)
+ cisco.iosxr.iosxr_acls:
+ config:
+ - afi: ipv4
+ acls:
+ - name: acl_2
+ aces:
+ - sequence: 11
+ grant: permit
+ protocol: igmp
+ source:
+ host: 198.51.100.130
+ destination:
+ any: true
+ ttl:
+ eq: 100
+
+ - sequence: 12
+ grant: deny
+ source:
+ any: true
+ destination:
+ any: true
+ protocol: icmp
+ state: rendered
+
+# Task Output (redacted)
+# -----------------------
+
+# "rendered": [
+# "ipv4 access-list acl_2",
+# "11 permit igmp host 198.51.100.130 any ttl eq 100",
+# "12 deny icmp any any"
+
+# Using parsed
+
+# parsed.cfg
+# ------------
+#
+# ipv4 access-list acl_1
+# 10 remark TEST_ACL_2_REMARK
+# ipv4 access-list acl_2
+# 11 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 authen routing log
+# 21 permit icmpv6 any any router-advertisement precedence network packet-length eq 576 destopts
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network packet-length eq 576 destopts
+
+- name: Parse externally provided ACL config to agnostic model
+ cisco.iosxr.iosxr_acls:
+ running_config: "{{ lookup('file', 'parsed.cfg') }}"
+ state: parsed
+
+# Task Output (redacted)
+# -----------------------
+# "parsed": [
+# {
+# "acls": [
+# {
+# "aces": [
+# {
+# "remark": "TEST_ACL_2_REMARK",
+# "sequence": 10
+# }
+# ],
+# "name": "acl_1"
+# },
+# {
+# "aces": [
+# {
+# "authen": true,
+# "destination": {
+# "any": true
+# },
+# "grant": "deny",
+# "log": true,
+# "protocol": "tcp",
+# "protocol_options": {
+# "tcp": {
+# "syn": true
+# }
+# },
+# "routing": true,
+# "sequence": 11,
+# "source": {
+# "port_protocol": {
+# "range": {
+# "end": "telnet",
+# "start": "ftp"
+# }
+# },
+# "prefix": "2001:db8:1234::/48"
+# },
+# "ttl": {
+# "range": {
+# "end": 250,
+# "start": 180
+# }
+# }
+# },
+# {
+# "destination": {
+# "any": true
+# },
+# "destopts": true,
+# "grant": "permit",
+# "packet_length": {
+# "eq": 576
+# },
+# "precedence": "network",
+# "protocol": "icmpv6",
+# "protocol_options": {
+# "icmpv6": {
+# "router_advertisement": true
+# }
+# },
+# "sequence": 21,
+# "source": {
+# "any": true
+# }
+# }
+# ],
+# "name": "acl_2"
+# }
+# ],
+# "afi": "ipv4"
+# },
+# {
+# "acls": [
+# {
+# "aces": [
+# {
+# "authen": true,
+# "destination": {
+# "any": true
+# },
+# "grant": "deny",
+# "log": true,
+# "protocol": "tcp",
+# "protocol_options": {
+# "tcp": {
+# "syn": true
+# }
+# },
+# "routing": true,
+# "sequence": 10,
+# "source": {
+# "port_protocol": {
+# "range": {
+# "end": "telnet",
+# "start": "ftp"
+# }
+# },
+# "prefix": "2001:db8:1234::/48"
+# },
+# "ttl": {
+# "range": {
+# "end": 250,
+# "start": 180
+# }
+# }
+# },
+# {
+# "destination": {
+# "any": true
+# },
+# "destopts": true,
+# "grant": "permit",
+# "packet_length": {
+# "eq": 576
+# },
+# "precedence": "network",
+# "protocol": "icmpv6",
+# "protocol_options": {
+# "icmpv6": {
+# "router_advertisement": true
+# }
+# },
+# "sequence": 20,
+# "source": {
+# "any": true
+# }
+# }
+# ],
+# "name": "acl6_1"
+# }
+# ],
+# "afi": "ipv6"
+# }
+# ]
+"""
+RETURN = """
+before:
+ description: The configuration prior to the model invocation.
+ returned: always
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The resulting configuration model invocation.
+ returned: when changed
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample:
+ - ipv6 access-list acl6_1
+ - 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 authen routing log
+ - 20 permit icmpv6 any any router-advertisement precedence network destopts
+ - ipv4 access-list acl_1
+ - 16 remark TEST_ACL_1_REMARK
+ - 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+ - 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.acls.acls import (
+ AclsArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.acls.acls import (
+ Acls,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+
+ module = AnsibleModule(
+ argument_spec=AclsArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ )
+
+ result = Acls(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_banner.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_banner.py
new file mode 100644
index 00000000..be75ecaf
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_banner.py
@@ -0,0 +1,316 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2017, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_banner
+author:
+- Trishna Guha (@trishnaguha)
+- Kedar Kekan (@kedarX)
+short_description: Manage multiline banners on Cisco IOS XR devices
+description:
+- This module will configure both exec and motd banners on remote device running Cisco
+ IOS XR. It allows playbooks to add or remove banner text from the running configuration.
+version_added: 1.0.0
+requirements:
+- ncclient >= 0.5.3 when using netconf
+- lxml >= 4.1.1 when using netconf
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+notes:
+- Tested against IOS XRv 6.1.3.
+- This module works with connection C(network_cli) and C(netconf). See L(the IOS-XR
+ Platform Options,../network/user_guide/platform_iosxr.html).
+options:
+ banner:
+ description:
+ - Specifies the type of banner to configure on remote device.
+ required: true
+ type: str
+ choices:
+ - login
+ - motd
+ text:
+ description:
+ - Banner text to be configured. Accepts multi line string, without empty lines.
+ When using a multi line string, the first and last characters must be the
+ start and end delimiters for the banner
+ Requires I(state=present).
+ type: str
+ state:
+ description:
+ - Existential state of the configuration on the device.
+ default: present
+ type: str
+ choices:
+ - present
+ - absent
+"""
+
+EXAMPLES = """
+- name: configure the login banner
+ cisco.iosxr.iosxr_banner:
+ banner: login
+ text: |
+ @this is my login banner
+ that contains a multiline
+ string@
+ state: present
+- name: remove the motd banner
+ cisco.iosxr.iosxr_banner:
+ banner: motd
+ state: absent
+- name: Configure banner from file
+ cisco.iosxr.iosxr_banner:
+ banner: motd
+ text: "{{ lookup('file', './config_partial/raw_banner.cfg') }}"
+ state: present
+"""
+
+RETURN = """
+commands:
+ description: The list of configuration mode commands sent to device with transport C(cli)
+ returned: always (empty list when no commands to send)
+ type: list
+ sample:
+ - banner login
+ - "@this is my login banner"
+ - that contains a multiline
+ - string@
+
+xml:
+ description: NetConf rpc xml sent to device with transport C(netconf)
+ returned: always (empty list when no xml rpc to send)
+ type: list
+ sample:
+ - '<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <banners xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-infra-infra-cfg">
+ <banner xc:operation="merge">
+ <banner-name>motd</banner-name>
+ <banner-text>Ansible banner example</banner-text>
+ </banner>
+ </banners>
+ </config>'
+"""
+
+import re
+import collections
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ get_config,
+ load_config,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ iosxr_argument_spec,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ build_xml,
+ is_cliconf,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ etree_find,
+ is_netconf,
+)
+
+
+class ConfigBase(object):
+ def __init__(self, module):
+ self._module = module
+ self._result = {"changed": False, "warnings": []}
+ self._want = {}
+ self._have = {}
+
+ def map_params_to_obj(self):
+ text = self._module.params["text"]
+ if text:
+ text = "{0}".format(str(text).strip())
+ self._want.update(
+ {
+ "banner": self._module.params["banner"],
+ "text": text,
+ "state": self._module.params["state"],
+ }
+ )
+
+
+class CliConfiguration(ConfigBase):
+ def __init__(self, module):
+ super(CliConfiguration, self).__init__(module)
+
+ def map_obj_to_commands(self):
+ commands = list()
+ state = self._module.params["state"]
+ if state == "absent":
+ if self._have.get("state") != "absent" and (
+ "text" in self._have.keys() and self._have["text"]
+ ):
+ commands.append(
+ "no banner {0!s}".format(self._module.params["banner"])
+ )
+ elif state == "present":
+ if self._want["text"] and self._want["text"].encode().decode(
+ "unicode_escape"
+ ) != self._have.get("text"):
+ banner_cmd = "banner {0!s} ".format(
+ self._module.params["banner"]
+ )
+ banner_cmd += self._want["text"].strip()
+ commands.append(banner_cmd)
+ self._result["commands"] = commands
+ if commands:
+ commit = not self._module.check_mode
+ diff = load_config(self._module, commands, commit=commit)
+ if diff:
+ self._result["diff"] = dict(prepared=diff)
+ self._result["changed"] = True
+
+ def map_config_to_obj(self):
+ cli_filter = "banner {0!s}".format(self._module.params["banner"])
+ output = get_config(self._module, config_filter=cli_filter)
+ match = re.search(r"banner (\S+) (.*)", output, re.DOTALL)
+ if match:
+ text = match.group(2)
+ else:
+ text = None
+ obj = {"banner": self._module.params["banner"], "state": "absent"}
+ if output:
+ obj["text"] = text
+ obj["state"] = "present"
+ self._have.update(obj)
+
+ def run(self):
+ self.map_params_to_obj()
+ self.map_config_to_obj()
+ self.map_obj_to_commands()
+
+ return self._result
+
+
+class NCConfiguration(ConfigBase):
+ def __init__(self, module):
+ super(NCConfiguration, self).__init__(module)
+ self._banners_meta = collections.OrderedDict()
+ self._banners_meta.update(
+ [
+ (
+ "banner",
+ {
+ "xpath": "banners/banner",
+ "tag": True,
+ "attrib": "operation",
+ },
+ ),
+ ("a:banner", {"xpath": "banner/banner-name"}),
+ (
+ "a:text",
+ {"xpath": "banner/banner-text", "operation": "edit"},
+ ),
+ ]
+ )
+
+ def map_obj_to_xml_rpc(self):
+ state = self._module.params["state"]
+ _get_filter = build_xml(
+ "banners",
+ xmap=self._banners_meta,
+ params=self._module.params,
+ opcode="filter",
+ )
+
+ running = get_config(
+ self._module, source="running", config_filter=_get_filter
+ )
+
+ banner_name = None
+ banner_text = None
+ if etree_find(running, "banner-text") is not None:
+ banner_name = etree_find(running, "banner-name").text
+ banner_text = etree_find(running, "banner-text").text
+
+ opcode = None
+ if (
+ state == "absent"
+ and banner_name == self._module.params["banner"]
+ and len(banner_text)
+ ):
+ opcode = "delete"
+ elif state == "present":
+ opcode = "merge"
+
+ self._result["xml"] = []
+ if opcode:
+ _edit_filter = build_xml(
+ "banners",
+ xmap=self._banners_meta,
+ params=self._module.params,
+ opcode=opcode,
+ )
+
+ if _edit_filter is not None:
+ commit = not self._module.check_mode
+ diff = load_config(
+ self._module,
+ _edit_filter,
+ commit=commit,
+ running=running,
+ nc_get_filter=_get_filter,
+ )
+
+ if diff:
+ self._result["xml"] = _edit_filter
+ if self._module._diff:
+ self._result["diff"] = dict(prepared=diff)
+
+ self._result["changed"] = True
+
+ def run(self):
+ self.map_params_to_obj()
+ self.map_obj_to_xml_rpc()
+
+ return self._result
+
+
+def main():
+ """ main entry point for module execution
+ """
+ argument_spec = dict(
+ banner=dict(required=True, choices=["login", "motd"]),
+ text=dict(),
+ state=dict(default="present", choices=["present", "absent"]),
+ )
+
+ argument_spec.update(iosxr_argument_spec)
+
+ required_if = [("state", "present", ("text",))]
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ )
+
+ config_object = None
+ if is_cliconf(module):
+ # Commenting the below cliconf deprecation support call for Ansible 2.9 as it'll be continued to be supported
+ # module.deprecate("cli support for 'iosxr_interface' is deprecated. Use transport netconf instead",
+ # version='2.9')
+ config_object = CliConfiguration(module)
+ elif is_netconf(module):
+ config_object = NCConfiguration(module)
+
+ result = None
+ if config_object is not None:
+ result = config_object.run()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp.py
new file mode 100644
index 00000000..7e496545
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp.py
@@ -0,0 +1,355 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# (c) 2019, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_bgp
+author: Nilashish Chakraborty (@NilashishC)
+short_description: Configure global BGP protocol settings on Cisco IOS-XR
+description:
+- This module provides configuration management of global BGP parameters on devices
+ running Cisco IOS-XR
+version_added: 1.0.0
+notes:
+- Tested against Cisco IOS XR Software Version 6.1.3
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+options:
+ config:
+ description:
+ - Specifies the BGP related configuration.
+ type: dict
+ suboptions:
+ bgp_as:
+ description:
+ - Specifies the BGP Autonomous System (AS) number to configure on the device.
+ type: int
+ required: true
+ router_id:
+ description:
+ - Configures the BGP routing process router-id value.
+ type: str
+ log_neighbor_changes:
+ description:
+ - Enable/disable logging neighbor up/down and reset reason.
+ type: bool
+ neighbors:
+ description:
+ - Specifies BGP neighbor related configurations.
+ type: list
+ elements: dict
+ suboptions:
+ neighbor:
+ description:
+ - Neighbor router address.
+ type: str
+ required: true
+ remote_as:
+ description:
+ - Remote AS of the BGP neighbor to configure.
+ type: int
+ required: true
+ update_source:
+ description:
+ - Source of the routing updates.
+ type: str
+ password:
+ description:
+ - Password to authenticate the BGP peer connection.
+ type: str
+ enabled:
+ description:
+ - Administratively shutdown or enable a neighbor.
+ type: bool
+ description:
+ description:
+ - Neighbor specific description.
+ type: str
+ advertisement_interval:
+ description:
+ - Specifies the minimum interval (in seconds) between sending BGP routing
+ updates.
+ - The range is from 0 to 600.
+ type: int
+ tcp_mss:
+ description:
+ - Specifies the TCP initial maximum segment size to use.
+ - The range is from 68 to 10000.
+ type: int
+ ebgp_multihop:
+ description:
+ - Specifies the maximum hop count for EBGP neighbors not on directly connected
+ networks.
+ - The range is from 0 to 255.
+ type: int
+ timers:
+ description:
+ - Specifies BGP neighbor timer related configurations.
+ type: dict
+ suboptions:
+ keepalive:
+ description:
+ - Frequency with which the Cisco IOS-XR software sends keepalive messages
+ to its peer.
+ - The range is from 0 to 65535.
+ type: int
+ holdtime:
+ description:
+ - Interval after not receiving a keepalive message that the software
+ declares a peer dead.
+ - The range is from 3 to 65535.
+ type: int
+ min_neighbor_holdtime:
+ description:
+ - Interval specifying the minimum acceptable hold-time from a BGP
+ neighbor.
+ - The minimum acceptable hold-time must be less than, or equal to,
+ the interval specified in the holdtime argument.
+ - The range is from 3 to 65535.
+ type: int
+ address_family:
+ description:
+ - Specifies BGP address family related configurations.
+ type: list
+ elements: dict
+ suboptions:
+ afi:
+ description:
+ - Type of address family to configure.
+ choices:
+ - ipv4
+ - ipv6
+ required: true
+ type: str
+ safi:
+ description:
+ - Specifies the type of cast for the address family.
+ choices:
+ - flowspec
+ - unicast
+ - multicast
+ - labeled-unicast
+ type: str
+ default: unicast
+ redistribute:
+ description:
+ - Specifies the redistribute information from another routing protocol.
+ type: list
+ elements: dict
+ suboptions:
+ protocol:
+ description:
+ - Specifies the protocol for configuring redistribute information.
+ type: str
+ choices:
+ - ospf
+ - ospfv3
+ - eigrp
+ - isis
+ - static
+ - connected
+ - lisp
+ - mobile
+ - rip
+ - subscriber
+ required: true
+ id:
+ description:
+ - Identifier for the routing protocol for configuring redistribute
+ information.
+ - Valid for protocols 'ospf', 'eigrp', 'isis' and 'ospfv3'.
+ type: str
+ metric:
+ description:
+ - Specifies the metric for redistributed routes.
+ type: int
+ route_map:
+ description:
+ - Specifies the route map reference.
+ type: str
+ networks:
+ description:
+ - Specify networks to announce via BGP.
+ - For operation replace, this option is mutually exclusive with root level
+ networks option.
+ type: list
+ elements: dict
+ suboptions:
+ network:
+ description:
+ - Network ID to announce via BGP.
+ required: true
+ aliases:
+ - prefix
+ type: str
+ masklen:
+ description:
+ - Subnet mask length for the network to announce(e.g, 8, 16, 24, etc.).
+ type: int
+ required: true
+ route_map:
+ description:
+ - Route map to modify the attributes.
+ type: str
+ operation:
+ description:
+ - Specifies the operation to be performed on the BGP process configured on the
+ device.
+ - In case of merge, the input configuration will be merged with the existing BGP
+ configuration on the device.
+ - In case of replace, if there is a diff between the existing configuration and
+ the input configuration, the existing configuration will be replaced by the
+ input configuration for every option that has the diff.
+ - In case of override, all the existing BGP configuration will be removed from
+ the device and replaced with the input configuration.
+ - In case of delete the existing BGP configuration will be removed from the device.
+ default: merge
+ type: str
+ choices:
+ - merge
+ - replace
+ - override
+ - delete
+"""
+
+EXAMPLES = """
+- name: configure global bgp as 65000
+ cisco.iosxr.iosxr_bgp:
+ bgp_as: 65000
+ router_id: 1.1.1.1
+ neighbors:
+ - neighbor: 182.168.10.1
+ remote_as: 500
+ description: PEER_1
+ - neighbor: 192.168.20.1
+ remote_as: 500
+ update_source: GigabitEthernet 0/0/0/0
+ address_family:
+ - name: ipv4
+ cast: unicast
+ networks:
+ - network: 192.168.2.0/23
+ - network: 10.0.0.0/8
+ redistribute:
+ - protocol: ospf
+ id: 400
+ metric: 110
+
+- name: remove bgp as 65000 from config
+ ios_bgp:
+ bgp_as: 65000
+ state: absent
+"""
+
+RETURN = """
+commands:
+ description: The list of configuration mode commands to send to the device
+ returned: always
+ type: list
+ sample:
+ - router bgp 65000
+ - bgp router-id 1.1.1.1
+ - neighbor 182.168.10.1 remote-as 500
+ - neighbor 182.168.10.1 description PEER_1
+ - neighbor 192.168.20.1 remote-as 500
+ - neighbor 192.168.20.1 update-source GigabitEthernet0/0/0/0
+ - address-family ipv4 unicast
+ - redistribute ospf 400 metric 110
+ - network 192.168.2.0/23
+ - network 10.0.0.0/8
+ - exit
+"""
+from ansible.module_utils._text import to_text
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers.module import (
+ NetworkModule,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers.cli.config.bgp.process import (
+ REDISTRIBUTE_PROTOCOLS,
+)
+
+
+def main():
+ """ main entry point for module execution
+ """
+ network_spec = {
+ "network": dict(aliases=["prefix"], required=True),
+ "masklen": dict(type="int", required=True),
+ "route_map": dict(),
+ }
+
+ redistribute_spec = {
+ "protocol": dict(choices=REDISTRIBUTE_PROTOCOLS, required=True),
+ "id": dict(),
+ "metric": dict(type="int"),
+ "route_map": dict(),
+ }
+
+ timer_spec = {
+ "keepalive": dict(type="int"),
+ "holdtime": dict(type="int"),
+ "min_neighbor_holdtime": dict(type="int"),
+ }
+
+ neighbor_spec = {
+ "neighbor": dict(required=True),
+ "remote_as": dict(type="int", required=True),
+ "update_source": dict(),
+ "password": dict(no_log=True),
+ "enabled": dict(type="bool"),
+ "description": dict(),
+ "advertisement_interval": dict(type="int"),
+ "ebgp_multihop": dict(type="int"),
+ "tcp_mss": dict(type="int"),
+ "timers": dict(type="dict", options=timer_spec),
+ }
+
+ address_family_spec = {
+ "afi": dict(choices=["ipv4", "ipv6"], required=True),
+ "safi": dict(
+ choices=["flowspec", "labeled-unicast", "multicast", "unicast"],
+ default="unicast",
+ ),
+ "networks": dict(type="list", elements="dict", options=network_spec),
+ "redistribute": dict(
+ type="list", elements="dict", options=redistribute_spec
+ ),
+ }
+
+ config_spec = {
+ "bgp_as": dict(type="int", required=True),
+ "router_id": dict(),
+ "log_neighbor_changes": dict(type="bool"),
+ "neighbors": dict(type="list", elements="dict", options=neighbor_spec),
+ "address_family": dict(
+ type="list", elements="dict", options=address_family_spec
+ ),
+ }
+
+ argument_spec = {
+ "config": dict(type="dict", options=config_spec),
+ "operation": dict(
+ default="merge", choices=["merge", "replace", "override", "delete"]
+ ),
+ }
+
+ module = NetworkModule(
+ argument_spec=argument_spec, supports_check_mode=True
+ )
+
+ try:
+ result = module.edit_config(config_filter="router bgp")
+ except Exception as exc:
+ module.fail_json(msg=to_text(exc))
+
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_command.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_command.py
new file mode 100644
index 00000000..68e990b1
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_command.py
@@ -0,0 +1,213 @@
+#!/usr/bin/python
+#
+# Copyright: Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+module: iosxr_command
+author: Ricardo Carrillo Cruz (@rcarrillocruz)
+short_description: Run commands on remote devices running Cisco IOS XR
+description:
+- Sends arbitrary commands to an IOS XR node and returns the results read from the
+ device. This module includes an argument that will cause the module to wait for
+ a specific condition before returning or timing out if the condition is not met.
+- This module does not support running commands in configuration mode. Please use
+ M(iosxr_config) to configure iosxr devices.
+version_added: 1.0.0
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+notes:
+- Make sure the user has been authorized to execute commands terminal length 0, terminal
+ width 512 and terminal exec prompt no-timestamp.
+- This module works with C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+- This module does not support C(netconf) connection.
+- Tested against IOS XR 6.1.3
+options:
+ commands:
+ description:
+ - List of commands to send to the remote iosxr device over the configured provider.
+ The resulting output from the command is returned. If the I(wait_for) argument
+ is provided, the module is not returned until the condition is satisfied or
+ the number of retries has expired.
+ - If a command sent to the device requires answering a prompt, it is possible to pass
+ a dict containing command, answer and prompt. Common answers are 'y' or "\\r"
+ (carriage return, must be double quotes). See examples
+ type: list
+ elements: raw
+ required: true
+ wait_for:
+ description:
+ - List of conditions to evaluate against the output of the command. The task will
+ wait for each condition to be true before moving forward. If the conditional
+ is not true within the configured number of retries, the task fails. See examples.
+ aliases:
+ - waitfor
+ type: list
+ elements: str
+ 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.
+ default: all
+ choices:
+ - any
+ - all
+ type: str
+ retries:
+ description:
+ - Specifies the number of retries a command should by tried before it is considered
+ failed. The command is run on the target device every retry and evaluated against
+ the I(wait_for) conditions.
+ default: 10
+ type: int
+ interval:
+ description:
+ - Configures the interval in seconds to wait between 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
+ type: int
+"""
+
+EXAMPLES = """
+- name: run show version on remote devices
+ cisco.iosxr.iosxr_command:
+ commands: show version
+
+- name: run show version and check to see if output contains iosxr
+ cisco.iosxr.iosxr_command:
+ commands: show version
+ wait_for: result[0] contains IOS-XR
+
+- name: run multiple commands on remote nodes
+ cisco.iosxr.iosxr_command:
+ commands:
+ - show version
+ - show interfaces
+ - {command: example command that prompts, prompt: expected prompt, answer: yes}
+
+- name: run multiple commands and evaluate the output
+ cisco.iosxr.iosxr_command:
+ commands:
+ - show version
+ - show interfaces
+ wait_for:
+ - result[0] contains IOS-XR
+ - result[1] contains Loopback0
+"""
+
+RETURN = """
+stdout:
+ description: The set of responses from the commands
+ returned: always apart from low level errors (such as action plugin)
+ type: list
+ sample: ['...', '...']
+stdout_lines:
+ description: The value of stdout split into a list
+ returned: always apart from low level errors (such as action plugin)
+ type: list
+ sample: [['...', '...'], ['...'], ['...']]
+failed_conditions:
+ description: The list of conditionals that have failed
+ returned: failed
+ type: list
+ sample: ['...', '...']
+"""
+import time
+
+from ansible.module_utils._text import to_text
+from ansible.module_utils.basic import AnsibleModule
+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 (
+ to_lines,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ run_commands,
+ iosxr_argument_spec,
+)
+
+
+def parse_commands(module, warnings):
+ commands = module.params["commands"]
+ for item in list(commands):
+ try:
+ command = item["command"]
+ except Exception:
+ command = item
+ if module.check_mode and not command.startswith("show"):
+ warnings.append(
+ "Only show commands are supported when using check mode, not "
+ "executing %s" % command
+ )
+ commands.remove(item)
+
+ return commands
+
+
+def main():
+ argument_spec = dict(
+ commands=dict(type="list", required=True, elements="raw"),
+ wait_for=dict(type="list", aliases=["waitfor"], elements="str"),
+ match=dict(default="all", choices=["all", "any"]),
+ retries=dict(default=10, type="int"),
+ interval=dict(default=1, type="int"),
+ )
+
+ argument_spec.update(iosxr_argument_spec)
+
+ module = AnsibleModule(
+ argument_spec=argument_spec, supports_check_mode=True
+ )
+
+ warnings = list()
+ result = {"changed": False, "warnings": warnings}
+ commands = parse_commands(module, warnings)
+ wait_for = module.params["wait_for"] or list()
+
+ try:
+ conditionals = [Conditional(c) for c in wait_for]
+ except AttributeError as exc:
+ module.fail_json(msg=to_text(exc))
+
+ retries = module.params["retries"]
+ interval = module.params["interval"]
+ match = module.params["match"]
+
+ while retries > 0:
+ responses = run_commands(module, commands)
+
+ for item in list(conditionals):
+ if item(responses):
+ if match == "any":
+ conditionals = list()
+ break
+ conditionals.remove(item)
+
+ if not conditionals:
+ break
+
+ time.sleep(interval)
+ retries -= 1
+
+ if conditionals:
+ failed_conditions = [item.raw for item in conditionals]
+ msg = "One or more conditional statements have not been satisfied"
+ module.fail_json(msg=msg, failed_conditions=failed_conditions)
+
+ result.update(
+ {"stdout": responses, "stdout_lines": list(to_lines(responses))}
+ )
+
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_config.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_config.py
new file mode 100644
index 00000000..2a5d3080
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_config.py
@@ -0,0 +1,480 @@
+#!/usr/bin/python
+#
+# Copyright: Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_config
+author: Ricardo Carrillo Cruz (@rcarrillocruz)
+short_description: Manage Cisco IOS XR configuration sections
+description:
+- Cisco IOS XR configurations use a simple block indent file syntax for segmenting
+ configuration into sections. This module provides an implementation for working
+ with IOS XR configuration sections in a deterministic way.
+version_added: 1.0.0
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+notes:
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+- Tested against IOS XRv 6.1.3.
+- This module does not support C(netconf) connection
+- Abbreviated commands are NOT idempotent, see L(Network FAQ,../network/user_guide/faq.html
+ #why-do-the-config-modules-always-return-changed-true-with-abbreviated-commands).
+- Avoid service disrupting changes (viz. Management IP) from config replace.
+- Do not use C(end) in the replace config file.
+- To ensure idempotency and correct diff the configuration lines in the relevant module options should be similar to how they
+ appear if present in the running configuration on device including the indentation.
+options:
+ lines:
+ description:
+ - The ordered set of commands that should be configured in the section. The commands
+ must be the exact same commands as found in the device running-config as found in the
+ device running-config to ensure idempotency and correct diff. Be sure to note the
+ configuration command syntax as some commands are automatically modified by the
+ device config parser.
+ type: list
+ elements: str
+ aliases:
+ - commands
+ parents:
+ description:
+ - The ordered set of parents that uniquely identify the section or hierarchy the
+ commands should be checked against. If the parents argument is omitted, the
+ commands are checked against the set of top level or global commands.
+ type: list
+ elements: str
+ src:
+ description:
+ - Specifies the source path to the file that contains the configuration or configuration
+ template to load. The path to the source file can either be the full path on
+ the Ansible control host or a relative path from the playbook or role root directory. This
+ argument is mutually exclusive with I(lines), I(parents). The configuration lines in the
+ source file should be similar to how it will appear if present in the running-configuration
+ of the device to ensure idempotency and correct diff.
+ type: path
+ before:
+ description:
+ - The ordered set of commands to push on to the command stack if a change needs
+ to be made. This allows the playbook designer the opportunity to perform configuration
+ commands prior to pushing any changes without affecting how the set of commands
+ are matched against the system.
+ type: list
+ elements: str
+ after:
+ description:
+ - The ordered set of commands to append to the end of the command stack if a change
+ needs to be made. Just like with I(before) this allows the playbook designer
+ to append a set of commands to be executed after the command set.
+ type: list
+ elements: str
+ match:
+ description:
+ - Instructs the module on the way to perform the matching of the set of commands
+ against the current device config. If match is set to I(line), commands are
+ matched line by line. If match is set to I(strict), command lines are matched
+ with respect to position. If match is set to I(exact), command lines must be
+ an equal match. Finally, if match is set to I(none), the module will not attempt
+ to compare the source configuration with the running configuration on the remote
+ device.
+ type: str
+ default: line
+ choices:
+ - line
+ - strict
+ - exact
+ - none
+ replace:
+ description:
+ - Instructs the module on the way to perform the configuration on the device. If
+ the replace argument is set to I(line) then the modified lines are pushed to
+ the device in configuration mode. If the replace argument is set to I(block)
+ then the entire command block is pushed to the device in configuration mode
+ if any line is not correct.
+ type: str
+ default: line
+ choices:
+ - line
+ - block
+ - config
+ force:
+ description:
+ - The force argument instructs the module to not consider the current devices
+ running-config. When set to true, this will cause the module to push the contents
+ of I(src) into the device without first checking if already configured.
+ - Note this argument should be considered deprecated. To achieve the equivalent,
+ set the C(match=none) which is idempotent. This argument will be removed in
+ a future release.
+ type: bool
+ default: no
+ config:
+ description:
+ - The module, by default, will connect to the remote device and retrieve the current
+ running-config to use as a base for comparing against the contents of source. There
+ are times when it is not desirable to have the task get the current running-config
+ for every task in a playbook. The I(config) argument allows the implementer
+ to pass in the configuration to use as the base config for comparison.
+ The configuration lines for this option should be similar to how it will appear if present
+ in the running-configuration of the device to ensure idempotency and correct diff.
+ type: str
+ backup:
+ description:
+ - This argument will cause the module to create a full backup of the current C(running-config)
+ from the remote device before any changes are made. If the C(backup_options)
+ value is not given, the backup file is written to the C(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.
+ type: str
+ default: configured by iosxr_config
+ admin:
+ description:
+ - Enters into administration configuration mode for making config changes to the
+ device.
+ type: bool
+ default: no
+ label:
+ description:
+ - Allows a commit label to be specified to be included when the configuration
+ is committed. A valid label must begin with an alphabet and not exceed 30 characters,
+ only alphabets, digits, hyphens and underscores are allowed. If the configuration
+ is not changed or committed, this argument is ignored.
+ type: str
+ 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.
+ suboptions:
+ filename:
+ description:
+ - The filename to be used to store the backup configuration. If 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>
+ type: str
+ 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.
+ type: path
+ type: dict
+ exclusive:
+ description:
+ - Enters into exclusive configuration mode that locks out all users from committing
+ configuration changes until the exclusive session ends.
+ type: bool
+ default: false
+"""
+
+EXAMPLES = """
+- name: configure top level configuration
+ cisco.iosxr.iosxr_config:
+ lines: hostname {{ inventory_hostname }}
+
+- name: configure interface settings
+ cisco.iosxr.iosxr_config:
+ lines:
+ - description test interface
+ - ip address 172.31.1.1 255.255.255.0
+ parents: interface GigabitEthernet0/0/0/0
+
+- name: load a config from disk and replace the current config
+ cisco.iosxr.iosxr_config:
+ src: config.cfg
+ replace: config
+ backup: yes
+
+- name: for idempotency, use full-form commands
+ cisco.iosxr.iosxr_config:
+ lines:
+ # - shut
+ - shutdown
+ # parents: int g0/0/0/1
+ parents: interface GigabitEthernet0/0/0/1
+
+- name: configurable backup path
+ cisco.iosxr.iosxr_config:
+ src: config.cfg
+ backup: yes
+ backup_options:
+ filename: backup.cfg
+ dir_path: /home/user
+"""
+
+RETURN = """
+commands:
+ description: The set of commands that will be pushed to the remote device
+ returned: If there are commands to run against the host
+ type: list
+ sample: ['hostname foo', 'router ospf 1', 'router-id 1.1.1.1']
+backup_path:
+ description: The full path to the backup file
+ returned: when backup is yes
+ type: str
+ sample: /playbooks/ansible/backup/iosxr01_config.2016-07-16@22:28:34
+filename:
+ description: The name of the backup file
+ returned: when backup is yes and filename is not specified in backup options
+ type: str
+ sample: iosxr01_config.2016-07-16@22:28:34
+shortname:
+ description: The full path to the backup file excluding the timestamp
+ returned: when backup is yes and filename is not specified in backup options
+ type: str
+ sample: /playbooks/ansible/backup/iosxr01_config
+date:
+ description: The date extracted from the backup file name
+ returned: when backup is yes
+ type: str
+ sample: "2016-07-16"
+time:
+ description: The time extracted from the backup file name
+ returned: when backup is yes
+ type: str
+ sample: "22:28:34"
+"""
+import re
+
+from ansible.module_utils._text import to_text, to_bytes
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import ConnectionError
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ load_config,
+ get_config,
+ get_connection,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ iosxr_argument_spec,
+ copy_file,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import (
+ NetworkConfig,
+ dumps,
+)
+
+DEFAULT_COMMIT_COMMENT = "configured by iosxr_config"
+
+
+def copy_file_to_node(module):
+ """ Copy config file to IOS-XR node. We use SFTP because older IOS-XR versions don't handle SCP very well.
+ """
+ src = "/tmp/ansible_config.txt"
+ file = open(src, "wb")
+ file.write(to_bytes(module.params["src"], errors="surrogate_or_strict"))
+ file.close()
+
+ dst = "/harddisk:/ansible_config.txt"
+ copy_file(module, src, dst, "sftp")
+
+ return True
+
+
+def check_args(module, warnings):
+ if module.params["comment"]:
+ if len(module.params["comment"]) > 60:
+ module.fail_json(
+ msg="comment argument cannot be more than 60 characters"
+ )
+ if module.params["label"]:
+ label = module.params["label"]
+ if len(label) > 30:
+ module.fail_json(
+ msg="label argument cannot be more than 30 characters"
+ )
+ if not label[0].isalpha():
+ module.fail_json(msg="label argument must begin with an alphabet")
+ valid_chars = re.match(r"[\w-]*$", label)
+ if not valid_chars:
+ module.fail_json(
+ msg="label argument must only contain alphabets,"
+ + "digits, underscores or hyphens"
+ )
+ if module.params["force"]:
+ warnings.append(
+ "The force argument is deprecated, please use "
+ "match=none instead. This argument will be "
+ "removed in the future"
+ )
+
+
+def get_running_config(module):
+ contents = module.params["config"]
+ if not contents:
+ contents = get_config(module)
+ return contents
+
+
+def get_candidate(module):
+ candidate = ""
+ if module.params["src"]:
+ candidate = module.params["src"]
+ elif module.params["lines"]:
+ candidate_obj = NetworkConfig(indent=1, comment_tokens=["!"])
+ parents = module.params["parents"] or list()
+ candidate_obj.add(module.params["lines"], parents=parents)
+ candidate = dumps(candidate_obj, "raw")
+ return candidate
+
+
+def run(module, result):
+ match = module.params["match"]
+ replace = module.params["replace"]
+ replace_config = replace == "config"
+ path = module.params["parents"]
+ comment = module.params["comment"]
+ admin = module.params["admin"]
+ exclusive = module.params["exclusive"]
+ check_mode = module.check_mode
+ label = module.params["label"]
+
+ candidate_config = get_candidate(module)
+ running_config = get_running_config(module)
+
+ commands = None
+ replace_file_path = None
+ connection = get_connection(module)
+ try:
+ response = connection.get_diff(
+ candidate=candidate_config,
+ running=running_config,
+ diff_match=match,
+ path=path,
+ diff_replace=replace,
+ )
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+
+ config_diff = response.get("config_diff")
+
+ if replace_config:
+ running_base_diff_resp = connection.get_diff(
+ candidate=running_config,
+ running=candidate_config,
+ diff_match=match,
+ path=path,
+ diff_replace=replace,
+ )
+ if config_diff or running_base_diff_resp["config_diff"]:
+ ret = copy_file_to_node(module)
+ if not ret:
+ module.fail_json(msg="Copy of config file to the node failed")
+
+ commands = ["load harddisk:/ansible_config.txt"]
+ replace_file_path = "harddisk:/ansible_config.txt"
+
+ if config_diff or commands:
+ if not replace_config:
+ commands = config_diff.split("\n")
+
+ if any((module.params["lines"], module.params["src"])):
+ msg = (
+ "To ensure idempotency and correct diff the input configuration lines should be"
+ " similar to how they appear if present in the running configuration on device"
+ )
+ if module.params["src"]:
+ msg += " including the indentation"
+ module.warn(msg)
+
+ if module.params["before"]:
+ commands[:0] = module.params["before"]
+
+ if module.params["after"]:
+ commands.extend(module.params["after"])
+
+ result["commands"] = commands
+
+ commit = not check_mode
+ diff = load_config(
+ module,
+ commands,
+ commit=commit,
+ replace=replace_file_path,
+ comment=comment,
+ admin=admin,
+ exclusive=exclusive,
+ label=label,
+ )
+ if diff:
+ result["diff"] = dict(prepared=diff)
+
+ result["changed"] = True
+
+
+def main():
+ """main entry point for module execution
+ """
+ backup_spec = dict(filename=dict(), dir_path=dict(type="path"))
+ argument_spec = dict(
+ src=dict(type="path"),
+ lines=dict(aliases=["commands"], type="list", elements="str"),
+ parents=dict(type="list", elements="str"),
+ before=dict(type="list", elements="str"),
+ after=dict(type="list", elements="str"),
+ match=dict(
+ default="line", choices=["line", "strict", "exact", "none"]
+ ),
+ replace=dict(default="line", choices=["line", "block", "config"]),
+ # this argument is deprecated in favor of setting match: none
+ # it will be removed in a future version
+ force=dict(default=False, type="bool"),
+ config=dict(),
+ backup=dict(type="bool", default=False),
+ backup_options=dict(type="dict", options=backup_spec),
+ comment=dict(default=DEFAULT_COMMIT_COMMENT),
+ admin=dict(type="bool", default=False),
+ exclusive=dict(type="bool", default=False),
+ label=dict(),
+ )
+
+ argument_spec.update(iosxr_argument_spec)
+
+ mutually_exclusive = [("lines", "src"), ("parents", "src")]
+
+ required_if = [
+ ("match", "strict", ["lines"]),
+ ("match", "exact", ["lines"]),
+ ("replace", "block", ["lines"]),
+ ("replace", "config", ["src"]),
+ ]
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ mutually_exclusive=mutually_exclusive,
+ required_if=required_if,
+ supports_check_mode=True,
+ )
+
+ if module.params["force"] is True:
+ module.params["match"] = "none"
+
+ warnings = list()
+ check_args(module, warnings)
+
+ result = dict(changed=False, warnings=warnings)
+
+ if module.params["backup"]:
+ result["__backup__"] = get_config(module)
+
+ if any((module.params["src"], module.params["lines"])):
+ run(module, result)
+
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_facts.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_facts.py
new file mode 100644
index 00000000..5ac8effa
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_facts.py
@@ -0,0 +1,218 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The module file for iosxr_facts
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_facts
+short_description: Get facts about iosxr devices.
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+description:
+- Collects facts from network devices running the iosxr 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.
+version_added: 1.0.0
+notes:
+- Tested against IOS-XR 6.1.3.
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+author:
+- Ricardo Carrillo Cruz (@rcarrillocruz)
+- Nilashish Chakraborty (@Nilashishc)
+options:
+ gather_subset:
+ description:
+ - When supplied, this argument will restrict the facts collected to a given subset. Possible
+ values for this argument include all, hardware, config, and 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.
+ required: false
+ default: '!config'
+ type: list
+ elements: str
+ 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,
+ lacp etc. 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', 'lacp', 'lacp_interfaces', 'lldp_global',
+ 'lldp_interfaces', 'interfaces', 'l2_interfaces', 'l3_interfaces', 'lag_interfaces',
+ 'acls', 'acl_interfaces', 'static_routes', 'ospfv2'.
+ required: false
+ type: list
+ elements: str
+"""
+
+EXAMPLES = """
+# Gather all facts
+- cisco.iosxr.iosxr_facts:
+ gather_subset: all
+ gather_network_resources: all
+
+# Collect only the config and default facts
+- cisco.iosxr.iosxr_facts:
+ gather_subset:
+ - config
+
+# Do not collect hardware facts
+- cisco.iosxr.iosxr_facts:
+ gather_subset:
+ - '!hardware'
+
+# Collect only the lacp facts
+- cisco.iosxr.iosxr_facts:
+ gather_subset:
+ - '!all'
+ - '!min'
+ gather_network_resources:
+ - lacp
+
+# Do not collect lacp_interfaces facts
+- cisco.iosxr.iosxr_facts:
+ gather_network_resources:
+ - '!lacp_interfaces'
+
+# Collect lacp and minimal default facts
+- cisco.iosxr.iosxr_facts:
+ gather_subset: min
+ gather_network_resources: lacp
+
+# Collect only the interfaces facts
+- cisco.iosxr.iosxr_facts:
+ gather_subset:
+ - '!all'
+ - '!min'
+ gather_network_resources:
+ - interfaces
+ - l2_interfaces
+"""
+
+RETURN = """
+ansible_net_gather_subset:
+ description: The list of fact subsets collected from the device
+ returned: always
+ type: list
+
+# default
+ansible_net_version:
+ description: The operating system version running on the remote device
+ returned: always
+ type: str
+ansible_net_hostname:
+ description: The configured hostname of the device
+ returned: always
+ type: str
+ansible_net_image:
+ description: The image file the device is running
+ returned: always
+ type: str
+ansible_net_api:
+ description: The name of the transport
+ returned: always
+ type: str
+ansible_net_python_version:
+ description: The Python version Ansible controller is using
+ returned: always
+ type: str
+ansible_net_model:
+ description: The model name returned from the device
+ returned: always
+ type: str
+
+# hardware
+ansible_net_filesystems:
+ description: All file system names available on the device
+ returned: when hardware is configured
+ type: list
+ansible_net_memfree_mb:
+ description: The available free memory on the remote device in Mb
+ returned: when hardware is configured
+ type: int
+ansible_net_memtotal_mb:
+ description: The total memory on the remote device in Mb
+ returned: when hardware is configured
+ type: int
+
+# config
+ansible_net_config:
+ description: The current active config from the device
+ returned: when config is configured
+ type: str
+
+# interfaces
+ansible_net_all_ipv4_addresses:
+ description: All IPv4 addresses configured on the device
+ returned: when interfaces is configured
+ type: list
+ansible_net_all_ipv6_addresses:
+ description: All IPv6 addresses configured on the device
+ returned: when interfaces is configured
+ type: list
+ansible_net_interfaces:
+ description: A hash of all interfaces running on the system
+ returned: when interfaces is configured
+ type: dict
+ansible_net_neighbors:
+ description: The list of LLDP neighbors from the remote device
+ returned: when interfaces is configured
+ type: dict
+
+# network resources
+ansible_net_gather_network_resources:
+ description: The list of fact resource subsets collected from the device
+ returned: always
+ type: list
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ iosxr_argument_spec,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.facts.facts import (
+ FactsArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import (
+ Facts,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: ansible_facts
+ """
+ argument_spec = FactsArgs.argument_spec
+ argument_spec.update(iosxr_argument_spec)
+
+ module = AnsibleModule(
+ argument_spec=argument_spec, supports_check_mode=True
+ )
+
+ 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()
+
+ ansible_facts, additional_warnings = result
+ warnings.extend(additional_warnings)
+
+ module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_interface.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_interface.py
new file mode 100644
index 00000000..d3dca6e9
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_interface.py
@@ -0,0 +1,1057 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2017, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_interface
+author:
+- Ganesh Nalawade (@ganeshrn)
+- Kedar Kekan (@kedarX)
+short_description: (deprecated, removed after 2022-06-01) Manage Interface on Cisco
+ IOS XR network devices
+description:
+- This module provides declarative management of Interfaces on Cisco IOS XR network
+ devices.
+version_added: 1.0.0
+deprecated:
+ alternative: iosxr_interfaces
+ why: Newer and updated modules released with more functionality in Ansible 2.9
+ removed_at_date: '2022-06-01'
+requirements:
+- ncclient >= 0.5.3 when using netconf
+- lxml >= 4.1.1 when using netconf
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+notes:
+- This module works with connection C(network_cli) and C(netconf). See L(the IOS-XR
+ Platform Options,../network/user_guide/platform_iosxr.html).
+- Tested against IOS XRv 6.1.3.
+- Preconfiguration of physical interfaces is not supported with C(netconf) transport.
+options:
+ name:
+ description:
+ - Name of the interface to configure in C(type + path) format. e.g. C(GigabitEthernet0/0/0/0)
+ type: str
+ required: true
+ description:
+ description:
+ - Description of Interface being configured.
+ type: str
+ enabled:
+ description:
+ - Removes the shutdown configuration, which removes the forced administrative
+ down on the interface, enabling it to move to an up or down state.
+ type: bool
+ default: true
+ active:
+ description:
+ - Whether the interface is C(active) or C(preconfigured). Preconfiguration allows
+ you to configure modular services cards before they are inserted into the router.
+ When the cards are inserted, they are instantly configured. Active cards are
+ the ones already inserted.
+ type: str
+ choices:
+ - active
+ - preconfigure
+ default: active
+ speed:
+ description:
+ - Configure the speed for an interface. Default is auto-negotiation when not configured.
+ choices:
+ - '10'
+ - '100'
+ - '1000'
+ type: str
+ mtu:
+ description:
+ - Sets the MTU value for the interface. Range is between 64 and 65535'
+ type: str
+ duplex:
+ description:
+ - Configures the interface duplex mode. Default is auto-negotiation when not configured.
+ type: str
+ choices:
+ - full
+ - half
+ tx_rate:
+ description:
+ - Transmit rate in bits per second (bps).
+ - This is state check parameter only.
+ - Supports conditionals, see L(Conditionals in Networking Modules,../network/user_guide/network_working_with_command_output.html)
+ type: str
+ rx_rate:
+ description:
+ - Receiver rate in bits per second (bps).
+ - This is state check parameter only.
+ - Supports conditionals, see L(Conditionals in Networking Modules,../network/user_guide/network_working_with_command_output.html)
+ type: str
+ 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), I(tx_rate) and I(rx_rate).
+ default: 10
+ type: int
+ aggregate:
+ description: List of interfaces definition
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Name of the interface to configure in C(type + path) format. e.g. C(GigabitEthernet0/0/0/0)
+ type: str
+ description:
+ description:
+ - Description of Interface being configured.
+ type: str
+ enabled:
+ description:
+ - Removes the shutdown configuration, which removes the forced administrative
+ down on the interface, enabling it to move to an up or down state.
+ type: bool
+ active:
+ description:
+ - Whether the interface is C(active) or C(preconfigured). Preconfiguration allows
+ you to configure modular services cards before they are inserted into the router.
+ When the cards are inserted, they are instantly configured. Active cards are
+ the ones already inserted.
+ type: str
+ choices:
+ - active
+ - preconfigure
+ speed:
+ description:
+ - Configure the speed for an interface. Default is auto-negotiation when not configured.
+ choices:
+ - '10'
+ - '100'
+ - '1000'
+ type: str
+ mtu:
+ description:
+ - Sets the MTU value for the interface. Range is between 64 and 65535'
+ type: str
+ duplex:
+ description:
+ - Configures the interface duplex mode. Default is auto-negotiation when not configured.
+ type: str
+ choices:
+ - full
+ - half
+ tx_rate:
+ description:
+ - Transmit rate in bits per second (bps).
+ - This is state check parameter only.
+ - Supports conditionals, see L(Conditionals in Networking Modules,../network/user_guide/network_working_with_command_output.html)
+ type: str
+ rx_rate:
+ description:
+ - Receiver rate in bits per second (bps).
+ - This is state check parameter only.
+ - Supports conditionals, see L(Conditionals in Networking Modules,../network/user_guide/network_working_with_command_output.html)
+ type: str
+ 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), I(tx_rate) and I(rx_rate).
+ type: int
+ state:
+ description:
+ - State of the Interface configuration, C(up) means present and operationally
+ up and C(down) means present and operationally C(down)
+ type: str
+ choices:
+ - present
+ - absent
+ - up
+ - down
+ state:
+ description:
+ - State of the Interface configuration, C(up) means present and operationally
+ up and C(down) means present and operationally C(down)
+ type: str
+ default: present
+ choices:
+ - present
+ - absent
+ - up
+ - down
+
+
+"""
+
+EXAMPLES = """
+- name: configure interface
+ cisco.iosxr.iosxr_interface:
+ name: GigabitEthernet0/0/0/2
+ description: test-interface
+ speed: 100
+ duplex: half
+ mtu: 512
+
+- name: remove interface
+ cisco.iosxr.iosxr_interface:
+ name: GigabitEthernet0/0/0/2
+ state: absent
+
+- name: make interface up
+ cisco.iosxr.iosxr_interface:
+ name: GigabitEthernet0/0/0/2
+ enabled: true
+
+- name: make interface down
+ cisco.iosxr.iosxr_interface:
+ name: GigabitEthernet0/0/0/2
+ enabled: false
+
+- name: Create interface using aggregate
+ cisco.iosxr.iosxr_interface:
+ aggregate:
+ - name: GigabitEthernet0/0/0/3
+ - name: GigabitEthernet0/0/0/2
+ speed: 100
+ duplex: full
+ mtu: 512
+ state: present
+
+- name: Create interface using aggregate along with additional params in aggregate
+ cisco.iosxr.iosxr_interface:
+ aggregate:
+ - {name: GigabitEthernet0/0/0/3, description: test-interface 3}
+ - {name: GigabitEthernet0/0/0/2, description: test-interface 2}
+ speed: 100
+ duplex: full
+ mtu: 512
+ state: present
+
+- name: Delete interface using aggregate
+ cisco.iosxr.iosxr_interface:
+ aggregate:
+ - name: GigabitEthernet0/0/0/3
+ - name: GigabitEthernet0/0/0/2
+ state: absent
+
+- name: Check intent arguments
+ cisco.iosxr.iosxr_interface:
+ name: GigabitEthernet0/0/0/5
+ state: up
+ delay: 20
+
+- name: Config + intent
+ cisco.iosxr.iosxr_interface:
+ name: GigabitEthernet0/0/0/5
+ enabled: false
+ state: down
+ delay: 20
+"""
+
+RETURN = """
+commands:
+ description: The list of configuration mode commands sent to device with transport C(cli)
+ returned: always (empty list when no commands to send)
+ type: list
+ sample:
+ - interface GigabitEthernet0/0/0/2
+ - description test-interface
+ - duplex half
+ - mtu 512
+
+xml:
+ description: NetConf rpc xml sent to device with transport C(netconf)
+ returned: always (empty list when no xml rpc to send)
+ type: list
+ sample:
+ - '<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <interface-configurations xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg">
+ <interface-configuration xc:operation="merge">
+ <active>act</active>
+ <interface-name>GigabitEthernet0/0/0/0</interface-name>
+ <description>test-interface-0</description>
+ <mtus><mtu>
+ <owner>GigabitEthernet</owner>
+ <mtu>512</mtu>
+ </mtu></mtus>
+ <ethernet xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-drivers-media-eth-cfg">
+ <speed>100</speed>
+ <duplex>half</duplex>
+ </ethernet>
+ </interface-configuration>
+ </interface-configurations></config>'
+"""
+import re
+from time import sleep
+from copy import deepcopy
+import collections
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ get_config,
+ load_config,
+ build_xml,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ run_commands,
+ iosxr_argument_spec,
+ get_oper,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ is_netconf,
+ is_cliconf,
+ etree_findall,
+ etree_find,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ conditional,
+ remove_default_spec,
+)
+
+
+def validate_mtu(value):
+ if value and not 64 <= int(value) <= 65535:
+ return False, "mtu must be between 64 and 65535"
+ return True, None
+
+
+class ConfigBase(object):
+ def __init__(self, module):
+ self._module = module
+ self._result = {"changed": False, "warnings": []}
+ self._want = list()
+ self._have = list()
+
+ def validate_param_values(self, param=None):
+ for key, value in param.items():
+ # validate the param value (if validator func exists)
+ validator = globals().get("validate_%s" % key)
+ if callable(validator):
+ rc, msg = validator(value)
+ if not rc:
+ self._module.fail_json(msg=msg)
+
+ def map_params_to_obj(self):
+ aggregate = self._module.params.get("aggregate")
+ if aggregate:
+ for item in aggregate:
+ for key in item:
+ if item.get(key) is None:
+ item[key] = self._module.params[key]
+
+ self.validate_param_values(item)
+ d = item.copy()
+
+ match = re.match(r"(^[a-z]+)([0-9/]+$)", d["name"], re.I)
+ if match:
+ d["owner"] = match.groups()[0]
+
+ if d["active"] == "preconfigure":
+ d["active"] = "pre"
+ else:
+ d["active"] = "act"
+
+ self._want.append(d)
+
+ else:
+ self.validate_param_values(self._module.params)
+ params = {
+ "name": self._module.params["name"],
+ "description": self._module.params["description"],
+ "speed": self._module.params["speed"],
+ "mtu": self._module.params["mtu"],
+ "duplex": self._module.params["duplex"],
+ "state": self._module.params["state"],
+ "delay": self._module.params["delay"],
+ "tx_rate": self._module.params["tx_rate"],
+ "rx_rate": self._module.params["rx_rate"],
+ "enabled": self._module.params["enabled"],
+ "active": self._module.params["active"],
+ }
+
+ match = re.match(r"(^[a-z]+)([0-9/]+$)", params["name"], re.I)
+ if match:
+ params["owner"] = match.groups()[0]
+
+ if params["active"] == "preconfigure":
+ params["active"] = "pre"
+ else:
+ params["active"] = "act"
+
+ self._want.append(params)
+
+
+class CliConfiguration(ConfigBase):
+ def __init__(self, module):
+ super(CliConfiguration, self).__init__(module)
+
+ def parse_shutdown(self, intf_config):
+ for cfg in intf_config:
+ match = re.search(r"%s" % "shutdown", cfg, re.M)
+ if match:
+ return True
+ return False
+
+ def parse_config_argument(self, intf_config, arg):
+ for cfg in intf_config:
+ match = re.search(r"%s (.+)$" % arg, cfg, re.M)
+ if match:
+ return match.group(1)
+
+ def search_obj_in_list(self, name):
+ for obj in self._have:
+ if obj["name"] == name:
+ return obj
+ return None
+
+ def map_config_to_obj(self):
+ data = get_config(self._module, config_filter="interface")
+ data_lines = data.splitlines()
+ start_indexes = [
+ i for i, e in enumerate(data_lines) if e.startswith("interface")
+ ]
+ end_indexes = [i for i, e in enumerate(data_lines) if e == "!"]
+
+ intf_configs = list()
+ for start_index, end_index in zip(start_indexes, end_indexes):
+ intf_configs.append(
+ [i.strip() for i in data_lines[start_index:end_index]]
+ )
+
+ if not intf_configs:
+ return list()
+
+ for intf_config in intf_configs:
+ name = intf_config[0].strip().split()[1]
+
+ active = "act"
+ if name == "preconfigure":
+ active = "pre"
+ name = intf_config[0].strip().split()[2]
+
+ obj = {
+ "name": name,
+ "description": self.parse_config_argument(
+ intf_config, "description"
+ ),
+ "speed": self.parse_config_argument(intf_config, "speed"),
+ "duplex": self.parse_config_argument(intf_config, "duplex"),
+ "mtu": self.parse_config_argument(intf_config, "mtu"),
+ "enabled": not bool(self.parse_shutdown(intf_config)),
+ "active": active,
+ "state": "present",
+ }
+ self._have.append(obj)
+
+ def map_obj_to_commands(self):
+ commands = list()
+
+ args = ("speed", "description", "duplex", "mtu")
+ for want_item in self._want:
+ name = want_item["name"]
+ disable = not want_item["enabled"]
+ state = want_item["state"]
+
+ obj_in_have = self.search_obj_in_list(name)
+ interface = "interface " + name
+
+ if state == "absent" and obj_in_have:
+ commands.append("no " + interface)
+
+ elif state in ("present", "up", "down"):
+ if obj_in_have:
+ for item in args:
+ candidate = want_item.get(item)
+ running = obj_in_have.get(item)
+ if candidate != running:
+ if candidate:
+ cmd = (
+ interface
+ + " "
+ + item
+ + " "
+ + str(candidate)
+ )
+ commands.append(cmd)
+
+ if disable and obj_in_have.get("enabled", False):
+ commands.append(interface + " shutdown")
+ elif not disable and not obj_in_have.get("enabled", False):
+ commands.append("no " + interface + " shutdown")
+ else:
+ for item in args:
+ value = want_item.get(item)
+ if value:
+ commands.append(
+ interface + " " + item + " " + str(value)
+ )
+ if not disable:
+ commands.append("no " + interface + " shutdown")
+ self._result["commands"] = commands
+
+ if commands:
+ commit = not self._module.check_mode
+ diff = load_config(self._module, commands, commit=commit)
+ if diff:
+ self._result["diff"] = dict(prepared=diff)
+ self._result["changed"] = True
+
+ def check_declarative_intent_params(self):
+ failed_conditions = []
+ for want_item in self._want:
+ want_state = want_item.get("state")
+ want_tx_rate = want_item.get("tx_rate")
+ want_rx_rate = want_item.get("rx_rate")
+ if (
+ want_state not in ("up", "down")
+ and not want_tx_rate
+ and not want_rx_rate
+ ):
+ continue
+
+ if self._result["changed"]:
+ sleep(want_item["delay"])
+
+ command = "show interfaces {0!s}".format(want_item["name"])
+ out = run_commands(self._module, command)[0]
+
+ if want_state in ("up", "down"):
+ match = re.search(r"%s (\w+)" % "line protocol is", out, re.M)
+ have_state = None
+ if match:
+ have_state = match.group(1)
+ if have_state.strip() == "administratively":
+ match = re.search(
+ r"%s (\w+)" % "administratively", out, re.M
+ )
+ if match:
+ have_state = match.group(1)
+
+ if have_state is None or not conditional(
+ want_state, have_state.strip()
+ ):
+ failed_conditions.append(
+ "state " + "eq({0!s})".format(want_state)
+ )
+
+ if want_tx_rate:
+ match = re.search(r"%s (\d+)" % "output rate", out, re.M)
+ have_tx_rate = None
+ if match:
+ have_tx_rate = match.group(1)
+
+ if have_tx_rate is None or not conditional(
+ want_tx_rate, have_tx_rate.strip(), cast=int
+ ):
+ failed_conditions.append("tx_rate " + want_tx_rate)
+
+ if want_rx_rate:
+ match = re.search(r"%s (\d+)" % "input rate", out, re.M)
+ have_rx_rate = None
+ if match:
+ have_rx_rate = match.group(1)
+
+ if have_rx_rate is None or not conditional(
+ want_rx_rate, have_rx_rate.strip(), cast=int
+ ):
+ failed_conditions.append("rx_rate " + want_rx_rate)
+
+ if failed_conditions:
+ msg = "One or more conditional statements have not been satisfied"
+ self._module.fail_json(
+ msg=msg, failed_conditions=failed_conditions
+ )
+
+ def run(self):
+ self.map_params_to_obj()
+ self.map_config_to_obj()
+ self.map_obj_to_commands()
+ self.check_declarative_intent_params()
+
+ return self._result
+
+
+class NCConfiguration(ConfigBase):
+ def __init__(self, module):
+ super(NCConfiguration, self).__init__(module)
+
+ self._intf_meta = collections.OrderedDict()
+ self._shut_meta = collections.OrderedDict()
+ self._data_rate_meta = collections.OrderedDict()
+ self._line_state_meta = collections.OrderedDict()
+
+ def map_obj_to_xml_rpc(self):
+ self._intf_meta.update(
+ [
+ (
+ "interface-configuration",
+ {
+ "xpath": "interface-configurations/interface-configuration",
+ "tag": True,
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:active",
+ {
+ "xpath": "interface-configurations/interface-configuration/active",
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:name",
+ {
+ "xpath": "interface-configurations/interface-configuration/interface-name"
+ },
+ ),
+ (
+ "a:description",
+ {
+ "xpath": "interface-configurations/interface-configuration/description",
+ "operation": "edit",
+ },
+ ),
+ (
+ "mtus",
+ {
+ "xpath": "interface-configurations/interface-configuration/mtus",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "mtu",
+ {
+ "xpath": "interface-configurations/interface-configuration/mtus/mtu",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:owner",
+ {
+ "xpath": "interface-configurations/interface-configuration/mtus/mtu/owner",
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:mtu",
+ {
+ "xpath": "interface-configurations/interface-configuration/mtus/mtu/mtu",
+ "operation": "edit",
+ },
+ ),
+ (
+ "CEthernet",
+ {
+ "xpath": "interface-configurations/interface-configuration/ethernet",
+ "tag": True,
+ "operation": "edit",
+ "ns": True,
+ },
+ ),
+ (
+ "a:speed",
+ {
+ "xpath": "interface-configurations/interface-configuration/ethernet/speed",
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:duplex",
+ {
+ "xpath": "interface-configurations/interface-configuration/ethernet/duplex",
+ "operation": "edit",
+ },
+ ),
+ ]
+ )
+
+ self._shut_meta.update(
+ [
+ (
+ "interface-configuration",
+ {
+ "xpath": "interface-configurations/interface-configuration",
+ "tag": True,
+ },
+ ),
+ (
+ "a:active",
+ {
+ "xpath": "interface-configurations/interface-configuration/active",
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:name",
+ {
+ "xpath": "interface-configurations/interface-configuration/interface-name"
+ },
+ ),
+ (
+ "shutdown",
+ {
+ "xpath": "interface-configurations/interface-configuration/shutdown",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ ]
+ )
+ state = self._module.params["state"]
+
+ _get_filter = build_xml(
+ "interface-configurations",
+ xmap=self._intf_meta,
+ params=self._want,
+ opcode="filter",
+ )
+
+ running = get_config(
+ self._module, source="running", config_filter=_get_filter
+ )
+ intfcfg_nodes = etree_findall(running, "interface-configuration")
+
+ intf_list = set()
+ shut_list = set()
+ for item in intfcfg_nodes:
+ intf_name = etree_find(item, "interface-name").text
+ if intf_name is not None:
+ intf_list.add(intf_name)
+
+ if etree_find(item, "shutdown") is not None:
+ shut_list.add(intf_name)
+
+ intf_params = list()
+ shut_params = list()
+ noshut_params = list()
+ for index, item in enumerate(self._want):
+ if item["name"] in intf_list:
+ intf_params.append(item)
+ if not item["enabled"]:
+ shut_params.append(item)
+ if item["name"] in shut_list and item["enabled"]:
+ noshut_params.append(item)
+
+ opcode = None
+ if state == "absent":
+ if intf_params:
+ opcode = "delete"
+ elif state in ("present", "up", "down"):
+ intf_params = self._want
+ opcode = "merge"
+
+ self._result["xml"] = []
+ _edit_filter_list = list()
+ if opcode:
+ _edit_filter_list.append(
+ build_xml(
+ "interface-configurations",
+ xmap=self._intf_meta,
+ params=intf_params,
+ opcode=opcode,
+ )
+ )
+
+ if opcode == "merge":
+ if len(shut_params):
+ _edit_filter_list.append(
+ build_xml(
+ "interface-configurations",
+ xmap=self._shut_meta,
+ params=shut_params,
+ opcode="merge",
+ )
+ )
+ if len(noshut_params):
+ _edit_filter_list.append(
+ build_xml(
+ "interface-configurations",
+ xmap=self._shut_meta,
+ params=noshut_params,
+ opcode="delete",
+ )
+ )
+ diff = None
+ if len(_edit_filter_list):
+ commit = not self._module.check_mode
+ diff = load_config(
+ self._module,
+ _edit_filter_list,
+ commit=commit,
+ running=running,
+ nc_get_filter=_get_filter,
+ )
+
+ if diff:
+ if self._module._diff:
+ self._result["diff"] = dict(prepared=diff)
+
+ self._result["xml"] = _edit_filter_list
+ self._result["changed"] = True
+
+ def check_declarative_intent_params(self):
+ failed_conditions = []
+
+ self._data_rate_meta.update(
+ [
+ (
+ "interfaces",
+ {"xpath": "infra-statistics/interfaces", "tag": True},
+ ),
+ (
+ "interface",
+ {
+ "xpath": "infra-statistics/interfaces/interface",
+ "tag": True,
+ },
+ ),
+ (
+ "a:name",
+ {
+ "xpath": "infra-statistics/interfaces/interface/interface-name"
+ },
+ ),
+ (
+ "cache",
+ {
+ "xpath": "infra-statistics/interfaces/interface/cache",
+ "tag": True,
+ },
+ ),
+ (
+ "data-rate",
+ {
+ "xpath": "infra-statistics/interfaces/interface/cache/data-rate",
+ "tag": True,
+ },
+ ),
+ (
+ "input-data-rate",
+ {
+ "xpath": "infra-statistics/interfaces/interface/cache/data-rate/input-data-rate",
+ "tag": True,
+ },
+ ),
+ (
+ "output-data-rate",
+ {
+ "xpath": "infra-statistics/interfaces/interface/cache/data-rate/output-data-rate",
+ "tag": True,
+ },
+ ),
+ ]
+ )
+
+ self._line_state_meta.update(
+ [
+ (
+ "data-nodes",
+ {"xpath": "interface-properties/data-nodes", "tag": True},
+ ),
+ (
+ "data-node",
+ {
+ "xpath": "interface-properties/data-nodes/data-node",
+ "tag": True,
+ },
+ ),
+ (
+ "system-view",
+ {
+ "xpath": "interface-properties/data-nodes/data-node/system-view",
+ "tag": True,
+ },
+ ),
+ (
+ "interfaces",
+ {
+ "xpath": "interface-properties/data-nodes/data-node/system-view/interfaces",
+ "tag": True,
+ },
+ ),
+ (
+ "interface",
+ {
+ "xpath": "interface-properties/data-nodes/data-node/system-view/interfaces/interface",
+ "tag": True,
+ },
+ ),
+ (
+ "a:name",
+ {
+ "xpath": "interface-properties/data-nodes/data-node/system-view/interfaces/interface/interface-name"
+ },
+ ),
+ (
+ "line-state",
+ {
+ "xpath": "interface-properties/data-nodes/data-node/system-view/interfaces/interface/line-state",
+ "tag": True,
+ },
+ ),
+ ]
+ )
+
+ _rate_filter = build_xml(
+ "infra-statistics",
+ xmap=self._data_rate_meta,
+ params=self._want,
+ opcode="filter",
+ )
+ out = get_oper(self._module, filter=_rate_filter)
+ data_rate_list = etree_findall(out, "interface")
+ data_rate_map = dict()
+ for item in data_rate_list:
+ data_rate_map.update(
+ {etree_find(item, "interface-name").text: dict()}
+ )
+ data_rate_map[etree_find(item, "interface-name").text].update(
+ {
+ "input-data-rate": etree_find(
+ item, "input-data-rate"
+ ).text,
+ "output-data-rate": etree_find(
+ item, "output-data-rate"
+ ).text,
+ }
+ )
+
+ _line_state_filter = build_xml(
+ "interface-properties",
+ xmap=self._line_state_meta,
+ params=self._want,
+ opcode="filter",
+ )
+ out = get_oper(self._module, filter=_line_state_filter)
+ line_state_list = etree_findall(out, "interface")
+ line_state_map = dict()
+ for item in line_state_list:
+ line_state_map.update(
+ {
+ etree_find(item, "interface-name")
+ .text: etree_find(item, "line-state")
+ .text
+ }
+ )
+
+ for want_item in self._want:
+ want_state = want_item.get("state")
+ want_tx_rate = want_item.get("tx_rate")
+ want_rx_rate = want_item.get("rx_rate")
+ if (
+ want_state not in ("up", "down")
+ and not want_tx_rate
+ and not want_rx_rate
+ ):
+ continue
+
+ if self._result["changed"]:
+ sleep(want_item["delay"])
+
+ if want_state in ("up", "down"):
+ if want_state not in line_state_map[want_item["name"]]:
+ failed_conditions.append(
+ "state " + "eq({0!s})".format(want_state)
+ )
+
+ if want_tx_rate:
+ if (
+ want_tx_rate
+ != data_rate_map[want_item["name"]]["output-data-rate"]
+ ):
+ failed_conditions.append("tx_rate " + want_tx_rate)
+
+ if want_rx_rate:
+ if (
+ want_rx_rate
+ != data_rate_map[want_item["name"]]["input-data-rate"]
+ ):
+ failed_conditions.append("rx_rate " + want_rx_rate)
+
+ if failed_conditions:
+ msg = "One or more conditional statements have not been satisfied"
+ self._module.fail_json(
+ msg=msg, failed_conditions=failed_conditions
+ )
+
+ def run(self):
+ self.map_params_to_obj()
+ self.map_obj_to_xml_rpc()
+ self.check_declarative_intent_params()
+ return self._result
+
+
+def main():
+ """ main entry point for module execution
+ """
+ element_spec = dict(
+ name=dict(type="str"),
+ description=dict(type="str"),
+ speed=dict(choices=["10", "100", "1000"]),
+ mtu=dict(),
+ duplex=dict(choices=["full", "half"]),
+ enabled=dict(default=True, type="bool"),
+ active=dict(
+ type="str", choices=["active", "preconfigure"], default="active"
+ ),
+ tx_rate=dict(),
+ rx_rate=dict(),
+ 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(iosxr_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,
+ )
+
+ config_object = None
+ if is_cliconf(module):
+ # Commenting the below cliconf deprecation support call for Ansible 2.9 as it'll be continued to be supported
+ # module.deprecate("cli support for 'iosxr_interface' is deprecated. Use transport netconf instead",
+ # version='2.9')
+ config_object = CliConfiguration(module)
+ elif is_netconf(module):
+ if module.params["active"] == "preconfigure":
+ module.fail_json(
+ msg="Physical interface pre-configuration is not supported with transport 'netconf'"
+ )
+ config_object = NCConfiguration(module)
+
+ result = {}
+ if config_object:
+ result = config_object.run()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_interfaces.py
new file mode 100644
index 00000000..8a607f65
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_interfaces.py
@@ -0,0 +1,558 @@
+#!/usr/bin/python
+#
+# 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/>.
+#
+
+"""
+The module file for iosxr_interfaces
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+DOCUMENTATION = """
+module: iosxr_interfaces
+short_description: Interfaces resource module
+description: This module manages the interface attributes on Cisco IOS-XR network
+ devices.
+version_added: 1.0.0
+author:
+- Sumit Jaiswal (@justjais)
+- Rohit Thakur (@rohitthakur2590)
+notes:
+- Tested against Cisco IOS-XRv Version 6.1.3 on VIRL.
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+options:
+ config:
+ description: A dictionary of interface options
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Full name of the interface to configure in C(type + path) format. e.g. C(GigabitEthernet0/0/0/0)
+ type: str
+ required: true
+ description:
+ description:
+ - Interface description.
+ type: str
+ enabled:
+ 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.
+ type: bool
+ speed:
+ description:
+ - Configure the speed for an interface. Default is auto-negotiation when not
+ configured.
+ type: int
+ mtu:
+ description:
+ - Sets the MTU value for the interface. Applicable for Ethernet interfaces
+ only.
+ - Refer to vendor documentation for valid values.
+ type: int
+ duplex:
+ description:
+ - Configures the interface duplex mode. Default is auto-negotiation when not
+ configured.
+ type: str
+ choices:
+ - full
+ - half
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config interface).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ choices:
+ - merged
+ - parsed
+ - deleted
+ - replaced
+ - rendered
+ - gathered
+ - overridden
+ default: merged
+ description:
+ - The state of the configuration after module completion
+ type: str
+"""
+
+EXAMPLES = """
+# Using merged
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# vrf custB
+# ipv4 address 178.18.169.23 255.255.255.0
+# dot1q native vlan 30
+# !
+# interface GigabitEthernet0/0/0/3
+# description Replaced by Ansible Team
+# mtu 2000
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# dot1q native vlan 1021
+# !
+- name: Configure Ethernet interfaces
+ cisco.iosxr.iosxr_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/2
+ description: Configured by Ansible
+ enabled: true
+ - name: GigabitEthernet0/0/0/3
+ description: Configured by Ansible Network
+ enabled: false
+ duplex: full
+ state: merged
+# After state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# description Configured and Merged by Ansible Network
+# vrf custB
+# ipv4 address 178.18.169.23 255.255.255.0
+# dot1q native vlan 30
+# !
+# interface GigabitEthernet0/0/0/3
+# description Configured and Merged by Ansible Network
+# mtu 2600
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex full
+# shutdown
+# dot1q native vlan 1021
+# !
+# Using replaced
+# Before state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# description Configured by Ansible
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# description Test
+# vrf custB
+# ipv4 address 178.18.169.23 255.255.255.0
+# dot1q native vlan 30
+# !
+# interface GigabitEthernet0/0/0/3
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# dot1q native vlan 1021
+# !
+- name: Configure following interfaces and replace their existing config
+ cisco.iosxr.iosxr_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/2
+ description: Configured by Ansible
+ enabled: true
+ mtu: 2000
+ - name: GigabitEthernet0/0/0/3
+ description: Configured by Ansible Network
+ enabled: false
+ duplex: auto
+ state: replaced
+# After state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# description Configured by Ansible
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# description Configured and Replaced by Ansible
+# mtu 2000
+# vrf custB
+# ipv4 address 178.18.169.23 255.255.255.0
+# dot1q native vlan 30
+# !
+# interface GigabitEthernet0/0/0/3
+# description Configured and Replaced by Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# dot1q native vlan 1021
+# !
+# Using overridden
+# Before state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# description Configured by Ansible
+# vrf custB
+# ipv4 address 178.18.169.23 255.255.255.0
+# dot1q native vlan 30
+# !
+# interface GigabitEthernet0/0/0/3
+# description Configured by Ansible
+# mtu 2600
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex full
+# shutdown
+# dot1q native vlan 1021
+# !
+- name: Override interfaces
+ cisco.iosxr.iosxr_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/2
+ description: Configured by Ansible
+ enabled: true
+ duplex: auto
+ - name: GigabitEthernet0/0/0/3
+ description: Configured by Ansible Network
+ enabled: false
+ speed: 1000
+ state: overridden
+# After state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# description Configured and Overridden by Ansible Network
+# vrf custB
+# ipv4 address 178.18.169.23 255.255.255.0
+# speed 1000
+# dot1q native vlan 30
+# !
+# interface GigabitEthernet0/0/0/3
+# description Configured and Overridden by Ansible Network
+# mtu 2000
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex full
+# shutdown
+# dot1q native vlan 1021
+# !
+# Using deleted
+# Before state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# description Configured and Overridden by Ansible Network
+# vrf custB
+# ipv4 address 178.18.169.23 255.255.255.0
+# speed 1000
+# dot1q native vlan 30
+# !
+# interface GigabitEthernet0/0/0/3
+# description Configured and Overridden by Ansible Network
+# mtu 2000
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex full
+# shutdown
+# dot1q native vlan 1021
+# !
+- name: Delete IOSXR interfaces as in given arguments
+ cisco.iosxr.iosxr_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/2
+ - name: GigabitEthernet0/0/0/3
+ state: deleted
+# After state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# vrf custB
+# ipv4 address 178.18.169.23 255.255.255.0
+# dot1q native vlan 30
+# !
+# interface GigabitEthernet0/0/0/3
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# dot1q native vlan 1021
+# !
+# Using parsed
+# parsed.cfg
+# ------------
+#
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 110
+# ipv4 address 172.31.1.1 255.255.255.0
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# !
+# - name: Convert ACL interfaces config to argspec without connecting to the appliance
+# cisco.iosxr.iosxr_interfaces:
+# running_config: "{{ lookup('file', './parsed.cfg') }}"
+# state: parsed
+# Task Output (redacted)
+# -----------------------
+# "parsed": [
+# {
+# "name": "MgmtEth0/RP0/CPU0/0"
+# },
+# {
+# "access_groups": [
+# {
+# "acls": [
+# {
+# "direction": "in",
+# "name": "acl_1"
+# },
+# {
+# "direction": "out",
+# "name": "acl_2"
+# }
+# ],
+# "afi": "ipv4"
+# },
+# {
+# "acls": [
+# {
+# "direction": "in",
+# "name": "acl6_1"
+# },
+# {
+# "direction": "out",
+# "name": "acl6_2"
+# }
+# ],
+# "afi": "ipv6"
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0"
+# },
+# {
+# "access_groups": [
+# {
+# "acls": [
+# {
+# "direction": "out",
+# "name": "acl_1"
+# }
+# ],
+# "afi": "ipv4"
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/1"
+# }
+# ]
+# }
+# Using rendered
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/0
+ description: Configured and Merged by Ansible-Network
+ mtu: 110
+ enabled: true
+ duplex: half
+ - name: GigabitEthernet0/0/0/1
+ description: Configured and Merged by Ansible-Network
+ mtu: 2800
+ enabled: false
+ speed: 100
+ duplex: full
+ state: rendered
+# Task Output (redacted)
+# -----------------------
+# "rendered": [
+# "interface GigabitEthernet0/0/0/0",
+# "description Configured and Merged by Ansible-Network",
+# "mtu 110",
+# "duplex half",
+# "no shutdown",
+# "interface GigabitEthernet0/0/0/1",
+# "description Configured and Merged by Ansible-Network",
+# "mtu 2800",
+# "speed 100",
+# "duplex full",
+# "shutdown"
+# ]
+# Using gathered
+# Before state:
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config interface
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 110
+# ipv4 address 172.31.1.1 255.255.255.0
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# !
+- name: Gather IOSXR interfaces as in given arguments
+ cisco.iosxr.iosxr_interfaces:
+ config:
+ state: gathered
+# Task Output (redacted)
+# -----------------------
+#
+# "gathered": [
+# {
+# "description": "test for ansible",
+# "enabled": false,
+# "name": "Loopback888"
+# },
+# {
+# "description": "Configured and Merged by Ansible-Network",
+# "duplex": "half",
+# "enabled": true,
+# "mtu": 110,
+# "name": "GigabitEthernet0/0/0/0"
+# },
+# {
+# "enabled": false,
+# "name": "GigabitEthernet0/0/0/3"
+# },
+# {
+# "enabled": false,
+# "name": "GigabitEthernet0/0/0/4"
+# }
+# ]
+# After state:
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config interface
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 110
+# ipv4 address 172.31.1.1 255.255.255.0
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# !
+"""
+
+RETURN = """
+before:
+ description: The configuration as structured data prior to module invocation.
+ returned: always
+ type: list
+ sample: The configuration returned will always be in the same format of the parameters above.
+after:
+ description: The configuration as structured data after module completion.
+ returned: when changed
+ type: list
+ sample: The configuration returned will always be in the same format of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device
+ returned: always
+ type: list
+ sample: ['interface GigabitEthernet0/0/0/2', 'description: Configured by Ansible', 'shutdown']
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.interfaces.interfaces import (
+ InterfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.interfaces.interfaces import (
+ Interfaces,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=InterfacesArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = Interfaces(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_l2_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_l2_interfaces.py
new file mode 100644
index 00000000..c92104d9
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_l2_interfaces.py
@@ -0,0 +1,687 @@
+#!/usr/bin/python
+#
+# 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
+
+GENERATOR_VERSION = "1.0"
+
+
+DOCUMENTATION = """
+module: iosxr_l2_interfaces
+short_description: L2 interfaces resource module
+description: This module manages the Layer-2 interface attributes on Cisco IOS-XR
+ devices.
+version_added: 1.0.0
+author:
+- Sumit Jaiswal (@justjais)
+- Rohit Thakur (@rohitthakur2590)
+notes:
+- Tested against Cisco IOS-XRv Version 6.1.3 on VIRL.
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+options:
+ config:
+ description: A dictionary of Layer-2 interface options
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Full name of the interface/sub-interface excluding any logical unit number,
+ e.g. GigabitEthernet0/0/0/1 or GigabitEthernet0/0/0/1.100.
+ type: str
+ required: true
+ native_vlan:
+ description:
+ - Configure a native VLAN ID for the trunk
+ type: int
+ l2transport:
+ description:
+ - Switchport mode access command to configure the interface as a layer 2 access
+ type: bool
+ l2protocol:
+ description:
+ - Configures Layer 2 protocol tunneling and protocol data unit (PDU) filtering
+ on an interface.
+ type: list
+ elements: dict
+ suboptions:
+ cdp:
+ description:
+ - Cisco Discovery Protocol (CDP) tunneling and data unit parameters.
+ choices:
+ - drop
+ - forward
+ - tunnel
+ type: str
+ pvst:
+ description:
+ - Configures the per-VLAN Spanning Tree Protocol (PVST) tunneling and
+ data unit parameters.
+ choices:
+ - drop
+ - forward
+ - tunnel
+ type: str
+ stp:
+ description:
+ - Spanning Tree Protocol (STP) tunneling and data unit parameters.
+ choices:
+ - drop
+ - forward
+ - tunnel
+ type: str
+ vtp:
+ description:
+ - VLAN Trunk Protocol (VTP) tunneling and data unit parameters.
+ choices:
+ - drop
+ - forward
+ - tunnel
+ type: str
+ q_vlan:
+ description:
+ - 802.1Q VLAN configuration. Note that it can accept either 2 VLAN IDs when
+ configuring Q-in-Q VLAN, or it will accept 1 VLAN ID and 'any' as input
+ list when configuring Q-in-any vlan as input. Note, that this option is
+ valid only with respect to Sub-Interface and is not valid when configuring
+ for Interface.
+ type: list
+ elements: int
+ propagate:
+ description:
+ - Propagate Layer 2 transport events. Note that it will work only when the
+ I(l2tranport) option is set to TRUE
+ type: bool
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config interface).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - rendered
+ - gathered
+ - parsed
+ default: merged
+ description:
+ - The state of the configuration after module completion
+ type: str
+"""
+
+EXAMPLES = """
+# Using merged
+#
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# !
+
+- name: Merge provided configuration with device configuration
+ cisco.iosxr.iosxr_l2_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/3
+ native_vlan: 20
+ - name: GigabitEthernet0/0/0/4
+ native_vlan: 40
+ l2transport: true
+ l2protocol:
+ - stp: tunnel
+ - name: GigabitEthernet0/0/0/3.900
+ l2transport: true
+ q_vlan:
+ - 20
+ - 40
+ state: merged
+
+# After state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# dot1q native vlan 20
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# dot1q native vlan 10
+# l2transport
+# l2protocol stp tunnel
+# !
+# !
+# interface GigabitEthernet0/0/0/3.900 l2transport
+# dot1q vlan 20 40
+# !
+
+# Using replaced
+#
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# dot1q native vlan 20
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# dot1q native vlan 10
+# l2transport
+# l2protocol stp tunnel
+# !
+# !
+# interface GigabitEthernet0/0/0/3.900 l2transport
+# dot1q vlan 20 40
+# !
+
+- name: Replaces device configuration of listed interfaces with provided configuration
+ cisco.iosxr.iosxr_l2_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/4
+ native_vlan: 40
+ l2transport: true
+ l2protocol:
+ - stp: forward
+ - name: GigabitEthernet0/0/0/3.900
+ q_vlan:
+ - 20
+ - any
+ state: replaced
+
+# After state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# dot1q native vlan 20
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# dot1q native vlan 40
+# l2transport
+# l2protocol stp forward
+# !
+# !
+# interface GigabitEthernet0/0/0/3.900 l2transport
+# dot1q vlan 20 any
+# !
+
+# Using overridden
+#
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# dot1q native vlan 20
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# dot1q native vlan 10
+# l2transport
+# l2protocol stp tunnel
+# !
+# !
+# interface GigabitEthernet0/0/0/3.900 l2transport
+# dot1q vlan 20 40
+# !
+
+- name: Override device configuration of all interfaces with provided configuration
+ cisco.iosxr.iosxr_l2_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/4
+ native_vlan: 40
+ l2transport: true
+ l2protocol:
+ - stp: forward
+ - name: GigabitEthernet0/0/0/3.900
+ q_vlan:
+ - 20
+ - any
+ state: overridden
+
+# After state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# dot1q native vlan 40
+# l2transport
+# l2protocol stp forward
+# !
+# !
+# interface GigabitEthernet0/0/0/3.900
+# dot1q vlan 20 any
+# !
+
+# Using deleted
+#
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# dot1q native vlan 20
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# dot1q native vlan 10
+# l2transport
+# l2protocol stp tunnel
+# !
+# !
+#
+
+- name: "Delete L2 attributes of given interfaces (Note: This won't delete the interface itself)"
+ cisco.iosxr.iosxr_l2_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/4
+ state: deleted
+
+# After state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# dot1q native vlan 20
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# !
+
+# Using Deleted without any config passed
+# "(NOTE: This will delete all of configured resource module attributes from each configured interface)"
+#
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# dot1q native vlan 20
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# dot1q native vlan 10
+# l2transport
+# l2protocol stp tunnel
+# !
+# !
+
+- name: "Delete L2 attributes of all interfaces (Note: This won't delete the interface itself)"
+ cisco.iosxr.iosxr_l2_interfaces:
+ state: deleted
+
+# After state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# !
+
+
+# Using parsed
+# parsed.cfg
+# ------------
+#
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 110
+# ipv4 address 172.31.1.1 255.255.255.0
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/1
+# dot1q native vlan 10
+# l2transport
+# l2protocol cdp forward
+# l2protocol pvst tunnel
+# propagate remote-status
+# !
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.900
+# encapsulation dot1q 20 second-dot1q 40
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# dot1q native vlan 40
+# !
+- name: Convert L2 interfaces config to argspec without connecting to the appliance
+ cisco.iosxr.iosxr_l2_interfaces:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+# Task Output (redacted)
+# -----------------------
+# "parsed": [
+# {
+# "name": "GigabitEthernet0/0/0/0"
+# },
+# {
+# "l2protocol": [
+# {
+# "cdp": "forward"
+# },
+# {
+# "pvst": "tunnel"
+# }
+# ],
+# "l2transport": true,
+# "name": "GigabitEthernet0/0/0/1",
+# "native_vlan": 10,
+# "propagate": true
+# },
+# {
+# "name": "GigabitEthernet0/0/0/3"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/3.900",
+# "q_vlan": [
+# 20,
+# 40
+# ]
+# },
+# {
+# "name": "GigabitEthernet0/0/0/4",
+# "native_vlan": 40
+# }
+# ]
+
+
+# Using rendered
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_l2_interfaces:
+ config:
+
+ - name: GigabitEthernet0/0/0/1
+ native_vlan: 10
+ l2transport: true
+ l2protocol:
+
+ - pvst: tunnel
+
+ - cdp: forward
+ propagate: true
+
+ - name: GigabitEthernet0/0/0/3.900
+ q_vlan:
+ - 20
+ - 40
+
+ - name: GigabitEthernet0/0/0/4
+ native_vlan: 40
+ state: rendered
+# Task Output (redacted)
+# -----------------------
+# "rendered": [
+# "interface GigabitEthernet0/0/0/1",
+# "dot1q native vlan 10",
+# "l2transport l2protocol pvst tunnel",
+# "l2transport l2protocol cdp forward",
+# "l2transport propagate remote-status",
+# "interface GigabitEthernet0/0/0/3.900",
+# "dot1q vlan 20 40",
+# "interface GigabitEthernet0/0/0/4",
+# "dot1q native vlan 40"
+# ]
+
+
+# Using gathered
+# Before state:
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config interface
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 110
+# ipv4 address 172.31.1.1 255.255.255.0
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/1
+# dot1q native vlan 10
+# l2transport
+# l2protocol cdp forward
+# l2protocol pvst tunnel
+# propagate remote-status
+# !
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.900
+# encapsulation dot1q 20 second-dot1q 40
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# dot1q native vlan 40
+# !
+- name: Gather IOSXR l2 interfaces as in given arguments
+ cisco.iosxr.iosxr_l2_interfaces:
+ config:
+ state: gathered
+# Task Output (redacted)
+# -----------------------
+#
+# "gathered": [
+# {
+# "name": "GigabitEthernet0/0/0/0"
+# },
+# {
+# "l2protocol": [
+# {
+# "cdp": "forward"
+# },
+# {
+# "pvst": "tunnel"
+# }
+# ],
+# "l2transport": true,
+# "name": "GigabitEthernet0/0/0/1",
+# "native_vlan": 10,
+# "propagate": true
+# },
+# {
+# "name": "GigabitEthernet0/0/0/3"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/3.900",
+# "q_vlan": [
+# 20,
+# 40
+# ]
+# },
+# {
+# "name": "GigabitEthernet0/0/0/4",
+# "native_vlan": 40
+# }
+# ]
+# After state:
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config interface
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 110
+# ipv4 address 172.31.1.1 255.255.255.0
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/1
+# dot1q native vlan 10
+# l2transport
+# l2protocol cdp forward
+# l2protocol pvst tunnel
+# propagate remote-status
+# !
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.900
+# encapsulation dot1q 20 second-dot1q 40
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# dot1q native vlan 40
+# !
+
+
+
+"""
+
+RETURN = """
+before:
+ description: The configuration as structured data prior to module invocation.
+ returned: always
+ type: list
+ sample: The configuration returned will always be in the same format of the parameters above.
+after:
+ description: The configuration as structured data after module completion.
+ returned: when changed
+ type: list
+ sample: The configuration returned will always be in the same format of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device
+ returned: always
+ type: list
+ sample: ['interface GigabitEthernet0/0/0/2', 'l2transport l2protocol pvst tunnel']
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.l2_interfaces.l2_interfaces import (
+ L2_InterfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.l2_interfaces.l2_interfaces import (
+ L2_Interfaces,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=L2_InterfacesArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = L2_Interfaces(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_l3_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_l3_interfaces.py
new file mode 100644
index 00000000..07af8314
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_l3_interfaces.py
@@ -0,0 +1,671 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat Inc.
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+##############################################
+# WARNING
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#
+##############################################
+
+"""
+The module file for ios_l3_interfaces
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_l3_interfaces
+short_description: L3 interfaces resource module
+description: This module provides declarative management of Layer-3 interface on Cisco
+ IOS-XR devices.
+version_added: 1.0.0
+author:
+- Sumit Jaiswal (@justjais)
+- Rohit Thakur (@rohitthakur2590)
+notes:
+- Tested against Cisco IOS-XRv Version 6.1.3 on VIRL.
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+options:
+ config:
+ description: A dictionary of Layer-3 interface options
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Full name of the interface excluding any logical unit number, i.e. GigabitEthernet0/1.
+ type: str
+ required: true
+ ipv4:
+ description:
+ - IPv4 address to be set for the Layer-3 interface mentioned in I(name) option.
+ - The address format is <ipv4 address>/<mask>, the mask is number in range
+ 0-32 eg. 192.168.0.1/24
+ type: list
+ elements: dict
+ suboptions:
+ address:
+ description:
+ - Configures the IPv4 address for Interface.
+ type: str
+ secondary:
+ description:
+ - Configures the IP address as a secondary address.
+ type: bool
+ ipv6:
+ description:
+ - IPv6 address to be set for the Layer-3 interface mentioned in I(name) option.
+ - The address format is <ipv6 address>/<mask>, the mask is number in range
+ 0-128 eg. fd5d:12c9:2201:1::1/64
+ type: list
+ elements: dict
+ suboptions:
+ address:
+ description:
+ - Configures the IPv6 address for Interface.
+ type: str
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config interface).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - parsed
+ - rendered
+ - gathered
+ default: merged
+ description:
+ - The state of the configuration after module completion
+ type: str
+"""
+
+EXAMPLES = """
+# Using merged
+
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv4 address 192.168.0.2 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# !
+# interface GigabitEthernet0/0/0/4
+# ipv6 address fd5d:12c9:2201:1::1/64
+# shutdown
+# !
+
+- name: Merge provided configuration with device configuration
+ cisco.iosxr.iosxr_l3_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/2
+ ipv4:
+ - address: 192.168.0.1/24
+ - name: GigabitEthernet0/0/0/3
+ ipv4:
+ - address: 192.168.2.1/24
+ secondary: true
+ state: merged
+
+# After state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# ipv4 address 192.168.0.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv4 address 192.168.1.0 255.255.255.0
+# ipv4 address 192.168.2.1 255.255.255.0 secondary
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# !
+# interface GigabitEthernet0/0/0/4
+# ipv6 address fd5d:12c9:2201:1::1/64
+# shutdown
+# !
+
+# Using overridden
+
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# ipv4 address 192.168.0.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv4 address 192.168.1.0 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# !
+# interface GigabitEthernet0/0/0/4
+# ipv6 address fd5d:12c9:2201:1::1/64
+# shutdown
+# !
+
+- name: Override device configuration of all interfaces with provided configuration
+ cisco.iosxr.iosxr_l3_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/3
+ ipv4:
+ - address: 192.168.0.1/24
+ - name: GigabitEthernet0/0/0/3.700
+ ipv4:
+ - address: 192.168.0.2/24
+ - address: 192.168.2.1/24
+ secondary: true
+ state: overridden
+
+# After state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv4 address 192.168.0.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# ipv4 address 192.168.0.2 255.255.255.0
+# ipv4 address 192.168.2.1 255.255.255.0 secondary
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# !
+
+# Using replaced
+
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv4 address 192.168.0.2 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# ipv4 address 192.168.0.1 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/4
+# ipv6 address fd5d:12c9:2201:1::1/64
+# shutdown
+# !
+
+- name: Replaces device configuration of listed interfaces with provided configuration
+ cisco.iosxr.iosxr_l3_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/3
+ ipv6:
+ - address: fd5d:12c9:2201:1::1/64
+ - name: GigabitEthernet0/0/0/4
+ ipv4:
+ - address: 192.168.0.2/24
+ state: replaced
+
+# After state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv6 address fd5d:12c9:2201:1::1/64
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# ipv4 address 192.168.0.1 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/4
+# ipv4 address 192.168.0.2 255.255.255.0
+# shutdown
+# !
+
+# Using deleted
+
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# ipv4 address 192.168.2.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# ipv4 address 192.168.3.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv4 address 192.168.0.2 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# ipv4 address 192.168.0.1 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/4
+# ipv6 address fd5d:12c9:2201:1::1/64
+# shutdown
+# !
+
+- name: "Delete L3 attributes of given interfaces (Note: This won't delete the interface itself)"
+ cisco.iosxr.iosxr_l3_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/3
+ - name: GigabitEthernet0/0/0/4
+ - name: GigabitEthernet0/0/0/3.700
+ state: deleted
+
+# After state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# ipv4 address 192.168.2.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# ipv4 address 192.168.3.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# !
+
+# Using Deleted without any config passed
+# "(NOTE: This will delete all of configured resource module attributes from each configured interface)"
+
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# ipv4 address 192.168.2.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# ipv4 address 192.168.3.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv4 address 192.168.0.2 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# ipv4 address 192.168.0.1 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/4
+# ipv6 address fd5d:12c9:2201:1::1/64
+# shutdown
+# !
+
+
+- name: "Delete L3 attributes of all interfaces (Note: This won't delete the interface itself)"
+ cisco.iosxr.iosxr_l3_interfaces:
+ state: deleted
+
+# After state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# !
+
+
+# Using parsed
+# parsed.cfg
+# ------------
+#
+# nterface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 66
+# ipv4 address 192.0.2.1 255.255.255.0
+# ipv4 address 192.0.2.2 255.255.255.0 secondary
+# ipv6 address 2001:db8:0:3::/64
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/1
+# description Configured and Merged by Ansible-Network
+# mtu 66
+# speed 100
+# duplex full
+# dot1q native vlan 10
+# l2transport
+# l2protocol cdp forward
+# l2protocol pvst tunnel
+# propagate remote-status
+# !
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv4 address 192.0.22.1 255.255.255.0
+# ipv4 address 192.0.23.1 255.255.255.0
+# !
+# - name: Convert L3 interfaces config to argspec without connecting to the appliance
+# cisco.iosxr.iosxr_l3_interfaces:
+# running_config: "{{ lookup('file', './parsed.cfg') }}"
+# state: parsed
+# Task Output (redacted)
+# -----------------------
+# "parsed": [
+# {
+# "ipv4": [
+# {
+# "address": "192.0.2.1 255.255.255.0"
+# },
+# {
+# "address": "192.0.2.2 255.255.255.0",
+# "secondary": true
+# }
+# ],
+# "ipv6": [
+# {
+# "address": "2001:db8:0:3::/64"
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/1"
+# },
+# {
+# "ipv4": [
+# {
+# "address": "192.0.22.1 255.255.255.0"
+# },
+# {
+# "address": "192.0.23.1 255.255.255.0"
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/3"
+# }
+# ]
+
+
+# Using rendered
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_l3_interfaces:
+ config:
+
+ - name: GigabitEthernet0/0/0/0
+ ipv4:
+
+ - address: 198.51.100.1/24
+
+ - name: GigabitEthernet0/0/0/1
+ ipv6:
+
+ - address: 2001:db8:0:3::/64
+ ipv4:
+
+ - address: 192.0.2.1/24
+
+ - address: 192.0.2.2/24
+ secondary: true
+ state: rendered
+# Task Output (redacted)
+# -----------------------
+# "rendered": [
+# "interface GigabitEthernet0/0/0/0",
+# "ipv4 address 198.51.100.1 255.255.255.0",
+# "interface GigabitEthernet0/0/0/1",
+# "ipv4 address 192.0.2.2 255.255.255.0 secondary",
+# "ipv4 address 192.0.2.1 255.255.255.0",
+# "ipv6 address 2001:db8:0:3::/64"
+# ]
+# Using gathered
+# Before state:
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config interface
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 66
+# ipv4 address 192.0.2.1 255.255.255.0
+# ipv4 address 192.0.2.2 255.255.255.0 secondary
+# ipv6 address 2001:db8:0:3::/64
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/1
+# description Configured and Merged by Ansible-Network
+# mtu 66
+# speed 100
+# duplex full
+# dot1q native vlan 10
+# l2transport
+# l2protocol cdp forward
+# l2protocol pvst tunnel
+# propagate remote-status
+# !
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# dot1q native vlan 40
+# !
+- name: Gather IOSXR l3 interfaces as in given arguments
+ cisco.iosxr.iosxr_l3_interfaces:
+ config:
+ state: gathered
+# Task Output (redacted)
+# -----------------------
+#
+# "gathered": [
+# {
+# "name": "Loopback888"
+# },
+# {
+# "ipv4": [
+# {
+# "address": "192.0.2.1 255.255.255.0"
+# },
+# {
+# "address": "192.0.2.2 255.255.255.0",
+# "secondary": true
+# }
+# ],
+# "ipv6": [
+# {
+# "address": "2001:db8:0:3::/64"
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/1"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/3"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/4"
+# }
+# ]
+# After state:
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config interface
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 66
+# ipv4 address 192.0.2.1 255.255.255.0
+# ipv4 address 192.0.2.2 255.255.255.0 secondary
+# ipv6 address 2001:db8:0:3::/64
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/1
+# description Configured and Merged by Ansible-Network
+# mtu 66
+# speed 100
+# duplex full
+# dot1q native vlan 10
+# l2transport
+# l2protocol cdp forward
+# l2protocol pvst tunnel
+# propagate remote-status
+# !
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# dot1q native vlan 40
+# !
+
+
+"""
+
+RETURN = """
+before:
+ description: The configuration as structured data prior to module invocation.
+ returned: always
+ type: list
+ sample: The configuration returned will always be in the same format of the parameters above.
+after:
+ description: The configuration as structured data after module completion.
+ returned: when changed
+ type: list
+ sample: The configuration returned will always be in the same format of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device
+ returned: always
+ type: list
+ sample: ['interface GigabitEthernet0/0/0/1', 'ipv4 address 192.168.0.1 255.255.255.0']
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.l3_interfaces.l3_interfaces import (
+ L3_InterfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.l3_interfaces.l3_interfaces import (
+ L3_Interfaces,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=L3_InterfacesArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = L3_Interfaces(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lacp.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lacp.py
new file mode 100644
index 00000000..a005f90a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lacp.py
@@ -0,0 +1,392 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_lacp
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_lacp
+short_description: LACP resource module
+description:
+- This module manages Global Link Aggregation Control Protocol (LACP) on IOS-XR devices.
+version_added: 1.0.0
+author:
+- Nilashish Chakraborty (@nilashishc)
+- Rohit Thakur (@rohitthakur2590)
+notes:
+- Tested against IOS-XR 6.1.3.
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+options:
+ config:
+ description: The provided configurations.
+ type: dict
+ suboptions:
+ system:
+ description: This option sets the default system parameters for LACP bundles.
+ type: dict
+ suboptions:
+ priority:
+ description:
+ - The system priority to use in LACP negotiations.
+ - Lower value is higher priority.
+ - Refer to vendor documentation for valid values.
+ type: int
+ mac:
+ type: dict
+ description:
+ - The system MAC related configuration for LACP.
+ suboptions:
+ address:
+ description:
+ - The system ID to use in LACP negotiations.
+ type: str
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config lacp).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state of the configuration after module completion.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - deleted
+ - parsed
+ - rendered
+ - gathered
+ default: merged
+"""
+EXAMPLES = """
+# Using merged
+#
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:iosxr01#show running-config lacp
+# Tue Jul 16 17:46:08.147 UTC
+# % No such configuration item(s)
+#
+#
+
+- name: Merge provided configuration with device configuration
+ cisco.iosxr.iosxr_lacp:
+ config:
+ system:
+ priority: 10
+ mac:
+ address: 00c1.4c00.bd15
+ state: merged
+
+#
+#
+# -----------------------
+# Module Execution Result
+# -----------------------
+#
+# "before": {}
+#
+#
+# "commands": [
+# "lacp system priority 10",
+# "lacp system mac 00c1.4c00.bd15"
+# ]
+#
+#
+# "after": {
+# "system": {
+# "mac": {
+# "address": "00c1.4c00.bd15"
+# },
+# "priority": 10
+# }
+# }
+#
+# -----------
+# After state
+# -----------
+#
+#
+# RP/0/0/CPU0:iosxr01#sh run lacp
+# Tue Jul 16 17:51:29.365 UTC
+# lacp system mac 00c1.4c00.bd15
+# lacp system priority 10
+#
+#
+
+# Using replaced
+#
+#
+# -------------
+# Before state
+# -------------
+#
+#
+# RP/0/0/CPU0:iosxr01#sh run lacp
+# Tue Jul 16 17:53:59.904 UTC
+# lacp system mac 00c1.4c00.bd15
+# lacp system priority 10
+#
+
+- name: Replace device global lacp configuration with the given configuration
+ cisco.iosxr.iosxr_lacp:
+ config:
+ system:
+ priority: 11
+ state: replaced
+#
+#
+# -----------------------
+# Module Execution Result
+# -----------------------
+# "before": {
+# "system": {
+# "mac": {
+# "address": "00c1.4c00.bd15"
+# },
+# "priority": 10
+# }
+# }
+#
+#
+# "commands": [
+# "no lacp system mac",
+# "lacp system priority 11"
+# ]
+#
+#
+# "after": {
+# "system": {
+# "priority": 11
+# }
+# }
+#
+# -----------
+# After state
+# -----------
+#
+#
+# RP/0/0/CPU0:iosxr01#sh run lacp
+# Tue Jul 16 18:02:40.379 UTC
+# lacp system priority 11
+#
+#
+
+# Using deleted
+#
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:iosxr01#sh run lacp
+# Tue Jul 16 18:37:09.727 UTC
+# lacp system mac 00c1.4c00.bd15
+# lacp system priority 11
+#
+#
+
+- name: Delete global LACP configurations from the device
+ cisco.iosxr.iosxr_lacp:
+ state: deleted
+
+#
+#
+# -----------------------
+# Module Execution Result
+# -----------------------
+# "before": {
+# "system": {
+# "mac": {
+# "address": "00c1.4c00.bd15"
+# },
+# "priority": 11
+# }
+# }
+#
+#
+# "commands": [
+# "no lacp system mac",
+# "no lacp system priority"
+# ]
+#
+#
+# "after": {}
+#
+# ------------
+# After state
+# ------------
+#
+#
+# RP/0/0/CPU0:iosxr01#sh run lacp
+# Tue Jul 16 18:39:44.116 UTC
+# % No such configuration item(s)
+#
+#
+
+
+# Using parsed
+# parsed.cfg
+# ------------
+#
+# lacp system mac 00c1.4c00.bd15
+# lacp system priority 11
+# - name: Convert LACP config to argspec without connecting to the appliance
+# cisco.iosxr.iosxr_lacp:
+# running_config: "{{ lookup('file', './parsed.cfg') }}"
+# state: parsed
+# Task Output (redacted)
+# -----------------------
+# "parsed": {
+# "system": {
+# "mac": {
+# "address": "00c1.4c00.bd15"
+# },
+# "priority": 11
+# }
+# }
+
+
+# Using rendered
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_lacp:
+ config:
+ system:
+ priority: 11
+ mac:
+ address: 00c1.4c00.bd15
+ state: rendered
+# Task Output (redacted)
+# -----------------------
+# "rendered": [
+# "lacp system priority 11",
+# "lacp system mac 00c1.4c00.bd15"
+# ]
+
+
+# Using gathered
+# Before state:
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config lacp
+# lacp system mac 00c1.4c00.bd15
+# lacp system priority 11
+- name: Gather IOSXR LACP configuration
+ cisco.iosxr.iosxr_lacp:
+ config:
+ state: gathered
+# Task Output (redacted)
+# -----------------------
+#
+# "gathered": {
+# "system": {
+# "mac": {
+# "address": "00c1.4c00.bd15"
+# },
+# "priority": 11
+# }
+# }
+# After state:
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config lacp
+# lacp system mac 00c1.4c00.bd15
+# lacp system priority
+
+
+"""
+RETURN = """
+before:
+ description: The configuration as structured data prior to module invocation.
+ returned: always
+ type: dict
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The configuration as structured data after module completion.
+ returned: when changed
+ type: dict
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample: ['lacp system priority 10', 'lacp system mac 00c1.4c00.bd15']
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lacp.lacp import (
+ LacpArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.lacp.lacp import (
+ Lacp,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=LacpArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = Lacp(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lacp_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lacp_interfaces.py
new file mode 100644
index 00000000..dc156891
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lacp_interfaces.py
@@ -0,0 +1,652 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_lacp_interfaces
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_lacp_interfaces
+short_description: LACP interfaces resource module
+description:
+- This module manages Link Aggregation Control Protocol (LACP) attributes of interfaces
+ on IOS-XR devices.
+version_added: 1.0.0
+notes:
+- Tested against IOS-XR 6.1.3.
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+author: Nilashish Chakraborty (@nilashishc)
+options:
+ config:
+ description: A dictionary of LACP interfaces options.
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Name/Identifier of the interface or Ether-Bundle.
+ type: str
+ churn_logging:
+ description:
+ - Specifies the parameter for logging of LACP churn events.
+ - Valid only for ether-bundles.
+ - Mode 'actor' logs actor churn events only.
+ - Mode 'partner' logs partner churn events only.
+ - Mode 'both' logs actor and partner churn events only.
+ type: str
+ choices:
+ - actor
+ - partner
+ - both
+ collector_max_delay:
+ description:
+ - Specifies the collector max delay to be signaled to the LACP partner.
+ - Valid only for ether-bundles.
+ - Refer to vendor documentation for valid values.
+ type: int
+ period:
+ description:
+ - Specifies the rate at which packets are sent or received.
+ - For ether-bundles, this specifies the period to be used by its member links.
+ - Refer to vendor documentation for valid values.
+ type: int
+ switchover_suppress_flaps:
+ description:
+ - Specifies the time for which to suppress flaps during a LACP switchover.
+ - Valid only for ether-bundles.
+ - Refer to vendor documentation for valid values.
+ type: int
+ system:
+ description:
+ - This dict object contains configurable options related to LACP system parameters
+ for ether-bundles.
+ type: dict
+ suboptions:
+ priority:
+ description:
+ - Specifies the system priority to use in LACP negotiations for the bundle.
+ - Refer to vendor documentation for valid values.
+ type: int
+ mac:
+ description:
+ - Specifies the system ID to use in LACP negotiations for the bundle,
+ encoded as a MAC address.
+ type: str
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config int).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state of the configuration after module completion.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - parsed
+ - gathered
+ - rendered
+ default: merged
+
+"""
+EXAMPLES = """
+# Using merged
+#
+#
+# ------------
+# Before state
+# ------------
+#
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh running-config interface
+# Sun Jul 21 18:01:35.079 UTC
+# interface Bundle-Ether10
+# !
+# interface Bundle-Ether11
+# !
+# interface Bundle-Ether12
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1'
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+#
+
+- name: Merge provided configuration with device configuration
+ cisco.iosxr.iosxr_lacp_interfaces:
+ config:
+ - name: Bundle-Ether10
+ churn_logging: actor
+ collector_max_delay: 100
+ switchover_suppress_flaps: 500
+
+ - name: Bundle-Ether11
+ system:
+ mac: 00c2.4c00.bd15
+
+ - name: GigabitEthernet0/0/0/1
+ period: 200
+ state: merged
+
+#
+#
+# -----------
+# After state
+# -----------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run int
+# Sun Jul 21 18:24:52.413 UTC
+# interface Bundle-Ether10
+# lacp churn logging actor
+# lacp switchover suppress-flaps 500
+# lacp collector-max-delay 100
+# !
+# interface Bundle-Ether11
+# lacp system mac 00c2.4c00.bd15
+# !
+# interface Bundle-Ether12
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# lacp period 200
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+
+
+# Using replaced
+#
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run int
+# Sun Jul 21 18:24:52.413 UTC
+# interface Bundle-Ether10
+# lacp churn logging actor
+# lacp switchover suppress-flaps 500
+# lacp collector-max-delay 100
+# !
+# interface Bundle-Ether11
+# lacp system mac 00c2.4c00.bd15
+# !
+# interface Bundle-Ether12
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# lacp period 200
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+
+- name: Replace LACP configuration of listed interfaces with provided configuration
+ cisco.iosxr.iosxr_lacp_interfaces:
+ config:
+ - name: Bundle-Ether10
+ churn_logging: partner
+
+ - name: GigabitEthernet0/0/0/2
+ period: 300
+ state: replaced
+
+#
+#
+# -----------
+# After state
+# -----------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run int
+# Sun Jul 21 18:50:21.929 UTC
+# interface Bundle-Ether10
+# lacp churn logging partner
+# !
+# interface Bundle-Ether11
+# lacp system mac 00c2.4c00.bd15
+# !
+# interface Bundle-Ether12
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# lacp period 200
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# lacp period 300
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+#
+
+
+# Using overridden
+#
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run int
+# Sun Jul 21 18:24:52.413 UTC
+# interface Bundle-Ether10
+# lacp churn logging actor
+# lacp switchover suppress-flaps 500
+# lacp collector-max-delay 100
+# !
+# interface Bundle-Ether11
+# lacp system mac 00c2.4c00.bd15
+# !
+# interface Bundle-Ether12
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# lacp period 200
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# lacp period 200
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+#
+
+- name: Override all interface LACP configuration with provided configuration
+ cisco.iosxr.iosxr_lacp_interfaces:
+ config:
+ - name: Bundle-Ether12
+ churn_logging: both
+ collector_max_delay: 100
+ switchover_suppress_flaps: 500
+
+ - name: GigabitEthernet0/0/0/1
+ period: 300
+ state: overridden
+
+#
+#
+# -----------
+# After state
+# -----------
+#
+#
+# RP/0/0/CPU0:an-iosxr(config-if)#do sh run int
+# Sun Jul 21 19:32:36.115 UTC
+# interface Bundle-Ether10
+# !
+# interface Bundle-Ether11
+# !
+# interface Bundle-Ether12
+# lacp churn logging both
+# lacp switchover suppress-flaps 500
+# lacp collector-max-delay 100
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# lacp period 300
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+
+
+# Using deleted
+#
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run int
+# Sun Jul 21 18:24:52.413 UTC
+# interface Bundle-Ether10
+# lacp churn logging actor
+# lacp switchover suppress-flaps 500
+# lacp collector-max-delay 100
+# !
+# interface Bundle-Ether11
+# lacp non-revertive
+# !
+# interface Bundle-Ether12
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# lacp period 200
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# lacp period 300
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+
+- name: Deleted LACP configurations of provided interfaces (Note - This won't delete
+ the interface itself)
+ cisco.iosxr.iosxr_lacp_interfaces:
+ config:
+ - name: Bundle-Ether10
+ - name: Bundle-Ether11
+ - name: GigabitEthernet0/0/0/1
+ - name: GigabitEthernet0/0/0/2
+ state: deleted
+
+#
+#
+# -----------
+# After state
+# -----------
+#
+#
+# Using parsed:
+
+# parsed.cfg
+# interface Bundle-Ether10
+# lacp churn logging actor
+# lacp switchover suppress-flaps 500
+# lacp collector-max-delay 100
+# !
+# interface Bundle-Ether11
+# lacp system mac 00c2.4c00.bd15
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# lacp period 200
+# !
+#
+
+- name: Convert lacp interfaces config to argspec without connecting to the appliance
+ cisco.iosxr.iosxr_lacp_interfaces:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+
+# --------------
+# Output:
+# --------------
+
+# parsed:
+# - name: Bundle-Ether10
+# churn_logging: actor
+# collector_max_delay: 100
+# switchover_suppress_flaps: 500
+#
+# - name: Bundle-Ether11
+# system:
+# mac: 00c2.4c00.bd15
+#
+# - name: GigabitEthernet0/0/0/1
+# period: 200
+#
+#
+
+# Using gathered:
+
+# Native config:
+# interface Bundle-Ether10
+# lacp churn logging actor
+# lacp switchover suppress-flaps 500
+# lacp collector-max-delay 100
+# !
+# interface Bundle-Ether11
+# lacp system mac 00c2.4c00.bd15
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# lacp period 200
+# !
+#
+
+- name: Gather IOSXR lacp interfaces configuration
+ cisco.iosxr.iosxr_lacp_interfaces:
+ config:
+ state: gathered
+
+# ----------
+# Output
+# ---------
+# gathered:
+# - name: Bundle-Ether10
+# churn_logging: actor
+# collector_max_delay: 100
+# switchover_suppress_flaps: 500
+#
+# - name: Bundle-Ether11
+# system:
+# mac: 00c2.4c00.bd15
+#
+# - name: GigabitEthernet0/0/0/1
+# period: 200
+
+# Using rendered:
+
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_lacp_interfaces:
+ config:
+ - name: Bundle-Ether10
+ churn_logging: actor
+ collector_max_delay: 100
+ switchover_suppress_flaps: 500
+
+ - name: Bundle-Ether11
+ system:
+ mac: 00c2.4c00.bd15
+
+ - name: GigabitEthernet0/0/0/1
+ period: 200
+ state: rendered
+
+# -------------
+# Output
+# -------------
+# rendered: [
+# - "interface Bundle-Ether10"
+# - " lacp churn logging actor"
+# - " lacp switchover suppress-flaps 500"
+# - " lacp collector-max-delay 100"
+# - "interface Bundle-Ether11"
+# - " lacp system mac 00c2.4c00.bd15"
+# - "interface MgmtEth0/0/CPU0/0"
+# - " ipv4 address 192.0.2.11 255.255.255.0"
+# - "interface GigabitEthernet0/0/0/1"
+# - " lacp period 200"
+#
+
+
+"""
+RETURN = """
+before:
+ description: The configuration as structured data prior to module invocation.
+ returned: always
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The configuration as structured data after module completion.
+ returned: when changed
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample: ['interface Bundle-Ether10', 'lacp churn logging partner', 'lacp period 150']
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lacp_interfaces.lacp_interfaces import (
+ Lacp_interfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.lacp_interfaces.lacp_interfaces import (
+ Lacp_interfaces,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=Lacp_interfacesArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = Lacp_interfaces(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lag_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lag_interfaces.py
new file mode 100644
index 00000000..201365e8
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lag_interfaces.py
@@ -0,0 +1,853 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_lag_interfaces
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+DOCUMENTATION = """
+module: iosxr_lag_interfaces
+short_description: LAG interfaces resource module
+description:
+- This module manages the attributes of LAG/Ether-Bundle interfaces on IOS-XR devices.
+version_added: 1.0.0
+notes:
+- Tested against IOS-XR 6.1.3.
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+author: Nilashish Chakraborty (@NilashishC)
+options:
+ config:
+ description: A provided Link Aggregation Group (LAG) configuration.
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Name/Identifier of the LAG/Ether-Bundle to configure.
+ type: str
+ required: true
+ members:
+ description:
+ - List of member interfaces for the LAG/Ether-Bundle.
+ type: list
+ elements: dict
+ suboptions:
+ member:
+ description:
+ - Name of the member interface.
+ type: str
+ mode:
+ description:
+ - Specifies the mode of the operation for the member interface.
+ - Mode 'active' runs LACP in active mode.
+ - Mode 'on' does not run LACP over the port.
+ - Mode 'passive' runs LACP in passive mode over the port.
+ - Mode 'inherit' runs LACP as configured in the bundle.
+ type: str
+ choices: ["on", "active", "passive", "inherit"]
+ mode:
+ description:
+ - LAG mode.
+ - Mode 'active' runs LACP in active mode over the port.
+ - Mode 'on' does not run LACP over the port.
+ - Mode 'passive' runs LACP in passive mode over the port.
+ type: str
+ choices: ["on", "active", "passive"]
+ links:
+ description:
+ - This dict contains configurable options related to LAG/Ether-Bundle links.
+ type: dict
+ suboptions:
+ max_active:
+ description:
+ - Specifies the limit on the number of links that can be active in the LAG/Ether-Bundle.
+ - Refer to vendor documentation for valid values.
+ type: int
+ min_active:
+ description:
+ - Specifies the minimum number of active links needed to bring up the LAG/Ether-Bundle.
+ - Refer to vendor documentation for valid values.
+ type: int
+ load_balancing_hash:
+ description:
+ - Specifies the hash function used for traffic forwarded over the LAG/Ether-Bundle.
+ - Option 'dst-ip' uses the destination IP as the hash function.
+ - Option 'src-ip' uses the source IP as the hash function.
+ type: str
+ choices: ["dst-ip", "src-ip"]
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config int).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state of the configuration after module completion.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - parsed
+ - rendered
+ - gathered
+ default: merged
+
+"""
+EXAMPLES = """
+# Using merged
+#
+#
+# ------------
+# Before state
+# ------------
+#
+# RP/0/0/CPU0:iosxr01#show run int
+# Sun Jul 7 19:42:59.416 UTC
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description "GigabitEthernet - 1"
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+#
+- name: Merge provided configuration with device configuration
+ cisco.iosxr.iosxr_lag_interfaces:
+ config:
+ - name: Bundle-Ether10
+ members:
+ - member: GigabitEthernet0/0/0/1
+ mode: inherit
+ - member: GigabitEthernet0/0/0/3
+ mode: inherit
+ mode: active
+ links:
+ max_active: 5
+ min_active: 2
+ load_balancing_hash: src-ip
+
+ - name: Bundle-Ether12
+ members:
+ - member: GigabitEthernet0/0/0/2
+ mode: passive
+ - member: GigabitEthernet0/0/0/4
+ mode: passive
+ load_balancing_hash: dst-ip
+ state: merged
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/0/CPU0:iosxr01#show run int
+# Sun Jul 7 20:51:17.685 UTC
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash src-ip
+# bundle maximum-active links 5
+# bundle minimum-active links 2
+# !
+# interface Bundle-Ether12
+# bundle load-balancing hash dst-ip
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# bundle id 12 mode passive
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# bundle id 12 mode passive
+# !
+#
+
+
+# Using replaced
+#
+#
+# -------------
+# Before state
+# -------------
+#
+#
+# RP/0/0/CPU0:iosxr01#sho run int
+# Sun Jul 7 20:58:06.527 UTC
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash src-ip
+# bundle maximum-active links 5
+# bundle minimum-active links 2
+# !
+# interface Bundle-Ether12
+# bundle load-balancing hash dst-ip
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# bundle id 12 mode passive
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# bundle id 12 mode passive
+# !
+#
+#
+- name: Replace device configuration of listed Bundles with provided configurations
+ cisco.iosxr.iosxr_lag_interfaces:
+ config:
+ - name: Bundle-Ether12
+ members:
+ - name: GigabitEthernet0/0/0/2
+ mode: passive
+
+ - name: Bundle-Ether11
+ members:
+ - name: GigabitEthernet0/0/0/4
+ load_balancing_hash: src-ip
+ state: replaced
+#
+#
+# -----------
+# After state
+# -----------
+#
+#
+# RP/0/0/CPU0:iosxr01#sh run int
+# Sun Jul 7 21:22:27.397 UTC
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash src-ip
+# bundle maximum-active links 5
+# bundle minimum-active links 2
+# !
+# interface Bundle-Ether11
+# bundle load-balancing hash src-ip
+# !
+# interface Bundle-Ether12
+# lacp mode passive
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# bundle id 12 mode on
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# bundle id 11 mode on
+# !
+#
+#
+
+
+# Using overridden
+#
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:iosxr01#sh run int
+# Sun Jul 7 21:22:27.397 UTC
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash src-ip
+# bundle maximum-active links 5
+# bundle minimum-active links 2
+# !
+# interface Bundle-Ether11
+# bundle load-balancing hash src-ip
+# !
+# interface Bundle-Ether12
+# lacp mode passive
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# bundle id 12 mode on
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# bundle id 11 mode on
+# !
+#
+#
+
+- name: Overrides all device configuration with provided configuration
+ cisco.iosxr.iosxr_lag_interfaces:
+ config:
+ - name: Bundle-Ether10
+ members:
+ - member: GigabitEthernet0/0/0/1
+ mode: inherit
+ - member: GigabitEthernet0/0/0/2
+ mode: inherit
+ mode: active
+ load_balancing_hash: dst-ip
+ state: overridden
+#
+#
+# ------------
+# After state
+# ------------
+#
+#
+# RP/0/0/CPU0:iosxr01#sh run int
+# Sun Jul 7 21:43:04.802 UTC
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash dst-ip
+# !
+# interface Bundle-Ether11
+# !
+# interface Bundle-Ether12
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+#
+
+
+# Using deleted
+#
+#
+# ------------
+# Before state
+# ------------
+#
+# RP/0/0/CPU0:iosxr01#sh run int
+# Sun Jul 7 21:22:27.397 UTC
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash src-ip
+# bundle maximum-active links 5
+# bundle minimum-active links 2
+# !
+# interface Bundle-Ether11
+# bundle load-balancing hash src-ip
+# !
+# interface Bundle-Ether12
+# lacp mode passive
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# bundle id 12 mode on
+# !n
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# bundle id 11 mode on
+# !
+#
+#
+
+- name: Delete attributes of given bundles and removes member interfaces from them
+ (Note - This won't delete the bundles themselves)
+ cisco.iosxr.iosxr_lag_interfaces:
+ config:
+ - name: Bundle-Ether10
+ - name: Bundle-Ether11
+ - name: Bundle-Ether12
+ state: deleted
+
+#
+#
+# ------------
+# After state
+# ------------
+#
+# RP/0/0/CPU0:iosxr01#sh run int
+# Sun Jul 7 21:49:50.004 UTC
+# interface Bundle-Ether10
+# !
+# interface Bundle-Ether11
+# !
+# interface Bundle-Ether12
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+#
+
+# Using deleted (without config)
+#
+#
+# ------------
+# Before state
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr#sh run int
+# Sun Aug 18 19:49:51.908 UTC
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash src-ip
+# bundle maximum-active links 10
+# bundle minimum-active links 2
+# !
+# interface Bundle-Ether11
+# bundle load-balancing hash dst-ip
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/1
+# bundle id 10 mode inherit
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# bundle id 10 mode passive
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# bundle id 11 mode passive
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# bundle id 11 mode passive
+# shutdown
+# !
+#
+
+- name: Delete attributes of all bundles and removes member interfaces from them (Note
+ - This won't delete the bundles themselves)
+ cisco.iosxr.iosxr_lag_interfaces:
+ state: deleted
+
+#
+#
+# ------------
+# After state
+# ------------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run int
+# Sun Aug 18 19:54:22.389 UTC
+# interface Bundle-Ether10
+# !
+# interface Bundle-Ether11
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.69 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# !
+
+# Using parsed:
+
+# parsed.cfg
+
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash src-ip
+# bundle maximum-active links 5
+# bundle minimum-active links 2
+# !
+# interface Bundle-Ether12
+# bundle load-balancing hash dst-ip
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# bundle id 12 mode passive
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# bundle id 12 mode passive
+# !
+#
+- name: Convert lag interfaces config to argspec without connecting to the appliance
+ cisco.iosxr.iosxr_lag_interfaces:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+
+# --------------
+# Output
+# --------------
+# parsed:
+# - name: Bundle-Ether10
+# members:
+# - member: GigabitEthernet0/0/0/1
+# mode: inherit
+# - member: GigabitEthernet0/0/0/3
+# mode: inherit
+# mode: active
+# links:
+# max_active: 5
+# min_active: 2
+# load_balancing_hash: src-ip
+
+# - name: Bundle-Ether12
+# members:
+# - member: GigabitEthernet0/0/0/2
+# mode: passive
+# - member: GigabitEthernet0/0/0/4
+# mode: passive
+# load_balancing_hash: dst-ip
+
+# using gathered
+
+# Device Config:
+# -------------
+
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash src-ip
+# bundle maximum-active links 5
+# bundle minimum-active links 2
+# !
+# interface Bundle-Ether12
+# bundle load-balancing hash dst-ip
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# bundle id 12 mode passive
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# bundle id 12 mode passive
+# !
+#
+
+- name: Gather IOSXR lag interfaces configuration
+ cisco.iosxr.iosxr_lag_interfaces:
+ config:
+ state: gathered
+
+# --------------
+# Output
+# --------------
+# gathered:
+# - name: Bundle-Ether10
+# members:
+# - member: GigabitEthernet0/0/0/1
+# mode: inherit
+# - member: GigabitEthernet0/0/0/3
+# mode: inherit
+# mode: active
+# links:
+# max_active: 5
+# min_active: 2
+# load_balancing_hash: src-ip
+
+# - name: Bundle-Ether12
+# members:
+# - member: GigabitEthernet0/0/0/2
+# mode: passive
+# - member: GigabitEthernet0/0/0/4
+# mode: passive
+# load_balancing_hash: dst-ip
+
+# Using rendered:
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_lag_interfaces:
+ config:
+ - name: Bundle-Ether10
+ members:
+ - member: GigabitEthernet0/0/0/1
+ mode: inherit
+ - member: GigabitEthernet0/0/0/3
+ mode: inherit
+ mode: active
+ links:
+ max_active: 5
+ min_active: 2
+ load_balancing_hash: src-ip
+
+ - name: Bundle-Ether12
+ members:
+ - member: GigabitEthernet0/0/0/2
+ mode: passive
+ - member: GigabitEthernet0/0/0/4
+ mode: passive
+ load_balancing_hash: dst-ip
+ state: rendered
+
+# Output:
+
+# rendered:
+# [
+# - "interface Bundle-Ether10"
+# - " lacp mode active"
+# - " bundle load-balancing hash src-ip"
+# - " bundle maximum-active links 5"
+# - " bundle minimum-active links 2"
+# - "interface Bundle-Ether12"
+# - " bundle load-balancing hash dst-ip"
+# - "interface Loopback888"
+# - " description test for ansible"
+# - " shutdown"
+# - "interface MgmtEth0/0/CPU0/0"
+# - " ipv4 address 192.0.2.11 255.255.255.0"
+# - "interface GigabitEthernet0/0/0/1"
+# - " description 'GigabitEthernet - 1""
+# - " bundle id 10 mode inherit"
+# - "interface GigabitEthernet0/0/0/2"
+# - " description "GigabitEthernet - 2""
+# - " bundle id 12 mode passive"
+# - "interface GigabitEthernet0/0/0/3"
+# - " description "GigabitEthernet - 3""
+# - " bundle id 10 mode inherit"
+# - "interface GigabitEthernet0/0/0/4"
+# - " description "GigabitEthernet - 4""
+# - " bundle id 12 mode passive"
+# ]
+#
+#
+
+
+"""
+RETURN = """
+before:
+ description: The configuration as structured data prior to module invocation.
+ returned: always
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The configuration as structured data after module completion.
+ returned: when changed
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample: ['interface Bundle-Ether10', 'bundle minimum-active links 2', 'bundle load-balancing hash src-ip']
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lag_interfaces.lag_interfaces import (
+ Lag_interfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.lag_interfaces.lag_interfaces import (
+ Lag_interfaces,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=Lag_interfacesArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = Lag_interfaces(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lldp_global.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lldp_global.py
new file mode 100644
index 00000000..0aa7bb4b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lldp_global.py
@@ -0,0 +1,489 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_lldp_global
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_lldp_global
+short_description: LLDP resource module
+description:
+- This module manages Global Link Layer Discovery Protocol (LLDP) settings on IOS-XR
+ devices.
+version_added: 1.0.0
+notes:
+- Tested against IOS-XR 6.1.3.
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+author: Nilashish Chakraborty (@NilashishC)
+options:
+ config:
+ description: The provided global LLDP configuration.
+ type: dict
+ suboptions:
+ holdtime:
+ description:
+ - Specifies the holdtime (in sec) to be sent in packets.
+ type: int
+ reinit:
+ description:
+ - Specifies the delay (in sec) for LLDP initialization on any interface.
+ type: int
+ subinterfaces:
+ description:
+ - Enable or disable LLDP over sub-interfaces.
+ type: bool
+ timer:
+ description:
+ - Specifies the rate at which LLDP packets are sent (in sec).
+ type: int
+ tlv_select:
+ description:
+ - Specifies the LLDP TLVs to enable or disable.
+ type: dict
+ suboptions:
+ management_address:
+ description:
+ - Enable or disable management address TLV.
+ type: bool
+ port_description:
+ description:
+ - Enable or disable port description TLV.
+ type: bool
+ system_capabilities:
+ description:
+ - Enable or disable system capabilities TLV.
+ type: bool
+ system_description:
+ description:
+ - Enable or disable system description TLV.
+ type: bool
+ system_name:
+ description:
+ - Enable or disable system name TLV.
+ type: bool
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config lldp).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state of the configuration after module completion.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - deleted
+ - parsed
+ - gathered
+ - rendered
+ default: merged
+
+"""
+EXAMPLES = """
+# Using merged
+#
+#
+# -------------
+# Before State
+# -------------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run lldp
+# Tue Aug 6 19:27:54.933 UTC
+# % No such configuration item(s)
+#
+#
+
+- name: Merge provided LLDP configuration with the existing configuration
+ cisco.iosxr.iosxr_lldp_global:
+ config:
+ holdtime: 100
+ reinit: 2
+ timer: 3000
+ subinterfaces: true
+ tlv_select:
+ management_address: false
+ system_description: false
+ state: merged
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {}
+#
+# "commands": [
+# "lldp subinterfaces enable",
+# "lldp holdtime 100",
+# "lldp reinit 2",
+# "lldp tlv-select system-description disable",
+# "lldp tlv-select management-address disable",
+# "lldp timer 3000"
+# ]
+#
+# "after": {
+# "holdtime": 100,
+# "reinit": 2,
+# "subinterfaces": true,
+# "timer": 3000,
+# "tlv_select": {
+# "management_address": false,
+# "system_description": false
+# }
+# }
+#
+#
+# ------------
+# After state
+# ------------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run lldp
+# Tue Aug 6 21:31:10.587 UTC
+# lldp
+# timer 3000
+# reinit 2
+# subinterfaces enable
+# holdtime 100
+# tlv-select
+# management-address disable
+# system-description disable
+# !
+# !
+#
+#
+
+
+# Using replaced
+#
+#
+# -------------
+# Before State
+# -------------
+#
+# RP/0/0/CPU0:an-iosxr#sh run lldp
+# Tue Aug 6 21:31:10.587 UTC
+# lldp
+# timer 3000
+# reinit 2
+# subinterfaces enable
+# holdtime 100
+# tlv-select
+# management-address disable
+# system-description disable
+# !
+# !
+#
+#
+
+- name: Replace existing LLDP device configuration with provided configuration
+ cisco.iosxr.iosxr_lldp_global:
+ config:
+ holdtime: 100
+ tlv_select:
+ port_description: false
+ system_description: true
+ management_description: true
+ state: replaced
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {
+# "holdtime": 100,
+# "reinit": 2,
+# "subinterfaces": true,
+# "timer": 3000,
+# "tlv_select": {
+# "management_address": false,
+# "system_description": false
+# }
+# }
+#
+# "commands": [
+# "no lldp reinit 2",
+# "no lldp subinterfaces enable",
+# "no lldp timer 3000",
+# "no lldp tlv-select management-address disable",
+# "no lldp tlv-select system-description disable",
+# "lldp tlv-select port-description disable"
+# ]
+#
+# "after": {
+# "holdtime": 100,
+# "tlv_select": {
+# "port_description": false
+# }
+# }
+#
+#
+# ------------
+# After state
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr#sh run lldp
+# Tue Aug 6 21:53:08.407 UTC
+# lldp
+# holdtime 100
+# tlv-select
+# port-description disable
+# !
+# !
+#
+#
+
+
+# Using deleted
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run lldp
+# Tue Aug 6 21:31:10.587 UTC
+# lldp
+# timer 3000
+# reinit 2
+# subinterfaces enable
+# holdtime 100
+# tlv-select
+# management-address disable
+# system-description disable
+# !
+# !
+#
+#
+
+- name: Deleted existing LLDP configurations from the device
+ cisco.iosxr.iosxr_lldp_global:
+ state: deleted
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {
+# "holdtime": 100,
+# "reinit": 2,
+# "subinterfaces": true,
+# "timer": 3000,
+# "tlv_select": {
+# "management_address": false,
+# "system_description": false
+# }
+# },
+#
+# "commands": [
+# "no lldp holdtime 100",
+# "no lldp reinit 2",
+# "no lldp subinterfaces enable",
+# "no lldp timer 3000",
+# "no lldp tlv-select management-address disable",
+# "no lldp tlv-select system-description disable"
+# ]
+#
+# "after": {}
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/0/CPU0:an-iosxr#sh run lldp
+# Tue Aug 6 21:38:31.187 UTC
+# lldp
+# !
+#
+# Using parsed:
+
+# parsed.cfg
+# lldp
+# timer 3000
+# reinit 2
+# subinterfaces enable
+# holdtime 100
+# tlv-select
+# management-address disable
+# system-description disable
+# !
+# !
+
+- name: Convert lldp global config to argspec without connecting to the appliance
+ cisco.iosxr.iosxr_lldp_global:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+
+# ------------------------
+# Module Execution Result
+# ------------------------
+# parsed:
+# holdtime: 100
+# reinit: 2
+# timer: 3000
+# subinterfaces: True
+# tlv_select:
+# management_address: False
+# system_description: False
+
+# using gathered:
+
+# Device config:
+# lldp
+# timer 3000
+# reinit 2
+# subinterfaces enable
+# holdtime 100
+# tlv-select
+# management-address disable
+# system-description disable
+# !
+# !
+
+- name: Gather IOSXR lldp global configuration
+ cisco.iosxr.iosxr_lldp_global:
+ config:
+ state: gathered
+
+
+# ------------------------
+# Module Execution Result
+# ------------------------
+# gathered:
+# holdtime: 100
+# reinit: 2
+# timer: 3000
+# subinterfaces: True
+# tlv_select:
+# management_address: False
+# system_description: False
+
+# using rendered:
+
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_lldp_global:
+ config:
+ holdtime: 100
+ reinit: 2
+ timer: 3000
+ subinterfaces: true
+ tlv_select:
+ management_address: false
+ system_description: false
+ state: rendered
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "rendered": [
+# "lldp subinterfaces enable",
+# "lldp holdtime 100",
+# "lldp reinit 2",
+# "lldp tlv-select system-description disable",
+# "lldp tlv-select management-address disable",
+# "lldp timer 3000"
+# ]
+
+
+
+"""
+RETURN = """
+before:
+ description: The configuration as structured data prior to module invocation.
+ returned: always
+ type: dict
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The configuration as structured data after module completion.
+ returned: when changed
+ type: dict
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample: ['lldp subinterfaces enable', 'lldp holdtime 100', 'no lldp tlv-select management-address disable']
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lldp_global.lldp_global import (
+ Lldp_globalArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.lldp_global.lldp_global import (
+ Lldp_global,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=Lldp_globalArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = Lldp_global(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lldp_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lldp_interfaces.py
new file mode 100644
index 00000000..f730f62a
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lldp_interfaces.py
@@ -0,0 +1,724 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_lldp_interfaces
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_lldp_interfaces
+short_description: LLDP interfaces resource module
+description:
+- This module manages Link Layer Discovery Protocol (LLDP) attributes of interfaces
+ on IOS-XR devices.
+version_added: 1.0.0
+notes:
+- Tested against IOS-XR 6.1.3.
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+author: Nilashish Chakraborty (@nilashishc)
+options:
+ config:
+ description: A dictionary of LLDP interfaces options.
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Name/Identifier of the interface or Ether-Bundle.
+ type: str
+ destination:
+ description:
+ - Specifies LLDP destination configuration on the interface.
+ suboptions:
+ mac_address:
+ description:
+ - Specifies the LLDP destination mac address on the interface.
+ type: str
+ choices:
+ - ieee-nearest-bridge
+ - ieee-nearest-non-tmpr-bridge
+ type: dict
+ receive:
+ description:
+ - Enable/disable LLDP RX on an interface.
+ type: bool
+ transmit:
+ description:
+ - Enable/disable LLDP TX on an interface.
+ type: bool
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config int).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state of the configuration after module completion.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - parsed
+ - rendered
+ - gathered
+ default: merged
+
+"""
+EXAMPLES = """
+# Using merged
+#
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 12:40:23.104 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# !
+#
+#
+
+- name: Merge provided configuration with running configuration
+ cisco.iosxr.iosxr_lldp_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ destination:
+ mac_address: ieee-nearest-non-tmpr-bridge
+ transmit: false
+
+ - name: GigabitEthernet0/0/0/2
+ destination:
+ mac_address: ieee-nearest-bridge
+ receive: false
+ state: merged
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+#
+# "before": [
+# {
+# "name": "TenGigE0/0/0/0"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/1"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/2"
+# }
+# ]
+#
+# "commands": [
+# "interface GigabitEthernet0/0/0/2",
+# "lldp destination mac-address ieee-nearest-non-tmpr-bridge",
+# "lldp transmit disable",
+# "interface GigabitEthernet0/0/0/1",
+# "lldp receive disable",
+# "lldp destination mac-address ieee-nearest-bridge"
+# ]
+#
+# "after": [
+# {
+# "name": "TenGigE0/0/0/0"
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/1",
+# "receive": false
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-non-tmpr-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/2",
+# "transmit": false
+# }
+# ]
+#
+#
+# ------------
+# After state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 12:49:51.517 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# lldp
+# receive disable
+# destination mac-address
+# ieee-nearest-bridge
+# !
+# !
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# lldp
+# transmit disable
+# destination mac-address
+# ieee-nearest-non-tmpr-bridge
+# !
+# !
+# !
+#
+#
+
+
+# Using replaced
+#
+#
+# -------------
+# Before state
+# -------------
+#
+#
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 12:49:51.517 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# lldp
+# receive disable
+# destination mac-address
+# ieee-nearest-bridge
+# !
+# !
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# lldp
+# transmit disable
+# destination mac-address
+# ieee-nearest-non-tmpr-bridge
+# !
+# !
+# !
+#
+#
+
+- name: Replace existing LLDP configurations of specified interfaces with provided
+ configuration
+ cisco.iosxr.iosxr_lldp_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ destination:
+ mac_address: ieee-nearest-non-tmpr-bridge
+ state: replaced
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": [
+# {
+# "name": "TenGigE0/0/0/0"
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/1",
+# "receive": false
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-non-tmpr-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/2",
+# "transmit": false
+# }
+# ]
+#
+#
+# "commands": [
+# "interface GigabitEthernet0/0/0/1",
+# "no lldp receive disable",
+# "lldp destination mac-address ieee-nearest-non-tmpr-bridge"
+# ]
+#
+#
+# "after": [
+# {
+# "name": "TenGigE0/0/0/0"
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-non-tmpr-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/1"
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-non-tmpr-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/2",
+# "transmit": false
+# }
+# ]
+#
+#
+# ------------
+# After state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 13:02:57.062 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# lldp
+# destination mac-address
+# ieee-nearest-non-tmpr-bridge
+# !
+# !
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# lldp
+# transmit disable
+# destination mac-address
+# ieee-nearest-non-tmpr-bridge
+# !
+# !
+# !
+#
+#
+
+
+# Using overridden
+#
+#
+# -------------
+# Before state
+# -------------
+#
+#
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 13:15:40.465 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# lldp
+# receive disable
+# destination mac-address
+# ieee-nearest-bridge
+# !
+# !
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# lldp
+# transmit disable
+# destination mac-address
+# ieee-nearest-non-tmpr-bridge
+# !
+# !
+# !
+#
+#
+
+- name: Override the LLDP configurations of all the interfaces with provided configurations
+ cisco.iosxr.iosxr_lldp_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ transmit: false
+ state: overridden
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+#
+# "before": [
+# {
+# "name": "TenGigE0/0/0/0"
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/1",
+# "receive": false
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-non-tmpr-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/2",
+# "transmit": false
+# }
+# ]
+#
+# "commands": [
+# "interface GigabitEthernet0/0/0/2",
+# "no lldp destination mac-address ieee-nearest-non-tmpr-bridge",
+# "no lldp transmit disable",
+# "interface GigabitEthernet0/0/0/1",
+# "no lldp destination mac-address ieee-nearest-bridge",
+# "no lldp receive disable",
+# "lldp transmit disable"
+# ]
+#
+#
+# "after": [
+# {
+# "name": "TenGigE0/0/0/0"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/1",
+# "transmit": false
+# },
+# {
+# "name": "GigabitEthernet0/0/0/2"
+# }
+# ]
+#
+#
+# ------------
+# After state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 13:22:25.604 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# lldp
+# transmit disable
+# !
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# !
+#
+#
+
+
+# Using deleted
+#
+#
+# -------------
+# Before state
+# -------------
+#
+#
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 13:26:21.498 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# lldp
+# receive disable
+# destination mac-address
+# ieee-nearest-bridge
+# !
+# !
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# lldp
+# transmit disable
+# destination mac-address
+# ieee-nearest-non-tmpr-bridge
+# !
+# !
+# !
+#
+#
+
+- name: Delete LLDP configurations of all interfaces (Note - This won't delete the
+ interfaces themselves)
+ cisco.iosxr.iosxr_lldp_interfaces:
+ state: deleted
+
+#
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+#
+# "before": [
+# {
+# "name": "TenGigE0/0/0/0"
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/1",
+# "receive": false
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-non-tmpr-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/2",
+# "transmit": false
+# }
+# ]
+#
+#
+# "commands": [
+# "interface GigabitEthernet0/0/0/1",
+# "no lldp destination mac-address ieee-nearest-bridge",
+# "no lldp receive disable",
+# "interface GigabitEthernet0/0/0/2",
+# "no lldp destination mac-address ieee-nearest-non-tmpr-bridge",
+# "no lldp transmit disable"
+# ]
+#
+#
+# "after": [
+# {
+# "name": "TenGigE0/0/0/0"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/1"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/2"
+# }
+# ]
+#
+#
+# ------------
+# After state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 13:30:14.618 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# !
+#
+#
+# Using parsed:
+# parsed.cfg
+
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# lldp
+# receive disable
+# destination mac-address
+# ieee-nearest-bridge
+# !
+# !
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# lldp
+# transmit disable
+# destination mac-address
+# ieee-nearest-non-tmpr-bridge
+
+- name: Convert lacp interfaces config to argspec without connecting to the appliance
+ cisco.iosxr.iosxr_lldp_interfaces:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+
+# ------------------------
+# Module Execution Result
+# ------------------------
+
+# parsed: [
+# - name: GigabitEthernet0/0/0/1
+# destination:
+# mac_address: ieee-nearest-non-tmpr-bridge
+# transmit: False
+
+# - name: GigabitEthernet0/0/0/2
+# destination:
+# mac_address: ieee-nearest-bridge
+# receive: False
+# ]
+
+# Using gathered:
+# Device config:
+
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 12:49:51.517 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# lldp
+# receive disable
+# destination mac-address
+# ieee-nearest-bridge
+# !
+# !
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# lldp
+# transmit disable
+# destination mac-address
+# ieee-nearest-non-tmpr-bridge
+
+- name: Gather IOSXR lldp interfaces configuration
+ cisco.iosxr.iosxr_lldp_interfaces:
+ config:
+ state: gathered
+
+# ------------------------
+# Module Execution Result
+# ------------------------
+
+# gathered:
+# - name: GigabitEthernet0/0/0/1
+# destination:
+# mac_address: ieee-nearest-non-tmpr-bridge
+# transmit: False
+
+# - name: GigabitEthernet0/0/0/2
+# destination:
+# mac_address: ieee-nearest-bridge
+# receive: False
+
+# Using rendred:
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_lldp_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ destination:
+ mac_address: ieee-nearest-non-tmpr-bridge
+ transmit: false
+
+ - name: GigabitEthernet0/0/0/2
+ destination:
+ mac_address: ieee-nearest-bridge
+ receive: false
+ state: rendered
+
+# ------------------------
+# Module Execution Result
+# ------------------------
+
+# "rendered": [
+# "interface GigabitEthernet0/0/0/2",
+# "lldp destination mac-address ieee-nearest-non-tmpr-bridge",
+# "lldp transmit disable",
+# "interface GigabitEthernet0/0/0/1",
+# "lldp receive disable",
+# "lldp destination mac-address ieee-nearest-bridge"
+# ]
+
+"""
+RETURN = """
+before:
+ description: The configuration as structured data prior to module invocation.
+ returned: always
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The configuration as structured data after module completion.
+ returned: when changed
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample: ['interface GigabitEthernet0/0/0/1', 'lldp destination mac-address ieee-nearest-non-tmpr-bridge', 'no lldp transmit disable']
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lldp_interfaces.lldp_interfaces import (
+ Lldp_interfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.lldp_interfaces.lldp_interfaces import (
+ Lldp_interfaces,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=Lldp_interfacesArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = Lldp_interfaces(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_logging.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_logging.py
new file mode 100644
index 00000000..bb6bf2e1
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_logging.py
@@ -0,0 +1,1220 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# (c) 2017, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_logging
+author:
+- Trishna Guha (@trishnaguha)
+- Kedar Kekan (@kedarX)
+short_description: Configuration management of system logging services on network
+ devices
+description:
+- This module provides declarative management configuration of system logging (syslog)
+ on Cisco IOS XR devices.
+version_added: 1.0.0
+requirements:
+- ncclient >= 0.5.3 when using netconf
+- lxml >= 4.1.1 when using netconf
+notes:
+- This module works with connection C(network_cli) and C(netconf). See L(the IOS-XR
+ Platform Options,../network/user_guide/platform_iosxr.html).
+- Tested against IOS XRv 6.1.3
+options:
+ dest:
+ description:
+ - Destination for system logging (syslog) messages.
+ choices:
+ - host
+ - console
+ - monitor
+ - buffered
+ - file
+ type: str
+ name:
+ description:
+ - When C(dest) = I(file) name indicates file-name
+ - When C(dest) = I(host) name indicates the host-name or ip-address of syslog
+ server.
+ type: str
+ vrf:
+ description:
+ - vrf name when syslog server is configured, C(dest) = C(host)
+ type: str
+ default: default
+ size:
+ description:
+ - Size of buffer when C(dest) = C(buffered). The acceptable value is in the range
+ I(307200 to 125000000 bytes). Default 307200
+ - Size of file when C(dest) = C(file). The acceptable value is in the range I(1
+ to 2097152)KB. Default 2 GB
+ type: int
+ facility:
+ description:
+ - To configure the type of syslog facility in which system logging (syslog) messages
+ are sent to syslog servers Optional config for C(dest) = C(host)
+ default: local7
+ type: str
+ hostnameprefix:
+ description:
+ - To append a hostname prefix to system logging (syslog) messages logged to syslog
+ servers. Optional config for C(dest) = C(host)
+ type: str
+ level:
+ description:
+ - Specifies the severity level for the logging.
+ type: str
+ default: debugging
+ aliases:
+ - severity
+ choices: ["emergencies", "alerts", "critical", "errors", "warning", "notifications", "informational", "debugging"]
+ aggregate:
+ description: List of syslog logging configuration definitions.
+ type: list
+ elements: dict
+ suboptions:
+ dest:
+ description:
+ - Destination for system logging (syslog) messages.
+ choices:
+ - host
+ - console
+ - monitor
+ - buffered
+ - file
+ type: str
+ name:
+ description:
+ - When C(dest) = I(file) name indicates file-name
+ - When C(dest) = I(host) name indicates the host-name or ip-address of syslog
+ server.
+ type: str
+ vrf:
+ description:
+ - vrf name when syslog server is configured, C(dest) = C(host)
+ type: str
+ size:
+ description:
+ - Size of buffer when C(dest) = C(buffered). The acceptable value is in the range
+ I(307200 to 125000000 bytes). Default 307200
+ - Size of file when C(dest) = C(file). The acceptable value is in the range I(1
+ to 2097152)KB. Default 2 GB
+ type: int
+ facility:
+ description:
+ - To configure the type of syslog facility in which system logging (syslog) messages
+ are sent to syslog servers Optional config for C(dest) = C(host)
+ type: str
+ hostnameprefix:
+ description:
+ - To append a hostname prefix to system logging (syslog) messages logged to syslog
+ servers. Optional config for C(dest) = C(host)
+ type: str
+ level:
+ description:
+ - Specifies the severity level for the logging.
+ type: str
+ aliases:
+ - severity
+ choices: ["emergencies", "alerts", "critical", "errors", "warning", "notifications", "informational", "debugging"]
+ state:
+ description:
+ - Existential state of the logging configuration on the node.
+ choices:
+ - present
+ - absent
+ type: str
+ state:
+ description:
+ - Existential state of the logging configuration on the node.
+ default: present
+ choices:
+ - present
+ - absent
+ type: str
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+"""
+
+EXAMPLES = """
+- name: configure logging for syslog server host
+ cisco.iosxr.iosxr_logging:
+ dest: host
+ name: 10.10.10.1
+ level: critical
+ state: present
+
+- name: add hostnameprefix configuration
+ cisco.iosxr.iosxr_logging:
+ hostnameprefix: host1
+ state: absent
+
+- name: add facility configuration
+ cisco.iosxr.iosxr_logging:
+ facility: local1
+ state: present
+
+- name: configure console logging level
+ cisco.iosxr.iosxr_logging:
+ dest: console
+ level: debugging
+ state: present
+
+- name: configure monitor logging level
+ cisco.iosxr.iosxr_logging:
+ dest: monitor
+ level: errors
+ state: present
+
+- name: configure syslog to a file
+ cisco.iosxr.iosxr_logging:
+ dest: file
+ name: file_name
+ size: 2048
+ level: errors
+ state: present
+
+- name: configure buffered logging with size
+ cisco.iosxr.iosxr_logging:
+ dest: buffered
+ size: 5100000
+
+- name: Configure logging using aggregate
+ cisco.iosxr.iosxr_logging:
+ aggregate:
+ - {dest: console, level: warning}
+ - {dest: buffered, size: 4800000}
+ - {dest: file, name: file3, size: 2048}
+ - {dest: host, name: host3, level: critical}
+
+- name: Delete logging using aggregate
+ cisco.iosxr.iosxr_logging:
+ aggregate:
+ - {dest: console, level: warning}
+ - {dest: buffered, size: 4800000}
+ - {dest: file, name: file3, size: 2048}
+ - {dest: host, name: host3, level: critical}
+ state: absent
+"""
+
+RETURN = """
+commands:
+ description: The list of configuration mode commands to send to the device
+ returned: always (empty list when no commands to send)
+ type: list
+ sample:
+ - logging 10.10.10.1 vrf default severity debugging
+ - logging facility local7
+ - logging hostnameprefix host1
+ - logging console critical
+ - logging buffered 2097153
+ - logging buffered warnings
+ - logging monitor errors
+ - logging file log_file maxfilesize 1024 severity info
+xml:
+ description: NetConf rpc xml sent to device with transport C(netconf)
+ returned: always (empty list when no xml rpc to send)
+ type: list
+ sample:
+ - '<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <syslog xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-infra-syslog-cfg">
+ <files>
+ <file xc:operation="delete">
+ <file-name>file1</file-name>
+ <file-log-attributes>
+ <max-file-size>2097152</max-file-size>
+ <severity>2</severity>
+ </file-log-attributes>
+ </file>
+ </files>
+ </syslog>
+ </config>'
+"""
+
+import re
+import collections
+from copy import deepcopy
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ get_config,
+ load_config,
+ build_xml,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ iosxr_argument_spec,
+ etree_findall,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ is_netconf,
+ is_cliconf,
+ etree_find,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ remove_default_spec,
+)
+
+
+severity_level = {
+ "emergency": "0",
+ "alert": "1",
+ "critical": "2",
+ "error": "3",
+ "warning": "4",
+ "notice": "5",
+ "info": "6",
+ "debug": "7",
+ "disable": "15",
+}
+
+severity_transpose = {
+ "emergencies": "emergency",
+ "alerts": "alert",
+ "critical": "critical",
+ "errors": "error",
+ "warning": "warning",
+ "notifications": "notice",
+ "informational": "info",
+ "debugging": "debug",
+}
+
+
+class ConfigBase(object):
+ def __init__(self, module):
+ self._flag = None
+ self._module = module
+ self._result = {"changed": False, "warnings": []}
+ self._want = list()
+ self._have = list()
+
+ def validate_size(self, value, type=None):
+ if value:
+ if type == "buffer":
+ if value and not int(307200) <= value <= int(125000000):
+ self._module.fail_json(
+ msg="buffer size must be between 307200 and 125000000"
+ )
+ elif type == "file":
+ if value and not int(1) <= value <= int(2097152):
+ self._module.fail_json(
+ msg="file size must be between 1 and 2097152"
+ )
+ return value
+
+ def map_params_to_obj(self, required_if=None):
+ aggregate = self._module.params.get("aggregate")
+ if aggregate:
+ for item in aggregate:
+ for key in item:
+ if item.get(key) is None:
+ item[key] = self._module.params[key]
+
+ d = item.copy()
+
+ if d["dest"] not in ("host", "file"):
+ d["name"] = None
+
+ if d["dest"] == "buffered":
+ if d["size"] is not None:
+ d["size"] = str(
+ self.validate_size(d["size"], "buffer")
+ )
+ else:
+ d["size"] = str(307200)
+ elif d["dest"] == "file":
+ if d["size"] is not None:
+ d["size"] = str(self.validate_size(d["size"], "file"))
+ else:
+ d["size"] = str(2097152)
+ else:
+ d["size"] = None
+
+ if self._flag == "NC":
+ d["level"] = severity_transpose[d["level"]]
+
+ self._want.append(d)
+
+ else:
+ params = self._module.params
+ if params["dest"] not in ("host", "file"):
+ params["name"] = None
+
+ if params["dest"] == "buffered":
+ if params["size"] is not None:
+ params["size"] = str(
+ self.validate_size(params["size"], "buffer")
+ )
+ else:
+ params["size"] = str(307200)
+ elif params["dest"] == "file":
+ if params["size"] is not None:
+ params["size"] = str(
+ self.validate_size(params["size"], "file")
+ )
+ else:
+ params["size"] = str(2097152)
+ else:
+ params["size"] = None
+
+ if self._flag == "NC":
+ params["level"] = severity_transpose[params["level"]]
+
+ self._want.append(
+ {
+ "dest": params["dest"],
+ "name": params["name"],
+ "vrf": params["vrf"],
+ "size": params["size"],
+ "facility": params["facility"],
+ "level": params["level"],
+ "hostnameprefix": params["hostnameprefix"],
+ "state": params["state"],
+ }
+ )
+
+
+class CliConfiguration(ConfigBase):
+ def __init__(self, module):
+ super(CliConfiguration, self).__init__(module)
+ self._file_list = set()
+ self._host_list = set()
+
+ def map_obj_to_commands(self):
+ commands = list()
+ for want_item in self._want:
+ dest = want_item["dest"]
+ name = want_item["name"]
+ size = want_item["size"]
+ facility = want_item["facility"]
+ level = want_item["level"]
+ vrf = want_item["vrf"]
+ hostnameprefix = want_item["hostnameprefix"]
+ state = want_item["state"]
+ del want_item["state"]
+
+ have_size = None
+ have_console_level = None
+ have_monitor_level = None
+ have_prefix = None
+ have_facility = None
+
+ for item in self._have:
+ if item["dest"] == "buffered":
+ have_size = item["size"]
+ if item["dest"] == "console":
+ have_console_level = item["level"]
+ if item["dest"] == "monitor":
+ have_monitor_level = item["level"]
+ if item["dest"] is None and item["hostnameprefix"] is not None:
+ have_prefix = item["hostnameprefix"]
+ if (
+ item["dest"] is None
+ and item["hostnameprefix"] is None
+ and item["facility"] is not None
+ ):
+ have_facility = item["facility"]
+
+ if state == "absent":
+ if dest == "host" and name in self._host_list:
+ commands.append("no logging {0} vrf {1}".format(name, vrf))
+ elif dest == "file" and name in self._file_list:
+ commands.append("no logging file {0}".format(name))
+ elif dest == "console" and have_console_level is not None:
+ commands.append("no logging {0}".format(dest))
+ elif dest == "monitor" and have_monitor_level:
+ commands.append("no logging {0}".format(dest))
+ elif dest == "buffered" and have_size:
+ commands.append("no logging {0}".format(dest))
+
+ if (
+ dest is None
+ and hostnameprefix is not None
+ and have_prefix == hostnameprefix
+ ):
+ commands.append(
+ "no logging hostnameprefix {0}".format(hostnameprefix)
+ )
+ if (
+ dest is None
+ and facility is not None
+ and have_facility == facility
+ ):
+ commands.append("no logging facility {0}".format(facility))
+
+ if state == "present":
+ if dest == "host" and name not in self._host_list:
+ if level == "errors" or level == "informational":
+ level = severity_transpose[level]
+ commands.append(
+ "logging {0} vrf {1} severity {2}".format(
+ name, vrf, level
+ )
+ )
+ elif dest == "file" and name not in self._file_list:
+ if level == "errors" or level == "informational":
+ level = severity_transpose[level]
+ commands.append(
+ "logging file {0} maxfilesize {1} severity {2}".format(
+ name, size, level
+ )
+ )
+ elif dest == "buffered" and (
+ have_size is None
+ or (have_size is not None and size != have_size)
+ ):
+ commands.append("logging buffered {0}".format(size))
+ elif dest == "console" and (
+ have_console_level is None
+ or (
+ have_console_level is not None
+ and have_console_level != level
+ )
+ ):
+ commands.append("logging console {0}".format(level))
+ elif dest == "monitor" and (
+ have_monitor_level is None
+ or (
+ have_monitor_level is not None
+ and have_monitor_level != level
+ )
+ ):
+ commands.append("logging monitor {0}".format(level))
+
+ if (
+ dest is None
+ and hostnameprefix is not None
+ and (
+ have_prefix is None
+ or (
+ have_prefix is not None
+ and hostnameprefix != have_prefix
+ )
+ )
+ ):
+ commands.append(
+ "logging hostnameprefix {0}".format(hostnameprefix)
+ )
+ if (
+ dest is None
+ and hostnameprefix is None
+ and facility != have_facility
+ ):
+ commands.append("logging facility {0}".format(facility))
+
+ self._result["commands"] = commands
+ if commands:
+ commit = not self._module.check_mode
+ diff = load_config(self._module, commands, commit=commit)
+ if diff:
+ self._result["diff"] = dict(prepared=diff)
+ self._result["changed"] = True
+
+ def parse_facility(self, line):
+ match = re.search(r"logging facility (\S+)", line, re.M)
+ facility = None
+ if match:
+ facility = match.group(1)
+
+ return facility
+
+ def parse_size(self, line, dest):
+ size = None
+
+ if dest == "buffered":
+ match = re.search(r"logging buffered (\S+)", line, re.M)
+ if match:
+ try:
+ int_size = int(match.group(1))
+ except ValueError:
+ int_size = None
+
+ if int_size is not None:
+ if isinstance(int_size, int):
+ size = str(match.group(1))
+ return size
+
+ def parse_hostnameprefix(self, line):
+ prefix = None
+ match = re.search(r"logging hostnameprefix (\S+)", line, re.M)
+ if match:
+ prefix = match.group(1)
+ return prefix
+
+ def parse_name(self, line, dest):
+ name = None
+ if dest == "file":
+ match = re.search(r"logging file (\S+)", line, re.M)
+ if match:
+ name = match.group(1)
+ elif dest == "host":
+ match = re.search(r"logging (\S+)", line, re.M)
+ if match:
+ name = match.group(1)
+
+ return name
+
+ def parse_level(self, line, dest):
+ level_group = (
+ "emergencies",
+ "alerts",
+ "critical",
+ "errors",
+ "warning",
+ "notifications",
+ "informational",
+ "debugging",
+ )
+
+ level = None
+ match = re.search(r"logging {0} (\S+)".format(dest), line, re.M)
+ if match:
+ if match.group(1) in level_group:
+ level = match.group(1)
+
+ return level
+
+ def parse_dest(self, line, group):
+ dest_group = ("console", "monitor", "buffered", "file")
+ dest = None
+ if group in dest_group:
+ dest = group
+ elif "vrf" in line:
+ dest = "host"
+
+ return dest
+
+ def parse_vrf(self, line, dest):
+ vrf = None
+ if dest == "host":
+ match = re.search(r"logging (\S+) vrf (\S+)", line, re.M)
+ if match:
+ vrf = match.group(2)
+ return vrf
+
+ def map_config_to_obj(self):
+ data = get_config(self._module, config_filter="logging")
+ lines = data.split("\n")
+
+ for line in lines:
+ match = re.search(r"logging (\S+)", line, re.M)
+ if match:
+ dest = self.parse_dest(line, match.group(1))
+ name = self.parse_name(line, dest)
+ if dest == "host" and name is not None:
+ self._host_list.add(name)
+ if dest == "file" and name is not None:
+ self._file_list.add(name)
+
+ self._have.append(
+ {
+ "dest": dest,
+ "name": name,
+ "size": self.parse_size(line, dest),
+ "facility": self.parse_facility(line),
+ "level": self.parse_level(line, dest),
+ "vrf": self.parse_vrf(line, dest),
+ "hostnameprefix": self.parse_hostnameprefix(line),
+ }
+ )
+
+ def run(self):
+ self.map_params_to_obj()
+ self.map_config_to_obj()
+ self.map_obj_to_commands()
+
+ return self._result
+
+
+class NCConfiguration(ConfigBase):
+ def __init__(self, module):
+ super(NCConfiguration, self).__init__(module)
+ self._flag = "NC"
+ self._log_file_meta = collections.OrderedDict()
+ self._log_host_meta = collections.OrderedDict()
+ self._log_console_meta = collections.OrderedDict()
+ self._log_monitor_meta = collections.OrderedDict()
+ self._log_buffered_size_meta = collections.OrderedDict()
+ self._log_buffered_level_meta = collections.OrderedDict()
+ self._log_facility_meta = collections.OrderedDict()
+ self._log_prefix_meta = collections.OrderedDict()
+
+ def map_obj_to_xml_rpc(self):
+ self._log_file_meta.update(
+ [
+ (
+ "files",
+ {
+ "xpath": "syslog/files",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "file",
+ {
+ "xpath": "syslog/files/file",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:name",
+ {
+ "xpath": "syslog/files/file/file-name",
+ "operation": "edit",
+ },
+ ),
+ (
+ "file-attrib",
+ {
+ "xpath": "syslog/files/file/file-log-attributes",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:size",
+ {
+ "xpath": "syslog/files/file/file-log-attributes/max-file-size",
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:level",
+ {
+ "xpath": "syslog/files/file/file-log-attributes/severity",
+ "operation": "edit",
+ },
+ ),
+ ]
+ )
+ self._log_host_meta.update(
+ [
+ (
+ "host-server",
+ {
+ "xpath": "syslog/host-server",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "vrfs",
+ {
+ "xpath": "syslog/host-server/vrfs",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "vrf",
+ {
+ "xpath": "syslog/host-server/vrfs/vrf",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:vrf",
+ {
+ "xpath": "syslog/host-server/vrfs/vrf/vrf-name",
+ "operation": "edit",
+ },
+ ),
+ (
+ "ipv4s",
+ {
+ "xpath": "syslog/host-server/vrfs/vrf/ipv4s",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "ipv4",
+ {
+ "xpath": "syslog/host-server/vrfs/vrf/ipv4s/ipv4",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:name",
+ {
+ "xpath": "syslog/host-server/vrfs/vrf/ipv4s/ipv4/address",
+ "operation": "edit",
+ },
+ ),
+ (
+ "ipv4-sev",
+ {
+ "xpath": "syslog/host-server/vrfs/vrf/ipv4s/ipv4/ipv4-severity-port",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:level",
+ {
+ "xpath": "syslog/host-server/vrfs/vrf/ipv4s/ipv4/ipv4-severity-port/severity",
+ "operation": "edit",
+ },
+ ),
+ ]
+ )
+ self._log_console_meta.update(
+ [
+ (
+ "a:enable-console",
+ {
+ "xpath": "syslog/enable-console-logging",
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "console",
+ {
+ "xpath": "syslog/console-logging",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:console-level",
+ {
+ "xpath": "syslog/console-logging/logging-level",
+ "operation": "edit",
+ },
+ ),
+ ]
+ )
+ self._log_monitor_meta.update(
+ [
+ (
+ "monitor",
+ {
+ "xpath": "syslog/monitor-logging",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:monitor-level",
+ {
+ "xpath": "syslog/monitor-logging/logging-level",
+ "operation": "edit",
+ },
+ ),
+ ]
+ )
+ self._log_buffered_size_meta.update(
+ [
+ (
+ "buffered",
+ {
+ "xpath": "syslog/buffered-logging",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:size",
+ {
+ "xpath": "syslog/buffered-logging/buffer-size",
+ "operation": "edit",
+ },
+ ),
+ ]
+ )
+ self._log_buffered_level_meta.update(
+ [
+ (
+ "buffered",
+ {
+ "xpath": "syslog/buffered-logging",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:level",
+ {
+ "xpath": "syslog/buffered-logging/logging-level",
+ "operation": "edit",
+ },
+ ),
+ ]
+ )
+ self._log_facility_meta.update(
+ [
+ (
+ "facility",
+ {
+ "xpath": "syslog/logging-facilities",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:facility",
+ {
+ "xpath": "syslog/logging-facilities/facility-level",
+ "operation": "edit",
+ },
+ ),
+ ]
+ )
+ self._log_prefix_meta.update(
+ [
+ (
+ "a:hostnameprefix",
+ {
+ "xpath": "syslog/host-name-prefix",
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ )
+ ]
+ )
+
+ state = self._module.params["state"]
+
+ _get_filter = build_xml("syslog", opcode="filter")
+ running = get_config(
+ self._module, source="running", config_filter=_get_filter
+ )
+
+ file_ele = etree_findall(running, "file")
+ file_list = list()
+ if len(file_ele):
+ for file in file_ele:
+ file_name = etree_find(file, "file-name")
+ file_list.append(
+ file_name.text if file_name is not None else None
+ )
+ vrf_ele = etree_findall(running, "vrf")
+ host_list = list()
+ for vrf in vrf_ele:
+ host_ele = etree_findall(vrf, "ipv4")
+ for host in host_ele:
+ host_name = etree_find(host, "address")
+ host_list.append(
+ host_name.text if host_name is not None else None
+ )
+
+ console_ele = etree_find(running, "console-logging")
+ console_level = (
+ etree_find(console_ele, "logging-level")
+ if console_ele is not None
+ else None
+ )
+ have_console = (
+ console_level.text if console_level is not None else None
+ )
+
+ monitor_ele = etree_find(running, "monitor-logging")
+ monitor_level = (
+ etree_find(monitor_ele, "logging-level")
+ if monitor_ele is not None
+ else None
+ )
+ have_monitor = (
+ monitor_level.text if monitor_level is not None else None
+ )
+
+ buffered_ele = etree_find(running, "buffered-logging")
+ buffered_size = (
+ etree_find(buffered_ele, "buffer-size")
+ if buffered_ele is not None
+ else None
+ )
+ have_buffered = (
+ buffered_size.text if buffered_size is not None else None
+ )
+
+ facility_ele = etree_find(running, "logging-facilities")
+ facility_level = (
+ etree_find(facility_ele, "facility-level")
+ if facility_ele is not None
+ else None
+ )
+ have_facility = (
+ facility_level.text if facility_level is not None else None
+ )
+
+ prefix_ele = etree_find(running, "host-name-prefix")
+ have_prefix = prefix_ele.text if prefix_ele is not None else None
+
+ file_params = list()
+ host_params = list()
+ console_params = dict()
+ monitor_params = dict()
+ buffered_params = dict()
+ facility_params = dict()
+ prefix_params = dict()
+
+ opcode = None
+ if state == "absent":
+ opcode = "delete"
+ for item in self._want:
+ if item["dest"] == "file" and item["name"] in file_list:
+ item["level"] = severity_level[item["level"]]
+ file_params.append(item)
+ elif item["dest"] == "host" and item["name"] in host_list:
+ item["level"] = severity_level[item["level"]]
+ host_params.append(item)
+ elif item["dest"] == "console" and have_console:
+ console_params.update({"console-level": item["level"]})
+ elif item["dest"] == "monitor" and have_monitor:
+ monitor_params.update({"monitor-level": item["level"]})
+ elif item["dest"] == "buffered" and have_buffered:
+ buffered_params["size"] = (
+ str(item["size"]) if item["size"] else None
+ )
+ buffered_params["level"] = (
+ item["level"] if item["level"] else None
+ )
+ elif (
+ item["dest"] is None
+ and item["hostnameprefix"] is None
+ and item["facility"] is not None
+ and have_facility
+ ):
+ facility_params.update({"facility": item["facility"]})
+ elif (
+ item["dest"] is None
+ and item["hostnameprefix"] is not None
+ and have_prefix
+ ):
+ prefix_params.update(
+ {"hostnameprefix": item["hostnameprefix"]}
+ )
+ elif state == "present":
+ opcode = "merge"
+ for item in self._want:
+ if item["dest"] == "file":
+ item["level"] = severity_level[item["level"]]
+ file_params.append(item)
+ elif item["dest"] == "host":
+ item["level"] = severity_level[item["level"]]
+ host_params.append(item)
+ elif item["dest"] == "console":
+ console_params.update({"console-level": item["level"]})
+ elif item["dest"] == "monitor":
+ monitor_params.update({"monitor-level": item["level"]})
+ elif item["dest"] == "buffered":
+ buffered_params["size"] = (
+ str(item["size"]) if item["size"] else None
+ )
+ buffered_params["level"] = (
+ item["level"] if item["level"] else None
+ )
+ elif (
+ item["dest"] is None
+ and item["hostnameprefix"] is None
+ and item["facility"] is not None
+ ):
+ facility_params.update({"facility": item["facility"]})
+ elif (
+ item["dest"] is None and item["hostnameprefix"] is not None
+ ):
+ prefix_params.update(
+ {"hostnameprefix": item["hostnameprefix"]}
+ )
+
+ self._result["xml"] = []
+ _edit_filter_list = list()
+ if opcode:
+ if len(file_params):
+ _edit_filter_list.append(
+ build_xml(
+ "syslog",
+ xmap=self._log_file_meta,
+ params=file_params,
+ opcode=opcode,
+ )
+ )
+ if len(host_params):
+ _edit_filter_list.append(
+ build_xml(
+ "syslog",
+ xmap=self._log_host_meta,
+ params=host_params,
+ opcode=opcode,
+ )
+ )
+ if len(console_params):
+ _edit_filter_list.append(
+ build_xml(
+ "syslog",
+ xmap=self._log_console_meta,
+ params=console_params,
+ opcode=opcode,
+ )
+ )
+ if len(monitor_params):
+ _edit_filter_list.append(
+ build_xml(
+ "syslog",
+ xmap=self._log_monitor_meta,
+ params=monitor_params,
+ opcode=opcode,
+ )
+ )
+ if len(buffered_params):
+ _edit_filter_list.append(
+ build_xml(
+ "syslog",
+ xmap=self._log_buffered_size_meta,
+ params=buffered_params,
+ opcode=opcode,
+ )
+ )
+ _edit_filter_list.append(
+ build_xml(
+ "syslog",
+ xmap=self._log_buffered_level_meta,
+ params=buffered_params,
+ opcode=opcode,
+ )
+ )
+ if len(facility_params):
+ _edit_filter_list.append(
+ build_xml(
+ "syslog",
+ xmap=self._log_facility_meta,
+ params=facility_params,
+ opcode=opcode,
+ )
+ )
+ if len(prefix_params):
+ _edit_filter_list.append(
+ build_xml(
+ "syslog",
+ xmap=self._log_prefix_meta,
+ params=prefix_params,
+ opcode=opcode,
+ )
+ )
+
+ diff = None
+ if len(_edit_filter_list):
+ commit = not self._module.check_mode
+ diff = load_config(
+ self._module,
+ _edit_filter_list,
+ commit=commit,
+ running=running,
+ nc_get_filter=_get_filter,
+ )
+
+ if diff:
+ if self._module._diff:
+ self._result["diff"] = dict(prepared=diff)
+
+ self._result["xml"] = _edit_filter_list
+ self._result["changed"] = True
+
+ def run(self):
+ self.map_params_to_obj()
+ self.map_obj_to_xml_rpc()
+
+ return self._result
+
+
+def main():
+ """ main entry point for module execution
+ """
+ element_spec = dict(
+ dest=dict(
+ type="str",
+ choices=["host", "console", "monitor", "buffered", "file"],
+ ),
+ name=dict(type="str"),
+ size=dict(type="int"),
+ vrf=dict(type="str", default="default"),
+ facility=dict(type="str", default="local7"),
+ hostnameprefix=dict(type="str"),
+ level=dict(
+ type="str",
+ default="debugging",
+ aliases=["severity"],
+ choices=[
+ "emergencies",
+ "alerts",
+ "critical",
+ "errors",
+ "warning",
+ "notifications",
+ "informational",
+ "debugging",
+ ],
+ ),
+ state=dict(default="present", choices=["present", "absent"]),
+ )
+
+ aggregate_spec = deepcopy(element_spec)
+
+ # remove default in aggregate spec, to handle common arguments
+ remove_default_spec(aggregate_spec)
+
+ mutually_exclusive = [("dest", "facility", "hostnameprefix")]
+
+ required_if = [
+ ("dest", "host", ["name"]),
+ ("dest", "file", ["name"]),
+ ("dest", "buffered", ["size"]),
+ ("dest", "console", ["level"]),
+ ("dest", "monitor", ["level"]),
+ ]
+
+ argument_spec = dict(
+ aggregate=dict(
+ type="list",
+ elements="dict",
+ options=aggregate_spec,
+ mutually_exclusive=mutually_exclusive,
+ required_if=required_if,
+ )
+ )
+
+ argument_spec.update(element_spec)
+ argument_spec.update(iosxr_argument_spec)
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ mutually_exclusive=mutually_exclusive,
+ required_if=required_if,
+ supports_check_mode=True,
+ )
+
+ config_object = None
+ if is_cliconf(module):
+ # Commenting the below cliconf deprecation support call for Ansible 2.9 as it'll be continued to be supported
+ # module.deprecate("cli support for 'iosxr_interface' is deprecated. Use transport netconf instead",
+ # version='2.9')
+ config_object = CliConfiguration(module)
+ elif is_netconf(module):
+ config_object = NCConfiguration(module)
+
+ if config_object:
+ result = config_object.run()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_netconf.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_netconf.py
new file mode 100644
index 00000000..a075958f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_netconf.py
@@ -0,0 +1,221 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# (c) 2017, Ansible by Red Hat, Inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_netconf
+author: Kedar Kekan (@kedarX)
+short_description: Configures NetConf sub-system service on Cisco IOS-XR devices
+description:
+- This module provides an abstraction that enables and configures the netconf system
+ service running on Cisco IOS-XR Software. This module can be used to easily enable
+ the Netconf API. Netconf provides a programmatic interface for working with configuration
+ and state resources as defined in RFC 6242.
+version_added: 1.0.0
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+options:
+ netconf_port:
+ description:
+ - This argument specifies the port the netconf service should listen on for SSH
+ connections. The default port as defined in RFC 6242 is 830.
+ required: false
+ type: int
+ default: 830
+ aliases:
+ - listens_on
+ netconf_vrf:
+ description:
+ - netconf vrf name
+ required: false
+ type: str
+ default: default
+ aliases:
+ - vrf
+ state:
+ description:
+ - Specifies the state of the C(iosxr_netconf) resource on the remote device. If
+ the I(state) argument is set to I(present) the netconf service will be configured. If
+ the I(state) argument is set to I(absent) the netconf service will be removed
+ from the configuration.
+ type: str
+ required: false
+ default: present
+ choices:
+ - present
+ - absent
+notes:
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+- Tested against Cisco IOS XR Software, Version 6.1.3
+"""
+
+EXAMPLES = """
+- name: enable netconf service on port 830
+ cisco.iosxr.iosxr_netconf:
+ listens_on: 830
+ state: present
+
+- name: disable netconf service
+ cisco.iosxr.iosxr_netconf:
+ state: absent
+"""
+
+RETURN = """
+commands:
+ description: Returns the command sent to the remote device
+ returned: when changed is True
+ type: str
+ sample: 'ssh server netconf port 830'
+"""
+import re
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ iosxr_argument_spec,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ get_config,
+ load_config,
+)
+from ansible.module_utils.six import iteritems
+
+USE_PERSISTENT_CONNECTION = True
+
+
+def map_obj_to_commands(updates):
+ want, have = updates
+ commands = list()
+
+ if want["state"] == "absent":
+ if have["state"] == "present":
+ commands.append("no netconf-yang agent ssh")
+
+ if "netconf_port" in have:
+ commands.append(
+ "no ssh server netconf port %s" % have["netconf_port"]
+ )
+
+ if have["netconf_vrf"]:
+ for vrf in have["netconf_vrf"]:
+ commands.append("no ssh server netconf vrf %s" % vrf)
+ else:
+ if have["state"] == "absent":
+ commands.append("netconf-yang agent ssh")
+
+ if want["netconf_port"] is not None and (
+ want["netconf_port"] != have.get("netconf_port")
+ ):
+ commands.append(
+ "ssh server netconf port %s" % want["netconf_port"]
+ )
+ if want["netconf_vrf"] is not None and (
+ want["netconf_vrf"] not in have["netconf_vrf"]
+ ):
+ commands.append("ssh server netconf vrf %s" % want["netconf_vrf"])
+
+ return commands
+
+
+def parse_vrf(config):
+ match = re.search(r"vrf (\w+)", config)
+ if match:
+ return match.group(1)
+
+
+def parse_port(config):
+ match = re.search(r"port (\d+)", config)
+ if match:
+ return int(match.group(1))
+
+
+def map_config_to_obj(module):
+ obj = {"state": "absent"}
+
+ netconf_config = get_config(module, config_filter="netconf-yang agent")
+
+ ssh_config = get_config(module, config_filter="ssh server")
+ ssh_config = [
+ config_line
+ for config_line in (line.strip() for line in ssh_config.splitlines())
+ if config_line
+ ]
+ obj["netconf_vrf"] = []
+ for config in ssh_config:
+ if "netconf port" in config:
+ obj.update({"netconf_port": parse_port(config)})
+ if "netconf vrf" in config:
+ obj["netconf_vrf"].append(parse_vrf(config))
+ if "ssh" in netconf_config and (
+ "netconf_port" in obj or obj["netconf_vrf"]
+ ):
+ obj.update({"state": "present"})
+
+ if "ssh" in netconf_config and "netconf_port" not in obj:
+ obj.update({"netconf_port": 830})
+
+ return obj
+
+
+def validate_netconf_port(value, module):
+ if not 1 <= value <= 65535:
+ module.fail_json(msg="netconf_port must be between 1 and 65535")
+
+
+def map_params_to_obj(module):
+ obj = {
+ "netconf_port": module.params["netconf_port"],
+ "netconf_vrf": module.params["netconf_vrf"],
+ "state": module.params["state"],
+ }
+
+ for key, value in iteritems(obj):
+ # validate the param value (if validator func exists)
+ validator = globals().get("validate_%s" % key)
+ if callable(validator):
+ validator(value, module)
+
+ return obj
+
+
+def main():
+ """main entry point for module execution
+ """
+ argument_spec = dict(
+ netconf_port=dict(type="int", default=830, aliases=["listens_on"]),
+ netconf_vrf=dict(aliases=["vrf"], default="default"),
+ state=dict(default="present", choices=["present", "absent"]),
+ )
+ argument_spec.update(iosxr_argument_spec)
+
+ module = AnsibleModule(
+ argument_spec=argument_spec, supports_check_mode=True
+ )
+
+ warnings = list()
+
+ result = {"changed": False, "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:
+ result["diff"] = dict(prepared=diff)
+ result["changed"] = True
+
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospf_interfaces.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospf_interfaces.py
new file mode 100644
index 00000000..0626461c
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospf_interfaces.py
@@ -0,0 +1,1210 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+"""
+The module file for iosxr_ospf_interfaces
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+module: iosxr_ospf_interfaces
+version_added: 1.2.0
+short_description: OSPF Interfaces Resource Module.
+description:
+ - This module manages OSPF(v2/v3) configuration of interfaces on devices running Cisco IOS-XR.
+author: Rohit Thakur (@rohitthakur2590)
+notes:
+ - Tested against IOS-XR 6.1.3
+ - This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html)
+options:
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config router ospf').
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ config:
+ description: A list of OSPF configuration for interfaces.
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Name/Identifier of the interface.
+ type: str
+ required: True
+ type:
+ description:
+ - Type of the interface.
+ type: str
+ required: True
+ address_family:
+ description:
+ - OSPF settings on the interfaces in address-family context.
+ type: list
+ elements: dict
+ suboptions:
+ afi:
+ description:
+ - Address Family Identifier (AFI) for OSPF settings on the interfaces.
+ type: str
+ choices: ['ipv4', 'ipv6']
+ required: True
+ processes:
+ description:
+ - Interfaces configuration for an OSPF process.
+ type: list
+ elements: dict
+ suboptions:
+ process_id:
+ description:
+ - OSPF process tag.
+ type: str
+ required: True
+ area:
+ description: Specify the area-id
+ type: dict
+ suboptions:
+ area_id:
+ description:
+ - OSPF interfaces area ID as a decimal value. Please
+ refer vendor documentation of Valid values.
+ - OSPF interfaces area ID in IP address format(e.g.
+ A.B.C.D)
+ type: str
+ apply_group_option:
+ description: Specify configuration from a group
+ type: dict
+ suboptions:
+ group_name:
+ description: Specify the name of the group
+ type: str
+ operation:
+ description: Specify the group config operation
+ type: str
+ choices: [add, remove, append]
+ authentication:
+ description: Enable authentication
+ type: dict
+ suboptions:
+ message_digest:
+ description: Use message-digest authentication
+ type: dict
+ suboptions:
+ keychain:
+ description: Specify keychain name
+ type: str
+ null_auth:
+ description: Use no authentication
+ type: bool
+ authentication_key:
+ description: Specify authentication password (key)
+ type: dict
+ suboptions:
+ password:
+ description: The OSPFv2 password (key)
+ type: str
+ clear:
+ description: Specifies an UNENCRYPTED password (key) will follow
+ type: str
+ encrypted:
+ description: Specifies an ENCRYPTED password (key) will follow
+ type: str
+ bfd:
+ description: Configure BFD parameters
+ type: dict
+ suboptions:
+ fast_detect:
+ description: Configure fast detection
+ type: dict
+ suboptions:
+ set:
+ description: Enable fast detection only
+ type: bool
+ strict_mode:
+ description: Hold down neighbor session until BFD session is up
+ type: bool
+ minimum_interval:
+ description: Hello interval in milli-seconds
+ type: int
+ multiplier:
+ description: Detect multiplier
+ type: int
+ cost:
+ description: Specify Interface cost
+ type: int
+ cost_fallback:
+ description: Specify Cost when cumulative bandwidth goes below the theshold
+ type: dict
+ suboptions:
+ cost:
+ description: Specify cost w.r.t cummulative bandwidth
+ type: int
+ threshold:
+ description: Specify threshold bandwidth when cost-fallback is applied
+ type: int
+ database_filter:
+ description: Filter OSPF LSAs during synchronization and flooding
+ type: dict
+ suboptions:
+ all_outgoing_lsa:
+ description: Filter all outgoing LSA
+ type: bool
+ dead_interval:
+ description: Specify interval after which a neighbor is declared dead
+ type: int
+ demand_circuit:
+ description: Enable/Disable demand circuits
+ type: bool
+ fast_reroute:
+ description: Specify IP Fast Reroute
+ type: dict
+ suboptions:
+ disabled:
+ description: Disable IP fast reroute
+ type: bool
+ per_link:
+ description: Specify per-prefix computation
+ type: dict
+ suboptions:
+ information_type:
+ description: Specify per-link LFA exclusion or FRR LFA candidate information
+ type: str
+ choices: ["exclude", "lfa_candidate"]
+ use_candidate_only:
+ description: Enable/Disable backup selection from candidate-list only
+ type: bool
+ interface:
+ description: Specify Per-link LFA exclusion information
+ type: dict
+ suboptions:
+ bvi:
+ description: Specify Bridge-Group Virtual Interface
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ bundle_ether:
+ description: Specify Aggregated Ethernet interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ pos_int:
+ description: Specify Aggregated pos interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ fast_ethernet:
+ description: Specify FastEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ fiftygige:
+ description: Specify FiftyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ fortygige:
+ description: Specify FortyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ fourhundredgige:
+ description: Specify FourHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ gigabitethernet:
+ description: Specify GigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ hundredgige:
+ description: Specify HundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ mgmteth:
+ description: Specify MgmtEth/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ multilink:
+ description: Specify Multilink network interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ pw_ether:
+ description: Specify PWHE Ethernet Interface
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ pw_iw:
+ description: Specify PWHE VC11 IP Interworking Interface
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ srp:
+ description: Specify SRP interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ serial:
+ description: Specify Serial network interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ tengige:
+ description: Specify TenGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ twentyfivegige:
+ description: Specify TwentyFiveGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ twohundredgige:
+ description: Specify TwoHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ nve:
+ description: Specify Network Virtualization Endpoint Interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ tunnel_ip:
+ description: Specify GRE/IPinIP Tunnel Interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ tunnel_ipsec:
+ description: Specify IPSec Tunnel interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ tunnel_mte:
+ description: Specify MPLS Traffic Engineering P2MP Tunnel interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ tunnel_mpls:
+ description: MPLS Transport Protocol Tunnel interface
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ flood_reduction:
+ description: Enable/Disable flood reduction
+ type: bool
+ hello_interval:
+ description: Specify Time between HELLO packets
+ type: int
+ link_down_fast_detect:
+ description: Configure interface down parameters
+ type: bool
+ message_digest_key:
+ description: Message digest authentication password (key)
+ type: dict
+ suboptions:
+ id:
+ description: Key ID
+ type: int
+ required: true
+ md5:
+ description: Use MD5 Algorithm
+ type: dict
+ required: true
+ suboptions:
+ password:
+ description: The OSPFv2 password (key)
+ type: str
+ clear:
+ description: Specifies an UNENCRYPTED password (key) will follow
+ type: bool
+ encrypted:
+ description: Specifies an ENCRYPTED password (key) will follow
+ type: bool
+ mpls_ldp_sync:
+ description: Enable/Disable MPLS LDP Sync
+ type: bool
+ mtu_ignore:
+ description: Enable/Disable ignoring of MTU in DBD packets
+ type: bool
+ network:
+ description: Specify Network type
+ type: str
+ choices: ["broadcast", "non-broadcast", "point-to-multipoint", "point-to-point"]
+ neighbors:
+ description: Specify a neighbor routers
+ type: list
+ elements: dict
+ suboptions:
+ neighbor_id:
+ description: Specify Neighbor address (name)
+ type: str
+ cost:
+ description: Specify OSPF cost for point-to-multipoint neighbor
+ type: int
+ db_filter_all_out:
+ description: Specify Filter OSPF LSA during synchronization and flooding for point-to-multipoint neighbor
+ type: bool
+ poll_interval:
+ description: Specify OSPF dead-router polling interval
+ type: int
+ priority:
+ description: Specify OSPF priority of non-broadcast neighbor
+ type: int
+ packet_size:
+ description: Customize size of OSPF packets upto MTU
+ type: int
+ passive:
+ description: Enable/Disable passive
+ type: bool
+ prefix_suppression:
+ description: Suppress advertisement of the prefixes
+ type: bool
+ priority:
+ description: Specify Router priority
+ type: int
+ retransmit_interval:
+ description: Specify time between retransmitting lost link state advertisements
+ type: int
+ security_ttl:
+ description: Enable security
+ type: dict
+ suboptions:
+ set:
+ description: Enable ttl security
+ type: bool
+ hops:
+ description: Maximum number of IP hops allowed <1-254>
+ type: int
+ transmit_delay:
+ description: Specify estimated time needed to send link-state update packet
+ type: int
+ state:
+ description:
+ - The state the configuration should be left in.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - gathered
+ - parsed
+ - rendered
+ default: merged
+"""
+EXAMPLES = """
+# Using merged
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# % No such configuration item(s)
+#
+
+- name: Merge provided OSPF interfaces configuration with the existing configuration
+ cisco.iosxr.iosxr_ospf_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/0
+ type: gigabitethernet
+ address_family:
+ - afi: ipv4
+ processes:
+ - process_id: "LAB3"
+ area:
+ area_id: 0.0.0.3
+ cost: 20
+ authentication:
+ message_digest:
+ keychain: cisco
+ - afi: ipv6
+ processes:
+ - process_id: "LAB3"
+ area:
+ area_id: 0.0.0.2
+ cost: 30
+ state: merged
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": []
+#
+# "commands": [
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 cost 20",
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest",
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest keychain cisco",
+# "router ospfv3 LAB3 area 0.0.0.2 interface GigabitEthernet 0/0/0/0 cost 30"
+# ]
+#
+# "after": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "authentication": {
+# "message_digest": {
+# "keychain": "cisco"
+# }
+# },
+# "cost": 20,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.3"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# },
+# {
+# "afi": "ipv6",
+# "cost": 30,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.2"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0",
+# "type": "gigabitethernet"
+# }
+# ]
+#
+#
+# ------------
+# After state
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config router ospf
+# Thu Oct 23 06:00:57.217 UTC
+# router ospf LAB
+# area 0.0.0.0
+# !
+# area 0.0.0.9
+# !
+# !
+# router ospf LAB1
+# area 0.0.0.1
+# !
+# area 0.0.0.3
+# !
+# !
+# router ospf LAB3
+# area 0.0.0.3
+# interface GigabitEthernet0/0/0/0
+# cost 20
+# authentication message-digest keychain cisco
+# !
+# !
+# !
+# router ospf ipv4
+# !
+
+# Using replaced
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config router ospf
+# Thu Oct 23 06:00:57.217 UTC
+# router ospf LAB
+# area 0.0.0.0
+# !
+# area 0.0.0.9
+# !
+# !
+# router ospf LAB1
+# area 0.0.0.1
+# !
+# area 0.0.0.3
+# !
+# !
+# router ospf LAB3
+# area 0.0.0.3
+# interface GigabitEthernet0/0/0/0
+# cost 20
+# authentication message-digest keychain cisco
+# !
+# !
+# !
+# router ospf ipv4
+# !
+
+- name: Replace OSPF interfaces configuration
+ cisco.iosxr.iosxr_ospf_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/0
+ type: gigabitethernet
+ address_family:
+ - afi: ipv4
+ processes:
+ - process_id: "LAB3"
+ area:
+ area_id: 0.0.0.3
+ cost: 30
+ authentication:
+ message_digest:
+ keychain: ciscoiosxr
+ - afi: ipv6
+ processes:
+ - process_id: "LAB3"
+ area:
+ area_id: 0.0.0.2
+ cost: 30
+ state: replaced
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "authentication": {
+# "message_digest": {
+# "keychain": "cisco"
+# }
+# },
+# "cost": 20,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.3"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# },
+# {
+# "afi": "ipv6",
+# "cost": 30,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.2"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0",
+# "type": "gigabitethernet"
+# }
+# ]
+#
+# "commands": [
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 cost 30",
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest",
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest keychain ciscoiosxr"
+# ]
+#
+# "after": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "authentication": {
+# "message_digest": {
+# "keychain": "ciscoiosxr"
+# }
+# },
+# "cost": 30,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.3"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# },
+# {
+# "afi": "ipv6",
+# "cost": 30,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.2"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0",
+# "type": "gigabitethernet"
+# }
+# ]
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config router ospf
+# Thu Oct 23 06:10:39.827 UTC
+# router ospf LAB
+# area 0.0.0.0
+# !
+# area 0.0.0.9
+# !
+# !
+# router ospf LAB1
+# area 0.0.0.1
+# !
+# area 0.0.0.3
+# !
+# !
+# router ospf LAB3
+# area 0.0.0.3
+# interface GigabitEthernet0/0/0/0
+# cost 30
+# authentication message-digest keychain ciscoiosxr
+# !
+# !
+# !
+# router ospf ipv4
+# !
+
+- name: Override existing OSPF interfaces configuration
+ cisco.iosxr.iosxr_ospf_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ type: gigabitethernet
+ address_family:
+ - afi: ipv4
+ processes:
+ - process_id: "LAB1"
+ area:
+ area_id: 0.0.0.3
+ cost: 10
+ authentication:
+ message_digest:
+ keychain: iosxr
+ state: overridden
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "authentication": {
+# "message_digest": {
+# "keychain": "ciscoiosxr"
+# }
+# },
+# "cost": 30,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.3"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# },
+# {
+# "afi": "ipv6",
+# "cost": 30,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.2"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0",
+# "type": "gigabitethernet"
+# }
+# ]
+#
+# "commands": [
+# "no router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0",
+# "no router ospfv3 LAB3 area 0.0.0.2 interface GigabitEthernet 0/0/0/0",
+# "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 cost 10",
+# "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 authentication message-digest",
+# "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 authentication message-digest keychain iosxr"
+# ]
+#
+# "after": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "authentication": {
+# "message_digest": {
+# "keychain": "iosxr"
+# }
+# },
+# "cost": 10,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.3"
+# },
+# "process_id": "LAB1"
+# }
+# ]
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/1",
+# "type": "gigabitethernet"
+# }
+# ]
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config router ospf
+# Thu Oct 23 06:28:15.025 UTC
+# router ospf LAB
+# area 0.0.0.0
+# !
+# area 0.0.0.9
+# !
+# !
+# router ospf LAB1
+# area 0.0.0.1
+# !
+# area 0.0.0.3
+# interface GigabitEthernet0/0/0/1
+# cost 10
+# authentication message-digest keychain iosxr
+# !
+# !
+# !
+# router ospf LAB3
+# area 0.0.0.3
+# !
+# !
+# router ospf ipv4
+# !
+
+# Using deleted
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config router ospf
+# Thu Oct 23 06:28:15.025 UTC
+# router ospf LAB
+# area 0.0.0.0
+# !
+# area 0.0.0.9
+# !
+# !
+# router ospf LAB1
+# area 0.0.0.1
+# !
+# area 0.0.0.3
+# interface GigabitEthernet0/0/0/1
+# cost 10
+# authentication message-digest keychain iosxr
+# !
+# !
+# !
+# router ospf LAB3
+# area 0.0.0.3
+# !
+# !
+# router ospf ipv4
+# !
+
+- name: Deleted existing OSPF interfaces from the device
+ cisco.iosxr.iosxr_ospf_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ type: gigabitethernet
+ state: deleted
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "authentication": {
+# "message_digest": {
+# "keychain": "iosxr"
+# }
+# },
+# "cost": 10,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.3"
+# },
+# "process_id": "LAB1"
+# }
+# ]
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/1",
+# "type": "gigabitethernet"
+# }
+# ],
+#
+# "commands": [
+# "no router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1"
+# ]
+#
+# "after": []
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config router ospf
+# Thu Oct 23 06:34:38.319 UTC
+# router ospf LAB
+# area 0.0.0.0
+# !
+# area 0.0.0.9
+# !
+# !
+# router ospf LAB1
+# area 0.0.0.1
+# !
+# area 0.0.0.3
+# !
+# !
+# router ospf LAB3
+# area 0.0.0.3
+# !
+# !
+# router ospf ipv4
+# !
+
+# Using parsed
+# parsed.cfg
+# ------------
+# router ospf LAB
+# area 0.0.0.0
+# !
+# area 0.0.0.9
+# !
+# !
+# router ospf LAB1
+# area 0.0.0.1
+# !
+# area 0.0.0.3
+# !
+# !
+# router ospf LAB3
+# area 0.0.0.3
+# interface GigabitEthernet0/0/0/0
+# cost 20
+# authentication message-digest keychain cisco
+# !
+# !
+# !
+# router ospf ipv4
+# !
+- name: Parsed the device configuration to get output commands
+ cisco.iosxr.iosxr_ospf_interfaces:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+#
+# "parsed": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "authentication": {
+# "message_digest": {
+# "keychain": "cisco"
+# }
+# },
+# "cost": 20,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.3"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0",
+# "type": "gigabitethernet"
+# }
+# ]
+#
+# Using rendered
+#
+#
+- name: Render the commands for provided configuration
+ cisco.iosxr.iosxr_ospf_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/0
+ type: gigabitethernet
+ address_family:
+ - afi: ipv4
+ processes:
+ - process_id: "LAB3"
+ area:
+ area_id: 0.0.0.3
+ cost: 20
+ authentication:
+ message_digest:
+ keychain: cisco
+ - afi: ipv6
+ processes:
+ - process_id: "LAB3"
+ area:
+ area_id: 0.0.0.2
+ cost: 30
+ state: rendered
+
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+#
+# "rendered": [
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 cost 20",
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest",
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest keychain cisco",
+# "router ospfv3 LAB3 area 0.0.0.2 interface GigabitEthernet 0/0/0/0 cost 30"
+# ]
+
+
+# Using gathered
+#
+# Before state:
+# -------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config router ospf
+# Thu Oct 23 06:50:38.743 UTC
+# router ospf LAB
+# area 0.0.0.0
+# !
+# area 0.0.0.9
+# !
+# !
+# router ospf LAB1
+# area 0.0.0.1
+# !
+# area 0.0.0.3
+# !
+# !
+# router ospf LAB3
+# area 0.0.0.3
+# interface GigabitEthernet0/0/0/0
+# cost 20
+# authentication message-digest keychain cisco
+# !
+# !
+# !
+# router ospf ipv4
+# !
+
+
+- name: Gather ospf_interfaces routes configuration
+ cisco.iosxr.iosxr_ospf_interfaces:
+ state: gathered
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+# "gathered": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "authentication": {
+# "message_digest": {
+# "keychain": "cisco"
+# }
+# },
+# "cost": 20,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.3"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# },
+# {
+# "afi": "ipv6",
+# "cost": 30,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.2"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0",
+# "type": "gigabitethernet"
+# }
+# ]
+#
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.ospf_interfaces.ospf_interfaces import (
+ Ospf_interfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.ospf_interfaces.ospf_interfaces import (
+ Ospf_interfaces,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ module = AnsibleModule(
+ argument_spec=Ospf_interfacesArgs.argument_spec,
+ mutually_exclusive=[["config", "running_config"]],
+ required_if=[
+ ["state", "merged", ["config"]],
+ ["state", "replaced", ["config"]],
+ ["state", "overridden", ["config"]],
+ ["state", "rendered", ["config"]],
+ ["state", "parsed", ["running_config"]],
+ ],
+ supports_check_mode=True,
+ )
+
+ result = Ospf_interfaces(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospfv2.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospfv2.py
new file mode 100644
index 00000000..660387bb
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospfv2.py
@@ -0,0 +1,2544 @@
+#!/usr/bin/python
+#
+# 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/>.
+#
+
+"""
+The module file for iosxr_ospfv2
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+module: iosxr_ospfv2
+short_description: OSPFv2 resource module
+description: This module manages global OSPFv2 configuration on devices running Cisco
+ IOS-XR
+version_added: 1.0.0
+author:
+- Rohit Thakur (@rohitthakur2590)
+notes:
+- Tested against IOS-XR 6.1.3
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html)
+options:
+ config:
+ description: A list of OSPFv2 process configuration
+ type: dict
+ suboptions:
+ processes:
+ description: A list of OSPFv2 instances configuration
+ type: list
+ elements: dict
+ suboptions:
+ address_family_unicast:
+ description: Enable unicast topology for ipv4 address family
+ type: bool
+ adjacency_stagger:
+ description: Stagger OSPFv2 adjacency bring up
+ type: dict
+ suboptions:
+ min_adjacency:
+ description: Initial number of neighbors to bring up per area (default
+ 2)
+ type: int
+ max_adjacency:
+ description: Maximum simultaneous neighbors to bring up
+ type: int
+ disable:
+ description: Disable stagger OSPFv2 adjacency
+ type: bool
+ authentication:
+ description: Enable authentication
+ type: dict
+ suboptions:
+ keychain:
+ description: Specify keychain name
+ type: str
+ message_digest:
+ description: Use message-digest authentication
+ type: dict
+ suboptions:
+ set:
+ description: Specify message-digest selection
+ type: bool
+ keychain:
+ description: Specify keychain name
+ type: str
+ no_auth:
+ description: Use no authentication
+ type: bool
+ apply_weight:
+ description: Enable weights configured under interfaces for load sharing
+ type: dict
+ suboptions:
+ bandwidth:
+ description: Reference bandwidth to use for calculation (Mbits/sec)
+ type: int
+ default_weight:
+ description: Specify default weight value to use when it is not configured
+ under interface
+ type: int
+ areas:
+ description: Configure OSPFv2 areas' properties
+ type: list
+ elements: dict
+ suboptions:
+ area_id:
+ description: Area ID as IP address or integer
+ type: str
+ required: true
+ authentication:
+ description: Enable authentication
+ type: dict
+ suboptions:
+ keychain:
+ description: Specify keychain name
+ type: str
+ message_digest:
+ description: Use message-digest authentication
+ type: dict
+ suboptions:
+ keychain:
+ description: Specify keychain name
+ type: str
+ no_auth:
+ description: Use no authentication
+ type: bool
+ authentication_key:
+ description: Used to mention authentication password (key)
+ type: dict
+ suboptions:
+ password:
+ description: The OSPFv2 password (key)
+ type: str
+ clear:
+ description: Specifies an UNENCRYPTED password (key) will follow
+ type: str
+ encrypted:
+ description: Specifies an ENCRYPTED password (key) will follow
+ type: str
+ default_cost:
+ description: Set the summary default-cost of a NSSA/stub area. Stub's
+ advertised external route metric
+ type: int
+ cost:
+ description: Interface cost
+ type: int
+ dead_interval:
+ description: Interval after which a neighbor is declared dead
+ type: int
+ hello_interval:
+ description: Time between HELLO packets
+ type: int
+ transmit_delay:
+ description: Estimated time needed to send link-state update packet
+ type: int
+ mpls:
+ description: Configure MPLS routing protocol parameters
+ type: dict
+ suboptions:
+ traffic_eng:
+ description: Configure an ospf area to run MPLS Traffic Engineering
+ type: bool
+ ldp:
+ description: Configure LDP parameters
+ type: dict
+ suboptions:
+ auto_config:
+ description: Enable LDP IGP interface auto-configuration
+ type: bool
+ sync:
+ description: Enable LDP IGP synchronization
+ type: bool
+ sync_igp_shortcuts:
+ description: LDP sync for igp-shortcut tunnels
+ type: bool
+ mtu_ignore:
+ description: Enable/Disable ignoring of MTU in DBD packets
+ type: str
+ choices:
+ - enable
+ - disable
+ bfd:
+ description: Configure BFD parameters
+ type: dict
+ suboptions:
+ fast_detect:
+ description: Configure fast detection
+ type: dict
+ suboptions:
+ set:
+ description: Enable fast detection only
+ type: bool
+ strict_mode:
+ description: Hold down neighbor session until BFD session is up
+ type: bool
+ minimum_interval:
+ description: Hello interval in milli-seconds
+ type: int
+ multiplier:
+ description: Detect multiplier
+ type: int
+ nssa:
+ description:
+ - NSSA settings for the area
+ type: dict
+ suboptions:
+ set:
+ description: Configure area as NSSA
+ type: bool
+ default_information_originate:
+ description: Originate default Type 7 LSA
+ type: dict
+ suboptions:
+ metric:
+ description: OSPFv2 default metric
+ type: int
+ metric_type:
+ description: Metric type for default routes
+ type: int
+ no_redistribution:
+ description: Do not send redistributed LSAs into NSSA area
+ type: bool
+ no_summary:
+ description: Do not send summary LSAs into NSSA area
+ type: bool
+ translate:
+ description: Translate LSA
+ type: dict
+ suboptions:
+ type7:
+ description:
+ - Translate from Type 7 to Type 5
+ type: dict
+ suboptions:
+ always:
+ description:
+ - Always translate LSAs
+ type: bool
+ ranges:
+ description: Summarize routes matching address/mask (border routers
+ only)
+ type: list
+ elements: dict
+ suboptions:
+ address:
+ description: IP in Prefix format (x.x.x.x/len)
+ type: str
+ required: true
+ advertise:
+ description: Advertise this range (default)
+ type: bool
+ not_advertise:
+ description: DoNotAdvertise this range
+ type: bool
+ route_policy:
+ description: Specify the route-policy to filter type 3 LSAs (list
+ can have one inbound and/or one outbound policy only)
+ type: list
+ elements: dict
+ suboptions:
+ parameters:
+ description: Specify parameter values for the policy
+ type: list
+ elements: str
+ direction:
+ description: Specify inbound or outbound
+ type: str
+ choices:
+ - in
+ - out
+ stub:
+ description:
+ - Settings for configuring the area as a stub
+ type: dict
+ suboptions:
+ set:
+ description:
+ - Configure the area as a stub
+ type: bool
+ no_summary:
+ description:
+ - Do not send summary LSA into stub area
+ type: bool
+ virtual_link:
+ description: Define a virtual link
+ type: list
+ elements: dict
+ suboptions:
+ id:
+ description: Router-ID of virtual link neighbor (A.B.C.D)
+ type: str
+ required: true
+ authentication:
+ description: Enable authentication
+ type: dict
+ suboptions:
+ keychain:
+ description: Specify keychain name
+ type: str
+ message_digest:
+ description: Use message-digest authentication
+ type: dict
+ suboptions:
+ keychain:
+ description: Specify keychain name
+ type: str
+ no_auth:
+ description: Use no authentication
+ type: bool
+ authentication_key:
+ description: Used to mention authentication password (key)
+ type: dict
+ suboptions:
+ password:
+ description: The OSPFv2 password (key)
+ type: str
+ clear:
+ description: Specifies an UNENCRYPTED password (key) will
+ follow
+ type: str
+ encrypted:
+ description: Specifies an ENCRYPTED password (key) will follow
+ type: str
+ dead_interval:
+ description: Interval after which a neighbor is declared dead
+ type: int
+ hello_interval:
+ description: Time between HELLO packets
+ type: int
+ retransmit_interval:
+ description: Delay between LSA retransmissions
+ type: int
+ transmit_delay:
+ description: Link state transmit delay
+ type: int
+ message_digest_key:
+ description: Message digest authentication password (key)
+ type: dict
+ suboptions:
+ id:
+ description: Key ID (1-255)
+ type: int
+ required: true
+ md5:
+ description: Use MD5 Algorithm
+ type: dict
+ suboptions:
+ password:
+ description: The OSPFv2 password (key)
+ type: str
+ clear:
+ description: Specifies an UNENCRYPTED password (key) will
+ follow
+ type: bool
+ encrypted:
+ description: Specifies an ENCRYPTED password (key) will
+ follow
+ type: bool
+
+ authentication_key:
+ description: Used to mention authentication password (key)
+ type: dict
+ suboptions:
+ password:
+ description: The OSPFv2 password (key)
+ type: str
+ clear:
+ description: Specifies an UNENCRYPTED password (key) will follow
+ type: bool
+ encrypted:
+ description: Specifies an ENCRYPTED password (key) will follow
+ type: bool
+ auto_cost:
+ description: Calculate OSPFv2 interface cost according to bandwidth
+ type: dict
+ suboptions:
+ reference_bandwidth:
+ description: Specify reference bandwidth in megabits per sec
+ type: int
+ disable:
+ description: Assign OSPFv2 cost based on interface type
+ type: bool
+ bfd:
+ description: Configure BFD parameters
+ type: dict
+ suboptions:
+ fast_detect:
+ description: Configure fast detection
+ type: dict
+ suboptions:
+ set:
+ description: Enable fast detection only
+ type: bool
+ strict_mode:
+ description: Hold down neighbor session until BFD session is up
+ type: bool
+ minimum_interval:
+ description: Hello interval in milli-seconds
+ type: int
+ multiplier:
+ description: Detect multiplier
+ type: int
+ capability:
+ description: Enable specific OSPFv2 feature
+ type: dict
+ suboptions:
+ type7:
+ description: NSSA capability
+ type: str
+ opaque:
+ description: Configure opaque LSA
+ type: dict
+ suboptions:
+ disable:
+ description: Disable Opaque LSA capability
+ type: bool
+ set:
+ description: Enable opaque LSA
+ type: bool
+ cost:
+ description: Interface cost (1-65535)
+ type: int
+ database_filter:
+ description: Filter OSPFv2 LSA during synchronization and flooding (all
+ outgoing LSA). Enable/Disable filtering
+ type: str
+ choices: [enable, disable]
+ dead_interval:
+ description: Interval after which a neighbor is declared dead
+ type: int
+ default_information_originate:
+ description: Distribute default route
+ type: dict
+ suboptions:
+ always:
+ description: Always advertise default route
+ type: bool
+ metric:
+ description: OSPFv2 default metric
+ type: int
+ metric_type:
+ description: OSPFv2 metric type for default routes
+ type: int
+ route_policy:
+ description: Apply route-policy to default-information origination
+ type: str
+ set:
+ description: Enable distribution of default route
+ type: bool
+ default_metric:
+ description: Set metric of redistributed routes
+ type: int
+ demand_circuit:
+ description: Enable/Disable OSPFv2 demand circuit
+ type: str
+ choices: [enable, disable]
+ distance:
+ description: Define an administrative distance
+ type: dict
+ suboptions:
+ admin_distance:
+ description: Administrative distance
+ type: list
+ elements: dict
+ suboptions:
+ value:
+ description: Distance value
+ type: int
+ source:
+ description: Source IP address
+ type: str
+ wildcard:
+ description: IP wild card bits (A.B.C.D)
+ type: str
+ access_list:
+ description: Access list name
+ type: str
+ ospf_distance:
+ description: OSPFv2 administrative distance
+ type: dict
+ suboptions:
+ external:
+ description: Distance for external routes
+ type: int
+ inter_area:
+ description: Distance for inter-area routes
+ type: int
+ intra_area:
+ description: Distance for intra-area routes
+ type: int
+ distribute_link_state:
+ description: Enable Distribution of LSAs to external services
+ type: dict
+ suboptions:
+ instance_id:
+ description: Set distribution process instance identifier
+ type: int
+ throttle:
+ description: Throttle time between successive LSA updates
+ type: int
+ distribute_bgp_ls:
+ description: Enable Distribution of LSAs to external services
+ type: dict
+ suboptions:
+ instance_id:
+ description: Set distribution process instance identifier
+ type: int
+ throttle:
+ description: Throttle time between successive LSA updates
+ type: int
+ distribute_list:
+ description: Filter networks in routing updates (list can have one inbound
+ and/or one outbound policy only)
+ type: list
+ elements: dict
+ suboptions:
+ access_list:
+ description: Inbound/outbound access-list
+ type: str
+ direction:
+ description: Filter incoming/outgoing routing updates
+ type: str
+ choices:
+ - in
+ - out
+ outgoing_params:
+ description: Specify additional parameters for outgoing updates only
+ type: dict
+ suboptions:
+ route_type:
+ description: Type of routes
+ type: str
+ choices:
+ - bgp
+ - connected
+ - dagr
+ - ospf
+ - static
+ id:
+ description:
+ - For BGP, specify AS number. 2-byte AS number (or) 4-byte AS
+ number in asdot (X.Y) format (or) 4-byte AS number in asplain
+ format
+ - For OSPF, specify OSPFv2 instance name
+ type: str
+ route_policy:
+ description: Route Policy to filter OSPFv2 prefixes (for incoming
+ updates only)
+ type: str
+ external_out:
+ description: Enable/Disable advertisement of intra-area prefixes as external
+ type: str
+ choices:
+ - enable
+ - disable
+ flood_reduction:
+ description: Enable/Disable OSPFv2 Flood Reduction
+ type: str
+ choices:
+ - enable
+ - disable
+ hello_interval:
+ description: Time between HELLO packets (<1-65535> seconds)
+ type: int
+ ignore_lsa_mospf:
+ description: Do not complain upon receiving MOSPFv2 Type 6 LSA
+ type: bool
+ link_down_fast_detect:
+ description: Enable fast or early detection of link-down events
+ type: bool
+ log_adjacency_changes:
+ description: Log adjacency state changes
+ type: dict
+ suboptions:
+ set:
+ description: Set log adjacency
+ type: bool
+ disable:
+ description: Disable log adjacency changes
+ type: bool
+ detail:
+ description: Log all state changes
+ type: bool
+ loopback_stub_network:
+ description: Advertise loopback as a stub network
+ type: str
+ choices:
+ - enable
+ - disable
+ max_lsa:
+ description:
+ - Feature to limit the number of non-self-originated LSAs
+ type: dict
+ suboptions:
+ threshold:
+ description:
+ - Threshold value (%) at which to generate a warning message
+ type: int
+ ignore_count:
+ description:
+ - Set count on how many times adjacencies can be suppressed
+ type: int
+ ignore_time:
+ description:
+ - Set number of minutes during which all adjacencies are suppressed
+ type: int
+ reset_time:
+ description:
+ - Set number of minutes after which ignore-count is reset to zero
+ type: int
+ warning_only:
+ description:
+ - Log a warning message when limit is exceeded
+ type: bool
+ max_metric:
+ description: Set maximum metric
+ type: dict
+ suboptions:
+ router_lsa:
+ description: Maximum metric in self-originated router-LSAs
+ type: dict
+ suboptions:
+ set:
+ description: Set router-lsa attribute
+ type: bool
+ external_lsa:
+ description: External LSA configuration
+ type: dict
+ suboptions:
+ set:
+ description: Set external-lsa attribute
+ type: bool
+ max_metric_value:
+ description: Set max metric value for external LSAs
+ type: int
+ include_stub:
+ description:
+ - Advertise Max metric for Stub links as well
+ type: bool
+ on_startup:
+ description:
+ - Effective only at startup
+ type: dict
+ suboptions:
+ set:
+ description:
+ - Set on-startup attribute
+ type: bool
+ wait_period:
+ description:
+ - Wait period in seconds after startup
+ type: int
+ wait_for_bgp_asn:
+ description:
+ - ASN of BGP to wait for
+ type: int
+ summary_lsa:
+ description:
+ - Summary LSAs configuration
+ type: dict
+ suboptions:
+ set:
+ description:
+ - Set summary-lsa attribute
+ type: bool
+ max_metric_value:
+ description:
+ - Max metric value for summary LSAs
+ type: int
+ message_digest_key:
+ description: Message digest authentication password (key)
+ type: dict
+ suboptions:
+ id:
+ description: Key ID
+ type: int
+ required: true
+ md5:
+ description: Use MD5 Algorithm
+ type: dict
+ required: true
+ suboptions:
+ password:
+ description: The OSPFv2 password (key)
+ type: str
+ clear:
+ description: Specifies an UNENCRYPTED password (key) will follow
+ type: bool
+ encrypted:
+ description: Specifies an ENCRYPTED password (key) will follow
+ type: bool
+ microloop_avoidance:
+ description: Avoid microloops
+ type: dict
+ suboptions:
+ protected:
+ description: Avoid microloops for protected prefixes only)
+ type: bool
+ rib_update_delay:
+ description: Delay to introduce between SPF and RIB updates
+ type: int
+ segment_routing:
+ description: Enable segment routing microloop avoidance
+ type: bool
+ monitor_convergence:
+ description: Enables OSPFv2 route convergence monitoring
+ type: dict
+ suboptions:
+ prefix_list:
+ description: Enables Individual Prefix Monitoring
+ type: str
+ track_external_routes:
+ description: Enables Tracking External(Type-5/7) Prefix monitoring
+ type: bool
+ track_ip_frr:
+ description: Enables Tracking IP-Frr Convergence
+ type: bool
+ track_summary_routes:
+ description: Enables Tracking Summary(Inter-Area) Prefix monitoring
+ type: bool
+ mpls:
+ description: Configure MPLS routing protocol parameters
+ type: dict
+ suboptions:
+ traffic_eng:
+ description: Routing protocol commands for MPLS Traffic Engineering
+ type: dict
+ suboptions:
+ autoroute_exclude:
+ description: Exclude IP address destinations from using TE tunnels
+ type: dict
+ suboptions:
+ route_policy:
+ description: Policy name
+ type: str
+ parameters:
+ description: Specify parameter values for the policy
+ type: list
+ elements: str
+ igp_intact:
+ description: Retain one or more IPv4 nexthops with tunnel nexthops
+ type: bool
+ ldp_sync_update:
+ description: Enable LDP sync induced metric propagation
+ type: bool
+ multicast_intact:
+ description: Publish multicast-intact paths to RIB
+ type: bool
+ router_id:
+ description: Traffic Engineering stable IP address for system
+ type: str
+ ldp:
+ description: Configure LDP parameters
+ type: dict
+ suboptions:
+ auto_config:
+ description: Enable LDP IGP interface auto-configuration
+ type: bool
+ sync:
+ description: Enable LDP IGP synchronization
+ type: bool
+ sync_igp_shortcuts:
+ description: LDP sync for igp-shortcut tunnels
+ type: bool
+ mtu_ignore:
+ description: Enable/Disable ignoring of MTU in DBD packets
+ type: str
+ choices:
+ - enable
+ - disable
+ network:
+ description: Network type
+ type: dict
+ suboptions:
+ broadcast:
+ description: Specify OSPFv2 broadcast multi-access network
+ type: bool
+ non_broadcast:
+ description: Specify OSPFv2 NBMA network
+ type: bool
+ point_to_multipoint:
+ description: Specify OSPFv2 point-to-multipoint network
+ type: bool
+ point_to_point:
+ description: Specify OSPFv2 point-to-point network
+ type: bool
+ nsf:
+ description: Non-stop forwarding
+ type: dict
+ suboptions:
+ cisco:
+ description: Cisco Non-stop forwarding
+ type: dict
+ suboptions:
+ enforce_global:
+ description: Cancel NSF restart when non-NSF-aware neighbors detected
+ for the whole OSPFv2 process
+ type: bool
+ set:
+ description: Enable Cisco NSF
+ type: bool
+ flush_delay_time:
+ description: Maximum time allowed for external route learning
+ type: int
+ ietf:
+ description: IETF graceful restart
+ type: dict
+ suboptions:
+ helper_disable:
+ description: Disable router's helper support level
+ type: bool
+ set:
+ description: Only enable ietf option
+ type: bool
+ interval:
+ description: Minimum interval between NSF restarts (<90-3600> seconds)
+ type: int
+ lifetime:
+ description: Maximum route lifetime following restart (<90-1800> seconds)
+ type: int
+ nsr:
+ description: Enable NSR for all VRFs in this process. 'False' option to
+ disable NSR for all VRFs in this process
+ type: bool
+ packet_size:
+ description: Size of OSPFv2 packets to use. min=576 max=MTU bytes
+ type: int
+ passive:
+ description: Enable/Disable passive
+ type: str
+ choices:
+ - enable
+ - disable
+ prefix_suppression:
+ description: Suppress advertisement of the prefixes
+ type: dict
+ suboptions:
+ set:
+ description: Set the suppression option
+ type: bool
+ secondary_address:
+ description: Enable/Disable secondary address suppression
+ type: bool
+ priority:
+ description: Router priority
+ type: int
+ process_id:
+ description: The OSPFv2 Process ID
+ type: str
+ required: true
+ protocol_shutdown:
+ description: Protocol specific configuration
+ type: dict
+ suboptions:
+ host_mode:
+ description: Only traffic destined for this box allowed(cisco-support)
+ type: bool
+ on_reload:
+ description: Shutdown post reload only
+ type: bool
+ set:
+ description: Shutdown the OSPFv2 Protocol
+ type: bool
+ limit:
+ description: High watermark for incoming priority events
+ type: dict
+ suboptions:
+ high:
+ description: Hello events are dropped when incoming event queue
+ exceeds this value
+ type: int
+ low:
+ description: DBD/LS Update/Req packets are dropped when incoming
+ event queue exceeds this value
+ type: int
+ medium:
+ description: LSA ACKs are dropped when incoming event queue exceeds
+ this value
+ type: int
+ redistribute:
+ description: Redistribute information from another routing Protocol
+ type: dict
+ suboptions:
+ route_type:
+ description: Route type to redistribute
+ type: str
+ choices: [application, bgp, connected, dagr, eigrp, isis, mobile,
+ ospf, rip, static, subscriber]
+ id:
+ description: OnePK application name for application routes (or) AS
+ number for bgp and eigrp (or) instance name for isis and ospf
+ type: str
+ level:
+ description: ISIS levels
+ choices: [1, 2, 12]
+ type: int
+ lsa_type_summary:
+ description: LSA type 3 for redistributed routes
+ type: bool
+ match:
+ description: Redistribution of routes. For OSPFv2 - external/internal/nssa-external
+ 1/2. For EIGRP - external/internal
+ type: str
+ metric:
+ description: Metric for redistributed routes
+ type: int
+ metric_type:
+ description: OSPFv2 exterior metric type for redistributed routes
+ type: int
+ choices: [1, 2]
+ route_policy:
+ description: Apply route-policy to redistribution
+ type: dict
+ suboptions:
+ name:
+ description: Name of the policy
+ type: str
+ parameters:
+ description: Specify parameter values for the policy
+ type: list
+ elements: str
+ nssa_only:
+ description: Redistribute to NSSA areas only
+ type: bool
+ preserve_med:
+ description: Preserve med of BGP routes
+ type: bool
+ tag:
+ description: Set tag for routes redistributed into OSPFv2
+ type: int
+ retransmit_interval:
+ description: Delay between LSA retransmissions
+ type: int
+ router_id:
+ description: OSPFv2 router-id in IPv4 address format (A.B.C.D)
+ type: str
+ security_ttl:
+ description: Enable security
+ type: dict
+ suboptions:
+ set:
+ description: Enable ttl security
+ type: bool
+ hops:
+ description: Maximum number of IP hops allowed <1-254>
+ type: int
+ summary_in:
+ description: Enable/Disable advertisement of external prefixes as inter-area
+ type: str
+ choices: [enable, disable]
+ summary_prefix:
+ description: Configure IP address summaries
+ type: list
+ elements: dict
+ suboptions:
+ prefix:
+ description: IP summary address/mask (A.B.C.D/prefix)
+ type: str
+ required: true
+ not_advertise:
+ description: Suppress routes that match the specified prefix/mask
+ pair
+ type: bool
+ tag:
+ description: Set tag
+ type: int
+ timers:
+ description: Configure timer related constants
+ type: dict
+ suboptions:
+ graceful_shutdown:
+ description: Timers for graceful shutdown(cisco-support)
+ type: dict
+ suboptions:
+ initial_delay:
+ description: Delay before starting graceful shutdown
+ type: int
+ retain_routes:
+ description: Time to keep routes active after graceful shutdown
+ type: int
+ lsa:
+ description: OSPFv2 global LSA timers
+ type: dict
+ suboptions:
+ group_pacing:
+ description: OSPFv2 LSA group pacing timer. Interval between group
+ of LSA being refreshed or maxaged
+ type: int
+ min_arrival:
+ description: OSPFv2 MinLSArrival timer. The minimum interval in
+ millisec between accepting the same LSA
+ type: int
+ refresh:
+ description: OSPFv2 LSA refresh interval. How often self-originated
+ LSAs should be refreshed, in seconds
+ type: int
+ throttle:
+ description: OSPFv2 throttle timers
+ type: dict
+ suboptions:
+ lsa_all:
+ description: LSA throttle timers for all types of OSPFv2 LSAs
+ type: dict
+ suboptions:
+ initial_delay:
+ description: Delay to generate first occurance of LSA in milliseconds
+ type: int
+ min_delay:
+ description: Minimum delay between originating the same LSA
+ in milliseconds
+ type: int
+ max_delay:
+ description: Maximum delay between originating the same LSA
+ in milliseconds
+ type: int
+ spf:
+ description: OSPFv2 SPF throttle timers
+ type: dict
+ suboptions:
+ change_delay:
+ description: Delay between receiving a change to SPF calculation
+ in milliseconds
+ type: int
+ second_delay:
+ description: Delay between first and second SPF calculation
+ in milliseconds
+ type: int
+ max_wait:
+ description: Maximum wait time in milliseconds for SPF calculations
+ type: int
+ fast_reroute:
+ description: Fast-reroute throttle timer. Delay between end of
+ SPF and start of the fast-reroute computation in milliseconds
+ type: int
+ pacing_flood:
+ description: OSPFv2 flood pacing timer. Interval in msec to pace flooding
+ on all interfaces
+ type: int
+ transmit_delay:
+ description: Estimated time needed to send link-state update packet
+ type: int
+ weight:
+ description: Interface weight
+ type: int
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config router ospf).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state the configuration should be left in.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - deleted
+ - parsed
+ - gathered
+ - rendered
+ - overridden
+ default: merged
+
+"""
+
+EXAMPLES = """
+# Using merged
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# Thu Jun 11 15:54:44.569 UTC
+# % No such configuration item(s)
+#
+
+- name: Merge provided OSPFv2 configuration with the existing configuration
+ cisco.iosxr.iosxr_ospfv2:
+ config:
+ processes:
+ - process_id: '27'
+ areas:
+ - area_id: '10'
+ hello_interval: 2
+ authentication:
+ keychain: ansi11393
+ - process_id: '26'
+ adjacency_stagger:
+ max_adjacency: 20
+ min_adjacency: 10
+ - process_id: '10'
+ authentication:
+ keychain: ansible_test1102
+ areas:
+ - area_id: '11'
+ default_cost: 5
+ cost: 11
+ - area_id: 22
+ default_cost: 6
+ - process_id: '30'
+ areas:
+ - area_id: 11
+ default_cost: 5
+ - area_id: 22
+ default_cost: 6
+
+ cost: 2
+ default_metric: 10
+ transmit_delay: 2
+ hello_interval: 1
+ dead_interval: 2
+ retransmit_interval: 2
+ weight: 2
+ packet_size: 577
+ priority: 1
+ router_id: 2.2.2.2
+ demand_circuit: enable
+ passive: disable
+ summary_in: enable
+ flood_reduction: disable
+ mtu_ignore: enable
+ external_out: disable
+ state: merged
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {}
+#
+# "commands": [
+# "router ospf 30",
+# "cost 2",
+# "weight 2",
+# "passive disable",
+# "priority 1",
+# "flood-reduction disable",
+# "default-metric 10",
+# "router-id 2.2.2.2",
+# "demand-circuit enable",
+# "packet-size 577",
+# "transmit-delay 2",
+# "summary-in enable",
+# "external-out disable",
+# "dead-interval 2",
+# "hello-interval 1",
+# "retransmit-interval 2",
+# "mtu-ignore enable",
+# "area 11 default-cost 5",
+# "area 22 default-cost 6",
+# "router ospf 26",
+# "adjacency stagger 10 20",
+# "authentication message-digest keychain ansible1101pass",
+# "router ospf 27",
+# "area 10 authentication keychain ansi11393",
+# "area 10 hello-interval 2",
+# "router ospf 10",
+# "authentication keychain ansible_test1102",
+# "area 11 default-cost 5",
+# "area 11 cost 11",
+# "area 22 default-cost 6"
+# ]
+#
+# "after": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "authentication": {
+# "keychain": "ansible_test1102"
+# },
+# "process_id": "10"
+# },
+# {
+# "adjacency_stagger": {
+# "max_adjacency": 20,
+# "min_adjacency": 10
+# },
+# "authentication": {
+# "message_digest": {
+# "keychain": "ansible1101pass"
+# }
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": "enable",
+# "external_out": "disable",
+# "flood_reduction": "disable",
+# "hello_interval": 1,
+# "mtu_ignore": "enable",
+# "packet_size": 577,
+# "passive": "disable",
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "summary_in": "enable",
+# "transmit_delay": 2,
+# "weight": 2
+# }
+# ]
+# }
+#
+#
+# ------------
+# After state
+# ------------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# Thu Jun 11 16:06:44.406 UTC
+# router ospf 10
+# authentication keychain ansible_test1102
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# authentication keychain ansi11393
+# hello-interval 2
+# !
+# !
+# router ospf 30
+# router-id 2.2.2.2
+# summary-in enable
+# external-out disable
+# cost 2
+# packet-size 577
+# weight 2
+# passive disable
+# priority 1
+# mtu-ignore enable
+# flood-reduction disable
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit enable
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+#
+
+
+# Using replaced
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# Thu Jun 11 16:06:44.406 UTC
+# router ospf 10
+# authentication keychain ansible_test1102
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# authentication keychain ansi11393
+# hello-interval 2
+# !
+# !
+# router ospf 30
+# router-id 2.2.2.2
+# summary-in enable
+# external-out disable
+# cost 2
+# packet-size 577
+# weight 2
+# passive disable
+# priority 1
+# mtu-ignore enable
+# flood-reduction disable
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit enable
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+#
+
+- name: Replace OSPFv2 routes configurations from the device
+ cisco.iosxr.iosxr_ospfv2:
+ config:
+ processes:
+ - process_id: 27
+ areas:
+ - area_id: 10
+ hello_interval: 2
+ - area_id: 20
+ cost: 2
+ default_cost: 2
+ authentication:
+ keychain: ansi11393
+ - process_id: 26
+ adjacency_stagger:
+ min_adjacency: 10
+ max_adjacency: 20
+ state: replaced
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "authentication": {
+# "keychain": "ansible_test1102"
+# },
+# "process_id": "10"
+# },
+# {
+# "adjacency_stagger": {
+# "max_adjacency": 20,
+# "min_adjacency": 10
+# },
+# "authentication": {
+# "message_digest": {
+# "keychain": "ansible1101pass"
+# }
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": "enable",
+# "external_out": "disable",
+# "flood_reduction": "disable",
+# "hello_interval": 1,
+# "mtu_ignore": "enable",
+# "packet_size": 577,
+# "passive": "disable",
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "summary_in": "enable",
+# "transmit_delay": 2,
+# "weight": 2
+# }
+# ]
+# }
+#
+# "commands": [
+# "router ospf 27",
+# "no area 10 authentication keychain ansi11393",
+# "area 20 authentication keychain ansi11393",
+# "area 20 default-cost 2",
+# "area 20 cost 2"
+# ]
+#
+# "after": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "authentication": {
+# "keychain": "ansible_test1102"
+# },
+# "process_id": "10"
+# },
+# {
+# "adjacency_stagger": {
+# "max_adjacency": 20,
+# "min_adjacency": 10
+# },
+# "authentication": {
+# "message_digest": {
+# "keychain": "ansible1101pass"
+# }
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# },
+# {
+# "area_id": "20",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "cost": 2,
+# "default_cost": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": "enable",
+# "external_out": "disable",
+# "flood_reduction": "disable",
+# "hello_interval": 1,
+# "mtu_ignore": "enable",
+# "packet_size": 577,
+# "passive": "disable",
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "summary_in": "enable",
+# "transmit_delay": 2,
+# "weight": 2
+# }
+# ]
+# }
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/RP0/CPU0:anton(config)#do show running-config router ospf
+# Thu Jun 11 16:40:31.038 UTC
+# router ospf 10
+# authentication keychain ansible_test1102
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# cost 2
+# authentication keychain ansi11393
+# default-cost 2
+# !
+# !
+# router ospf 30
+# router-id 2.2.2.2
+# summary-in enable
+# external-out disable
+# cost 2
+# packet-size 577
+# weight 2
+# passive disable
+# priority 1
+# mtu-ignore enable
+# flood-reduction disable
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit enable
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+#
+
+
+# Using overridden
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# Thu Jun 11 16:06:44.406 UTC
+# router ospf 10
+# authentication keychain ansible_test1102
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# authentication keychain ansi11393
+# hello-interval 2
+# !
+# !
+# router ospf 30
+# router-id 2.2.2.2
+# summary-in enable
+# external-out disable
+# cost 2
+# packet-size 577
+# weight 2
+# passive disable
+# priority 1
+# mtu-ignore enable
+# flood-reduction disable
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit enable
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+#
+
+- name: Override existing OSPFv2 configurations from the device
+ cisco.iosxr.iosxr_ospfv2:
+ config:
+ processes:
+ - process_id: 27
+ areas:
+ - area_id: 10
+ hello_interval: 2
+ authentication:
+ keychain: ansi11393
+ - area_id: 20
+ cost: 2
+ default_cost: 2
+ authentication:
+ keychain: ansi11393
+ - process_id: 26
+ adjacency_stagger:
+ min_adjacency: 10
+ max_adjacency: 20
+ state: overridden
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "authentication": {
+# "keychain": "ansible_test1102"
+# },
+# "process_id": "10"
+# },
+# {
+# "adjacency_stagger": {
+# "max_adjacency": 20,
+# "min_adjacency": 10
+# },
+# "authentication": {
+# "message_digest": {
+# "keychain": "ansible1101pass"
+# }
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": "enable",
+# "external_out": "disable",
+# "flood_reduction": "disable",
+# "hello_interval": 1,
+# "mtu_ignore": "enable",
+# "packet_size": 577,
+# "passive": "disable",
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "summary_in": "enable",
+# "transmit_delay": 2,
+# "weight": 2
+# }
+# ]
+# }
+#
+# "commands": [
+# "router ospf 10",
+# "no authentication keychain ansible_test1102",
+# "no area 11 default-cost 5",
+# "no area 11 cost 11",
+# "no area 22 default-cost 6",
+# "router ospf 30",
+# "no cost 2",
+# "no weight 2",
+# "no passive disable",
+# "no priority 1",
+# "no flood-reduction disable",
+# "no default-metric 10",
+# "no router-id 2.2.2.2",
+# "no demand-circuit enable",
+# "no packet-size 577",
+# "no transmit-delay 2",
+# "no summary-in enable",
+# "no external-out disable",
+# "no dead-interval 2",
+# "no hello-interval 1",
+# "no retransmit-interval 2",
+# "no mtu-ignore enable",
+# "no area 11 default-cost 5",
+# "no area 22 default-cost 6",
+# "router ospf 27",
+# "area 20 authentication keychain ansi11393",
+# "area 20 default-cost 2",
+# "area 20 cost 2"
+# ]
+#
+# "after": {
+# "processes": [
+# {
+# "process_id": "10"
+# },
+# {
+# "adjacency_stagger": {
+# "max_adjacency": 20,
+# "min_adjacency": 10
+# },
+# "authentication": {
+# "message_digest": {
+# "keychain": "ansible1101pass"
+# }
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "hello_interval": 2
+# },
+# {
+# "area_id": "20",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "cost": 2,
+# "default_cost": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "process_id": "30"
+# }
+# ]
+# }
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# Thu Jun 11 16:50:36.332 UTC
+# router ospf 10
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# authentication keychain ansi11393
+# hello-interval 2
+# !
+# area 20
+# cost 2
+# authentication keychain ansi11393
+# default-cost 2
+# !
+# !
+# router ospf 30
+# !
+#
+
+
+# Using deleted
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# Thu Jun 11 16:06:44.406 UTC
+# router ospf 10
+# authentication keychain ansible_test1102
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# authentication keychain ansi11393
+# hello-interval 2
+# !
+# !
+# router ospf 30
+# router-id 2.2.2.2
+# summary-in enable
+# external-out disable
+# cost 2
+# packet-size 577
+# weight 2
+# passive disable
+# priority 1
+# mtu-ignore enable
+# flood-reduction disable
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit enable
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+#
+
+- name: Deleted existing OSPFv2 configurations from the device
+ cisco.iosxr.iosxr_ospfv2:
+ config:
+ processes:
+ - process_id: '10'
+ - process_id: '26'
+ - process_id: '27'
+ - process_id: '30'
+ state: deleted
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "authentication": {
+# "keychain": "ansible_test1102"
+# },
+# "process_id": "10"
+# },
+# {
+# "adjacency_stagger": {
+# "max_adjacency": 20,
+# "min_adjacency": 10
+# },
+# "authentication": {
+# "message_digest": {
+# "keychain": "ansible1101pass"
+# }
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": "enable",
+# "external_out": "disable",
+# "flood_reduction": "disable",
+# "hello_interval": 1,
+# "mtu_ignore": "enable",
+# "packet_size": 577,
+# "passive": "disable",
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "summary_in": "enable",
+# "transmit_delay": 2,
+# "weight": 2
+# }
+# ]
+# },
+#
+# "commands": [
+# "router ospf 10",
+# "no authentication keychain ansible_test1102",
+# "no area 11 default-cost 5",
+# "no area 11 cost 11",
+# "no area 22 default-cost 6",
+# "router ospf 26",
+# "no adjacency stagger 10 20",
+# "no authentication message-digest keychain ansible1101pass",
+# "router ospf 27",
+# "no area 10 authentication keychain ansi11393",
+# "no area 10 hello-interval 2",
+# "router ospf 30",
+# "no cost 2",
+# "no weight 2",
+# "no passive disable",
+# "no priority 1",
+# "no flood-reduction disable",
+# "no default-metric 10",
+# "no router-id 2.2.2.2",
+# "no demand-circuit enable",
+# "no packet-size 577",
+# "no transmit-delay 2",
+# "no summary-in enable",
+# "no external-out disable",
+# "no dead-interval 2",
+# "no hello-interval 1",
+# "no retransmit-interval 2",
+# "no mtu-ignore enable",
+# "no area 11 default-cost 5",
+# "no area 22 default-cost 6"
+# ]
+#
+# "after": {
+# "processes": [
+# {
+# "process_id": "10"
+# },
+# {
+# "process_id": "26"
+# },
+# {
+# "process_id": "27"
+# },
+# {
+# "process_id": "30"
+# }
+# ]
+# }
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/RP0/CPU0:anton(config)#show running-config router ospf
+# Thu Jun 11 17:07:34.218 UTC
+# router ospf 10
+# !
+# router ospf 26
+# !
+# router ospf 27
+# !
+# router ospf 30
+# !
+
+
+# Using parsed
+# parsed.cfg
+# ------------
+# Thu Jun 11 17:28:51.918 UTC
+# router ospf 10
+# authentication keychain ansible_test1102
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# authentication keychain ansi11393
+# hello-interval 2
+# !
+# !
+# router ospf 30
+# router-id 2.2.2.2
+# summary-in enable
+# external-out disable
+# cost 2
+# packet-size 577
+# weight 2
+# passive disable
+# priority 1
+# mtu-ignore enable
+# flood-reduction disable
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit enable
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+- name: Parsed the device configuration to get output commands
+ cisco.iosxr.iosxr_ospfv2:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+#
+# "parsed": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "authentication": {
+# "keychain": "ansible_test1102"
+# },
+# "process_id": "10"
+# },
+# {
+# "adjacency_stagger": {
+# "max_adjacency": 20,
+# "min_adjacency": 10
+# },
+# "authentication": {
+# "message_digest": {
+# "keychain": "ansible1101pass"
+# }
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": "enable",
+# "external_out": "disable",
+# "flood_reduction": "disable",
+# "hello_interval": 1,
+# "mtu_ignore": "enable",
+# "packet_size": 577,
+# "passive": "disable",
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "summary_in": "enable",
+# "transmit_delay": 2,
+# "weight": 2
+# }
+# ]
+# }
+
+
+
+# Using rendered
+#
+#
+- name: Render the commands for provided configuration
+ cisco.iosxr.iosxr_ospfv2:
+ config:
+ processes:
+ - process_id: 27
+ areas:
+ - area_id: 10
+ hello_interval: 2
+ authentication:
+ keychain: ansi11393
+ - process_id: 26
+ adjacency_stagger:
+ min_adjacency: 10
+ max_adjacency: 20
+ - process_id: 10
+ authentication:
+ keychain: ansible_test1102
+ areas:
+ - area_id: 11
+ default_cost: 5
+ cost: 11
+ - area_id: 22
+ default_cost: 6
+ - process_id: 30
+ areas:
+ - area_id: 11
+ default_cost: 5
+ - area_id: 22
+ default_cost: 6
+
+ cost: 2
+ default_metric: 10
+ transmit_delay: 2
+ hello_interval: 1
+ dead_interval: 2
+ retransmit_interval: 2
+ weight: 2
+ packet_size: 577
+ priority: 1
+ router_id: 2.2.2.2
+ demand_circuit: enable
+ passive: disable
+ summary_in: enable
+ flood_reduction: disable
+ mtu_ignore: enable
+ external_out: disable
+ state: rendered
+
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+#
+# "rendered": [
+# "router ospf 27",
+# "area 10 authentication keychain ansi11393",
+# "area 10 hello-interval 2",
+# "router ospf 26",
+# "adjacency stagger 10 20",
+# "authentication message-digest keychain ansible1101pass",
+# "router ospf 10",
+# "authentication keychain ansible_test1102",
+# "area 11 default-cost 5",
+# "area 11 cost 11",
+# "area 22 default-cost 6",
+# "router ospf 30",
+# "cost 2",
+# "weight 2",
+# "passive disable",
+# "priority 1",
+# "flood-reduction disable",
+# "default-metric 10",
+# "router-id 2.2.2.2",
+# "demand-circuit enable",
+# "packet-size 577",
+# "transmit-delay 2",
+# "summary-in enable",
+# "external-out disable",
+# "dead-interval 2",
+# "hello-interval 1",
+# "retransmit-interval 2",
+# "mtu-ignore enable",
+# "area 11 default-cost 5",
+# "area 22 default-cost 6"
+# ]
+
+
+# Using gathered
+#
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# Thu Jun 11 16:06:44.406 UTC
+# router ospf 10
+# authentication keychain ansible_test1102
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# authentication keychain ansi11393
+# hello-interval 2
+# !
+# !
+# router ospf 30
+# router-id 2.2.2.2
+# summary-in enable
+# external-out disable
+# cost 2
+# packet-size 577
+# weight 2
+# passive disable
+# priority 1
+# mtu-ignore enable
+# flood-reduction disable
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit enable
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+#
+- name: Gather ospfv2 routes configuration
+ cisco.iosxr.iosxr_ospfv2:
+ state: gathered
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+# "gathered": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "authentication": {
+# "keychain": "ansible_test1102"
+# },
+# "process_id": "10"
+# },
+# {
+# "adjacency_stagger": {
+# "max_adjacency": 20,
+# "min_adjacency": 10
+# },
+# "authentication": {
+# "message_digest": {
+# "keychain": "ansible1101pass"
+# }
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": "enable",
+# "external_out": "disable",
+# "flood_reduction": "disable",
+# "hello_interval": 1,
+# "mtu_ignore": "enable",
+# "packet_size": 577,
+# "passive": "disable",
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "summary_in": "enable",
+# "transmit_delay": 2,
+# "weight": 2
+# }
+# ]
+# }
+#
+# After state:
+# -------------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# Thu Jun 11 16:06:44.406 UTC
+# router ospf 10
+# authentication keychain ansible_test1102
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# authentication keychain ansi11393
+# hello-interval 2
+# !
+# !
+# router ospf 30
+# router-id 2.2.2.2
+# summary-in enable
+# external-out disable
+# cost 2
+# packet-size 577
+# weight 2
+# passive disable
+# priority 1
+# mtu-ignore enable
+# flood-reduction disable
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit enable
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+#
+#
+
+"""
+RETURN = """
+before:
+ description: The configuration prior to the model invocation.
+ returned: always
+ type: dict
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The resulting configuration model invocation.
+ returned: when changed
+ type: dict
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample:
+ - "router ospf 30"
+ - "authentication message-digest keychain 'ansible1101pass'"
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.ospfv2.ospfv2 import (
+ Ospfv2Args,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.ospfv2.ospfv2 import (
+ Ospfv2,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=Ospfv2Args.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+ result = Ospfv2(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospfv3.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospfv3.py
new file mode 100644
index 00000000..ae9f5719
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospfv3.py
@@ -0,0 +1,2783 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_ospfv3
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+module: iosxr_ospfv3
+version_added: 1.1.0
+short_description: ospfv3 resource module
+description:
+ - This module manages global ospfv3 configuration on devices running Cisco IOS-XR
+author: Rohit Thakur (@rohitthakur2590)
+notes:
+ - Tested against IOS-XR 6.1.3
+ - This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html)
+options:
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config router ospfv3).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ config:
+ description: A list of ospfv3 process configuration
+ type: dict
+ suboptions:
+ processes:
+ description: A list of ospfv3 instances configuration
+ type: list
+ elements: dict
+ suboptions:
+ process_id:
+ description: The OSPFv3 Process ID
+ type: str
+ required: true
+ address_family_unicast:
+ description: Enable unicast topology for ipv4 address family
+ type: bool
+ authentication:
+ description: Enable authentication
+ type: dict
+ suboptions:
+ disable:
+ description: Do not authenticate OSPFv3 packets
+ type: bool
+ default: false
+ ipsec:
+ description: Specify IPSec AH authentication attributes
+ type: dict
+ suboptions:
+ spi:
+ description: Specify the Security Parameter Index value
+ type: int
+ algorithim_type:
+ description: Specify the type of algorithim
+ type: str
+ choices: ["md5", "sha1"]
+ key:
+ description: Specify key
+ type: str
+ clear_key:
+ description: Specify key in cleartext form
+ type: str
+ password_key:
+ description: Specify key in encrypted form
+ type: str
+ auto_cost:
+ description: Calculate ospfv3 interface cost according to bandwidth
+ type: dict
+ suboptions:
+ reference_bandwidth:
+ description: Specify reference bandwidth in megabits per sec
+ type: int
+ disable:
+ description: Assign ospfv3 cost based on interface type
+ type: bool
+ bfd:
+ description: Configure BFD parameters
+ type: dict
+ suboptions:
+ fast_detect:
+ description: Configure fast detection
+ type: dict
+ suboptions:
+ set:
+ description: Enable fast detection only
+ type: bool
+ strict_mode:
+ description: Hold down neighbor session until BFD session is up
+ type: bool
+ minimum_interval:
+ description: Hello interval in milli-seconds
+ type: int
+ multiplier:
+ description: Detect multiplier
+ type: int
+ areas:
+ description: Configure ospfv3 areas' properties
+ type: list
+ elements: dict
+ suboptions:
+ area_id:
+ description: Area ID as IP address or integer
+ type: str
+ required: True
+ authentication:
+ description: Enable authentication
+ type: dict
+ suboptions:
+ disable:
+ description: Do not authenticate OSPFv3 packets
+ type: bool
+ default: false
+ ipsec:
+ description: Specify IPSec AH authentication attributes
+ type: dict
+ suboptions:
+ spi:
+ description: Specify the Security Parameter Index value
+ type: int
+ algorithim_type:
+ description: Specify the type of algorithim
+ type: str
+ choices: ["md5", "sha1"]
+ key:
+ description: Specify key
+ type: str
+ clear_key:
+ description: Specify key in cleartext form
+ type: str
+ password_key:
+ description: Specify key in encrypted form
+ type: str
+ bfd:
+ description: Configure BFD parameters
+ type: dict
+ suboptions:
+ fast_detect:
+ description: Configure fast detection
+ type: dict
+ suboptions:
+ set:
+ description: Enable fast detection only
+ type: bool
+ strict_mode:
+ description: Hold down neighbor session until BFD session is up
+ type: bool
+ minimum_interval:
+ description: Hello interval in milli-seconds
+ type: int
+ multiplier:
+ description: Detect multiplier
+ type: int
+ cost:
+ description: Interface cost
+ type: int
+ database_filter:
+ description: Filter LSAs during synchronization and flooding
+ type: dict
+ suboptions:
+ all_outgoing_lsa:
+ description: Filter all outgoing LSA
+ type: bool
+ dead_interval:
+ description: Interval after which a neighbor is declared dead
+ type: int
+ default_cost:
+ description: Set the summary default-cost of a NSSA/stub area. Stub's advertised external route metric
+ type: int
+ demand_circuit:
+ description: Enable/Disable ospfv3 demand circuit
+ type: bool
+ distrinbute_rib_prefix_list_name:
+ description: Filter LSAs during synchronization and flooding
+ type: str
+ fast_reroute:
+ description: Specify IP Fast Reroute
+ type: dict
+ suboptions:
+ disabled:
+ description: Disable IP fast reroute
+ type: bool
+ per_link:
+ description: Specify per-prefix computation
+ type: dict
+ suboptions:
+ information_type:
+ description: Specify per-link LFA exclusion or FRR LFA candidate information
+ type: str
+ choices: ["exclude", "lfa_candidate"]
+ use_candidate_only:
+ description: Enable/Disable backup selection from candidate-list only
+ type: bool
+ interface:
+ description: Specify Per-link LFA exclusion information
+ type: dict
+ suboptions:
+ bvi:
+ description: Specify Bridge-Group Virtual Interface
+ type: list
+ elements: int
+ bundle_ether:
+ description: Specify Aggregated Ethernet interface(s)
+ type: list
+ elements: int
+ pos_int:
+ description: Specify Aggregated pos interface(s)
+ type: list
+ elements: int
+ fast_ethernet:
+ description: Specify FastEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fiftygige:
+ description: Specify FiftyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fortygige:
+ description: Specify FortyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fourhundredgige:
+ description: Specify FourHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ gigabitethernet:
+ description: Specify GigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ hundredgige:
+ description: Specify HundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ mgmteth:
+ description: Specify MgmtEth/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ multilink:
+ description: Specify Multilink network interface(s)
+ type: list
+ elements: str
+ pw_ether:
+ description: Specify PWHE Ethernet Interface
+ type: list
+ elements: int
+ pw_iw:
+ description: Specify PWHE VC11 IP Interworking Interface
+ type: list
+ elements: int
+ srp:
+ description: Specify SRP interface(s)
+ type: list
+ elements: str
+ serial:
+ description: Specify Serial network interface(s)
+ type: list
+ elements: str
+ tengige:
+ description: Specify TenGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ twentyfivegige:
+ description: Specify TwentyFiveGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ twohundredgige:
+ description: Specify TwoHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ nve:
+ description: Specify Network Virtualization Endpoint Interface(s)
+ type: list
+ elements: int
+ tunnel_ip:
+ description: Specify GRE/IPinIP Tunnel Interface(s)
+ type: list
+ elements: int
+ tunnel_ipsec:
+ description: Specify IPSec Tunnel interface(s)
+ type: list
+ elements: int
+ tunnel_mte:
+ description: Specify MPLS Traffic Engineering P2MP Tunnel interface(s)
+ type: list
+ elements: int
+ tunnel_mpls:
+ description: MPLS Transport Protocol Tunnel interface
+ type: int
+ per_prefix:
+ description: Specify per-prefix computation
+ type: dict
+ suboptions:
+ information_type:
+ description: Specify per_prefix LFA exclusion or FRR LFA candidate information
+ type: str
+ choices: ["exclude", "lfa_candidate"]
+ use_candidate_only:
+ description: Enable/Disable backup selection from candidate-list only
+ type: bool
+ interface:
+ description: Specify Per-link LFA exclusion information
+ type: dict
+ suboptions:
+ bvi:
+ description: Specify Bridge-Group Virtual Interface
+ type: list
+ elements: int
+ bundle_ether:
+ description: Specify Aggregated Ethernet interface(s)
+ type: list
+ elements: int
+ pos_int:
+ description: Specify Aggregated pos interface(s)
+ type: list
+ elements: int
+ fast_ethernet:
+ description: Specify FastEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fiftygige:
+ description: Specify FiftyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fortygige:
+ description: Specify FortyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fourhundredgige:
+ description: Specify FourHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ gigabitethernet:
+ description: Specify GigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ hundredgige:
+ description: Specify HundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ mgmteth:
+ description: Specify MgmtEth/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ multilink:
+ description: Specify Multilink network interface(s)
+ type: list
+ elements: str
+ pw_ether:
+ description: Specify PWHE Ethernet Interface
+ type: list
+ elements: int
+ pw_iw:
+ description: Specify PWHE VC11 IP Interworking Interface
+ type: list
+ elements: int
+ srp:
+ description: Specify SRP interface(s)
+ type: list
+ elements: str
+ serial:
+ description: Specify Serial network interface(s)
+ type: list
+ elements: str
+ tengige:
+ description: Specify TenGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ twentyfivegige:
+ description: Specify TwentyFiveGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ twohundredgige:
+ description: Specify TwoHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ nve:
+ description: Specify Network Virtualization Endpoint Interface(s)
+ type: list
+ elements: int
+ tunnel_ip:
+ description: Specify GRE/IPinIP Tunnel Interface(s)
+ type: list
+ elements: int
+ tunnel_ipsec:
+ description: Specify IPSec Tunnel interface(s)
+ type: list
+ elements: int
+ tunnel_mte:
+ description: Specify MPLS Traffic Engineering P2MP Tunnel interface(s)
+ type: list
+ elements: int
+ tunnel_mpls:
+ description: MPLS Transport Protocol Tunnel interface
+ type: int
+ flood_reduction:
+ description: Enable/Disable flood reduction
+ type: bool
+ hello_interval:
+ description: Specify Time between HELLO packets
+ type: int
+ instance_id:
+ description: Specify instance ID
+ type: int
+ mtu_ignore:
+ description: Enable/Disable ignoring of MTU in DBD packets
+ type: bool
+ mpls_ldp_sync:
+ description: Enable/Disable MPLS LDP Sync
+ type: bool
+ network:
+ description: Specify Network type
+ type: str
+ choices: ["broadcast", "non-broadcast", "point-to-multipoint", "point-to-point"]
+ nssa:
+ description: NSSA settings for the area
+ type: dict
+ suboptions:
+ set:
+ description: Configure area as NSSA
+ type: bool
+ default_information_originate:
+ description: Originate default Type 7 LSA
+ type: dict
+ suboptions:
+ set:
+ description: Set nssa to default information originate
+ type: bool
+ metric:
+ description: ospfv3 default metric
+ type: int
+ metric_type:
+ description: Metric type for default routes
+ type: int
+ no_redistribution:
+ description: Do not send redistributed LSAs into NSSA area
+ type: bool
+ no_summary:
+ description: Do not send summary LSAs into NSSA area
+ type: bool
+ translate:
+ description: Translate LSA
+ type: dict
+ suboptions:
+ type7:
+ description: Translate from Type 7 to Type 5
+ type: dict
+ suboptions:
+ always:
+ description: Always translate LSAs
+ type: bool
+ required: true
+ packet_size:
+ description: Specify limit size of OSPFv3 packets
+ type: int
+ passive:
+ description: Enable/Disable routing updates on an interface
+ type: bool
+ prefix_suppression:
+ description: Hide all transit addresses on this interface
+ type: bool
+ priority:
+ description: Specify Router priority
+ type: int
+ ranges:
+ description: Summarize routes matching address/mask (border routers only)
+ type: list
+ elements: dict
+ suboptions:
+ address:
+ description: IP in Prefix format (X:X::X/length)
+ type: str
+ required: True
+ cost:
+ description: Specify user specified metric for this range
+ type: int
+ advertise:
+ description: Advertise this range (default)
+ type: bool
+ not_advertise:
+ description: DoNotAdvertise this range
+ type: bool
+ retransmit_interval:
+ description: Specify Delay between LSA retransmissions
+ type: int
+ stub:
+ description: Settings for configuring the area as a stub
+ type: dict
+ suboptions:
+ set:
+ description: Configure the area as a stub
+ type: bool
+ no_summary:
+ description: Do not send summary LSA into stub area
+ type: bool
+ transmit_delay:
+ description: Specify estimated time needed to send link-state update packet
+ type: int
+ virtual_link:
+ description: Define a virtual link
+ type: list
+ elements: dict
+ suboptions:
+ id:
+ description: Router-ID of virtual link neighbor (A.B.C.D)
+ type: str
+ required: True
+ authentication:
+ description: Enable authentication
+ type: dict
+ suboptions:
+ disable:
+ description: Do not authenticate OSPFv3 packets
+ type: bool
+ default: false
+ ipsec:
+ description: Specify IPSec AH authentication attributes
+ type: dict
+ suboptions:
+ spi:
+ description: Specify the Security Parameter Index value
+ type: int
+ algorithim_type:
+ description: Specify the type of algorithim
+ type: str
+ choices: ["md5", "sha1"]
+ key:
+ description: Specify key
+ type: str
+ clear_key:
+ description: Specify key in cleartext form
+ type: str
+ password_key:
+ description: Specify key in encrypted form
+ type: str
+ dead_interval:
+ description: Interval after which a neighbor is declared dead
+ type: int
+ hello_interval:
+ description: Time between HELLO packets
+ type: int
+ retransmit_interval:
+ description: Delay between LSA retransmissions
+ type: int
+ transmit_delay:
+ description: Link state transmit delay
+ type: int
+ encryption:
+ description: Encrypt and authenticate OSPFv3 packets
+ type: dict
+ suboptions:
+ disable:
+ description: Do not encrypt OSPFv3 packets
+ type: bool
+ default: false
+ ipsec:
+ description: Specify IPSec ESP encryption and authentication
+ type: dict
+ suboptions:
+ spi:
+ description: Specify the Security Parameter Index value
+ type: int
+ esp:
+ description: Specify encryption parameters
+ type: dict
+ suboptions:
+ triple_des:
+ description: This specify the triple DES algorithim
+ type: dict
+ suboptions:
+ key:
+ description: Cleartext 3DES key
+ type: str
+ clear_key:
+ description: Specify 3DES key in cleartext form
+ type: str
+ password_key:
+ description: Specify 3DES key in encrypted form
+ type: str
+ aes:
+ description: This specify the aes algorithim
+ type: dict
+ suboptions:
+ algorithim_type:
+ description: Specify the bit encryption for aes algorithim
+ type: str
+ choices: ["192", "256"]
+ key:
+ description: Cleartext AES key
+ type: str
+ clear_key:
+ description: Specify AES key in cleartext form
+ type: str
+ password_key:
+ description: Specify AES key in encrypted form
+ type: str
+ des:
+ description: This specify the des algorithim
+ type: dict
+ suboptions:
+ key:
+ description: Cleartext AES key
+ type: str
+ clear_key:
+ description: Specify AES key in cleartext form
+ type: str
+ password_key:
+ description: Specify AES key in encrypted form
+ type: str
+ null_encryption:
+ description: Specify null encryption attributes
+ type: dict
+ suboptions:
+ authentication:
+ description: Specify authentication parameters
+ type: dict
+ suboptions:
+ algorithim_type:
+ description: Specify the type of algorithim
+ type: str
+ choices: ["md5", "sha1"]
+ key:
+ description: Specify key
+ type: str
+ clear_key:
+ description: Specify key in cleartext form
+ type: str
+ password_key:
+ description: Specify key in encrypted form
+ type: str
+ encryption:
+ description: Encrypt and authenticate OSPFv3 packets
+ type: dict
+ suboptions:
+ disable:
+ description: Do not encrypt OSPFv3 packets
+ type: bool
+ default: false
+ ipsec:
+ description: Specify IPSec ESP encryption and authentication
+ type: dict
+ suboptions:
+ spi:
+ description: Specify the Security Parameter Index value
+ type: int
+ esp:
+ description: Specify encryption parameters
+ type: dict
+ suboptions:
+ triple_des:
+ description: This specify the triple DES algorithim
+ type: dict
+ suboptions:
+ key:
+ description: Cleartext 3DES key
+ type: str
+ clear_key:
+ description: Specify 3DES key in cleartext form
+ type: str
+ password_key:
+ description: Specify 3DES key in encrypted form
+ type: str
+ aes:
+ description: This specify the aes algorithim
+ type: dict
+ suboptions:
+ algorithim_type:
+ description: Specify the bit encryption for aes algorithim
+ type: str
+ choices: ["192", "256"]
+ key:
+ description: Cleartext AES key
+ type: str
+ clear_key:
+ description: Specify AES key in cleartext form
+ type: str
+ password_key:
+ description: Specify AES key in encrypted form
+ type: str
+ des:
+ description: This specify the des algorithim
+ type: dict
+ suboptions:
+ key:
+ description: Cleartext AES key
+ type: str
+ clear_key:
+ description: Specify AES key in cleartext form
+ type: str
+ password_key:
+ description: Specify AES key in encrypted form
+ type: str
+ null_encryption:
+ description: Specify null encryption attributes
+ type: dict
+ suboptions:
+ authentication:
+ description: Specify authentication parameters
+ type: dict
+ suboptions:
+ algorithim_type:
+ description: Specify the type of algorithim
+ type: str
+ choices: ["md5", "sha1"]
+ key:
+ description: Specify key
+ type: str
+ clear_key:
+ description: Specify key in cleartext form
+ type: str
+ password_key:
+ description: Specify key in encrypted form
+ type: str
+ capability:
+ description: Enable specific OSPFv3 feature
+ type: dict
+ suboptions:
+ type7:
+ description: Specify type7 nssa capability
+ type: dict
+ suboptions:
+ prefer:
+ description: Prefer type7 externals over type5
+ type: bool
+ translate:
+ description: Translate type7 to type5
+ type: bool
+ cost:
+ description: Specify Interface cost
+ type: int
+ database_filter:
+ description: Filter LSAs during synchronization and flooding
+ type: dict
+ suboptions:
+ all_outgoing_lsa:
+ description: Filter all outgoing LSA
+ type: bool
+ dead_interval:
+ description: Interval after which a neighbor is declared dead
+ type: int
+ default_information_originate:
+ description: Control distribution of default information
+ type: dict
+ suboptions:
+ always:
+ description: Always advertise default route
+ type: bool
+ metric:
+ description: ospfv3 default metric
+ type: int
+ metric_type:
+ description: ospfv3 metric type for default routes
+ type: int
+ route_policy:
+ description: Apply route-policy to default-information origination
+ type: str
+ tag:
+ description: Set tag for default route
+ type: int
+ set:
+ description: Enable distribution of default route
+ type: bool
+ default_metric:
+ description: Set metric of redistributed routes
+ type: int
+ demand_circuit:
+ description: Enable/Disable ospfv3 demand circuit
+ type: bool
+ distance:
+ description: Define an administrative distance
+ type: dict
+ suboptions:
+ admin_distance:
+ description: Administrative distance
+ type: int
+ ospfv3_distance:
+ description: ospfv3 administrative distance
+ type: dict
+ suboptions:
+ external:
+ description: Distance for external routes
+ type: int
+ inter_area:
+ description: Distance for inter-area routes
+ type: int
+ intra_area:
+ description: Distance for intra-area routes
+ type: int
+ distribute_list:
+ description: Filter prefixes to/from RIB
+ type: dict
+ suboptions:
+ prefix_list:
+ description: Filter prefixes based on an IPv6 prefix-list
+ type: list
+ elements: str
+ suboptions:
+ name:
+ description: Specify Prefix-list name
+ type: str
+ in:
+ description: Filter prefixes installed to RIB
+ type: bool
+ out:
+ description: Filter prefixes redistributed from RIB
+ type: bool
+ encryption:
+ description: Encrypt and authenticate OSPFv3 packets
+ type: dict
+ suboptions:
+ disable:
+ description: Do not encrypt OSPFv3 packets
+ type: bool
+ default: false
+ ipsec:
+ description: Specify IPSec ESP encryption and authentication
+ type: dict
+ suboptions:
+ spi:
+ description: Specify the Security Parameter Index value
+ type: int
+ esp:
+ description: Specify encryption parameters
+ type: dict
+ suboptions:
+ triple_des:
+ description: This specify the triple DES algorithim
+ type: dict
+ suboptions:
+ key:
+ description: Cleartext 3DES key
+ type: str
+ clear_key:
+ description: Specify 3DES key in cleartext form
+ type: str
+ password_key:
+ description: Specify 3DES key in encrypted form
+ type: str
+ aes:
+ description: This specify the aes algorithim
+ type: dict
+ suboptions:
+ algorithim_type:
+ description: Specify the bit encryption for aes algorithim
+ type: str
+ choices: ["192", "256"]
+ key:
+ description: Cleartext AES key
+ type: str
+ clear_key:
+ description: Specify AES key in cleartext form
+ type: str
+ password_key:
+ description: Specify AES key in encrypted form
+ type: str
+ des:
+ description: This specify the des algorithim
+ type: dict
+ suboptions:
+ key:
+ description: Cleartext AES key
+ type: str
+ clear_key:
+ description: Specify AES key in cleartext form
+ type: str
+ password_key:
+ description: Specify AES key in encrypted form
+ type: str
+ null_encryption:
+ description: Specify null encryption attributes
+ type: dict
+ suboptions:
+ authentication:
+ description: Specify authentication parameters
+ type: dict
+ suboptions:
+ algorithim_type:
+ description: Specify the type of algorithim
+ type: str
+ choices: ["md5", "sha1"]
+ key:
+ description: Specify key
+ type: str
+ clear_key:
+ description: Specify key in cleartext form
+ type: str
+ password_key:
+ description: Specify key in encrypted form
+ type: str
+ fast_reroute:
+ description: Specify IP Fast Reroute
+ type: dict
+ suboptions:
+ disabled:
+ description: Disable IP fast reroute
+ type: bool
+ per_link:
+ description: Specify per-prefix computation
+ type: dict
+ suboptions:
+ information_type:
+ description: Specify per-link LFA exclusion or FRR LFA candidate information
+ type: str
+ choices: ["exclude", "lfa_candidate"]
+ use_candidate_only:
+ description: Enable/Disable backup selection from candidate-list only
+ type: bool
+ interface:
+ description: Specify Per-link LFA exclusion information
+ type: dict
+ suboptions:
+ bvi:
+ description: Specify Bridge-Group Virtual Interface
+ type: list
+ elements: int
+ bundle_ether:
+ description: Specify Aggregated Ethernet interface(s)
+ type: list
+ elements: int
+ pos_int:
+ description: Specify Aggregated pos interface(s)
+ type: list
+ elements: int
+ fast_ethernet:
+ description: Specify FastEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fiftygige:
+ description: Specify FiftyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fortygige:
+ description: Specify FortyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fourhundredgige:
+ description: Specify FourHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ gigabitethernet:
+ description: Specify GigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ hundredgige:
+ description: Specify HundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ mgmteth:
+ description: Specify MgmtEth/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ multilink:
+ description: Specify Multilink network interface(s)
+ type: list
+ elements: str
+ pw_ether:
+ description: Specify PWHE Ethernet Interface
+ type: list
+ elements: int
+ pw_iw:
+ description: Specify PWHE VC11 IP Interworking Interface
+ type: list
+ elements: int
+ srp:
+ description: Specify SRP interface(s)
+ type: list
+ elements: str
+ serial:
+ description: Specify Serial network interface(s)
+ type: list
+ elements: str
+ tengige:
+ description: Specify TenGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ twentyfivegige:
+ description: Specify TwentyFiveGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ twohundredgige:
+ description: Specify TwoHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ nve:
+ description: Specify Network Virtualization Endpoint Interface(s)
+ type: list
+ elements: int
+ tunnel_ip:
+ description: Specify GRE/IPinIP Tunnel Interface(s)
+ type: list
+ elements: int
+ tunnel_ipsec:
+ description: Specify IPSec Tunnel interface(s)
+ type: list
+ elements: int
+ tunnel_mte:
+ description: Specify MPLS Traffic Engineering P2MP Tunnel interface(s)
+ type: list
+ elements: int
+ tunnel_mpls:
+ description: MPLS Transport Protocol Tunnel interface
+ type: int
+ per_prefix:
+ description: Specify per-prefix computation
+ type: dict
+ suboptions:
+ information_type:
+ description: Specify per_prefix LFA exclusion or FRR LFA candidate information
+ type: str
+ choices: ["exclude", "lfa_candidate"]
+ use_candidate_only:
+ description: Enable/Disable backup selection from candidate-list only
+ type: bool
+ interface:
+ description: Specify Per-link LFA exclusion information
+ type: dict
+ suboptions:
+ bvi:
+ description: Specify Bridge-Group Virtual Interface
+ type: list
+ elements: int
+ bundle_ether:
+ description: Specify Aggregated Ethernet interface(s)
+ type: list
+ elements: int
+ post_int:
+ description: Specify Aggregated pos interface(s)
+ type: list
+ elements: int
+ fast_ethernet:
+ description: Specify FastEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fiftygige:
+ description: Specify FiftyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fortygige:
+ description: Specify FortyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fourhundredgige:
+ description: Specify FourHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ gigabitethernet:
+ description: Specify GigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ hundredgige:
+ description: Specify HundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ mgmteth:
+ description: Specify MgmtEth/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ multilink:
+ description: Specify Multilink network interface(s)
+ type: list
+ elements: str
+ pw_ether:
+ description: Specify PWHE Ethernet Interface
+ type: list
+ elements: int
+ pw_iw:
+ description: Specify PWHE VC11 IP Interworking Interface
+ type: list
+ elements: int
+ srp:
+ description: Specify SRP interface(s)
+ type: list
+ elements: str
+ serial:
+ description: Specify Serial network interface(s)
+ type: list
+ elements: str
+ tengige:
+ description: Specify TenGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ twentyfivegige:
+ description: Specify TwentyFiveGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ twohundredgige:
+ description: Specify TwoHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ nve:
+ description: Specify Network Virtualization Endpoint Interface(s)
+ type: list
+ elements: int
+ tunnel_ip:
+ description: Specify GRE/IPinIP Tunnel Interface(s)
+ type: list
+ elements: int
+ tunnel_ipsec:
+ description: Specify IPSec Tunnel interface(s)
+ type: list
+ elements: int
+ tunnel_mte:
+ description: Specify MPLS Traffic Engineering P2MP Tunnel interface(s)
+ type: list
+ elements: int
+ tunnel_mpls:
+ description: MPLS Transport Protocol Tunnel interface
+ type: int
+ flood_reduction:
+ description: Enable/Disable flood reduction
+ type: bool
+ graceful_restart:
+ description: Enable Graceful-Restart
+ type: dict
+ suboptions:
+ set:
+ description: Set graceful restart
+ type: bool
+ helper_disable:
+ description: Disable router's helper support level
+ type: bool
+ min_interval:
+ description: Minimum interval between Graceful Restarts
+ type: int
+ max_interval:
+ description: Maximum route lifetime following restart
+ type: int
+ hello_interval:
+ description: Specify Time between HELLO packets
+ type: int
+ ignore_mospf_type6_lsa:
+ description: Ignore MOSPF Type 6 LSA
+ type: bool
+ instance_id:
+ description: Specify instance ID
+ type: int
+ log_adjacency_changes:
+ description: Log adjacency state changes
+ type: dict
+ suboptions:
+ set:
+ description: Set log adjacency
+ type: bool
+ disable:
+ description: Disable log adjacency changes
+ type: bool
+ detail:
+ description: Log all state changes
+ type: bool
+ maximum:
+ description: Set OSPFv3 limits
+ type: dict
+ suboptions:
+ interfaces:
+ description: Specify limit for number of interfaces
+ type: int
+ paths:
+ description: Specify limit for number of paths
+ type: int
+ redistributed_prefixes:
+ description: Specify limit for number of redistributed prefixes
+ type: int
+ mpls_ldp_sync:
+ description: Enable/Disable MPLS LDP Sync
+ type: bool
+ mtu_ignore:
+ description: Enable/Disable ignoring of MTU in DBD packets
+ type: bool
+ network:
+ description: Specify Network type
+ type: str
+ choices: ["broadcast", "non-broadcast", "point-to-multipoint", "point-to-point"]
+ nsr:
+ description: Enable/Disable NSR for all VRFs in this process
+ type: bool
+ packet_size:
+ description: Specify limit size of OSPFv3 packets
+ type: int
+ passive:
+ description: Enable/Disable routing updates on an interface
+ type: bool
+ prefix_suppression:
+ description: Hide all transit addresses on this interface
+ type: bool
+ priority:
+ description: Specify Router priority
+ type: int
+ protocol_shutdown:
+ description: Gracefully shutdown the OSPFv3 protocol
+ type: bool
+ redistribute:
+ description: Redistribute information from another routing Protocol
+ type: dict
+ suboptions:
+ application:
+ description: Specify application routes
+ type: list
+ elements: dict
+ suboptions:
+ id:
+ description: OnePK Application name
+ type: str
+ required: true
+ set:
+ description: Set application route
+ type: bool
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ bgp:
+ description: Specify bgp routes
+ type: list
+ elements: dict
+ suboptions:
+ id:
+ description: BGP process name
+ type: int
+ required: true
+ set:
+ description: Set bgp route number
+ type: bool
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ preserved_med:
+ description: Specify preserve med of BGP routes
+ type: str
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ connected:
+ description: Specify connected routes
+ type: dict
+ suboptions:
+ set:
+ description: Set connected route
+ type: bool
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ eigrp:
+ description: Specify eigrp routes
+ type: list
+ elements: dict
+ suboptions:
+ id:
+ description: EIGRP process name
+ type: int
+ required: true
+ set:
+ description: Set bgp route number
+ type: bool
+ match:
+ description: Redistribution of EIGRP routes
+ type: str
+ choices: ["external", "internal"]
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ isis:
+ description: Specify IS-IS routes
+ type: list
+ elements: dict
+ suboptions:
+ id:
+ description: IS-IS name
+ type: str
+ required: true
+ set:
+ description: Set IS-IS route number
+ type: bool
+ level:
+ description: Specify IS-IS level routes
+ type: str
+ choices: ["level-1", "level-1-2", "level-2"]
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ mobile:
+ description: Specify mobile routes
+ type: dict
+ suboptions:
+ set:
+ description: Set mobile route number
+ type: bool
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ ospfv3:
+ description: Specify ospfv3 routes
+ type: list
+ elements: dict
+ suboptions:
+ id:
+ description: OSPFv3 process name
+ type: str
+ required: true
+ set:
+ description: Set ospfv3 route number
+ type: bool
+ match:
+ description: Redistribution of OSPFv3 routes
+ type: dict
+ suboptions:
+ external:
+ description: Redistribute OSPFv3 external routes
+ type: int
+ choices: ["1", "2"]
+ nssa_external:
+ description: Redistribute NSSA OSPFv3 external routes
+ type: int
+ choices: ["1", "2"]
+ internal:
+ description: Redistribute OSPFv3 internal routes
+ type: bool
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ static:
+ description: Specify static routes
+ type: dict
+ suboptions:
+ set:
+ description: Set static route
+ type: bool
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ subscriber:
+ description: Specify subscriber routes
+ type: dict
+ suboptions:
+ set:
+ description: Set static route
+ type: bool
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ retransmit_interval:
+ description: Delay between LSA retransmissions
+ type: int
+ router_id:
+ description: ospfv3 router-id in IPv4 address format (A.B.C.D)
+ type: str
+ spf_prefix_priority:
+ description: Specify SPF configuration
+ type: dict
+ suboptions:
+ disable:
+ description: Disable SPF prefix priority
+ type: bool
+ route_policy:
+ description: Specify the route-policy to prioritize route install
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify name of the policy
+ type: str
+ value:
+ description: Specify parameter values for the policy ()
+ type: str
+ stub_router:
+ description: Enter stub router configuration submode
+ type: dict
+ suboptions:
+ router_lsa:
+ description: Modify self originated router LSAs
+ type: dict
+ suboptions:
+ advertise_with:
+ description: Advertise LSAs with specified type
+ type: str
+ choices: ["max-metric", "r-bit", "v6-bit"]
+ always:
+ description: Force ospfv3 stub router mode unconditionally
+ type: bool
+ external_lsa:
+ description: Override External LSA metric in stub router mode
+ type: dict
+ suboptions:
+ set:
+ description: Set external lsa
+ type: bool
+ metric:
+ description: Metric to use while in stub router mode
+ type: int
+ include_stub:
+ description: Set maximum metric for stub links in stub router mode
+ type: bool
+ on_proc_migration:
+ description: Enter stub router mode on ospfv3 process migration
+ type: int
+ on_proc_restart:
+ description: Enter stub router mode on ospfv3 process restart
+ type: int
+ on_startup:
+ description: Enter stub router mode on startup
+ type: dict
+ suboptions:
+ time:
+ description: Time in seconds to stay in stub router mode
+ type: int
+ wait_for_bgp:
+ description: Exit stub router mode when BGP converges
+ type: bool
+ on_switchover:
+ description: Enter stub router mode on RP switchover
+ type: int
+ summary_lsa:
+ description: Override Summary LSA metric in stub router mode
+ type: dict
+ suboptions:
+ set:
+ description: Enable summary LSA
+ type: bool
+ metric:
+ description: Metric to use while in stub router mode
+ type: int
+ summary_prefix:
+ description: Configure IP address summaries
+ type: list
+ elements: dict
+ suboptions:
+ prefix:
+ description: IP summary address/mask (A.B.C.D/prefix)
+ type: str
+ required: True
+ not_advertise:
+ description: Suppress routes that match the specified prefix/mask pair
+ type: bool
+ tag:
+ description: Set tag
+ type: int
+ timers:
+ description: Adjust routing timers
+ type: dict
+ suboptions:
+ lsa_arrival:
+ description: Specify LSA arrival timers
+ type: int
+ pacing:
+ description: Specify pacing timers
+ type: dict
+ suboptions:
+ flood:
+ description: Flood pacing timer
+ type: int
+ lsa_group:
+ description: LSA group pacing timer
+ type: int
+ retransmission:
+ description: LSA group pacing timer
+ type: int
+ throttle:
+ description: Adjust throttle timers
+ type: dict
+ suboptions:
+ lsa:
+ description: Specify LSA throttle timers
+ type: dict
+ suboptions:
+ all_lsa_initial:
+ description: Delay to generate first occurrence of LSA in milliseconds
+ type: int
+ all_lsa_minimum:
+ description: Minimum delay between originating the same LSA in milliseconds
+ type: int
+ spf:
+ description: Specify SPF throttle timers
+ type: dict
+ suboptions:
+ spf_initial:
+ description: Delay to generate first occurrence of SPF in ms
+ type: int
+ spf_minimum:
+ description: Minimum delay between originating the same SPF in ms
+ type: int
+ trace:
+ description: Specify OSPF tracing options
+ type: dict
+ suboptions:
+ size:
+ description: Delete existing buffer and create one with N entries
+ type: str
+ value:
+ description: Specify trace entry
+ type: int
+ transmit_delay:
+ description: Estimated time needed to send link-state update packet
+ type: int
+ state:
+ description:
+ - The state the configuration should be left in
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - gathered
+ - rendered
+ - parsed
+ default: merged
+"""
+EXAMPLES = """
+# Using merged
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospfv3
+# Thu Jun 11 15:54:44.569 UTC
+# % No such configuration item(s)
+#
+
+- name: Merge provided OSPFv3 configuration with the existing configuration
+ cisco.iosxr.iosxr_ospfv3:
+ config:
+ processes:
+ - process_id: 27
+ areas:
+ - area_id: 10
+ hello_interval: 2
+ - process_id: 26
+ authentication:
+ disable: true
+ - process_id: 10
+ areas:
+ - area_id: 11
+ default_cost: 5
+ cost: 11
+ - area_id: 22
+ default_cost: 6
+ - process_id: 30
+ areas:
+ - area_id: 11
+ default_cost: 5
+ - area_id: 22
+ default_cost: 6
+ cost: 2
+ default_metric: 10
+ transmit_delay: 2
+ hello_interval: 1
+ dead_interval: 2
+ retransmit_interval: 2
+ packet_size: 577
+ priority: 1
+ router_id: '2.2.2.2'
+ demand_circuit: true
+ mtu_ignore: true
+ state: merged
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {}
+#
+# "commands": [
+# "router ospfv3 10",
+# "area 11 default-cost 5",
+# "area 11 cost 11",
+# "area 22 default-cost 6",
+# "router ospfv3 26",
+# "authentication disable",
+# "router ospfv3 27",
+# "area 10 hello-interval 2",
+# "router ospfv3 30",
+# "cost 2",
+# "priority 1",
+# "default-metric 10",
+# "router-id 2.2.2.2",
+# "demand-circuit",
+# "packet-size 577",
+# "transmit-delay 2",
+# "dead-interval 2",
+# "hello-interval 1",
+# "retransmit-interval 2",
+# "mtu-ignore",
+# "area 11 default-cost 5",
+# "area 22 default-cost 6"
+# ]
+#
+# "after": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "process_id": "10"
+# },
+# {
+# "authentication": {
+# "disable": true
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": true,
+# "hello_interval": 1,
+# "mtu_ignore": true,
+# "packet_size": 577,
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "transmit_delay": 2
+# }
+# ]
+# }
+#
+#
+# ------------
+# After state
+# ------------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospfv3
+# router ospfv3 10
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# !
+# area 30
+# !
+# !
+# router ospfv3 30
+# cost 2
+# priority 1
+# mtu-ignore
+# packet-size 577
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit
+# hello-interval 1
+# transmit-delay 2
+# router-id 2.2.2.2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# router ospfv3 10
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# !
+# area 30
+# !
+# !
+# router ospfv3 30
+# cost 2
+# priority 1
+# mtu-ignore
+# packet-size 577
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit
+# hello-interval 1
+# transmit-delay 2
+# router-id 2.2.2.2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+
+
+
+# Using replaced
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# router ospfv3 10
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# !
+# area 30
+# !
+# !
+# router ospfv3 30
+# cost 2
+# priority 1
+# mtu-ignore
+# packet-size 577
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit
+# hello-interval 1
+# transmit-delay 2
+# router-id 2.2.2.2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# router ospfv3 10
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# !
+# area 30
+# !
+# !
+# router ospfv3 30
+# cost 2
+# priority 1
+# mtu-ignore
+# packet-size 577
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit
+# hello-interval 1
+# transmit-delay 2
+# router-id 2.2.2.2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+
+- name: Replace OSPFv3 routes configurations from the device
+ cisco.iosxr.iosxr_ospfv3:
+ config:
+ processes:
+ - process_id: 27
+ areas:
+ - area_id: 10
+ hello_interval: 2
+ - area_id: 20
+ cost: 2
+ default_cost: 2
+ - process_id: 26
+ authentication:
+ disable: true
+ state: replaced
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "process_id": "10"
+# },
+# {
+# "authentication": {
+# "disable": true
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": true,
+# "hello_interval": 1,
+# "mtu_ignore": true,
+# "packet_size": 577,
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "transmit_delay": 2
+# }
+# ]
+# }
+#
+# "commands": [
+# "router ospfv3 27",
+# "area 20 default-cost 2",
+# "area 20 cost 2"
+# ]
+#
+# "after": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "process_id": "10"
+# },
+# {
+# "authentication": {
+# "disable": true
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# },
+# {
+# "area_id": "20",
+# "cost": 2,
+# "default_cost": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": true,
+# "hello_interval": 1,
+# "mtu_ignore": true,
+# "packet_size": 577,
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "transmit_delay": 2
+# }
+# ]
+# }
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/RP0/CPU0:anton(config)#do show running-config router ospfv3
+# router ospfv3 10
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# cost 2
+# default-cost 2
+# !
+# area 30
+# !
+# !
+# router ospfv3 30
+# cost 2
+# priority 1
+# mtu-ignore
+# packet-size 577
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit
+# hello-interval 1
+# transmit-delay 2
+# router-id 2.2.2.2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+
+
+- name: Override existing OSPFv3 configurations from the device
+ cisco.iosxr.iosxr_ospfv3:
+ config:
+ processes:
+ - process_id: 27
+ areas:
+ - area_id: 10
+ hello_interval: 2
+ authentication:
+ disable: true
+ - area_id: 20
+ cost: 2
+ default_cost: 2
+ authentication:
+ disable: true
+ - process_id: 26
+ areas:
+ - area_id: 10
+ hello_interval: 2
+ authentication:
+ disable: true
+ state: overridden
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "process_id": "10"
+# },
+# {
+# "authentication": {
+# "disable": true
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# },
+# {
+# "area_id": "20",
+# "cost": 2,
+# "default_cost": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": true,
+# "hello_interval": 1,
+# "mtu_ignore": true,
+# "packet_size": 577,
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "transmit_delay": 2
+# }
+# ]
+# }
+#
+# "commands": [
+# "router ospfv3 10",
+# "no area 11 default-cost 5",
+# "no area 11 cost 11",
+# "no area 22 default-cost 6",
+# "router ospfv3 30",
+# "no cost 2",
+# "no priority 1",
+# "no default-metric 10",
+# "no router-id 2.2.2.2",
+# "no demand-circuit",
+# "no packet-size 577",
+# "no transmit-delay 2",
+# "no dead-interval 2",
+# "no hello-interval 1",
+# "no retransmit-interval 2",
+# "no mtu-ignore",
+# "no area 11 default-cost 5",
+# "no area 22 default-cost 6",
+# "router ospfv3 26",
+# "area 10 hello-interval 4"
+# ]
+#
+# "after": {
+# "processes": [
+# {
+# "process_id": "10"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 4
+# }
+# ],
+# "authentication": {
+# "disable": true
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# },
+# {
+# "area_id": "20",
+# "cost": 2,
+# "default_cost": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "process_id": "30"
+# }
+# ]
+# }
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospfv3
+# router ospfv3 10
+# area 11
+# !
+# area 22
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# area 10
+# hello-interval 4
+# !
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# cost 2
+# default-cost 2
+# !
+# area 30
+# !
+# !
+# router ospfv3 30
+# area 11
+# !
+# area 22
+# !
+# !
+
+
+
+# Using deleted
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospfv3
+# router ospfv3 10
+# area 11
+# !
+# area 22
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# area 10
+# hello-interval 4
+# !
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# cost 2
+# default-cost 2
+# !
+# area 30
+# !
+# !
+# router ospfv3 30
+# area 11
+# !
+# area 22
+# !
+# !
+
+- name: Deleted existing OSPFv3 configurations from the device
+ cisco.iosxr.iosxr_ospfv3:
+ config:
+ processes:
+ - process_id: '10'
+ - process_id: '26'
+ - process_id: '27'
+ - process_id: '30'
+ state: deleted
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {
+# "processes": [
+# {
+# "process_id": "10"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 4
+# }
+# ],
+# "authentication": {
+# "disable": true
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# },
+# {
+# "area_id": "20",
+# "cost": 2,
+# "default_cost": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "process_id": "30"
+# }
+# ]
+# },
+#
+# "commands": [
+# "router ospfv3 26",
+# "no authentication disable",
+# "no area 10 hello-interval 4",
+# "router ospfv3 27",
+# "no area 10 hello-interval 2",
+# "no area 20 default-cost 2",
+# "no area 20 cost 2"
+# ]
+#
+# "after": {
+# "processes": [
+# {
+# "process_id": "10"
+# },
+# {
+# "process_id": "26"
+# },
+# {
+# "process_id": "27"
+# },
+# {
+# "process_id": "30"
+# }
+# ]
+# }
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/RP0/CPU0:anton(config)#show running-config router ospfv3
+# router ospfv3 10
+# !
+# router ospfv3 26
+# !
+# router ospfv3 27
+# !
+# router ospfv3 30
+# !
+
+
+# Using parsed
+# parsed.cfg
+# ------------
+# router ospfv3 10
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# !
+# router ospfv3 30
+# router-id 2.2.2.2
+# cost 2
+# packet-size 577
+# priority 1
+# mtu-ignore
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+- name: Parsed the device configuration to get output commands
+ cisco.iosxr.iosxr_ospfv3:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+#
+# "parsed": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "process_id": "10"
+# },
+# {
+# "authentication": {
+# "disable": true
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": true,
+# "hello_interval": 1,
+# "mtu_ignore": true,
+# "packet_size": 577,
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "transmit_delay": 2
+# }
+# ]
+# }
+#
+# Using rendered
+#
+#
+- name: Render the commands for provided configuration
+ cisco.iosxr.iosxr_ospfv3:
+ config:
+ processes:
+ - process_id: 27
+ areas:
+ - area_id: 10
+ hello_interval: 2
+ - process_id: 26
+ authentication:
+ disable: true
+ - process_id: 10
+ areas:
+ - area_id: 11
+ default_cost: 5
+ cost: 11
+ - area_id: 22
+ default_cost: 6
+ - process_id: 30
+ areas:
+ - area_id: 11
+ default_cost: 5
+ - area_id: 22
+ default_cost: 6
+ cost: 2
+ default_metric: 10
+ transmit_delay: 2
+ hello_interval: 1
+ dead_interval: 2
+ retransmit_interval: 2
+ packet_size: 577
+ priority: 1
+ router_id: '2.2.2.2'
+ demand_circuit: true
+ mtu_ignore: true
+ state: rendered
+
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+#
+# "rendered": [
+# "router ospfv3 27",
+# "area 10 hello-interval 2",
+# "router ospfv3 26",
+# "authentication disable",
+# "router ospfv3 10",
+# "area 11 default-cost 5",
+# "area 11 cost 11",
+# "area 22 default-cost 6",
+# "router ospfv3 30",
+# "cost 2",
+# "priority 1",
+# "default-metric 10",
+# "router-id 2.2.2.2",
+# "demand-circuit",
+# "packet-size 577",
+# "transmit-delay 2",
+# "dead-interval 2",
+# "hello-interval 1",
+# "retransmit-interval 2",
+# "mtu-ignore",
+# "area 11 default-cost 5",
+# "area 22 default-cost 6"
+# ]
+
+
+# Using gathered
+#
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# router ospfv3 10
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# area 10
+# !
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# !
+# area 30
+# !
+# !
+# router ospfv3 30
+# cost 2
+# priority 1
+# mtu-ignore
+# packet-size 577
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit
+# hello-interval 1
+# transmit-delay 2
+# router-id 2.2.2.2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+
+- name: Gather ospfv3 routes configuration
+ cisco.iosxr.iosxr_ospfv3:
+ state: gathered
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+# "gathered": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "process_id": "10"
+# },
+# {
+# "authentication": {
+# "disable": true
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": true,
+# "hello_interval": 1,
+# "mtu_ignore": true,
+# "packet_size": 577,
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "transmit_delay": 2
+# }
+# ]
+# }
+#
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.ospfv3.ospfv3 import (
+ Ospfv3Args,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.ospfv3.ospfv3 import (
+ Ospfv3,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ module = AnsibleModule(
+ argument_spec=Ospfv3Args.argument_spec,
+ mutually_exclusive=[["config", "running_config"]],
+ required_if=[
+ ["state", "merged", ["config"]],
+ ["state", "replaced", ["config"]],
+ ["state", "overridden", ["config"]],
+ ["state", "rendered", ["config"]],
+ ["state", "parsed", ["running_config"]],
+ ],
+ supports_check_mode=True,
+ )
+
+ result = Ospfv3(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_static_routes.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_static_routes.py
new file mode 100644
index 00000000..238582d2
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_static_routes.py
@@ -0,0 +1,854 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_static_routes
+"""
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_static_routes
+short_description: Static routes resource module
+description:
+- This module manages static routes on devices running Cisco IOS-XR.
+version_added: 1.0.0
+author: Nilashish Chakraborty (@NilashishC)
+options:
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config router static).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ config:
+ description: A dictionary of static route options.
+ type: list
+ elements: dict
+ suboptions:
+ vrf:
+ description:
+ - The VRF to which the static route(s) belong.
+ type: str
+ address_families:
+ description: A dictionary specifying the address family to which the static
+ route(s) belong.
+ type: list
+ elements: dict
+ suboptions:
+ afi:
+ description:
+ - Specifies the top level address family indicator.
+ type: str
+ choices:
+ - ipv4
+ - ipv6
+ required: true
+ safi:
+ description:
+ - Specifies the subsequent address family indicator.
+ type: str
+ choices:
+ - unicast
+ - multicast
+ required: true
+ routes:
+ description: A dictionary that specifies the static route configurations.
+ elements: dict
+ type: list
+ suboptions:
+ dest:
+ description:
+ - An IPv4 or IPv6 address in CIDR notation that specifies the destination
+ network for the static route.
+ type: str
+ required: true
+ next_hops:
+ description:
+ - Next hops to the specified destination.
+ type: list
+ elements: dict
+ suboptions:
+ forward_router_address:
+ description:
+ - The IP address of the next hop that can be used to reach the
+ destination network.
+ type: str
+ interface:
+ description:
+ - The interface to use to reach the destination.
+ type: str
+ dest_vrf:
+ description:
+ - The destination VRF.
+ type: str
+ admin_distance:
+ description:
+ - The administrative distance for this static route.
+ - Refer to vendor documentation for valid values.
+ type: int
+ metric:
+ description:
+ - Specifes the metric for this static route.
+ - Refer to vendor documentation for valid values.
+ type: int
+ description:
+ description:
+ - Specifies the description for this static route.
+ type: str
+ vrflabel:
+ description:
+ - Specifies the VRF label for this static route.
+ - Refer to vendor documentation for valid values.
+ type: int
+ tag:
+ description:
+ - Specifies a numeric tag for this static route.
+ - Refer to vendor documentation for valid values.
+ type: int
+ track:
+ description:
+ - Specifies the object to be tracked.
+ - This enables object tracking for static routes.
+ type: str
+ tunnel_id:
+ description:
+ - Specifies a tunnel id for the route.
+ - Refer to vendor documentation for valid values.
+ type: int
+ state:
+ description:
+ - The state the configuration should be left in.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - gathered
+ - rendered
+ - parsed
+ default: merged
+
+"""
+EXAMPLES = """
+
+# Using merged
+
+# Before state
+# -------------
+# RP/0/RP0/CPU0:ios#show running-config router static
+# Sat Feb 22 07:46:30.089 UTC
+# % No such configuration item(s)
+#
+- name: Merge the provided configuration with the exisiting running configuration
+ cisco.iosxr.iosxr_static_routes:
+ config:
+ - address_families:
+ - afi: ipv4
+ safi: unicast
+ routes:
+ - dest: 192.0.2.16/28
+ next_hops:
+ - forward_router_address: 192.0.2.10
+ interface: FastEthernet0/0/0/1
+ description: LAB
+ metric: 120
+ tag: 10
+
+ - interface: FastEthernet0/0/0/5
+ track: ip_sla_1
+
+ - dest: 192.0.2.32/28
+ next_hops:
+ - forward_router_address: 192.0.2.11
+ admin_distance: 100
+
+ - afi: ipv6
+ safi: unicast
+ routes:
+ - dest: 2001:db8:1000::/36
+ next_hops:
+ - interface: FastEthernet0/0/0/7
+ description: DC
+
+ - interface: FastEthernet0/0/0/8
+ forward_router_address: 2001:db8:2000:2::1
+
+ - vrf: DEV_SITE
+ address_families:
+ - afi: ipv4
+ safi: unicast
+ routes:
+ - dest: 192.0.2.48/28
+ next_hops:
+ - forward_router_address: 192.0.2.12
+ description: DEV
+ dest_vrf: test_1
+
+ - dest: 192.0.2.80/28
+ next_hops:
+ - interface: FastEthernet0/0/0/2
+ forward_router_address: 192.0.2.14
+ dest_vrf: test_1
+ track: ip_sla_2
+ vrflabel: 124
+ state: merged
+
+# After state
+# -------------
+# RP/0/RP0/CPU0:ios#show running-config router static
+# Sat Feb 22 07:49:11.754 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV
+# 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+# !
+# !
+# !
+
+# Using merged to update existing static routes
+
+# Before state
+# -------------
+# RP/0/RP0/CPU0:ios#show running-config router static
+# Sat Feb 22 07:49:11.754 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV
+# 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+# !
+# !
+# !
+
+- name: Update existing static routes configuration using merged
+ cisco.iosxr.iosxr_static_routes:
+ config:
+ - vrf: DEV_SITE
+ address_families:
+ - afi: ipv4
+ safi: unicast
+ routes:
+ - dest: 192.0.2.48/28
+ next_hops:
+ - forward_router_address: 192.0.2.12
+ vrflabel: 2301
+ dest_vrf: test_1
+
+ - dest: 192.0.2.80/28
+ next_hops:
+ - interface: FastEthernet0/0/0/2
+ forward_router_address: 192.0.2.14
+ dest_vrf: test_1
+ description: rt_test_1
+ state: merged
+
+# After state
+# -------------
+# RP/0/RP0/CPU0:ios#show running-config router static
+# Sat Feb 22 07:49:11.754 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV vrflabel 2301
+# 192.0.2.80/28 vrf test_1 192.0.2.14 FastEthernet0/0/0/2 description rt_test_1 track ip_sla_2 vrflabel 124
+# !
+# !
+# !
+
+# Using replaced to replace all next hop entries for a single destination network
+
+# Before state
+# --------------
+
+# RP/0/RP0/CPU0:ios#sh running-config router static
+# Sat Feb 22 07:59:08.669 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV
+# 192.0.2.48/28 GigabitEthernet0/0/0/1 192.0.3.24 vrflabel 2302
+# 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+# !
+# !
+# !
+
+- name: Replace device configurations of static routes with provided configurations
+ cisco.iosxr.iosxr_static_routes:
+ config:
+ - vrf: DEV_SITE
+ address_families:
+ - afi: ipv4
+ safi: unicast
+ routes:
+ - dest: 192.0.2.48/28
+ next_hops:
+ - forward_router_address: 192.0.2.15
+ interface: FastEthernet0/0/0/3
+ description: DEV_NEW
+ dest_vrf: dev_test_2
+ state: replaced
+
+# After state
+# ------------
+# RP/0/RP0/CPU0:ios#sh running-config router static
+# Sat Feb 22 08:04:07.085 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf dev_test_2 FastEthernet0/0/0/3 192.0.2.15 description DEV_NEW
+# 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+# !
+# !
+# !
+
+# Using overridden to override all static route entries on the device
+
+# Before state
+# -------------
+# RP/0/RP0/CPU0:ios#sh running-config router static
+# Sat Feb 22 07:59:08.669 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV
+# 192.0.2.48/28 GigabitEthernet0/0/0/1 192.0.3.24 vrflabel 2302
+# 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+# !
+# !
+# !
+
+- name: Overridde all static routes configuration with provided configuration
+ cisco.iosxr.iosxr_static_routes:
+ config:
+ - vrf: DEV_NEW
+ address_families:
+ - afi: ipv4
+ safi: unicast
+ routes:
+ - dest: 192.0.2.48/28
+ next_hops:
+ - forward_router_address: 192.0.2.15
+ interface: FastEthernet0/0/0/3
+ description: DEV1
+ - afi: ipv6
+ safi: unicast
+ routes:
+ - dest: 2001:db8:3000::/36
+ next_hops:
+ - interface: FastEthernet0/0/0/4
+ forward_router_address: 2001:db8:2000:2::2
+ description: PROD1
+ track: ip_sla_1
+ state: overridden
+
+# After state
+# -------------
+# RP/0/RP0/CPU0:ios#sh running-config router static
+# Sat Feb 22 08:07:41.516 UTC
+# router static
+# vrf DEV_NEW
+# address-family ipv4 unicast
+# 192.0.2.48/28 FastEthernet0/0/0/3 192.0.2.15 description DEV1
+# !
+# address-family ipv6 unicast
+# 2001:db8:3000::/36 FastEthernet0/0/0/4 2001:db8:2000:2::2 description PROD1 track ip_sla_1
+# !
+# !
+# !
+
+# Using deleted to delete all destination network entries under a single AFI
+
+# Before state
+# -------------
+# RP/0/RP0/CPU0:ios#sh running-config router static
+# Sat Feb 22 07:59:08.669 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV
+# 192.0.2.48/28 GigabitEthernet0/0/0/1 192.0.3.24 vrflabel 2302
+# 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+# !
+# !
+# !
+
+- name: Delete all destination network entries under a single AFI
+ cisco.iosxr.iosxr_static_routes:
+ config:
+ - vrf: DEV_SITE
+ address_families:
+ - afi: ipv4
+ safi: unicast
+ state: deleted
+
+# After state
+# ------------
+
+# RP/0/RP0/CPU0:ios#sh running-config router static
+# Sat Feb 22 08:16:41.464 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# !
+# !
+
+# Using deleted to remove all static route entries from the device
+
+# Before state
+# -------------
+# RP/0/RP0/CPU0:ios#sh running-config router static
+# Sat Feb 22 07:59:08.669 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV
+# 192.0.2.48/28 GigabitEthernet0/0/0/1 192.0.3.24 vrflabel 2302
+# 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+# !
+# !
+# !
+
+- name: Delete static routes configuration
+ cisco.iosxr.iosxr_static_routes:
+ state: deleted
+
+# After state
+# ------------
+# RP/0/RP0/CPU0:ios#sh running-config router static
+# Sat Feb 22 08:50:43.038 UTC
+# % No such configuration item(s)
+
+# Using gathered to gather static route facts from the device
+
+- name: Gather static routes facts from the device using iosxr_static_routes module
+ cisco.iosxr.iosxr_static_routes:
+ state: gathered
+
+# Task output (redacted)
+# -----------------------
+# "gathered": [
+# {
+# "address_families": [
+# {
+# "afi": "ipv4",
+# "routes": [
+# {
+# "dest": "192.0.2.16/28",
+# "next_hops": [
+# {
+# "description": "LAB",
+# "forward_router_address": "192.0.2.10",
+# "interface": "FastEthernet0/0/0/1",
+# "metric": 120,
+# "tag": 10
+# },
+# {
+# "interface": "FastEthernet0/0/0/5",
+# "track": "ip_sla_1"
+# }
+# ]
+# },
+# {
+# "dest": "192.0.2.32/28",
+# "next_hops": [
+# {
+# "admin_distance": 100,
+# "forward_router_address": "192.0.2.11"
+# }
+# ]
+# }
+# ],
+# "safi": "unicast"
+# },
+# {
+# "afi": "ipv6",
+# "routes": [
+# {
+# "dest": "2001:db8:1000::/36",
+# "next_hops": [
+# {
+# "description": "DC",
+# "interface": "FastEthernet0/0/0/7"
+# },
+# {
+# "forward_router_address": "2001:db8:2000:2::1",
+# "interface": "FastEthernet0/0/0/8"
+# }
+# ]
+# }
+# ],
+# "safi": "unicast"
+# }
+# ]
+# },
+# {
+# "address_families": [
+# {
+# "afi": "ipv4",
+# "routes": [
+# {
+# "dest": "192.0.2.48/28",
+# "next_hops": [
+# {
+# "description": "DEV",
+# "dest_vrf": "test_1",
+# "forward_router_address": "192.0.2.12"
+# },
+# {
+# "forward_router_address": "192.0.3.24",
+# "interface": "GigabitEthernet0/0/0/1",
+# "vrflabel": 2302
+# }
+# ]
+# },
+# {
+# "dest": "192.0.2.80/28",
+# "next_hops": [
+# {
+# "dest_vrf": "test_1",
+# "forward_router_address": "192.0.2.14",
+# "interface": "FastEthernet0/0/0/2",
+# "track": "ip_sla_2",
+# "vrflabel": 124
+# }
+# ]
+# }
+# ],
+# "safi": "unicast"
+# }
+# ],
+# "vrf": "DEV_SITE"
+# }
+# ]
+
+# Using rendered
+
+- name: Render platform specific commands (without connecting to the device)
+ cisco.iosxr.iosxr_static_routes:
+ config:
+ - vrf: DEV_SITE
+ address_families:
+ - afi: ipv4
+ safi: unicast
+ routes:
+ - dest: 192.0.2.48/28
+ next_hops:
+ - forward_router_address: 192.0.2.12
+ description: DEV
+ dest_vrf: test_1
+
+ - dest: 192.0.2.80/28
+ next_hops:
+ - interface: FastEthernet0/0/0/2
+ forward_router_address: 192.0.2.14
+ dest_vrf: test_1
+ track: ip_sla_2
+ vrflabel: 124
+
+# Task Output (redacted)
+# -----------------------
+# "rendered": [
+# "router static"s,
+# "vrf DEV_SITE",
+# "address-family ipv4 unicast",
+# "192.0.2.48/28 vrf test_1 192.0.2.12 description DEV",
+# "192.0.2.80/28 vrf test_1 192.0.2.14 FastEthernet0/0/0/2 track ip_sla_2 vrflabel 124"
+
+# Using parsed
+
+# parsed.cfg
+# ------------
+# Fri Nov 29 21:10:41.896 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV
+# 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+# !
+# !
+# !
+
+- name: Use parsed state to convert externally supplied device specific static routes
+ commands to structured format
+ cisco.iosxr.iosxr_static_routes:
+ running_config: "{{ lookup('file', '../../fixtures/parsed.cfg') }}"
+ state: parsed
+
+# Task output (redacted)
+# -----------------------
+# "parsed": [
+# {
+# "address_families": [
+# {
+# "afi": "ipv4",
+# "routes": [
+# {
+# "dest": "192.0.2.16/28",
+# "next_hops": [
+# {
+# "description": "LAB",
+# "forward_router_address": "192.0.2.10",
+# "interface": "FastEthernet0/0/0/1",
+# "metric": 120,
+# "tag": 10
+# },
+# {
+# "interface": "FastEthernet0/0/0/5",
+# "track": "ip_sla_1"
+# }
+# ]
+# },
+# {
+# "dest": "192.0.2.32/28",
+# "next_hops": [
+# {
+# "admin_distance": 100,
+# "forward_router_address": "192.0.2.11"
+# }
+# ]
+# }
+# ],
+# "safi": "unicast"
+# },
+# {
+# "afi": "ipv6",
+# "routes": [
+# {
+# "dest": "2001:db8:1000::/36",
+# "next_hops": [
+# {
+# "description": "DC",
+# "interface": "FastEthernet0/0/0/7"
+# },
+# {
+# "forward_router_address": "2001:db8:2000:2::1",
+# "interface": "FastEthernet0/0/0/8"
+# }
+# ]
+# }
+# ],
+# "safi": "unicast"
+# }
+# ]
+# },
+# {
+# "address_families": [
+# {
+# "afi": "ipv4",
+# "routes": [
+# {
+# "dest": "192.0.2.48/28",
+# "next_hops": [
+# {
+# "description": "DEV",
+# "dest_vrf": "test_1",
+# "forward_router_address": "192.0.2.12"
+# }
+# ]
+# },
+# {
+# "dest": "192.0.2.80/28",
+# "next_hops": [
+# {
+# "dest_vrf": "test_1",
+# "forward_router_address": "192.0.2.14",
+# "interface": "FastEthernet0/0/0/2",
+# "track": "ip_sla_2",
+# "vrflabel": 124
+# }
+# ]
+# }
+# ],
+# "safi": "unicast"
+# }
+# ],
+# "vrf": "DEV_SITE"
+# }
+# ]
+# }
+"""
+RETURN = """
+before:
+ description: The configuration prior to the model invocation.
+ returned: always
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The resulting configuration model invocation.
+ returned: when changed
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample:
+ - router static
+ - vrf dev_site
+ - address-family ipv4 unicast
+ - 192.0.2.48/28 192.0.2.12 FastEthernet0/0/0/1 track ip_sla_10 description dev1
+ - address-family ipv6 unicast
+ - no 2001:db8:1000::/36
+ - 2001:db8:3000::/36 2001:db8:2000:2::2 FastEthernet0/0/0/4 track ip_sla_11 description prod1
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.static_routes.static_routes import (
+ Static_routesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.static_routes.static_routes import (
+ Static_routes,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+ mutually_exclusive = [("config", "running_config")]
+
+ module = AnsibleModule(
+ argument_spec=Static_routesArgs.argument_spec,
+ required_if=required_if,
+ mutually_exclusive=mutually_exclusive,
+ supports_check_mode=True,
+ )
+
+ result = Static_routes(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_system.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_system.py
new file mode 100644
index 00000000..4e9ccc6f
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_system.py
@@ -0,0 +1,943 @@
+#!/usr/bin/python
+#
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_system
+author:
+- Peter Sprygada (@privateip)
+- Kedar Kekan (@kedarX)
+short_description: Manage the system attributes on Cisco IOS XR devices
+description:
+- This module provides declarative management of node system attributes on Cisco IOS
+ XR devices. It provides an option to configure host system parameters or remove
+ those parameters from the device active configuration.
+version_added: 1.0.0
+requirements:
+- ncclient >= 0.5.3 when using netconf
+- lxml >= 4.1.1 when using netconf
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+notes:
+- This module works with connection C(network_cli) and C(netconf). See L(the IOS-XR
+ Platform Options,../network/user_guide/platform_iosxr.html).
+- Tested against IOS XRv 6.1.3
+- name-servers I(state=absent) operation with C(netconf) transport is a success, but
+ with rpc-error. This is due to XR platform issue. Recommended to use I(ignore_errors)
+ option with the task as a workaround.
+options:
+ hostname:
+ description:
+ - Configure the device hostname parameter. This option takes an ASCII string value.
+ type: str
+ vrf:
+ description:
+ - VRF name for domain services
+ type: str
+ default: "default"
+ domain_name:
+ description:
+ - Configure the IP domain name on the remote device to the provided value. Value
+ should be in the dotted name form and will be appended to the C(hostname) to
+ create a fully-qualified domain name.
+ type: str
+ domain_search:
+ description:
+ - Provides the list of domain suffixes to append to the hostname for the purpose
+ of doing name resolution. This argument accepts a list of names and will be
+ reconciled with the current active configuration on the running node.
+ type: list
+ elements: str
+ lookup_source:
+ description:
+ - The C(lookup_source) argument provides one or more source interfaces to use
+ for performing DNS lookups. The interface provided in C(lookup_source) must
+ be a valid interface configured on the device.
+ type: str
+ lookup_enabled:
+ description:
+ - Provides administrative control for enabling or disabling DNS lookups. When
+ this argument is set to True, lookups are performed and when it is set to False,
+ lookups are not performed.
+ type: bool
+ default: true
+ name_servers:
+ description:
+ - The C(name_serves) argument accepts a list of DNS name servers by way of either
+ FQDN or IP address to use to perform name resolution lookups. This argument
+ accepts wither a list of DNS servers See examples.
+ type: list
+ elements: str
+ state:
+ description:
+ - State of the configuration values in the device's current active configuration. When
+ set to I(present), the values should be configured in the device active configuration
+ and when set to I(absent) the values should not be in the device active configuration
+ default: present
+ choices:
+ - present
+ - absent
+ type: str
+"""
+
+EXAMPLES = """
+- name: configure hostname and domain-name (default vrf=default)
+ cisco.iosxr.iosxr_system:
+ hostname: iosxr01
+ domain_name: test.example.com
+ domain_search:
+ - ansible.com
+ - redhat.com
+ - cisco.com
+- name: remove configuration
+ cisco.iosxr.iosxr_system:
+ hostname: iosxr01
+ domain_name: test.example.com
+ domain_search:
+ - ansible.com
+ - redhat.com
+ - cisco.com
+ state: absent
+- name: configure hostname and domain-name with vrf
+ cisco.iosxr.iosxr_system:
+ hostname: iosxr01
+ vrf: nondefault
+ domain_name: test.example.com
+ domain_search:
+ - ansible.com
+ - redhat.com
+ - cisco.com
+- name: configure DNS lookup sources
+ cisco.iosxr.iosxr_system:
+ lookup_source: MgmtEth0/0/CPU0/0
+ lookup_enabled: true
+- name: configure name servers
+ cisco.iosxr.iosxr_system:
+ name_servers:
+ - 8.8.8.8
+ - 8.8.4.4
+"""
+
+RETURN = """
+commands:
+ description: The list of configuration mode commands to send to the device
+ returned: always
+ type: list
+ sample:
+ - hostname iosxr01
+ - ip domain-name test.example.com
+xml:
+ description: NetConf rpc xml sent to device with transport C(netconf)
+ returned: always (empty list when no xml rpc to send)
+ type: list
+ sample:
+ - '<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <ip-domain xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ip-domain-cfg">
+ <vrfs>
+ <vrf>
+ <vrf-name>default</vrf-name>
+ <lists>
+ <list xc:operation="merge">
+ <order>0</order>
+ <list-name>redhat.com</list-name>
+ </list>
+ </lists>
+ </vrf>
+ </vrfs>
+ </ip-domain>
+ </config>'
+"""
+
+import re
+import collections
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ get_config,
+ load_config,
+ etree_findall,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ is_cliconf,
+ is_netconf,
+ etree_find,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ iosxr_argument_spec,
+ build_xml,
+)
+
+
+def diff_list(want, have):
+ adds = set(want).difference(have)
+ removes = set(have).difference(want)
+ return (adds, removes)
+
+
+class ConfigBase(object):
+ def __init__(self, module):
+ self._module = module
+ self._result = {"changed": False, "warnings": []}
+ self._want = dict()
+ self._have = dict()
+
+ def map_params_to_obj(self):
+ self._want.update(
+ {
+ "hostname": self._module.params["hostname"],
+ "vrf": self._module.params["vrf"],
+ "domain_name": self._module.params["domain_name"],
+ "domain_search": self._module.params["domain_search"],
+ "lookup_source": self._module.params["lookup_source"],
+ "lookup_enabled": self._module.params["lookup_enabled"],
+ "name_servers": self._module.params["name_servers"],
+ }
+ )
+
+
+class CliConfiguration(ConfigBase):
+ def __init__(self, module):
+ super(CliConfiguration, self).__init__(module)
+
+ def map_obj_to_commands(self):
+ commands = list()
+ state = self._module.params["state"]
+
+ def needs_update(x):
+ return self._want.get(x) and (
+ self._want.get(x) != self._have.get(x)
+ )
+
+ if state == "absent":
+ if self._have["hostname"] != "ios":
+ commands.append("no hostname")
+ if self._have["domain_name"]:
+ commands.append("no domain name")
+ if self._have["lookup_source"]:
+ commands.append(
+ "no domain lookup source-interface {0!s}".format(
+ self._have["lookup_source"]
+ )
+ )
+ if not self._have["lookup_enabled"]:
+ commands.append("no domain lookup disable")
+ for item in self._have["name_servers"]:
+ commands.append("no domain name-server {0!s}".format(item))
+ for item in self._have["domain_search"]:
+ commands.append("no domain list {0!s}".format(item))
+
+ elif state == "present":
+ if needs_update("hostname"):
+ commands.append(
+ "hostname {0!s}".format(self._want["hostname"])
+ )
+
+ if needs_update("domain_name"):
+ commands.append(
+ "domain name {0!s}".format(self._want["domain_name"])
+ )
+
+ if needs_update("lookup_source"):
+ commands.append(
+ "domain lookup source-interface {0!s}".format(
+ self._want["lookup_source"]
+ )
+ )
+
+ cmd = None
+ if (
+ not self._want["lookup_enabled"]
+ and self._have["lookup_enabled"]
+ ):
+ cmd = "domain lookup disable"
+ elif (
+ self._want["lookup_enabled"]
+ and not self._have["lookup_enabled"]
+ ):
+ cmd = "no domain lookup disable"
+ if cmd is not None:
+ commands.append(cmd)
+
+ if self._want["name_servers"] is not None:
+ adds, removes = diff_list(
+ self._want["name_servers"], self._have["name_servers"]
+ )
+ for item in adds:
+ commands.append("domain name-server {0!s}".format(item))
+ for item in removes:
+ commands.append("no domain name-server {0!s}".format(item))
+
+ if self._want["domain_search"] is not None:
+ adds, removes = diff_list(
+ self._want["domain_search"], self._have["domain_search"]
+ )
+ for item in adds:
+ commands.append("domain list {0!s}".format(item))
+ for item in removes:
+ commands.append("no domain list {0!s}".format(item))
+
+ self._result["commands"] = []
+ if commands:
+ commit = not self._module.check_mode
+ diff = load_config(self._module, commands, commit=commit)
+ if diff:
+ self._result["diff"] = dict(prepared=diff)
+
+ self._result["commands"] = commands
+ self._result["changed"] = True
+
+ def parse_hostname(self, config):
+ match = re.search(r"^hostname (\S+)", config, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_domain_name(self, config):
+ match = re.search(r"^domain name (\S+)", config, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_lookup_source(self, config):
+ match = re.search(
+ r"^domain lookup source-interface (\S+)", config, re.M
+ )
+ if match:
+ return match.group(1)
+
+ def map_config_to_obj(self):
+ config = get_config(self._module)
+ self._have.update(
+ {
+ "hostname": self.parse_hostname(config),
+ "domain_name": self.parse_domain_name(config),
+ "domain_search": re.findall(
+ r"^domain list (\S+)", config, re.M
+ ),
+ "lookup_source": self.parse_lookup_source(config),
+ "lookup_enabled": "domain lookup disable" not in config,
+ "name_servers": re.findall(
+ r"^domain name-server (\S+)", config, re.M
+ ),
+ }
+ )
+
+ def run(self):
+ self.map_params_to_obj()
+ self.map_config_to_obj()
+ self.map_obj_to_commands()
+
+ return self._result
+
+
+class NCConfiguration(ConfigBase):
+ def __init__(self, module):
+ super(NCConfiguration, self).__init__(module)
+ self._system_meta = collections.OrderedDict()
+ self._system_domain_meta = collections.OrderedDict()
+ self._system_server_meta = collections.OrderedDict()
+ self._hostname_meta = collections.OrderedDict()
+ self._lookup_source_meta = collections.OrderedDict()
+ self._lookup_meta = collections.OrderedDict()
+
+ def map_obj_to_xml_rpc(self):
+ self._system_meta.update(
+ [
+ (
+ "vrfs",
+ {
+ "xpath": "ip-domain/vrfs",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "vrf",
+ {
+ "xpath": "ip-domain/vrfs/vrf",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:vrf",
+ {
+ "xpath": "ip-domain/vrfs/vrf/vrf-name",
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:domain_name",
+ {
+ "xpath": "ip-domain/vrfs/vrf/name",
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ ]
+ )
+
+ self._system_domain_meta.update(
+ [
+ (
+ "vrfs",
+ {
+ "xpath": "ip-domain/vrfs",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "vrf",
+ {
+ "xpath": "ip-domain/vrfs/vrf",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:vrf",
+ {
+ "xpath": "ip-domain/vrfs/vrf/vrf-name",
+ "operation": "edit",
+ },
+ ),
+ (
+ "lists",
+ {
+ "xpath": "ip-domain/vrfs/vrf/lists",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "list",
+ {
+ "xpath": "ip-domain/vrfs/vrf/lists/list",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:order",
+ {
+ "xpath": "ip-domain/vrfs/vrf/lists/list/order",
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:domain_search",
+ {
+ "xpath": "ip-domain/vrfs/vrf/lists/list/list-name",
+ "operation": "edit",
+ },
+ ),
+ ]
+ )
+
+ self._system_server_meta.update(
+ [
+ (
+ "vrfs",
+ {
+ "xpath": "ip-domain/vrfs",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "vrf",
+ {
+ "xpath": "ip-domain/vrfs/vrf",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:vrf",
+ {
+ "xpath": "ip-domain/vrfs/vrf/vrf-name",
+ "operation": "edit",
+ },
+ ),
+ (
+ "servers",
+ {
+ "xpath": "ip-domain/vrfs/vrf/servers",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "server",
+ {
+ "xpath": "ip-domain/vrfs/vrf/servers/server",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:order",
+ {
+ "xpath": "ip-domain/vrfs/vrf/servers/server/order",
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:name_servers",
+ {
+ "xpath": "ip-domain/vrfs/vrf/servers/server/server-address",
+ "operation": "edit",
+ },
+ ),
+ ]
+ )
+
+ self._hostname_meta.update(
+ [
+ (
+ "a:hostname",
+ {
+ "xpath": "host-names/host-name",
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ )
+ ]
+ )
+
+ self._lookup_source_meta.update(
+ [
+ (
+ "vrfs",
+ {
+ "xpath": "ip-domain/vrfs",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "vrf",
+ {
+ "xpath": "ip-domain/vrfs/vrf",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:vrf",
+ {
+ "xpath": "ip-domain/vrfs/vrf/vrf-name",
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:lookup_source",
+ {
+ "xpath": "ip-domain/vrfs/vrf/source-interface",
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ ]
+ )
+
+ self._lookup_meta.update(
+ [
+ (
+ "vrfs",
+ {
+ "xpath": "ip-domain/vrfs",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "vrf",
+ {
+ "xpath": "ip-domain/vrfs/vrf",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:vrf",
+ {
+ "xpath": "ip-domain/vrfs/vrf/vrf-name",
+ "operation": "edit",
+ },
+ ),
+ (
+ "lookup",
+ {
+ "xpath": "ip-domain/vrfs/vrf/lookup",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ ]
+ )
+
+ state = self._module.params["state"]
+ _get_filter = build_xml("ip-domain", opcode="filter")
+ running = get_config(
+ self._module, source="running", config_filter=_get_filter
+ )
+ _get_filter = build_xml("host-names", opcode="filter")
+ hostname_runn = get_config(
+ self._module, source="running", config_filter=_get_filter
+ )
+
+ hostname_ele = etree_find(hostname_runn, "host-name")
+ hostname = hostname_ele.text if hostname_ele is not None else None
+
+ vrf_ele = etree_findall(running, "vrf")
+ vrf_map = {}
+ for vrf in vrf_ele:
+ name_server_list = list()
+ domain_list = list()
+ vrf_name_ele = etree_find(vrf, "vrf-name")
+ vrf_name = vrf_name_ele.text if vrf_name_ele is not None else None
+
+ domain_name_ele = etree_find(vrf, "name")
+ domain_name = (
+ domain_name_ele.text if domain_name_ele is not None else None
+ )
+
+ domain_ele = etree_findall(vrf, "list-name")
+ for domain in domain_ele:
+ domain_list.append(domain.text)
+
+ server_ele = etree_findall(vrf, "server-address")
+ for server in server_ele:
+ name_server_list.append(server.text)
+
+ lookup_source_ele = etree_find(vrf, "source-interface")
+ lookup_source = (
+ lookup_source_ele.text
+ if lookup_source_ele is not None
+ else None
+ )
+
+ lookup_enabled = (
+ False if etree_find(vrf, "lookup") is not None else True
+ )
+
+ vrf_map[vrf_name] = {
+ "domain_name": domain_name,
+ "domain_search": domain_list,
+ "name_servers": name_server_list,
+ "lookup_source": lookup_source,
+ "lookup_enabled": lookup_enabled,
+ }
+
+ opcode = None
+ hostname_param = {}
+ lookup_param = {}
+ system_param = {}
+ sys_server_params = list()
+ sys_domain_params = list()
+ add_domain_params = list()
+ del_domain_params = list()
+ add_server_params = list()
+ del_server_params = list()
+ lookup_source_params = {}
+
+ try:
+ sys_node = vrf_map[self._want["vrf"]]
+ except KeyError:
+ sys_node = {
+ "domain_name": None,
+ "domain_search": [],
+ "name_servers": [],
+ "lookup_source": None,
+ "lookup_enabled": True,
+ }
+
+ if state == "absent":
+ opcode = "delete"
+
+ def needs_update(x):
+ return (
+ self._want[x] is not None and self._want[x] == sys_node[x]
+ )
+
+ if needs_update("domain_name"):
+ system_param = {
+ "vrf": self._want["vrf"],
+ "domain_name": self._want["domain_name"],
+ }
+
+ if needs_update("hostname"):
+ hostname_param = {"hostname": hostname}
+
+ if (
+ not self._want["lookup_enabled"]
+ and not sys_node["lookup_enabled"]
+ ):
+ lookup_param["vrf"] = self._want["vrf"]
+
+ if needs_update("lookup_source"):
+ lookup_source_params["vrf"] = self._want["vrf"]
+ lookup_source_params["lookup_source"] = self._want[
+ "lookup_source"
+ ]
+
+ if self._want["domain_search"]:
+ domain_param = {}
+ domain_param["domain_name"] = self._want["domain_name"]
+ domain_param["vrf"] = self._want["vrf"]
+ domain_param["order"] = "0"
+ for domain in self._want["domain_search"]:
+ if domain in sys_node["domain_search"]:
+ domain_param["domain_search"] = domain
+ sys_domain_params.append(domain_param.copy())
+
+ if self._want["name_servers"]:
+ server_param = {}
+ server_param["vrf"] = self._want["vrf"]
+ server_param["order"] = "0"
+ for server in self._want["name_servers"]:
+ if server in sys_node["name_servers"]:
+ server_param["name_servers"] = server
+ sys_server_params.append(server_param.copy())
+
+ elif state == "present":
+ opcode = "merge"
+
+ def needs_update(x):
+ return self._want[x] is not None and (
+ sys_node[x] is None
+ or (
+ sys_node[x] is not None
+ and self._want[x] != sys_node[x]
+ )
+ )
+
+ if needs_update("domain_name"):
+ system_param = {
+ "vrf": self._want["vrf"],
+ "domain_name": self._want["domain_name"],
+ }
+
+ if (
+ self._want["hostname"] is not None
+ and self._want["hostname"] != hostname
+ ):
+ hostname_param = {"hostname": self._want["hostname"]}
+
+ if not self._want["lookup_enabled"] and sys_node["lookup_enabled"]:
+ lookup_param["vrf"] = self._want["vrf"]
+
+ if needs_update("lookup_source"):
+ lookup_source_params["vrf"] = self._want["vrf"]
+ lookup_source_params["lookup_source"] = self._want[
+ "lookup_source"
+ ]
+
+ if self._want["domain_search"]:
+ domain_adds, domain_removes = diff_list(
+ self._want["domain_search"], sys_node["domain_search"]
+ )
+ domain_param = {}
+ domain_param["domain_name"] = self._want["domain_name"]
+ domain_param["vrf"] = self._want["vrf"]
+ domain_param["order"] = "0"
+ for domain in domain_adds:
+ if domain not in sys_node["domain_search"]:
+ domain_param["domain_search"] = domain
+ add_domain_params.append(domain_param.copy())
+ for domain in domain_removes:
+ if domain in sys_node["domain_search"]:
+ domain_param["domain_search"] = domain
+ del_domain_params.append(domain_param.copy())
+
+ if self._want["name_servers"]:
+ server_adds, server_removes = diff_list(
+ self._want["name_servers"], sys_node["name_servers"]
+ )
+ server_param = {}
+ server_param["vrf"] = self._want["vrf"]
+ server_param["order"] = "0"
+ for domain in server_adds:
+ if domain not in sys_node["name_servers"]:
+ server_param["name_servers"] = domain
+ add_server_params.append(server_param.copy())
+ for domain in server_removes:
+ if domain in sys_node["name_servers"]:
+ server_param["name_servers"] = domain
+ del_server_params.append(server_param.copy())
+
+ self._result["xml"] = []
+ _edit_filter_list = list()
+ if opcode:
+ if hostname_param:
+ _edit_filter_list.append(
+ build_xml(
+ "host-names",
+ xmap=self._hostname_meta,
+ params=hostname_param,
+ opcode=opcode,
+ )
+ )
+
+ if system_param:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._system_meta,
+ params=system_param,
+ opcode=opcode,
+ )
+ )
+
+ if lookup_source_params:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._lookup_source_meta,
+ params=lookup_source_params,
+ opcode=opcode,
+ )
+ )
+ if lookup_param:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._lookup_meta,
+ params=lookup_param,
+ opcode=opcode,
+ )
+ )
+
+ if opcode == "delete":
+ if sys_domain_params:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._system_domain_meta,
+ params=sys_domain_params,
+ opcode=opcode,
+ )
+ )
+ if sys_server_params:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._system_server_meta,
+ params=sys_server_params,
+ opcode=opcode,
+ )
+ )
+ if self._want["vrf"] != "default":
+ self._result["warnings"] = [
+ "name-servers delete operation with non-default vrf is a success, "
+ "but with rpc-error. Recommended to use 'ignore_errors' option with the task as a workaround"
+ ]
+ elif opcode == "merge":
+ if add_domain_params:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._system_domain_meta,
+ params=add_domain_params,
+ opcode=opcode,
+ )
+ )
+ if del_domain_params:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._system_domain_meta,
+ params=del_domain_params,
+ opcode="delete",
+ )
+ )
+
+ if add_server_params:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._system_server_meta,
+ params=add_server_params,
+ opcode=opcode,
+ )
+ )
+ if del_server_params:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._system_server_meta,
+ params=del_server_params,
+ opcode="delete",
+ )
+ )
+
+ diff = None
+ if _edit_filter_list:
+ commit = not self._module.check_mode
+ diff = load_config(
+ self._module,
+ _edit_filter_list,
+ commit=commit,
+ running=running,
+ nc_get_filter=_get_filter,
+ )
+
+ if diff:
+ if self._module._diff:
+ self._result["diff"] = dict(prepared=diff)
+
+ self._result["xml"] = _edit_filter_list
+ self._result["changed"] = True
+
+ def run(self):
+ self.map_params_to_obj()
+ self.map_obj_to_xml_rpc()
+
+ return self._result
+
+
+def main():
+ """ Main entry point for Ansible module execution
+ """
+ argument_spec = dict(
+ hostname=dict(type="str"),
+ vrf=dict(type="str", default="default"),
+ domain_name=dict(type="str"),
+ domain_search=dict(type="list", elements="str"),
+ name_servers=dict(type="list", elements="str"),
+ lookup_source=dict(type="str"),
+ lookup_enabled=dict(type="bool", default=True),
+ state=dict(choices=["present", "absent"], default="present"),
+ )
+
+ argument_spec.update(iosxr_argument_spec)
+
+ module = AnsibleModule(
+ argument_spec=argument_spec, supports_check_mode=True
+ )
+
+ config_object = None
+ if is_cliconf(module):
+ # Commenting the below cliconf deprecation support call for Ansible 2.9 as it'll be continued to be supported
+ # module.deprecate("cli support for 'iosxr_interface' is deprecated. Use transport netconf instead",
+ # version='2.9')
+ config_object = CliConfiguration(module)
+ elif is_netconf(module):
+ config_object = NCConfiguration(module)
+
+ result = None
+ if config_object:
+ result = config_object.run()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_user.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_user.py
new file mode 100644
index 00000000..e1c39905
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/modules/iosxr_user.py
@@ -0,0 +1,973 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# (c) 2017, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_user
+author:
+- Trishna Guha (@trishnaguha)
+- Sebastiaan van Doesselaar (@sebasdoes)
+- Kedar Kekan (@kedarX)
+short_description: Manage the aggregate of local users on Cisco IOS XR 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
+ aggregate of usernames in the current running config. It also supports purging usernames
+ from the configuration that are not explicitly defined.
+version_added: 1.0.0
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+notes:
+- This module works with connection C(network_cli) and C(netconf). See L(the IOS-XR
+ Platform Options,../network/user_guide/platform_iosxr.html).
+- Tested against IOS XRv 6.1.3
+options:
+ aggregate:
+ description:
+ - The set of username objects to be configured on the remote Cisco IOS XR 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
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - The username to be configured on the Cisco IOS XR 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).
+ type: str
+ required: true
+ configured_password:
+ description:
+ - The password to be configured on the Cisco IOS XR device. The password needs
+ to be provided in clear text. Password is encrypted on the device when used
+ with I(cli) and by Ansible when used with I(netconf) using the same MD5 hash
+ technique with salt size of 3. Please note that this option is not same as C(provider
+ password).
+ type: str
+ 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.
+ type: str
+ choices:
+ - on_create
+ - always
+ group:
+ description:
+ - Configures the group for the username in the device running configuration. The
+ argument accepts a string value defining the group name. This argument does
+ not check if the group has been configured on the device.
+ type: str
+ aliases:
+ - role
+ groups:
+ description:
+ - Configures the groups for the username in the device running configuration.
+ The argument accepts a list of group names. This argument does not check if
+ the group has been configured on the device. It is similar to the aggregate
+ command for usernames, but lets you configure multiple groups for the user(s).
+ type: list
+ elements: str
+ admin:
+ description:
+ - Enters into administration configuration mode for making config changes to the
+ device.
+ - Applicable only when using network_cli transport
+ type: bool
+ 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
+ type: str
+ choices:
+ - present
+ - absent
+ public_key:
+ description:
+ - Configures the contents of the public keyfile to upload to the IOS-XR node.
+ This enables users to login using the accompanying private key. IOS-XR only
+ accepts base64 decoded files, so this will be decoded and uploaded to the node.
+ Do note that this requires an OpenSSL public key file, PuTTy generated files
+ will not work! Mutually exclusive with public_key_contents. If used with multiple
+ users in aggregates, then the same key file is used for all users.
+ type: str
+ public_key_contents:
+ description:
+ - Configures the contents of the public keyfile to upload to the IOS-XR node.
+ This enables users to login using the accompanying private key. IOS-XR only
+ accepts base64 decoded files, so this will be decoded and uploaded to the node.
+ Do note that this requires an OpenSSL public key file, PuTTy generated files
+ will not work! Mutually exclusive with public_key.If used with multiple users
+ in aggregates, then the same key file is used for all users.
+ type: str
+ name:
+ description:
+ - The username to be configured on the Cisco IOS XR 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).
+ type: str
+ configured_password:
+ description:
+ - The password to be configured on the Cisco IOS XR device. The password needs
+ to be provided in clear text. Password is encrypted on the device when used
+ with I(cli) and by Ansible when used with I(netconf) using the same MD5 hash
+ technique with salt size of 3. Please note that this option is not same as C(provider
+ password).
+ type: str
+ 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.
+ type: str
+ default: always
+ choices:
+ - on_create
+ - always
+ group:
+ description:
+ - Configures the group for the username in the device running configuration. The
+ argument accepts a string value defining the group name. This argument does
+ not check if the group has been configured on the device.
+ type: str
+ aliases:
+ - role
+ groups:
+ description:
+ - Configures the groups for the username in the device running configuration.
+ The argument accepts a list of group names. This argument does not check if
+ the group has been configured on the device. It is similar to the aggregate
+ command for usernames, but lets you configure multiple groups for the user(s).
+ type: list
+ elements: str
+ 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 and the current defined set of users.
+ type: bool
+ default: false
+ admin:
+ description:
+ - Enters into administration configuration mode for making config changes to the
+ device.
+ - Applicable only when using network_cli transport
+ 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
+ type: str
+ default: present
+ choices:
+ - present
+ - absent
+ public_key:
+ description:
+ - Configures the contents of the public keyfile to upload to the IOS-XR node.
+ This enables users to login using the accompanying private key. IOS-XR only
+ accepts base64 decoded files, so this will be decoded and uploaded to the node.
+ Do note that this requires an OpenSSL public key file, PuTTy generated files
+ will not work! Mutually exclusive with public_key_contents. If used with multiple
+ users in aggregates, then the same key file is used for all users.
+ type: str
+ public_key_contents:
+ description:
+ - Configures the contents of the public keyfile to upload to the IOS-XR node.
+ This enables users to login using the accompanying private key. IOS-XR only
+ accepts base64 decoded files, so this will be decoded and uploaded to the node.
+ Do note that this requires an OpenSSL public key file, PuTTy generated files
+ will not work! Mutually exclusive with public_key.If used with multiple users
+ in aggregates, then the same key file is used for all users.
+ type: str
+
+requirements:
+- ncclient >= 0.5.3 when using netconf
+- lxml >= 4.1.1 when using netconf
+- base64 when using I(public_key_contents) or I(public_key)
+- paramiko when using I(public_key_contents) or I(public_key)
+"""
+
+EXAMPLES = """
+- name: create a new user
+ cisco.iosxr.iosxr_user:
+ name: ansible
+ configured_password: mypassword
+ state: present
+- name: create a new user in admin configuration mode
+ cisco.iosxr.iosxr_user:
+ name: ansible
+ configured_password: mypassword
+ admin: true
+ state: present
+- name: remove all users except admin
+ cisco.iosxr.iosxr_user:
+ purge: true
+- name: set multiple users to group sys-admin
+ cisco.iosxr.iosxr_user:
+ aggregate:
+ - name: netop
+ - name: netend
+ group: sysadmin
+ state: present
+- name: set multiple users to multiple groups
+ cisco.iosxr.iosxr_user:
+ aggregate:
+ - name: netop
+ - name: netend
+ groups:
+ - sysadmin
+ - root-system
+ state: present
+- name: Change Password for User netop
+ cisco.iosxr.iosxr_user:
+ name: netop
+ configured_password: '{{ new_password }}'
+ update_password: always
+ state: present
+- name: Add private key authentication for user netop
+ cisco.iosxr.iosxr_user:
+ name: netop
+ state: present
+ public_key_contents: "{{ lookup('file', '/home/netop/.ssh/id_rsa.pub' }}"
+"""
+
+RETURN = """
+commands:
+ description: The list of configuration mode commands to send to the device
+ returned: always
+ type: list
+ sample:
+ - username ansible secret password group sysadmin
+ - username admin secret admin
+xml:
+ description: NetConf rpc xml sent to device with transport C(netconf)
+ returned: always (empty list when no xml rpc to send)
+ type: list
+ sample:
+ - '<config xmlns:xc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">
+ <aaa xmlns=\"http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-lib-cfg\">
+ <usernames xmlns=\"http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-locald-cfg\">
+ <username xc:operation=\"merge\">
+ <name>test7</name>
+ <usergroup-under-usernames>
+ <usergroup-under-username>
+ <name>sysadmin</name>
+ </usergroup-under-username>
+ </usergroup-under-usernames>
+ <secret>$1$ZsXC$zZ50wqhDC543ZWQkkAHLW0</secret>
+ </username>
+ </usernames>
+ </aaa>
+ </config>'
+"""
+
+import os
+from functools import partial
+from copy import deepcopy
+import collections
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.compat.paramiko import paramiko
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ remove_default_spec,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ get_config,
+ load_config,
+ is_netconf,
+ is_cliconf,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ iosxr_argument_spec,
+ build_xml,
+ etree_findall,
+)
+
+try:
+ from base64 import b64decode
+
+ HAS_B64 = True
+except ImportError:
+ HAS_B64 = False
+
+
+class PublicKeyManager(object):
+ def __init__(self, module, result):
+ self._module = module
+ self._result = result
+
+ def convert_key_to_base64(self):
+ """ IOS-XR only accepts base64 decoded files, this converts the public key to a temp file.
+ """
+ if self._module.params["aggregate"]:
+ name = "aggregate"
+ else:
+ name = self._module.params["name"]
+
+ if self._module.params["public_key_contents"]:
+ key = self._module.params["public_key_contents"]
+ elif self._module.params["public_key"]:
+ readfile = open(self._module.params["public_key"], "r")
+ key = readfile.read()
+ splitfile = key.split()[1]
+
+ base64key = b64decode(splitfile)
+ base64file = open("/tmp/publickey_%s.b64" % (name), "wb")
+ base64file.write(base64key)
+ base64file.close()
+
+ return "/tmp/publickey_%s.b64" % (name)
+
+ def copy_key_to_node(self, base64keyfile):
+ """ Copy key to IOS-XR node. We use SFTP because older IOS-XR versions don't handle SCP very well.
+ """
+ provider = self._module.params.get("provider") or {}
+ node = provider.get("host")
+ if node is None:
+ return False
+
+ user = provider.get("username")
+ if user is None:
+ return False
+
+ password = provider.get("password")
+ ssh_keyfile = provider.get("ssh_keyfile")
+
+ if self._module.params["aggregate"]:
+ name = "aggregate"
+ else:
+ name = self._module.params["name"]
+
+ src = base64keyfile
+ dst = "/harddisk:/publickey_%s.b64" % (name)
+
+ ssh = paramiko.SSHClient()
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ if not ssh_keyfile:
+ ssh.connect(node, username=user, password=password)
+ else:
+ ssh.connect(node, username=user, allow_agent=True)
+ sftp = ssh.open_sftp()
+ sftp.put(src, dst)
+ sftp.close()
+ ssh.close()
+
+ def addremovekey(self, command):
+ """ Add or remove key based on command
+ """
+ provider = self._module.params.get("provider") or {}
+ node = provider.get("host")
+ if node is None:
+ return False
+
+ user = provider.get("username")
+ if user is None:
+ return False
+
+ password = provider.get("password")
+ ssh_keyfile = provider.get("ssh_keyfile")
+
+ ssh = paramiko.SSHClient()
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ if not ssh_keyfile:
+ ssh.connect(node, username=user, password=password)
+ else:
+ ssh.connect(node, username=user, allow_agent=True)
+ ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(
+ "%s \r" % (command)
+ )
+ readmsg = ssh_stdout.read(
+ 100
+ ) # We need to read a bit to actually apply for some reason
+ if (
+ ("already" in readmsg)
+ or ("removed" in readmsg)
+ or ("really" in readmsg)
+ ):
+ ssh_stdin.write("yes\r")
+ ssh_stdout.read(
+ 1
+ ) # We need to read a bit to actually apply for some reason
+ ssh.close()
+
+ return readmsg
+
+ def run(self):
+ if self._module.params["state"] == "present":
+ if not self._module.check_mode:
+ key = self.convert_key_to_base64()
+ copykeys = self.copy_key_to_node(key)
+ if copykeys is False:
+ self._result["warnings"].append(
+ "Please set up your provider before running this playbook"
+ )
+
+ if self._module.params["aggregate"]:
+ for user in self._module.params["aggregate"]:
+ cmdtodo = (
+ "admin crypto key import authentication rsa username %s harddisk:/publickey_aggregate.b64"
+ % (user)
+ )
+ addremove = self.addremovekey(cmdtodo)
+ if addremove is False:
+ self._result["warnings"].append(
+ "Please set up your provider before running this playbook"
+ )
+ else:
+ cmdtodo = (
+ "admin crypto key import authentication rsa username %s harddisk:/publickey_%s.b64"
+ % (
+ self._module.params["name"],
+ self._module.params["name"],
+ )
+ )
+ addremove = self.addremovekey(cmdtodo)
+ if addremove is False:
+ self._result["warnings"].append(
+ "Please set up your provider before running this playbook"
+ )
+ elif self._module.params["state"] == "absent":
+ if not self._module.check_mode:
+ if self._module.params["aggregate"]:
+ for user in self._module.params["aggregate"]:
+ cmdtodo = (
+ "admin crypto key zeroize authentication rsa username %s"
+ % (user)
+ )
+ addremove = self.addremovekey(cmdtodo)
+ if addremove is False:
+ self._result["warnings"].append(
+ "Please set up your provider before running this playbook"
+ )
+ else:
+ cmdtodo = (
+ "admin crypto key zeroize authentication rsa username %s"
+ % (self._module.params["name"])
+ )
+ addremove = self.addremovekey(cmdtodo)
+ if addremove is False:
+ self._result["warnings"].append(
+ "Please set up your provider before running this playbook"
+ )
+ elif self._module.params["purge"] is True:
+ if not self._module.check_mode:
+ cmdtodo = "admin crypto key zeroize authentication rsa all"
+ addremove = self.addremovekey(cmdtodo)
+ if addremove is False:
+ self._result["warnings"].append(
+ "Please set up your provider before running this playbook"
+ )
+
+ return self._result
+
+
+def search_obj_in_list(name, lst):
+ for o in lst:
+ if o["name"] == name:
+ return o
+
+ return None
+
+
+class ConfigBase(object):
+ def __init__(self, module, result, flag=None):
+ self._module = module
+ self._result = result
+ self._want = list()
+ self._have = list()
+
+ def get_param_value(self, key, item):
+ # if key doesn't exist in the item, get it from module.params
+ if not item.get(key):
+ value = self._module.params[key]
+
+ # if key does exist, do a type check on it to validate it
+ else:
+ value_type = self._module.argument_spec[key].get("type", "str")
+ type_checker = self._module._CHECK_ARGUMENT_TYPES_DISPATCHER[
+ value_type
+ ]
+ type_checker(item[key])
+ value = item[key]
+
+ # validate the param value (if validator func exists)
+ validator = globals().get("validate_%s" % key)
+ if all((value, validator)):
+ validator(value, self._module)
+
+ return value
+
+ def map_params_to_obj(self):
+ users = self._module.params["aggregate"]
+
+ aggregate = list()
+ if not users:
+ if (
+ not self._module.params["name"]
+ and self._module.params["purge"]
+ ):
+ pass
+ elif not self._module.params["name"]:
+ self._module.fail_json(msg="username is required")
+ else:
+ aggregate = [{"name": self._module.params["name"]}]
+ else:
+ for item in users:
+ if not isinstance(item, dict):
+ aggregate.append({"name": item})
+ elif "name" not in item:
+ self._module.fail_json(msg="name is required")
+ else:
+ aggregate.append(item)
+
+ for item in aggregate:
+ get_value = partial(self.get_param_value, item=item)
+ item["configured_password"] = get_value("configured_password")
+ item["group"] = get_value("group")
+ item["groups"] = get_value("groups")
+ item["state"] = get_value("state")
+ self._want.append(item)
+
+
+class CliConfiguration(ConfigBase):
+ def __init__(self, module, result):
+ super(CliConfiguration, self).__init__(module, result)
+
+ def map_config_to_obj(self):
+ data = get_config(self._module, config_filter="username")
+ users = data.strip().rstrip("!").split("!")
+
+ for user in users:
+ user_config = user.strip().splitlines()
+
+ name = user_config[0].strip().split()[1]
+ group = None
+
+ if len(user_config) > 1:
+ group_or_secret = user_config[1].strip().split()
+ if group_or_secret[0] == "group":
+ group = group_or_secret[1]
+
+ obj = {
+ "name": name,
+ "state": "present",
+ "configured_password": None,
+ "group": group,
+ }
+ self._have.append(obj)
+
+ def map_obj_to_commands(self):
+ commands = list()
+
+ for w in self._want:
+ name = w["name"]
+ state = w["state"]
+
+ obj_in_have = search_obj_in_list(name, self._have)
+
+ if state == "absent" and obj_in_have:
+ commands.append("no username " + name)
+ elif state == "present" and not obj_in_have:
+ user_cmd = "username " + name
+ commands.append(user_cmd)
+
+ if w["configured_password"]:
+ commands.append(
+ user_cmd + " secret " + w["configured_password"]
+ )
+ if w["group"]:
+ commands.append(user_cmd + " group " + w["group"])
+ elif w["groups"]:
+ for group in w["groups"]:
+ commands.append(user_cmd + " group " + group)
+
+ elif state == "present" and obj_in_have:
+ user_cmd = "username " + name
+
+ if (
+ self._module.params["update_password"] == "always"
+ and w["configured_password"]
+ ):
+ commands.append(
+ user_cmd + " secret " + w["configured_password"]
+ )
+ if w["group"] and w["group"] != obj_in_have["group"]:
+ commands.append(user_cmd + " group " + w["group"])
+ elif w["groups"]:
+ for group in w["groups"]:
+ commands.append(user_cmd + " group " + group)
+
+ if self._module.params["purge"]:
+ want_users = [x["name"] for x in self._want]
+ have_users = [x["name"] for x in self._have]
+ for item in set(have_users).difference(set(want_users)):
+ if item != "admin":
+ commands.append("no username %s" % item)
+
+ if "no username admin" in commands:
+ self._module.fail_json(msg="cannot delete the `admin` account")
+
+ self._result["commands"] = []
+ if commands:
+ commit = not self._module.check_mode
+ admin = self._module.params["admin"]
+ diff = load_config(
+ self._module, commands, commit=commit, admin=admin
+ )
+ if diff:
+ self._result["diff"] = dict(prepared=diff)
+
+ self._result["commands"] = commands
+ self._result["changed"] = True
+
+ def run(self):
+ self.map_params_to_obj()
+ self.map_config_to_obj()
+ self.map_obj_to_commands()
+
+ return self._result
+
+
+class NCConfiguration(ConfigBase):
+ def __init__(self, module, result):
+ super(NCConfiguration, self).__init__(module, result)
+ self._locald_meta = collections.OrderedDict()
+ self._locald_group_meta = collections.OrderedDict()
+
+ def generate_md5_hash(self, arg):
+ """
+ Generate MD5 hash with randomly generated salt size of 3.
+ :param arg:
+ :return passwd:
+ """
+ cmd = "openssl passwd -salt `openssl rand -base64 3` -1 "
+ return os.popen(cmd + arg).readlines()[0].strip()
+
+ def map_obj_to_xml_rpc(self):
+ self._locald_meta.update(
+ [
+ (
+ "aaa_locald",
+ {"xpath": "aaa/usernames", "tag": True, "ns": True},
+ ),
+ (
+ "username",
+ {
+ "xpath": "aaa/usernames/username",
+ "tag": True,
+ "attrib": "operation",
+ },
+ ),
+ ("a:name", {"xpath": "aaa/usernames/username/name"}),
+ (
+ "a:configured_password",
+ {
+ "xpath": "aaa/usernames/username/secret",
+ "operation": "edit",
+ },
+ ),
+ ]
+ )
+
+ self._locald_group_meta.update(
+ [
+ (
+ "aaa_locald",
+ {"xpath": "aaa/usernames", "tag": True, "ns": True},
+ ),
+ (
+ "username",
+ {
+ "xpath": "aaa/usernames/username",
+ "tag": True,
+ "attrib": "operation",
+ },
+ ),
+ ("a:name", {"xpath": "aaa/usernames/username/name"}),
+ (
+ "usergroups",
+ {
+ "xpath": "aaa/usernames/username/usergroup-under-usernames",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "usergroup",
+ {
+ "xpath": "aaa/usernames/username/usergroup-under-usernames/usergroup-under-username",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:group",
+ {
+ "xpath": "aaa/usernames/username/usergroup-under-usernames/usergroup-under-username/name",
+ "operation": "edit",
+ },
+ ),
+ ]
+ )
+
+ state = self._module.params["state"]
+ _get_filter = build_xml("aaa", opcode="filter")
+ running = get_config(
+ self._module, source="running", config_filter=_get_filter
+ )
+
+ elements = etree_findall(running, "username")
+ users = list()
+ for element in elements:
+ name_list = etree_findall(element, "name")
+ users.append(name_list[0].text)
+ list_size = len(name_list)
+ if list_size == 1:
+ self._have.append(
+ {"name": name_list[0].text, "group": None, "groups": None}
+ )
+ elif list_size == 2:
+ self._have.append(
+ {
+ "name": name_list[0].text,
+ "group": name_list[1].text,
+ "groups": None,
+ }
+ )
+ elif list_size > 2:
+ name_iter = iter(name_list)
+ next(name_iter)
+ tmp_list = list()
+ for name in name_iter:
+ tmp_list.append(name.text)
+
+ self._have.append(
+ {
+ "name": name_list[0].text,
+ "group": None,
+ "groups": tmp_list,
+ }
+ )
+
+ locald_params = list()
+ locald_group_params = list()
+ opcode = None
+
+ if state == "absent":
+ opcode = "delete"
+ for want_item in self._want:
+ if want_item["name"] in users:
+ want_item["configured_password"] = None
+ locald_params.append(want_item)
+ elif state == "present":
+ opcode = "merge"
+ for want_item in self._want:
+ if want_item["name"] not in users:
+ want_item["configured_password"] = self.generate_md5_hash(
+ want_item["configured_password"]
+ )
+ locald_params.append(want_item)
+
+ if want_item["group"] is not None:
+ locald_group_params.append(want_item)
+ if want_item["groups"] is not None:
+ for group in want_item["groups"]:
+ want_item["group"] = group
+ locald_group_params.append(want_item.copy())
+ else:
+ if (
+ self._module.params["update_password"] == "always"
+ and want_item["configured_password"] is not None
+ ):
+ want_item[
+ "configured_password"
+ ] = self.generate_md5_hash(
+ want_item["configured_password"]
+ )
+ locald_params.append(want_item)
+ else:
+ want_item["configured_password"] = None
+
+ obj_in_have = search_obj_in_list(
+ want_item["name"], self._have
+ )
+ if (
+ want_item["group"] is not None
+ and want_item["group"] != obj_in_have["group"]
+ ):
+ locald_group_params.append(want_item)
+ elif want_item["groups"] is not None:
+ for group in want_item["groups"]:
+ want_item["group"] = group
+ locald_group_params.append(want_item.copy())
+
+ purge_params = list()
+ if self._module.params["purge"]:
+ want_users = [x["name"] for x in self._want]
+ have_users = [x["name"] for x in self._have]
+ for item in set(have_users).difference(set(want_users)):
+ if item != "admin":
+ purge_params.append({"name": item})
+
+ self._result["xml"] = []
+ _edit_filter_list = list()
+ if opcode is not None:
+ if locald_params:
+ _edit_filter_list.append(
+ build_xml(
+ "aaa",
+ xmap=self._locald_meta,
+ params=locald_params,
+ opcode=opcode,
+ )
+ )
+
+ if locald_group_params:
+ _edit_filter_list.append(
+ build_xml(
+ "aaa",
+ xmap=self._locald_group_meta,
+ params=locald_group_params,
+ opcode=opcode,
+ )
+ )
+
+ if purge_params:
+ _edit_filter_list.append(
+ build_xml(
+ "aaa",
+ xmap=self._locald_meta,
+ params=purge_params,
+ opcode="delete",
+ )
+ )
+
+ diff = None
+ if _edit_filter_list:
+ commit = not self._module.check_mode
+ diff = load_config(
+ self._module,
+ _edit_filter_list,
+ commit=commit,
+ running=running,
+ nc_get_filter=_get_filter,
+ )
+
+ if diff:
+ if self._module._diff:
+ self._result["diff"] = dict(prepared=diff)
+
+ self._result["xml"] = _edit_filter_list
+ self._result["changed"] = True
+
+ def run(self):
+ self.map_params_to_obj()
+ self.map_obj_to_xml_rpc()
+
+ return self._result
+
+
+def main():
+ """ main entry point for module execution
+ """
+ element_spec = dict(
+ name=dict(type="str"),
+ configured_password=dict(type="str", no_log=True),
+ update_password=dict(
+ type="str", default="always", choices=["on_create", "always"]
+ ),
+ admin=dict(type="bool", default=False),
+ public_key=dict(type="str"),
+ public_key_contents=dict(type="str"),
+ group=dict(type="str", aliases=["role"]),
+ groups=dict(type="list", elements="str"),
+ state=dict(
+ type="str", 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)
+
+ mutually_exclusive = [
+ ("name", "aggregate"),
+ ("public_key", "public_key_contents"),
+ ("group", "groups"),
+ ]
+
+ argument_spec = dict(
+ aggregate=dict(
+ type="list",
+ elements="dict",
+ options=aggregate_spec,
+ aliases=["users", "collection"],
+ ),
+ purge=dict(type="bool", default=False),
+ )
+
+ argument_spec.update(element_spec)
+ argument_spec.update(iosxr_argument_spec)
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ mutually_exclusive=mutually_exclusive,
+ supports_check_mode=True,
+ )
+
+ if module.params["public_key_contents"] or module.params["public_key"]:
+ if not HAS_B64:
+ module.fail_json(
+ msg="library base64 is required but does not appear to be "
+ "installed. It can be installed using `pip install base64`"
+ )
+ if paramiko is None:
+ module.fail_json(
+ msg="library paramiko is required but does not appear to be "
+ "installed. It can be installed using `pip install paramiko`"
+ )
+
+ result = {"changed": False, "warnings": []}
+
+ config_object = None
+ if is_cliconf(module):
+ # Commenting the below cliconf deprecation support call for Ansible 2.9 as it'll be continued to be supported
+ # module.deprecate("cli support for 'iosxr_interface' is deprecated. Use transport netconf instead",
+ # version='2.9')
+ config_object = CliConfiguration(module, result)
+ elif is_netconf(module):
+ config_object = NCConfiguration(module, result)
+
+ if config_object:
+ result = config_object.run()
+
+ if module.params["public_key_contents"] or module.params["public_key"]:
+ pubkey_object = PublicKeyManager(module, result)
+ result = pubkey_object.run()
+
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/netconf/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/netconf/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/netconf/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/netconf/iosxr.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/netconf/iosxr.py
new file mode 100644
index 00000000..6e9255e0
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/netconf/iosxr.py
@@ -0,0 +1,297 @@
+#
+# (c) 2017 Red Hat Inc.
+# (c) 2017 Kedar Kekan (kkekan@redhat.com)
+#
+# 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
+netconf: iosxr
+short_description: Use iosxr netconf plugin to run netconf commands on Cisco IOSXR
+ platform
+description:
+- This iosxr plugin provides low level abstraction apis for sending and receiving
+ netconf commands from Cisco iosxr network devices.
+version_added: 1.0.0
+options:
+ ncclient_device_handler:
+ type: str
+ default: iosxr
+ description:
+ - Specifies the ncclient device handler name for Cisco iosxr network os. To identify
+ the ncclient device handler name refer ncclient library documentation.
+"""
+
+import json
+import re
+import collections
+
+from ansible.module_utils._text import to_native, to_text
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.netconf import (
+ remove_namespaces,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ build_xml,
+ etree_find,
+)
+from ansible.errors import AnsibleConnectionFailure
+from ansible.plugins.netconf import NetconfBase, ensure_ncclient
+
+try:
+ from ncclient import manager
+ from ncclient.operations import RPCError
+ from ncclient.transport.errors import SSHUnknownHostError
+ from ncclient.xml_ import to_xml
+
+ HAS_NCCLIENT = True
+except (
+ ImportError,
+ AttributeError,
+): # paramiko and gssapi are incompatible and raise AttributeError not ImportError
+ HAS_NCCLIENT = False
+
+
+class Netconf(NetconfBase):
+ def get_device_info(self):
+ device_info = {}
+ device_info["network_os"] = "iosxr"
+ install_meta = collections.OrderedDict()
+ install_meta.update(
+ [
+ (
+ "boot-variables",
+ {"xpath": "install/boot-variables", "tag": True},
+ ),
+ (
+ "boot-variable",
+ {
+ "xpath": "install/boot-variables/boot-variable",
+ "tag": True,
+ "lead": True,
+ },
+ ),
+ ("software", {"xpath": "install/software", "tag": True}),
+ (
+ "alias-devices",
+ {"xpath": "install/software/alias-devices", "tag": True},
+ ),
+ (
+ "alias-device",
+ {
+ "xpath": "install/software/alias-devices/alias-device",
+ "tag": True,
+ },
+ ),
+ (
+ "m:device-name",
+ {
+ "xpath": "install/software/alias-devices/alias-device/device-name",
+ "value": "disk0:",
+ },
+ ),
+ ]
+ )
+
+ install_filter = build_xml("install", install_meta, opcode="filter")
+ try:
+ reply = self.get(install_filter)
+ resp = remove_namespaces(
+ re.sub(r'<\?xml version="1.0" encoding="UTF-8"\?>', "", reply)
+ )
+ ele_boot_variable = etree_find(resp, "boot-variable/boot-variable")
+ if ele_boot_variable is not None:
+ device_info["network_os_image"] = re.split(
+ "[:|,]", ele_boot_variable.text
+ )[1]
+ ele_package_name = etree_find(reply, "package-name")
+ if ele_package_name is not None:
+ device_info["network_os_package"] = ele_package_name.text
+ device_info["network_os_version"] = re.split(
+ "-", ele_package_name.text
+ )[-1]
+
+ hostname_filter = build_xml("host-names", opcode="filter")
+ reply = self.get(hostname_filter)
+ resp = remove_namespaces(
+ re.sub(r'<\?xml version="1.0" encoding="UTF-8"\?>', "", reply)
+ )
+ hostname_ele = etree_find(resp.strip(), "host-name")
+ device_info["network_os_hostname"] = (
+ hostname_ele.text if hostname_ele is not None else None
+ )
+ except Exception as exc:
+ self._connection.queue_message(
+ "vvvv", "Fail to retrieve device info %s" % exc
+ )
+ return device_info
+
+ def get_capabilities(self):
+ result = dict()
+ result["rpc"] = self.get_base_rpc()
+ result["network_api"] = "netconf"
+ result["device_info"] = self.get_device_info()
+ result["server_capabilities"] = list(self.m.server_capabilities)
+ result["client_capabilities"] = list(self.m.client_capabilities)
+ result["session_id"] = self.m.session_id
+ result["device_operations"] = self.get_device_operations(
+ result["server_capabilities"]
+ )
+ return json.dumps(result)
+
+ @staticmethod
+ @ensure_ncclient
+ def guess_network_os(obj):
+ """
+ Guess the remote network os name
+ :param obj: Netconf connection class object
+ :return: Network OS name
+ """
+ try:
+ m = manager.connect(
+ host=obj._play_context.remote_addr,
+ port=obj._play_context.port or 830,
+ username=obj._play_context.remote_user,
+ password=obj._play_context.password,
+ key_filename=obj.key_filename,
+ hostkey_verify=obj.get_option("host_key_checking"),
+ look_for_keys=obj.get_option("look_for_keys"),
+ allow_agent=obj._play_context.allow_agent,
+ timeout=obj.get_option("persistent_connect_timeout"),
+ # We need to pass in the path to the ssh_config file when guessing
+ # the network_os so that a jumphost is correctly used if defined
+ ssh_config=obj._ssh_config,
+ )
+ except SSHUnknownHostError as exc:
+ raise AnsibleConnectionFailure(to_native(exc))
+
+ guessed_os = None
+ for c in m.server_capabilities:
+ if re.search("IOS-XR", c):
+ guessed_os = "iosxr"
+ break
+
+ m.close_session()
+ return guessed_os
+
+ # TODO: change .xml to .data_xml, when ncclient supports data_xml on all platforms
+ def get(self, filter=None, remove_ns=False):
+ if isinstance(filter, list):
+ filter = tuple(filter)
+ try:
+ resp = self.m.get(filter=filter)
+ if remove_ns:
+ response = remove_namespaces(resp)
+ else:
+ response = (
+ resp.data_xml if hasattr(resp, "data_xml") else resp.xml
+ )
+ return response
+ except RPCError as exc:
+ raise Exception(to_xml(exc.xml))
+
+ def get_config(self, source=None, filter=None, remove_ns=False):
+ if isinstance(filter, list):
+ filter = tuple(filter)
+ try:
+ resp = self.m.get_config(source=source, filter=filter)
+ if remove_ns:
+ response = remove_namespaces(resp)
+ else:
+ response = (
+ resp.data_xml if hasattr(resp, "data_xml") else resp.xml
+ )
+ return response
+ except RPCError as exc:
+ raise Exception(to_xml(exc.xml))
+
+ def edit_config(
+ self,
+ config=None,
+ format="xml",
+ target="candidate",
+ default_operation=None,
+ test_option=None,
+ error_option=None,
+ remove_ns=False,
+ ):
+ if config is None:
+ raise ValueError("config value must be provided")
+ try:
+ resp = self.m.edit_config(
+ config,
+ format=format,
+ target=target,
+ default_operation=default_operation,
+ test_option=test_option,
+ error_option=error_option,
+ )
+ if remove_ns:
+ response = remove_namespaces(resp)
+ else:
+ response = (
+ resp.data_xml if hasattr(resp, "data_xml") else resp.xml
+ )
+ return response
+ except RPCError as exc:
+ raise Exception(to_xml(exc.xml))
+
+ def commit(
+ self, confirmed=False, timeout=None, persist=None, remove_ns=False
+ ):
+ timeout = to_text(timeout, errors="surrogate_or_strict")
+ try:
+ resp = self.m.commit(
+ confirmed=confirmed, timeout=timeout, persist=persist
+ )
+ if remove_ns:
+ response = remove_namespaces(resp)
+ else:
+ response = (
+ resp.data_xml if hasattr(resp, "data_xml") else resp.xml
+ )
+ return response
+ except RPCError as exc:
+ raise Exception(to_xml(exc.xml))
+
+ def validate(self, source="candidate", remove_ns=False):
+ try:
+ resp = self.m.validate(source=source)
+ if remove_ns:
+ response = remove_namespaces(resp)
+ else:
+ response = (
+ resp.data_xml if hasattr(resp, "data_xml") else resp.xml
+ )
+ return response
+ except RPCError as exc:
+ raise Exception(to_xml(exc.xml))
+
+ def discard_changes(self, remove_ns=False):
+ try:
+ resp = self.m.discard_changes()
+ if remove_ns:
+ response = remove_namespaces(resp)
+ else:
+ response = (
+ resp.data_xml if hasattr(resp, "data_xml") else resp.xml
+ )
+ return response
+ except RPCError as exc:
+ raise Exception(to_xml(exc.xml))
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/terminal/__init__.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/terminal/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/terminal/__init__.py
diff --git a/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/terminal/iosxr.py b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/terminal/iosxr.py
new file mode 100644
index 00000000..89a7fd15
--- /dev/null
+++ b/collections-debian-merged/ansible_collections/cisco/iosxr/plugins/terminal/iosxr.py
@@ -0,0 +1,57 @@
+#
+# (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 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"]]>]]>[\r\n]?"),
+ ]
+
+ terminal_stderr_re = [
+ re.compile(br"% ?Error"),
+ re.compile(br"% ?Bad secret"),
+ re.compile(br"% ?This command is not authorized"),
+ re.compile(br"invalid input", re.I),
+ re.compile(br"(?:incomplete|ambiguous) command", re.I),
+ re.compile(br"(?<!\()connection timed out(?!\))", re.I),
+ re.compile(br"[^\r\n]+ not found", re.I),
+ re.compile(br"'[^']' +returned error code: ?\d+"),
+ re.compile(br"Failed to commit", re.I),
+ ]
+
+ def on_open_shell(self):
+ try:
+ for cmd in (
+ b"terminal length 0",
+ b"terminal width 512",
+ b"terminal exec prompt no-timestamp",
+ ):
+ self._exec_cli_command(cmd)
+ except AnsibleConnectionFailure:
+ raise AnsibleConnectionFailure("unable to set terminal parameters")