diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-18 05:52:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-18 05:52:22 +0000 |
commit | 38b7c80217c4e72b1d8988eb1e60bb6e77334114 (patch) | |
tree | 356e9fd3762877d07cde52d21e77070aeff7e789 /ansible_collections/cisco/iosxr/plugins/module_utils | |
parent | Adding upstream version 7.7.0+dfsg. (diff) | |
download | ansible-38b7c80217c4e72b1d8988eb1e60bb6e77334114.tar.xz ansible-38b7c80217c4e72b1d8988eb1e60bb6e77334114.zip |
Adding upstream version 9.4.0+dfsg.upstream/9.4.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/cisco/iosxr/plugins/module_utils')
44 files changed, 4476 insertions, 744 deletions
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/common/__init__.py index e69de29bb..e69de29bb 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/__init__.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/common/__init__.py diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_address_family/bgp_address_family.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_address_family/bgp_address_family.py index 7413c1ad9..10d4e1666 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_address_family/bgp_address_family.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_address_family/bgp_address_family.py @@ -149,6 +149,9 @@ class Bgp_address_familyArgs(object): # pylint: disable=R0903 }, "dampening": { "type": "dict", + "mutually_exclusive": [ + ["set", "value", "route_policy"], + ], "options": { "set": {"type": "bool"}, "value": {"type": "int"}, diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_global/bgp_global.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_global/bgp_global.py index 051e26996..3009b9f32 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_global/bgp_global.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_global/bgp_global.py @@ -270,6 +270,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "options": { "fast_detect": { "type": "dict", + "mutually_exclusive": [ + ["set", "disable", "strict_mode"], + ], "options": { "set": {"type": "bool"}, "disable": {"type": "bool"}, @@ -292,6 +295,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "options": { "send": { "type": "dict", + "mutually_exclusive": [ + ["set", "disable"], + ], "options": { "set": {"type": "bool"}, "disable": {"type": "bool"}, @@ -299,6 +305,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "receive": { "type": "dict", + "mutually_exclusive": [ + ["set", "disable"], + ], "options": { "set": {"type": "bool"}, "disable": {"type": "bool"}, @@ -317,6 +326,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "all": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": { "type": "bool", @@ -332,6 +344,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "description": {"type": "str"}, "dmz_link_bandwidth": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": {"type": "bool"}, "set": {"type": "bool"}, @@ -340,6 +355,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "dscp": {"type": "str"}, "ebgp_multihop": { "type": "dict", + "mutually_exclusive": [ + ["value", "mpls"], + ], "options": { "value": {"type": "int"}, "mpls": {"type": "bool"}, @@ -347,6 +365,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "ebgp_recv_extcommunity_dmz": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": {"type": "bool"}, "set": {"type": "bool"}, @@ -354,6 +375,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "ebgp_send_extcommunity_dmz": { "type": "dict", + "mutually_exclusive": [ + ["set", "cumulatie", "inheritance_disable"], + ], "options": { "inheritance_disable": {"type": "bool"}, "cumulatie": {"type": "bool"}, @@ -362,6 +386,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "egress_engineering": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": {"type": "bool"}, "set": {"type": "bool"}, @@ -377,6 +404,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "set": {"type": "bool"}, "activate": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": { "type": "bool", @@ -386,6 +416,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "as_prepends": { "type": "dict", + "mutually_exclusive": [ + ["value", "inheritance_disable"], + ], "options": { "inheritance_disable": { "type": "bool", @@ -395,6 +428,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "local_preference": { "type": "dict", + "mutually_exclusive": [ + ["value", "inheritance_disable"], + ], "options": { "value": {"type": "int"}, "inheritance_disable": { @@ -413,6 +449,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "ignore_connected_check": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": {"type": "bool"}, "set": {"type": "bool"}, @@ -421,6 +460,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "keychain": { "type": "dict", "no_log": False, + "mutually_exclusive": [ + ["name", "inheritance_disable"], + ], "options": { "name": {"type": "str"}, "inheritance_disable": {"type": "bool"}, @@ -431,6 +473,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "options": { "address": { "type": "dict", + "mutually_exclusive": [ + ["ipv4_address", "inheritance_disable"], + ], "options": { "ipv4_address": {"type": "str"}, "inheritance_disable": { @@ -442,8 +487,24 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "local_as": { "type": "dict", + "mutually_exclusive": [ + ["value", "inheritance_disable"], + ], "options": { "value": {"type": "int"}, + "no_prepend": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "replace_as": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "dual_as": {"type": "bool"}, + }, + }, + }, + }, "inheritance_disable": {"type": "bool"}, }, }, @@ -455,6 +516,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "options": { "in": { "type": "dict", + "mutually_exclusive": [ + ["value", "disable", "inheritance_disable"], + ], "options": { "value": {"type": "int"}, "disable": {"type": "bool"}, @@ -465,6 +529,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "out": { "type": "dict", + "mutually_exclusive": [ + ["value", "disable", "inheritance_disable"], + ], "options": { "value": {"type": "int"}, "disable": {"type": "bool"}, @@ -486,6 +553,19 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, }, }, + "password": { + "type": "dict", + "no_log": False, + "mutually_exclusive": [ + ["encrypted", "inheritance_disable"], + ], + "options": { + "encrypted": {"type": "str", "no_log": True}, + "inheritance_disable": { + "type": "bool", + }, + }, + }, "receive_buffer_size": {"type": "int"}, "remote_as": {"type": "int"}, "send_buffer_size": {"type": "int"}, @@ -495,6 +575,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "shutdown": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": {"type": "bool"}, "set": {"type": "bool"}, @@ -505,6 +588,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "options": { "mss": { "type": "dict", + "mutually_exclusive": [ + ["value", "inheritance_disable"], + ], "options": { "value": {"type": "int"}, "inheritance_disable": { @@ -523,6 +609,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "ttl_security": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": {"type": "bool"}, "set": {"type": "bool"}, @@ -568,10 +657,24 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, }, "update_source": {"type": "str"}, + "use": { + "type": "dict", + "options": { + "neighbor_group": { + "type": "str", + }, + "session_group": { + "type": "str", + }, + }, + }, }, }, "nsr": { "type": "dict", + "mutually_exclusive": [ + ["set", "disable"], + ], "options": { "set": {"type": "bool"}, "disable": {"type": "bool"}, @@ -862,6 +965,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "options": { "fast_detect": { "type": "dict", + "mutually_exclusive": [ + ["set", "disable", "strict_mode"], + ], "options": { "set": {"type": "bool"}, "disable": {"type": "bool"}, @@ -886,6 +992,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "options": { "send": { "type": "dict", + "mutually_exclusive": [ + ["set", "disable"], + ], "options": { "set": { "type": "bool", @@ -897,6 +1006,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "receive": { "type": "dict", + "mutually_exclusive": [ + ["set", "disable"], + ], "options": { "set": { "type": "bool", @@ -921,6 +1033,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "all": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": { "type": "bool", @@ -938,6 +1053,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "description": {"type": "str"}, "dmz_link_bandwidth": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": { "type": "bool", @@ -955,6 +1073,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "ebgp_recv_extcommunity_dmz": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": { "type": "bool", @@ -964,6 +1085,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "ebgp_send_extcommunity_dmz": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": { "type": "bool", @@ -974,6 +1098,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "egress_engineering": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": { "type": "bool", @@ -991,6 +1118,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "set": {"type": "bool"}, "activate": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": { "type": "bool", @@ -1000,6 +1130,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "as_prepends": { "type": "dict", + "mutually_exclusive": [ + ["value", "inheritance_disable"], + ], "options": { "inheritance_disable": { "type": "bool", @@ -1009,6 +1142,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "local_preference": { "type": "dict", + "mutually_exclusive": [ + ["value", "inheritance_disable"], + ], "options": { "value": {"type": "int"}, "inheritance_disable": { @@ -1027,6 +1163,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "ignore_connected_check": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": { "type": "bool", @@ -1036,6 +1175,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "keychain": { "type": "dict", + "mutually_exclusive": [ + ["name", "inheritance_disable"], + ], "no_log": False, "options": { "name": {"type": "str"}, @@ -1049,6 +1191,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "options": { "address": { "type": "dict", + "mutually_exclusive": [ + ["ipv4_address", "inheritance_disable"], + ], "options": { "ipv4_address": { "type": "str", @@ -1062,8 +1207,24 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "local_as": { "type": "dict", + "mutually_exclusive": [ + ["value", "inheritance_disable"], + ], "options": { "value": {"type": "int"}, + "no_prepend": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "replace_as": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "dual_as": {"type": "bool"}, + }, + }, + }, + }, "inheritance_disable": { "type": "bool", }, @@ -1077,6 +1238,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "options": { "in": { "type": "dict", + "mutually_exclusive": [ + ["value", "disable", "inheritance_disable"], + ], "options": { "value": { "type": "int", @@ -1091,6 +1255,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "out": { "type": "dict", + "mutually_exclusive": [ + ["value", "disable", "inheritance_disable"], + ], "options": { "value": { "type": "int", @@ -1118,6 +1285,19 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, }, }, + "password": { + "type": "dict", + "mutually_exclusive": [ + ["encrypted", "inheritance_disable"], + ], + "no_log": False, + "options": { + "encrypted": {"type": "str", "no_log": True}, + "inheritance_disable": { + "type": "bool", + }, + }, + }, "receive_buffer_size": {"type": "int"}, "remote_as": {"type": "int"}, "send_buffer_size": {"type": "int"}, @@ -1131,6 +1311,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "shutdown": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": { "type": "bool", @@ -1143,6 +1326,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "options": { "mss": { "type": "dict", + "mutually_exclusive": [ + ["value", "inheritance_disable"], + ], "options": { "value": {"type": "int"}, "inheritance_disable": { @@ -1161,6 +1347,9 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, "ttl_security": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "inheritance_disable": { "type": "bool", @@ -1208,6 +1397,17 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 }, }, "update_source": {"type": "str"}, + "use": { + "type": "dict", + "options": { + "neighbor_group": { + "type": "str", + }, + "session_group": { + "type": "str", + }, + }, + }, }, }, "rd": { @@ -1239,6 +1439,7 @@ class Bgp_globalArgs(object): # pylint: disable=R0903 "deleted", "merged", "replaced", + "overridden", "gathered", "rendered", "parsed", diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_neighbor_address_family/bgp_neighbor_address_family.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_neighbor_address_family/bgp_neighbor_address_family.py index a720860b7..68e1bbeae 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_neighbor_address_family/bgp_neighbor_address_family.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_neighbor_address_family/bgp_neighbor_address_family.py @@ -80,6 +80,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 "send_cost_community_disable": {"type": "bool"}, "send_med": { "type": "dict", + "mutually_exclusive": [ + ["set", "disable"], + ], "options": { "set": {"type": "bool"}, "disable": {"type": "bool"}, @@ -89,10 +92,16 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 }, "allowas_in": { "type": "dict", + "mutually_exclusive": [ + ["set", "value"], + ], "options": {"value": {"type": "int"}, "set": {"type": "bool"}}, }, "as_override": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "set": {"type": "bool"}, "inheritance_disable": {"type": "bool"}, @@ -105,6 +114,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 }, "default_originate": { "type": "dict", + "mutually_exclusive": [ + ["set", "route_policy", "inheritance_disable"], + ], "options": { "set": {"type": "bool"}, "route_policy": {"type": "str"}, @@ -137,6 +149,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 "multipath": {"type": "bool"}, "next_hop_self": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "set": {"type": "bool"}, "inheritance_disable": {"type": "bool"}, @@ -179,6 +194,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 }, "route_reflector_client": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "set": {"type": "bool"}, "inheritance_disable": {"type": "bool"}, @@ -186,6 +204,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 }, "send_community_ebgp": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "set": {"type": "bool"}, "inheritance_disable": {"type": "bool"}, @@ -193,6 +214,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 }, "send_community_gshut_ebgp": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "set": {"type": "bool"}, "inheritance_disable": {"type": "bool"}, @@ -200,6 +224,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 }, "send_extended_community_ebgp": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "set": {"type": "bool"}, "inheritance_disable": {"type": "bool"}, @@ -207,6 +234,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 }, "send_multicast_attributes": { "type": "dict", + "mutually_exclusive": [ + ["set", "disable"], + ], "options": { "set": {"type": "bool"}, "disable": {"type": "bool"}, @@ -217,6 +247,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 "options": { "inbound": { "type": "dict", + "mutually_exclusive": [ + ["set", "always", "inheritance_disable"], + ], "options": { "set": {"type": "bool"}, "always": {"type": "bool"}, @@ -271,6 +304,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 "send_cost_community_disable": {"type": "bool"}, "send_med": { "type": "dict", + "mutually_exclusive": [ + ["set", "disable"], + ], "options": { "set": {"type": "bool"}, "disable": {"type": "bool"}, @@ -280,6 +316,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 }, "allowas_in": { "type": "dict", + "mutually_exclusive": [ + ["value", "set"], + ], "options": { "value": {"type": "int"}, "set": {"type": "bool"}, @@ -288,6 +327,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 "as_override": { "type": "dict", "aliases": ["as_overrride"], + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "set": {"type": "bool"}, "inheritance_disable": {"type": "bool"}, @@ -299,6 +341,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 }, "default_originate": { "type": "dict", + "mutually_exclusive": [ + ["set", "route_policy", "inheritance_disable"], + ], "options": { "set": {"type": "bool"}, "route_policy": {"type": "str"}, @@ -331,6 +376,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 "multipath": {"type": "bool"}, "next_hop_self": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "set": {"type": "bool"}, "inheritance_disable": {"type": "bool"}, @@ -364,6 +412,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 }, "route_reflector_client": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "set": {"type": "bool"}, "inheritance_disable": {"type": "bool"}, @@ -371,6 +422,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 }, "send_community_ebgp": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "set": {"type": "bool"}, "inheritance_disable": {"type": "bool"}, @@ -378,6 +432,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 }, "send_community_gshut_ebgp": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "set": {"type": "bool"}, "inheritance_disable": {"type": "bool"}, @@ -385,6 +442,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 }, "send_extended_community_ebgp": { "type": "dict", + "mutually_exclusive": [ + ["set", "inheritance_disable"], + ], "options": { "set": {"type": "bool"}, "inheritance_disable": {"type": "bool"}, @@ -395,6 +455,9 @@ class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903 "options": { "inbound": { "type": "dict", + "mutually_exclusive": [ + ["set", "always", "inheritance_disable"], + ], "options": { "set": {"type": "bool"}, "always": {"type": "bool"}, diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_templates/__init__.py index e69de29bb..e69de29bb 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/__init__.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_templates/__init__.py diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_templates/bgp_templates.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_templates/bgp_templates.py new file mode 100644 index 000000000..793f26282 --- /dev/null +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_templates/bgp_templates.py @@ -0,0 +1,612 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 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 +# ansible.content_builder. +# +# Manually editing this file is not advised. +# +# To update the argspec make the desired changes +# in the documentation in the module file and re-run +# ansible.content_builder commenting out +# the path to external 'docstring' in build.yaml. +# +############################################## + +""" +The arg spec for the iosxr_bgp_templates module +""" + + +class Bgp_templatesArgs(object): # pylint: disable=R0903 + """The arg spec for the iosxr_bgp_templates module""" + + argument_spec = { + "config": { + "type": "dict", + "options": { + "as_number": {"type": "str"}, + "neighbor": { + "type": "list", + "elements": "dict", + "options": { + "name": {"type": "str"}, + "address_family": { + "type": "list", + "elements": "dict", + "options": { + "afi": { + "type": "str", + "choices": ["ipv4", "ipv6"], + }, + "safi": { + "type": "str", + "choices": [ + "flowspec", + "mdt", + "multicast", + "mvpn", + "rt-filter", + "tunnel", + "unicast", + "labeled-unicast", + "sr-policy", + ], + }, + "signalling": { + "type": "dict", + "options": { + "bgp_disable": {"type": "bool"}, + "ldp_disable": {"type": "bool"}, + }, + }, + "advertise": { + "type": "dict", + "options": { + "local_labeled_route": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "disable": {"type": "bool"}, + }, + }, + "permanent_network": {"type": "bool"}, + }, + }, + "aigp": { + "type": "dict", + "options": { + "disable": {"type": "bool"}, + "set": {"type": "bool"}, + "send_cost_community_disable": { + "type": "bool", + }, + "send_med": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "disable": {"type": "bool"}, + }, + }, + }, + }, + "allowas_in": { + "type": "dict", + "options": { + "value": {"type": "int"}, + "set": {"type": "bool"}, + }, + }, + "as_override": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "inheritance_disable": {"type": "bool"}, + }, + }, + "bestpath_origin_as_allow_invalid": { + "type": "bool", + }, + "capability_orf_prefix": { + "type": "str", + "choices": ["both", "send", "none", "receive"], + }, + "default_originate": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "route_policy": {"type": "str"}, + "inheritance_disable": {"type": "bool"}, + }, + }, + "encapsulation_type_srv6": {"type": "bool"}, + "long_lived_graceful_restart": { + "type": "dict", + "options": { + "capable": {"type": "bool"}, + "stale_time": { + "type": "dict", + "options": { + "send": {"type": "int"}, + "accept": {"type": "int"}, + }, + }, + }, + }, + "maximum_prefix": { + "type": "dict", + "options": { + "max_limit": {"type": "int"}, + "threshold_value": {"type": "int"}, + "restart": {"type": "int"}, + "warning_only": {"type": "bool"}, + "discard_extra_paths": {"type": "bool"}, + }, + }, + "multipath": {"type": "bool"}, + "next_hop_self": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "inheritance_disable": {"type": "bool"}, + }, + }, + "next_hop_unchanged": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "inheritance_disable": {"type": "bool"}, + "multipath": {"type": "bool"}, + }, + }, + "optimal_route_reflection_group_name": { + "type": "str", + }, + "orf_route_policy": {"type": "str"}, + "origin_as": { + "type": "dict", + "options": { + "validation": { + "type": "dict", + "options": { + "disable": {"type": "bool"}, + }, + }, + }, + }, + "remove_private_AS": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "inbound": {"type": "bool"}, + "entire_aspath": {"type": "bool"}, + "inheritance_disable": {"type": "bool"}, + }, + }, + "route_policy": { + "type": "dict", + "options": { + "inbound": {"type": "str"}, + "outbound": {"type": "str"}, + }, + }, + "route_reflector_client": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "inheritance_disable": {"type": "bool"}, + }, + }, + "send_community_ebgp": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "inheritance_disable": {"type": "bool"}, + }, + }, + "send_community_gshut_ebgp": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "inheritance_disable": {"type": "bool"}, + }, + }, + "send_extended_community_ebgp": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "inheritance_disable": {"type": "bool"}, + }, + }, + "send_multicast_attributes": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "disable": {"type": "bool"}, + }, + }, + "soft_reconfiguration": { + "type": "dict", + "options": { + "inbound": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "always": {"type": "bool"}, + "inheritance_disable": { + "type": "bool", + }, + }, + }, + }, + }, + "weight": {"type": "int"}, + "update": { + "type": "dict", + "options": { + "out_originator_loopcheck_disable": { + "type": "bool", + }, + "out_originator_loopcheck_set": { + "type": "bool", + }, + }, + }, + "use": {"type": "str"}, + }, + }, + "advertisement_interval": {"type": "int"}, + "bfd": { + "type": "dict", + "options": { + "fast_detect": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "disable": {"type": "bool"}, + "strict_mode": {"type": "bool"}, + }, + }, + "minimum_interval": {"type": "int"}, + "multiplier": {"type": "int"}, + }, + }, + "bmp_activate": { + "type": "dict", + "options": {"server": {"type": "int"}}, + }, + "capability": { + "type": "dict", + "options": { + "additional_paths": { + "type": "dict", + "options": { + "send": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "disable": {"type": "bool"}, + }, + }, + "receive": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "disable": {"type": "bool"}, + }, + }, + }, + }, + "suppress": { + "type": "dict", + "options": { + "four_byte_AS": { + "type": "dict", + "options": {"set": {"type": "bool"}}, + }, + "all": { + "type": "dict", + "options": { + "inheritance_disable": { + "type": "bool", + }, + "set": {"type": "bool"}, + }, + }, + }, + }, + }, + }, + "cluster_id": {"type": "str"}, + "description": {"type": "str"}, + "dmz_link_bandwidth": { + "type": "dict", + "options": { + "inheritance_disable": {"type": "bool"}, + "set": {"type": "bool"}, + }, + }, + "dscp": {"type": "str"}, + "ebgp_multihop": { + "type": "dict", + "options": { + "value": {"type": "int"}, + "mpls": {"type": "bool"}, + }, + }, + "ebgp_recv_extcommunity_dmz": { + "type": "dict", + "options": { + "inheritance_disable": {"type": "bool"}, + "set": {"type": "bool"}, + }, + }, + "ebgp_send_extcommunity_dmz": { + "type": "dict", + "options": { + "inheritance_disable": {"type": "bool"}, + "cumulatie": {"type": "bool"}, + "set": {"type": "bool"}, + }, + }, + "egress_engineering": { + "type": "dict", + "options": { + "inheritance_disable": {"type": "bool"}, + "set": {"type": "bool"}, + }, + }, + "enforce_first_as": { + "type": "dict", + "options": {"disable": {"type": "bool"}}, + }, + "graceful_maintenance": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "activate": { + "type": "dict", + "options": { + "inheritance_disable": {"type": "bool"}, + "set": {"type": "bool"}, + }, + }, + "as_prepends": { + "type": "dict", + "options": { + "inheritance_disable": {"type": "bool"}, + "value": {"type": "int"}, + }, + }, + "local_preference": { + "type": "dict", + "options": { + "value": {"type": "int"}, + "inheritance_disable": {"type": "bool"}, + }, + }, + }, + }, + "graceful_restart": { + "type": "dict", + "options": { + "restart_time": {"type": "int"}, + "stalepath_time": {"type": "int"}, + }, + }, + "ignore_connected_check": { + "type": "dict", + "options": { + "inheritance_disable": {"type": "bool"}, + "set": {"type": "bool"}, + }, + }, + "idle_watch_time": {"type": "int"}, + "internal_vpn_client": {"type": "bool"}, + "keychain": { + "type": "dict", + "no_log": False, + "options": { + "name": {"type": "str", "no_log": True}, + "inheritance_disable": {"type": "bool"}, + }, + }, + "local": { + "type": "dict", + "options": { + "address": { + "type": "dict", + "options": { + "ipv4_address": {"type": "str"}, + "inheritance_disable": {"type": "bool"}, + }, + }, + }, + }, + "local_as": { + "type": "dict", + "options": { + "value": {"type": "int"}, + "no_prepend": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "replace_as": { + "type": "dict", + "options": { + "set": {"type": "bool"}, + "dual_as": {"type": "bool"}, + }, + }, + }, + }, + "inheritance_disable": {"type": "bool"}, + }, + }, + "local_address_subnet": {"type": "str"}, + "log": { + "type": "dict", + "options": { + "log_message": { + "type": "dict", + "options": { + "in": { + "type": "dict", + "options": { + "value": {"type": "int"}, + "disable": {"type": "bool"}, + "inheritance_disable": { + "type": "bool", + }, + }, + }, + "out": { + "type": "dict", + "options": { + "value": {"type": "int"}, + "disable": {"type": "bool"}, + "inheritance_disable": { + "type": "bool", + }, + }, + }, + }, + }, + }, + }, + "maximum_peers": {"type": "int"}, + "password": { + "type": "dict", + "no_log": False, + "options": { + "encrypted": {"type": "str", "no_log": True}, + "inheritance_disable": {"type": "bool"}, + }, + }, + "peer_set": {"type": "int"}, + "precedence": { + "type": "str", + "choices": [ + "critical", + "flash", + "flash-override", + "immediate", + "internet", + "network", + "priority", + "routine", + ], + }, + "receive_buffer_size": {"type": "int"}, + "remote_as": {"type": "int"}, + "remote_as_list": {"type": "str"}, + "send_buffer_size": {"type": "int"}, + "session_open_mode": { + "type": "str", + "choices": ["active-only", "both", "passive-only"], + }, + "shutdown": { + "type": "dict", + "options": { + "inheritance_disable": {"type": "bool"}, + "set": {"type": "bool"}, + }, + }, + "tcp": { + "type": "dict", + "options": { + "mss": { + "type": "dict", + "options": { + "value": {"type": "int"}, + "inheritance_disable": {"type": "bool"}, + }, + }, + }, + }, + "timers": { + "type": "dict", + "options": { + "keepalive_time": {"type": "int"}, + "holdtime": {"type": "int"}, + "min_holdtime": {"type": "int"}, + }, + }, + "ttl_security": { + "type": "dict", + "options": { + "inheritance_disable": {"type": "bool"}, + "set": {"type": "bool"}, + }, + }, + "update": { + "type": "dict", + "options": { + "in": { + "type": "dict", + "options": { + "filtering": { + "type": "dict", + "options": { + "attribute_filter": { + "type": "dict", + "options": { + "group": {"type": "str"}, + }, + }, + "logging": { + "type": "dict", + "options": { + "disable": {"type": "bool"}, + }, + }, + "update_message": { + "type": "dict", + "options": { + "buffers": {"type": "int"}, + }, + }, + }, + }, + }, + }, + }, + }, + "update_source": {"type": "str"}, + "use": { + "type": "dict", + "options": { + "neighbor_group": {"type": "str"}, + "session_group": {"type": "str"}, + }, + }, + }, + }, + }, + }, + "running_config": {"type": "str"}, + "state": { + "type": "str", + "choices": [ + "deleted", + "merged", + "overridden", + "replaced", + "gathered", + "rendered", + "parsed", + ], + "default": "merged", + }, + } # pylint: disable=C0301 diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/l2_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/l2_interfaces.py index e58ddebbb..dff2f7680 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/l2_interfaces.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/l2_interfaces.py @@ -69,6 +69,7 @@ class L2_InterfacesArgs(object): "type": "list", }, "q_vlan": {"type": "list", "elements": "int"}, + "qvlan": {"type": "list", "elements": "str"}, "propagate": {"type": "bool"}, "encapsulation": { "type": "dict", diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/lacp.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/lacp.py index 2bdda1778..3fcaf8cb0 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/lacp.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/lacp.py @@ -58,6 +58,7 @@ class LacpArgs(object): # pylint: disable=R0903 "choices": [ "merged", "replaced", + "overridden", "deleted", "parsed", "rendered", diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/lldp_global.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/lldp_global.py index 6c6c39479..117065223 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/lldp_global.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/lldp_global.py @@ -62,6 +62,7 @@ class Lldp_globalArgs(object): # pylint: disable=R0903 "choices": [ "merged", "replaced", + "overridden", "deleted", "parsed", "rendered", diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/acls.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/acls.py index 9f9b1ea61..0e0ea7d00 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/acls.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/acls.py @@ -502,7 +502,8 @@ class Acls(ConfigBase): ) ^ set(flatten_dict(want_ace.get("protocol_options", {}))) if delta or protocol_opt_delta: - want_ace = self._dict_merge(have_ace, want_ace) + if self.state not in ["replaced"]: + want_ace = self._dict_merge(have_ace, want_ace) return self._compute_commands(want_ace) def _prepare_for_diff(self, ace): diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_global/bgp_global.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_global/bgp_global.py index 69b752be9..4cb4083c6 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_global/bgp_global.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_global/bgp_global.py @@ -116,6 +116,7 @@ class Bgp_global(ResourceModule): """ if self.state not in ["parsed", "gathered"]: self.generate_commands() + # import epdb;epdb.serve() self.run_commands() return self.result @@ -123,7 +124,7 @@ class Bgp_global(ResourceModule): """Generate configuration commands to send based on want, have and desired state. """ - if self.state in ["merged", "replaced"]: + if self.state in ["merged", "replaced", "overridden"]: w_asn = self.want.get("as_number") h_asn = self.have.get("as_number") @@ -242,6 +243,8 @@ class Bgp_global(ResourceModule): for the Bgp_global neighbor resource. """ neighbor_parsers = [ + "use.neighbor_group", + "use.session_group", "advertisement_interval", "bfd_fast_detect_disable", "bfd_fast_detect_strict_mode", @@ -275,6 +278,8 @@ class Bgp_global(ResourceModule): "local", "local_address", "origin_as", + "password_inheritance_disable", + "password_encrypted", "remote_as", "receive_buffer_size", "send_buffer_size", diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_templates/__init__.py index e69de29bb..e69de29bb 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/__init__.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_templates/__init__.py diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_templates/bgp_templates.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_templates/bgp_templates.py new file mode 100644 index 000000000..c62687dfa --- /dev/null +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_templates/bgp_templates.py @@ -0,0 +1,295 @@ +# +# -*- coding: utf-8 -*- +# Copyright 2023 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_bgp_templates 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 copy import deepcopy + +from ansible.module_utils.six import iteritems +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module import ( + ResourceModule, +) +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.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.bgp_templates import ( + Bgp_templatesTemplate, +) + + +class Bgp_templates(ResourceModule): + """ + The iosxr_bgp_templates config class + """ + + def __init__(self, module): + super(Bgp_templates, self).__init__( + empty_fact_val={}, + facts_module=Facts(module), + module=module, + resource="bgp_templates", + tmplt=Bgp_templatesTemplate(), + ) + self.parsers = [ + "router", + "advertise.local_labeled_route.disable", + "advertise.local_labeled_route.set", + "advertise.permanent_network", + "aigp.set", + "aigp.disable", + "aigp.send_med", + "aigp.send_cost_community_disable", + "allowas_in", + "as_override", + "bestpath_origin_as_allow_invalid", + "capability_orf_prefix", + "default_originate.set", + "default_originate.route_policy", + "default_originate.inheritance_disable", + "long_lived_graceful_restart_capable", + "long_lived_graceful_restart_stale_time", + "maximum_prefix", + "multipath", + "next_hop_self", + "next_hop_unchanged.set", + "next_hop_unchanged.inheritance_disable", + "next_hop_unchanged.multipath", + "optimal_route_reflection_group_name", + "origin_as", + "remove_private_AS", + "remove_private_AS.set", + "route_reflector_client", + "send_community_ebgp", + "send_community_gshut_ebgp", + "send_extended_community_ebgp", + "send_multicast_attributes", + "soft_reconfiguration", + "weight", + "route_policy.inbound", + "route_policy.outbound", + "signalling", + "update.out_originator_loopcheck_disable", + "update.out_originator_loopcheck_set", + "use", + ] + + 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. + """ + w_asn = self.want.pop("as_number", "") + h_asn = self.have.pop("as_number", "") + + asn = w_asn or h_asn + wantd = self._bgp_list_to_dict(deepcopy(self.want)) + haved = self._bgp_list_to_dict(deepcopy(self.have)) + # 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} + wantd = {} + + if self.state in ["overridden", "deleted"]: + cmds = [] + for k, have in iteritems(haved.get("neighbor", {})): + if k not in wantd.get("neighbor", {}): + cmds.append("no neighbor-group {0}".format(have["name"])) + self.commands.extend(cmds) + + self._compare(asn, want=wantd, have=haved) + + def sort_commands(self, index): + old_cmd = self.commands[index:] + self.commands = self.commands[0:index] + self.commands.extend( + [each for each in old_cmd if "no" in each] + + [each for each in old_cmd if "no" not in each], + ) + + def _compare(self, asn, 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 Bgp_global network resource. + """ + self._compare_ngs(want=want, have=have) + if self.commands and "router bgp" not in self.commands[0]: + self.commands.insert(0, "router bgp {0}".format(asn)) + + def _compare_ngs(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 Bgp_global neighbor resource. + """ + neighbor_parsers = [ + "use.neighbor_group", + "use.session_group", + "advertisement_interval", + "bfd_fast_detect_disable", + "bfd_fast_detect_strict_mode", + "bfd_fast_detect_set", + "bfd_nbr_minimum_interval", + "bfd_nbr_multiplier", + "bmp_activate", + "dmz_link_bandwidth", + "dmz_link_bandwidth_inheritance_disable", + "neighbor_description", + "neighbor_cluster_id", + "dscp", + "ebgp_multihop_value", + "ebgp_multihop_mpls", + "ebgp_recv_extcommunity_dmz", + "ebgp_recv_extcommunity_dmz_set", + "ebgp_send_extcommunity_dmz", + "ebgp_send_extcommunity_dmz_set", + "ebgp_send_extcommunity_dmz_cumulatie", + "egress_engineering", + "egress_engineering_set", + "idle_watch_time", + "internal_vpn_client", + "ignore_connected_check", + "ignore_connected_check_set", + "neighbor_enforce_first_as_disable", + "neighbor_graceful_restart_restart_time", + "neighbor_graceful_restart_stalepath_time", + "keychain", + "keychain_name", + "local_as_inheritance_disable", + "local_as", + "local", + "local_address", + "origin_as", + "password_inheritance_disable", + "password_encrypted", + "peer_set", + "precedence", + "remote_as", + "remote_as_list", + "receive_buffer_size", + "send_buffer_size", + "session_open_mode", + "neighbor_shutdown", + "neighbor_shutdown_inheritance_disable", + "neighbor_tcp_mss", + "neighbor_tcp_mss_inheritance_disable", + "neighbor_timers_keepalive", + "update_source", + "neighbor_ttl_security_inheritance_disable", + "neighbor_ttl_security", + "neighbor_graceful_maintenance_set", + "neighbor_graceful_maintenance_activate", + "neighbor_graceful_maintenance_activate_inheritance_disable", + "neighbor_graceful_maintenance_as_prepends", + "neighbor_graceful_maintenance_local_preference_disable", + "neighbor_graceful_maintenance_local_preference", + "neighbor_graceful_maintenance_as_prepends_value", + "neighbor_capability_additional_paths_send", + "neighbor_capability_additional_paths_send_disable", + "neighbor_capability_additional_paths_rcv_disable", + "neighbor_capability_additional_paths_rcv", + "neighbor_capability_suppress_four_byte_AS", + "neighbor_capability_suppress_all", + "neighbor_capability_suppress_all_inheritance_disable", + "neighbor_log_message_in_value", + "neighbor_log_message_in_disable", + "neighbor_log_message_in_inheritance_disable", + "neighbor_log_message_out_value", + "neighbor_log_message_out_disable", + "neighbor_log_message_out_inheritance_disable", + "neighbor_update_in_filtering_attribute_filter_group", + "neighbor_update_in_filtering_logging_disable", + "neighbor_update_in_filtering_message_buffers", + ] + + want_nbr = want.get("neighbor", {}) + have_nbr = have.get("neighbor", {}) + for name, entry in iteritems(want_nbr): + have = have_nbr.pop(name, {}) + begin = len(self.commands) + self.compare(parsers=neighbor_parsers, want=entry, have=have) + if self.state in ["replaced", "overridden"]: + self.sort_commands(begin) + self._compare_af(want=entry, have=have) + name = entry.get("name", "") + if len(self.commands) != begin: + self.commands.insert( + begin, + self._tmplt.render( + {"name": name}, + "neighbor_group", + False, + ), + ) + + def _compare_af(self, want, have): + """Custom handling of afs option + :params want: the want BGP dictionary + :params have: the have BGP dictionary + """ + wafs = want.get("address_family", {}) + hafs = have.get("address_family", {}) + for name, entry in iteritems(wafs): + begin = len(self.commands) + af_have = hafs.pop(name, {}) + self.compare(parsers=self.parsers, want=entry, have=af_have) + if self.state in ["replaced", "overridden"]: + self.sort_commands(begin) + if len(self.commands) != begin or (not af_have and entry): + self.commands.insert( + begin, + self._tmplt.render( + {"afi": entry.get("afi"), "safi": entry.get("safi")}, + "address_family", + False, + ), + ) + + for name, entry in iteritems(hafs): + self.addcmd( + {"afi": entry.get("afi"), "safi": entry.get("safi")}, + "address_family", + True, + ) + + def _bgp_list_to_dict(self, data): + if "neighbor" in data: + for nbr in data["neighbor"]: + if "address_family" in nbr: + nbr["address_family"] = { + (x["afi"], x.get("safi")): x for x in nbr["address_family"] + } + data["neighbor"] = {x["name"]: x for x in data["neighbor"]} + return data diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/interfaces.py index 2a0c18852..d13206109 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/interfaces.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/interfaces.py @@ -181,21 +181,33 @@ class Interfaces(ConfigBase): to the desired configuration """ commands = [] + not_in_have = set() + in_have = set() for each in have: for interface in want: - if each["name"] == interface["name"] or interface["name"] in each["name"]: + 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)) + kwargs = {"want": interface, "have": each} + commands.extend(self._clear_config(**kwargs)) continue have_dict = filter_dict_having_none_value(interface, each) - want = dict() - commands.extend(self._clear_config(want, have_dict)) + commands.extend(self._clear_config(dict(), have_dict)) commands.extend(self._set_config(interface, each)) + # 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, {})) # Remove the duplicate interface call commands = remove_duplicate_interface(commands) @@ -305,6 +317,17 @@ class Interfaces(ConfigBase): and want.get("duplex") != have.get("duplex") ): remove_command_from_config_list(interface, "duplex", commands) + + if interface_type.lower() in [ + "gigabitethernet", + "fourhundredgige", + "fiftygige", + "fortygige", + "hundredgige", + "twohundredgige", + "tengige", + "twentyfivegige", + ]: if have.get("mtu") and want.get("mtu") != have.get("mtu"): remove_command_from_config_list(interface, "mtu", commands) diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/l2_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/l2_interfaces.py index c571d3fa0..da44bb709 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/l2_interfaces.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/l2_interfaces.py @@ -262,12 +262,20 @@ class L2_Interfaces(ConfigBase): return commands + def _handle_deprecated(self, config): + if config.get("q_vlan"): + config["qvlan"] = config.get("q_vlan") + del config["q_vlan"] + return config + 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 = self._handle_deprecated(want) + have = self._handle_deprecated(have) diff = dict_diff(have, want) if diff: # For merging with already configured l2protocol @@ -286,7 +294,7 @@ class L2_Interfaces(ConfigBase): wants_native = diff.get("native_vlan") l2transport = diff.get("l2transport") - q_vlan = diff.get("q_vlan") + qvlan = diff.get("qvlan") encapsulation = diff.get("encapsulation") propagate = diff.get("propagate") if l2_protocol_bool is False: @@ -308,18 +316,16 @@ class L2_Interfaces(ConfigBase): ) add_command_to_config_list(interface, cmd, commands) - if q_vlan and "." in interface: - q_vlans = " ".join(map(str, want.get("q_vlan"))) - if q_vlans != have.get("q_vlan"): + if qvlan and "." in interface: + q_vlans = " ".join(map(str, want.get("qvlan"))) + if q_vlans != have.get("qvlan"): cmd = "dot1q vlan {0}".format(q_vlans) add_command_to_config_list(interface, cmd, commands) else: if l2transport or l2protocol: for each in l2protocol: each = dict(each) - if isinstance(each, dict) and "cpsv" in list( - each.keys(), - ): + if isinstance(each, dict) and each.get("cpsv"): cmd = "l2transport l2protocol {0} {1}".format( "cpsv", each.get("cpsv"), @@ -361,6 +367,8 @@ class L2_Interfaces(ConfigBase): def _clear_config(self, want, have): # Delete the interface config based on the want and have config commands = [] + want = self._handle_deprecated(want) + have = self._handle_deprecated(have) if want.get("name"): interface = "interface " + want["name"] @@ -375,7 +383,7 @@ class L2_Interfaces(ConfigBase): commands, ) - if have.get("q_vlan"): + if have.get("qvlan"): remove_command_from_config_list( interface, "encapsulation dot1q", diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/l3_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/l3_interfaces.py index 98b7c5965..9b55e2f91 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/l3_interfaces.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/l3_interfaces.py @@ -11,6 +11,8 @@ created from __future__ import absolute_import, division, print_function +import copy + __metaclass__ = type @@ -119,7 +121,7 @@ class L3_Interfaces(ConfigBase): to the desired configuration """ want = self._module.params["config"] - have = existing_l3_interfaces_facts + have = copy.deepcopy(existing_l3_interfaces_facts) resp = self.set_state(want, have) return to_list(resp) @@ -308,8 +310,12 @@ class L3_Interfaces(ConfigBase): 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 + each["address"] = validate_n_expand_ipv4(module, each) + + if have.get("ipv4"): + for each in have.get("ipv4"): + if each.get("address") != "dhcp": + each["address"] = validate_n_expand_ipv4(module, each) # Get the diff b/w want and have want_dict = dict_to_set(want) diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/lacp.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/lacp.py index 8a6744e54..ee0a7768d 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/lacp.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/lacp.py @@ -137,6 +137,7 @@ class Lacp(ConfigBase): :returns: the commands necessary to migrate the current configuration to the desired configuration """ + commands = [] 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( @@ -148,7 +149,7 @@ class Lacp(ConfigBase): commands = self._state_deleted(want, have) elif self.state in ("merged", "rendered"): commands = self._state_merged(want, have) - elif self.state == "replaced": + elif self.state in ["replaced", "overridden"]: commands = self._state_replaced(want, have) return commands diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/lldp_global.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/lldp_global.py index e4fda3c7c..a5c872f6f 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/lldp_global.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/lldp_global.py @@ -80,7 +80,6 @@ class Lldp_global(ConfigBase): 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 @@ -136,6 +135,7 @@ class Lldp_global(ConfigBase): :returns: the commands necessary to migrate the current configuration to the desired configuration """ + commands = [] state = self._module.params["state"] if state in ("merged", "replaced", "rendered") and not want: self._module.fail_json( @@ -148,7 +148,7 @@ class Lldp_global(ConfigBase): commands = self._state_deleted(want, have) elif state in ("merged", "rendered"): commands = self._state_merged(want, have) - elif state == "replaced": + elif state in ["replaced", "overridden"]: commands = self._state_replaced(want, have) return commands diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/logging_global/logging_global.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/logging_global/logging_global.py index ff790e548..d3d5223be 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/logging_global/logging_global.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/logging_global/logging_global.py @@ -178,7 +178,6 @@ class Logging_global(ResourceModule): self.addcmd(hentry, x, negate=True) def list_to_dict(self, config): - data = deepcopy(config) if "tls_servers" in data: data["tls_servers"] = {x["name"]: x for x in data["tls_servers"]} diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py index 05ce42472..16e0bc3e9 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py @@ -10,7 +10,6 @@ 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.rm_base.resource_module import ( @@ -107,22 +106,11 @@ class Ospfv3(ResourceModule): 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 state is overridden, first remove processes that are in have but not in want + if self.state in ["overridden", "deleted"]: + for k, have in iteritems(haved): 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, {})) + self.addcmd(have, "pid", True) for k, want in iteritems(wantd): self._compare(want=want, have=haved.pop(k, {})) diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ping/ping.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ping/ping.py index ce2a5229c..587fbde98 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ping/ping.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ping/ping.py @@ -84,7 +84,7 @@ class Ping: Returns the percent of packet loss, received packets, transmitted packets, and RTT data. """ - if type(ping_results) == list: + if isinstance(ping_results, list): ping_results = ping_results[0] ping_data = PingTemplate(lines=ping_results.splitlines()) diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/snmp_server/snmp_server.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/snmp_server/snmp_server.py index 9ee3e1a12..b69f2abd7 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/snmp_server/snmp_server.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/snmp_server/snmp_server.py @@ -281,7 +281,6 @@ class Snmp_server(ResourceModule): "users", "targets", ]: - wantx = want.get(x, {}) havex = have.get(x, {}) if "." in x: @@ -350,7 +349,6 @@ class Snmp_server(ResourceModule): return host_dict def list_to_dict(self, config): - data = deepcopy(config) if data.get("vrfs"): diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/static_routes.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/static_routes.py index b558f01af..ce8694389 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/static_routes.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/static_routes.py @@ -439,6 +439,57 @@ class Static_routes(ConfigBase): return commands + def _static_route_popper(self, want_afi, have_afi): + """ """ + commands = [] + + update_commands = [] + if not want_afi.get("routes", []): + commands.append( + "no address-family {0} {1}".format( + have_afi["afi"], + have_afi["safi"], + ), + ) + else: + for have_route in have_afi.get("routes", []): + want_route = ( + search_obj_in_list( + have_route["dest"], + want_afi.get("routes", []), + key="dest", + ) + or {} + ) + + rotated_want_next_hops = self.rotate_next_hops( + want_route.get("next_hops", {}), + ) + rotated_have_next_hops = self.rotate_next_hops( + have_route.get("next_hops", {}), + ) + + for key in rotated_want_next_hops.keys(): + if key in rotated_have_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) + if update_commands: + update_commands.insert( + 0, + "address-family {0} {1}".format( + have_afi["afi"], + have_afi["safi"], + ), + ) + commands.extend(update_commands) + + return commands + def _state_deleted(self, want, have): """The command generator when state is deleted @@ -460,12 +511,8 @@ class Static_routes(ConfigBase): or {} ) if have_afi: - commands.append( - "no address-family {0} {1}".format( - have_afi["afi"], - have_afi["safi"], - ), - ) + commands.extend(self._static_route_popper(want_afi, have_afi)) + if "vrf" in want and commands: commands.insert(0, "vrf {0}".format(want["vrf"])) diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_templates/__init__.py index e69de29bb..e69de29bb 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/__init__.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_templates/__init__.py diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_templates/bgp_templates.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_templates/bgp_templates.py new file mode 100644 index 000000000..98889ae59 --- /dev/null +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_templates/bgp_templates.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 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 bgp_templates 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 ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils + +from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.bgp_templates.bgp_templates import ( + Bgp_templatesArgs, +) +from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.bgp_templates import ( + Bgp_templatesTemplate, +) +from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import ( + flatten_config, +) + + +class Bgp_templatesFacts(object): + """The iosxr bgp_templates facts class""" + + def __init__(self, module, subspec="config", options="options"): + self._module = module + self.argument_spec = Bgp_templatesArgs.argument_spec + + def get_config(self, connection): + return connection.get("show running-config router bgp") + + def populate_facts(self, connection, ansible_facts, data=None): + """Populate the facts for Bgp_templates 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_config(connection) + data = flatten_config(data, "neighbor-group") + # parse native config using the Bgp_templates template + bgp_templates_parser = Bgp_templatesTemplate(lines=data.splitlines(), module=self._module) + objs = bgp_templates_parser.parse() + if objs: + objs["neighbor"] = self._post_parse(objs).get( + "neighbor", + [], + ) + ansible_facts["ansible_network_resources"].pop("bgp_templates", None) + + params = utils.remove_empties( + bgp_templates_parser.validate_config(self.argument_spec, {"config": objs}, redact=True), + ) + + facts["bgp_templates"] = params.get("config", {}) + ansible_facts["ansible_network_resources"].update(facts) + + return ansible_facts + + def _post_parse(self, data): + """Converts the intermediate data structure + to valid format as per argspec. + :param obj: dict + """ + if "neighbor" in data: + data["neighbor"] = sorted( + list(data["neighbor"].values()), + key=lambda k, s="name": k[s], + ) + for nbrg in data["neighbor"]: + if nbrg.get("address_family"): + nbrg["address_family"] = list(nbrg["address_family"].values()) + return data diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/facts.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/facts.py index 4d7e7b100..5cafa587d 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/facts.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/facts.py @@ -34,6 +34,9 @@ from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.bg from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.bgp_neighbor_address_family.bgp_neighbor_address_family import ( Bgp_neighbor_address_familyFacts, ) +from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.bgp_templates.bgp_templates import ( + Bgp_templatesFacts, +) from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.hostname.hostname import ( HostnameFacts, ) @@ -122,6 +125,7 @@ FACT_RESOURCE_SUBSETS = dict( ntp_global=Ntp_globalFacts, snmp_server=Snmp_serverFacts, hostname=HostnameFacts, + bgp_templates=Bgp_templatesFacts, ) diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/interfaces.py index e89dbca2e..5efcd6084 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/interfaces.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/interfaces.py @@ -92,24 +92,24 @@ class InterfacesFacts(object): 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) + if match: + 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/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/l2_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/l2_interfaces.py index cdb1d72cf..f562e20f8 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/l2_interfaces.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/l2_interfaces.py @@ -93,18 +93,17 @@ class L2_InterfacesFacts(object): """ config = deepcopy(spec) match = re.search(r"^(\S+)", conf) + if match: + intf = match.group(1) - intf = match.group(1) + if intf.lower() == "preconfigure": + match = re.search(r"^(\S+) (.*)", conf) + if match: + intf = match.group(2) - 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 get_interface_type(intf) == "unknown": - return {} - - if intf.lower().startswith("gi"): config["name"] = intf # populate the facts from the configuration @@ -128,11 +127,11 @@ class L2_InterfacesFacts(object): encapsulation.group(2).split("second-dot1q ")[1], ) else: - config["q_vlan"] = [] + config["qvlan"] = [] if dot1q: - config["q_vlan"].append(int(dot1q.split(" ")[0])) + config["qvlan"].append(dot1q.split(" ")[0]) if len(dot1q.split(" ")) > 1: - config["q_vlan"].append(int(dot1q.split(" ")[2])) + config["qvlan"].append(dot1q.split(" ")[2]) if utils.parse_conf_cmd_arg(conf, "l2transport", True): config["l2transport"] = True diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/l3_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/l3_interfaces.py index bf5ce5f85..b4dba858e 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/l3_interfaces.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/l3_interfaces.py @@ -27,6 +27,7 @@ from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec. ) from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import ( get_interface_type, + netmask_to_cidr, ) @@ -93,39 +94,45 @@ class L3_InterfacesFacts(object): """ 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) + if match: + 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"] = self.format_ipv4(each.split(" secondary")[0]) + each_ipv4["secondary"] = True + elif "secondary" not in each and "dhcp" not in each: + each_ipv4["address"] = self.format_ipv4(each) + elif "dhcp" in each: + each_ipv4["address"] = "dhcp" + 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) + + def format_ipv4(self, address): + if address.split(" ")[1]: + cidr_val = netmask_to_cidr(address.split(" ")[1]) + return address.split(" ")[0] + "/" + cidr_val diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/base.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/base.py index 9e346d36c..cc657f42a 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/base.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/base.py @@ -30,7 +30,6 @@ from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr im class FactsBase(object): - COMMANDS = frozenset() def __init__(self, module): @@ -58,8 +57,7 @@ class Default(FactsBase): device_info = resp["device_info"] platform_facts["system"] = device_info["network_os"] - - for item in ("model", "image", "version", "platform", "hostname"): + for item in ("serialnum", "model", "image", "version", "platform", "hostname"): val = device_info.get("network_os_%s" % item) if val: platform_facts[item] = val @@ -71,13 +69,14 @@ class Default(FactsBase): class Hardware(FactsBase): - - COMMANDS = ["dir /all", "show memory summary"] + COMMANDS = ["dir /all", "show memory summary", "show processes cpu | include CPU utilization"] def populate(self): super(Hardware, self).populate() + data = self.responses[0] self.facts["filesystems"] = self.parse_filesystems(data) + self.facts["cpu_utilization"] = self.parse_cpu_utilization(self.responses[2]) data = self.responses[1] match = re.search(r"Physical Memory: (\d+)M total \((\d+)", data) @@ -88,9 +87,29 @@ class Hardware(FactsBase): def parse_filesystems(self, data): return re.findall(r"^Directory of (\S+)", data, re.M) + def parse_cpu_utilization(self, data): + facts = {} + cpu_utilization_regex = re.compile( + r""" + ^CPU\sutilization\sfor\sone\sminute:(\s(?P<one_min>[0-9]+)?%)?; + \sfive\sminutes:\s(?P<five_mins>[0-9]+)?%; + \sfifteen\sminutes:\s(?P<fifteen_mins>[0-9]+)?% + """, + re.VERBOSE, + ) -class Config(FactsBase): + for line in data.split("\n"): + cpu_utilization_match = cpu_utilization_regex.match(line) + if cpu_utilization_match: + facts["one_minute"] = int(cpu_utilization_match.group("one_min")) + facts["five_minutes"] = int(cpu_utilization_match.group("five_mins")) + facts["fifteen_minutes"] = int(cpu_utilization_match.group("fifteen_mins")) + + return facts + + +class Config(FactsBase): COMMANDS = ["show running-config"] def populate(self): @@ -99,7 +118,6 @@ class Config(FactsBase): class Interfaces(FactsBase): - COMMANDS = [ "show interfaces", "show ipv6 interface", diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/ospfv2.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/ospfv2.py index 240ecb4d5..b5c2693f1 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/ospfv2.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/ospfv2.py @@ -19,7 +19,7 @@ import re from copy import deepcopy from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils -from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network_template import ( +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.network_template import ( NetworkTemplate, ) diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/ospfv3.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/ospfv3.py index 49302ce9b..d34f15fbd 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/ospfv3.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/ospfv3.py @@ -13,7 +13,7 @@ import re from copy import deepcopy from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils -from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.network_template import ( +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.network_template import ( NetworkTemplate, ) diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/iosxr.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/iosxr.py index ea15fdfcd..c7498aa19 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/iosxr.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/iosxr.py @@ -36,7 +36,6 @@ import re from difflib import Differ from ansible.module_utils._text import to_bytes, to_text -from ansible.module_utils.basic import env_fallback from ansible.module_utils.connection import Connection, ConnectionError from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.netconf import ( NetconfConnection, @@ -146,7 +145,6 @@ def build_xml_subtree(container_ele, xmap, param=None, opcode=None): 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: @@ -430,7 +428,6 @@ def load_config( nc_get_filter=None, label=None, ): - conn = get_connection(module) diff = None diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/address_family.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/address_family.py deleted file mode 100644 index 0d5393407..000000000 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/address_family.py +++ /dev/null @@ -1,133 +0,0 @@ -# -# (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/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/neighbors.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/neighbors.py deleted file mode 100644 index 29e4a1d2e..000000000 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/neighbors.py +++ /dev/null @@ -1,136 +0,0 @@ -# -# (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/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/process.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/process.py deleted file mode 100644 index bd2c08ae1..000000000 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/process.py +++ /dev/null @@ -1,121 +0,0 @@ -# -# (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.cli.config.bgp.address_family import ( - AddressFamily, -) -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.providers import ( - CliProvider, - register_provider, -) - - -REDISTRIBUTE_PROTOCOLS = [ - "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/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/module.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/module.py deleted file mode 100644 index afb9b9e7e..000000000 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/module.py +++ /dev/null @@ -1,71 +0,0 @@ -# -# (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._text import to_text -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 - - -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/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/providers.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/providers.py deleted file mode 100644 index 94220ffaf..000000000 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/providers.py +++ /dev/null @@ -1,127 +0,0 @@ -# -# (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.config import ( - NetworkConfig, -) -from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list - - -_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/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_address_family.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_address_family.py index a1d9bfda8..f5ced0b0b 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_address_family.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_address_family.py @@ -74,7 +74,6 @@ def _tmpl_bgp_dampening(config_data): def _tmpl_maximum_paths_ibgp(config_data): - ibgp_conf = config_data.get("maximum_paths", {}).get("ibgp", {}) if ibgp_conf: command = "maximum-paths ibgp" @@ -97,7 +96,6 @@ def _tmpl_maximum_paths_ibgp(config_data): def _tmpl_maximum_paths_ebgp(config_data): - ebgp_conf = config_data.get("maximum_paths", {}).get("ebgp", {}) if ebgp_conf: command = "maximum-paths ebgp" @@ -111,7 +109,6 @@ def _tmpl_maximum_paths_ebgp(config_data): def _tmpl_maximum_paths_eibgp(config_data): - eibgp_conf = config_data.get("maximum_paths", {}).get("eibgp", {}) if eibgp_conf: command = "maximum-paths ebgp" @@ -137,7 +134,6 @@ def _tmpl_nexthop(config_data): nexthop_conf = config_data.get("nexthop", {}) commands = [] if nexthop_conf: - if "resolution_prefix_length_minimum" in nexthop_conf: command = "nexthop resolution prefix-length minimum " + str( nexthop_conf["resolution_prefix_length_minimum"], diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_global.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_global.py index f584d13f5..c1a5962c7 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_global.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_global.py @@ -32,6 +32,21 @@ def _tmplt_confederation_peers(config_data): return cmds +def _templ_local_as(config_data): + conf = config_data.get("local_as", {}) + if conf.get("value"): + command = "local-as " + str(conf.get("value", {})) + if "no_prepend" in conf: + if "replace_as" in conf.get("no_prepend", {}): + if "dual_as" in conf.get("no_prepend", {}).get("replace_as", {}): + command += " no-prepend replace-as dual-as" + elif "set" in conf.get("no_prepend", {}).get("replace_as", {}): + command += " no-prepend replace-as" + elif "set" in conf.get("no_prepend", {}): + command += " no-prepend" + return command + + class Bgp_globalTemplate(NetworkTemplate): def __init__(self, lines=None, module=None): super(Bgp_globalTemplate, self).__init__( @@ -2052,10 +2067,12 @@ class Bgp_globalTemplate(NetworkTemplate): r""" \s+(?P<nbr_address>neighbor\s\S+) \s(?P<local_as>local-as\s\S+) + (\s(?P<no_prepend>no-prepend))? + (\s(?P<replace_as>replace-as))? + (\s(?P<dual_as>dual-as))? $""", re.VERBOSE, ), - "setval": "local-as {{ local_as.value }}", - "compval": "local_as.value", + "setval": _templ_local_as, "result": { "vrfs": { '{{ "vrf_" + vrf|d() }}': { @@ -2063,6 +2080,14 @@ class Bgp_globalTemplate(NetworkTemplate): "{{nbr_address.split(" ")[1]}}": { "local_as": { "value": "{{ local_as.split(" ")[1] }}", + "no_prepend": + { + "set": "{{ True if no_prepend is defined and replace_as is undefined and dual_as is undefined else None}}", + "replace_as": { + "set": "{{ True if replace_as is defined and dual_as is undefined}}", + "dual_as": "{{ not not dual_as}}", + }, + }, }, }, }, @@ -2152,6 +2177,55 @@ class Bgp_globalTemplate(NetworkTemplate): }, }, { + "name": "password_inheritance_disable", + "getval": re.compile( + r""" + \s+(?P<nbr_address>neighbor\s\S+) + \s(?P<password>password\sinheritance-disable) + $""", re.VERBOSE, + ), + "setval": "password inheritance-disable", + "compval": "password.inheritance_disable", + "result": { + "vrfs": { + '{{ "vrf_" + vrf|d() }}': { + "neighbors": { + "{{nbr_address.split(" ")[1]}}": { + "password": { + "inheritance_disable": "{{ True if password is defined }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "password_encrypted", + "getval": re.compile( + r""" + \s+(?P<nbr_address>neighbor\s\S+) + \spassword\sencrypted + \s(?P<password>\S+) + $""", re.VERBOSE, + ), + "setval": "password encrypted {{password.encrypted}}", + "compval": "password.encrypted", + "result": { + "vrfs": { + '{{ "vrf_" + vrf|d() }}': { + "neighbors": { + "{{nbr_address.split(" ")[1]}}": { + "password": { + "encrypted": "{{ password }}", + }, + }, + }, + }, + }, + }, + }, + { "name": "receive_buffer_size", "getval": re.compile( r""" @@ -2360,6 +2434,52 @@ class Bgp_globalTemplate(NetworkTemplate): }, }, { + "name": "use.neighbor_group", + "getval": re.compile( + r""" + \s+(?P<nbr_address>neighbor\s\S+) + \suse\sneighbor-group\s(?P<neighbor_group>\S+) + $""", re.VERBOSE, + ), + "setval": "use neighbor-group {{ use.neighbor_group }}", + "result": { + "vrfs": { + '{{ "vrf_" + vrf|d() }}': { + "neighbors": { + "{{nbr_address.split(" ")[1]}}": { + "use": { + "neighbor_group": "{{ neighbor_group }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "use.session_group", + "getval": re.compile( + r""" + \s+(?P<nbr_address>neighbor\s\S+) + \suse\ssession-group\s(?P<session_group>\S+) + $""", re.VERBOSE, + ), + "setval": "use session-group {{ use.session_group }}", + "result": { + "vrfs": { + '{{ "vrf_" + vrf|d() }}': { + "neighbors": { + "{{nbr_address.split(" ")[1]}}": { + "use": { + "session_group": "{{ session_group }}", + }, + }, + }, + }, + }, + }, + }, + { "name": "update_source", "getval": re.compile( r""" diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_templates.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_templates.py new file mode 100644 index 000000000..f0274944c --- /dev/null +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_templates.py @@ -0,0 +1,2816 @@ +# -*- coding: utf-8 -*- +# Copyright 2023 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 Bgp_templates parser templates file. This contains +a list of parser definitions and associated functions that +facilitates both facts gathering and native command generation for +the given network resource. +""" + +import re + +from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.network_template import ( + NetworkTemplate, +) + + +UNIQUE_NEIB_ADD = "{{ nbr_address }}" + + +def _tmpl_maximum_prefix(config_data): + conf = config_data.get("maximum_prefix", {}) + if conf: + command = "maximum-prefix" + if "max_limit" in conf: + command += " " + str(conf["max_limit"]) + if "threshold_value" in conf: + command += " " + str(conf["threshold_value"]) + if "restart" in conf: + command += " restart " + str(conf["restart"]) + elif "warning_only" in conf: + command += " warning-only" + elif "discard_extra_paths" in conf: + command += " discard-extra-paths" + + return command + + +def _tmpl_soft_reconfiguration(config_data): + conf = config_data.get("soft_reconfiguration", {}) + if conf: + command = "soft-reconfiguration " + if "inbound" in conf: + command += "inbound" + if "set" in conf["inbound"]: + pass + elif "always" in conf["inbound"]: + command += " always" + if "inheritance_disable" in conf["inbound"]: + command += " inheritance-disable" + + return command + + +def _tmpl_remove_private_AS(config_data): + conf = config_data.get("remove_private_AS", {}) + if conf: + command = "remove-private-AS" + if "inbound" in conf: + command += " inbound" + if "entire_aspath" in conf: + command += " entire-aspath" + if "inheritance_disable" in conf: + command += " inheritance-disable" + return command + + +def _templ_local_as(config_data): + conf = config_data.get("local_as", {}) + if conf.get("value"): + command = "local-as " + str(conf.get("value", {})) + if "no_prepend" in conf: + command = "local-as" + if "replace_as" in conf.get("no_prepend", {}): + if "dual_as" in conf.get("no_prepend", {}).get("replace_as", {}): + command += " no-prepend replace-as dual-as" + elif "set" in conf.get("no_prepend", {}).get("replace_as", {}): + command += " no-prepend replace-as" + elif "set" in conf.get("no_prepend", {}): + command += " no-prepend" + return command + + +class Bgp_templatesTemplate(NetworkTemplate): + def __init__(self, lines=None, module=None): + super(Bgp_templatesTemplate, self).__init__( + lines=lines, + tmplt=self, + module=module, + ) + + # fmt: off + PARSERS = [ + { + "name": "router", + "getval": re.compile( + r""" + ^router\s + bgp + \s(?P<as_num>\S+) + $""", + re.VERBOSE, + ), + "setval": "router bgp {{ as_number }}", + "compval": "as_number", + "result": {"as_number": "{{ as_num }}"}, + "shared": True, + }, + { + "name": "address_family", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + (?P<address_family>\s+address-family\s(?P<afi>\S+)\s(?P<safi>\S+)) + $""", re.VERBOSE, + ), + "setval": "address-family {{ afi}} {{safi}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "afi": "{{ afi}}", + "safi": "{{safi}}", + }, + }, + }, + }, + }, + "shared": True, + }, + { + "name": "neighbor_group", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + $""", re.VERBOSE, + ), + "setval": "neighbor-group {{ name}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "name": UNIQUE_NEIB_ADD, + }, + }, + }, + "shared": True, + }, + { + "name": "signalling", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sSignalling(?P<signalling>) + (\sbgp\sdisable(?P<b_disable>))? + (\sldp\sdisable(?P<l_disable>))? + $""", re.VERBOSE, + ), + "setval": "{{ 'signalling bgp disable' if signalling.bgp_disable else 'signalling ldp disable' }} ", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "signalling": { + "bgp_disable": "{{ True if b_disable is defined }}", + "ldp_disable": "{{ True if l_disable is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "advertise.local_labeled_route.set", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + (?P<a_Set>\sadvertise\slocal-labeled-route(?P<a_set>)) + $""", re.VERBOSE, + ), + "setval": "advertise local-labeled-route", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "advertise": { + "local_labeled_route": { + "set": "{{ True if a_set is defined}}", + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "advertise.local_labeled_route.disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sadvertise + (\slocal-labeled-route\sdisable(?P<l_disable>))? + $""", re.VERBOSE, + ), + "setval": "advertise local-labeled-route disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "advertise": { + "local_labeled_route": { + "disable": "{{ True if l_disable is defined}}", + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "advertise.permanent_network", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sadvertise + (\spermanent-network(?P<set>))? + $""", re.VERBOSE, + ), + "setval": "advertise permanent-network", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "advertise": { + "permanent_network": "{{ True if set is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "aigp.set", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + (?P<aigp>\saigp) + $""", re.VERBOSE, + ), + "setval": "aigp", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "aigp": { + "set": "{{ True if aigp is defined }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "aigp.disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \saigp(?P<aigp>) + (\sdisable(?P<disable>)) + $""", re.VERBOSE, + ), + "setval": "aigp disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "aigp": { + "disable": "{{ True if disable is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "aigp.send_med", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \saigp(?P<aigp>) + (\ssend\smed(?P<send_med>))? + (\ssend\smed\sdisable(?P<send_disable>))? + $""", re.VERBOSE, + ), + "setval": "'aigp send med disable' if {{aigp.send_med.disable}} is defined else 'aigp send med'", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "aigp": { + "send_med": { + "set": "{{ True if send_med is defined }}", + "disable": "{{ True if send_disable is defined}}", + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "aigp.send_cost_community_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \saigp(?P<aigp>) + (\ssend\scost-community\sdisable(?P<cc_disable>))? + $""", re.VERBOSE, + ), + "setval": "aigp send cost-community disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "aigp": { + "send_cost_community_disable": "{{True if cc_disable is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "allowas_in", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sallowas-in(?P<allowas_in>)(\s(?P<value>\S+))? + $""", re.VERBOSE, + ), + "setval": "allowas-in {{allowas_in.value if allowas_in.value is defined }}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "allowas_in": { + "set": "{{True if allowas_in is defined and value is not defined}}", + "value": "{{value }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "as_override", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sas-override(?P<as_override>) + (\sinheritance-disable(?P<inheritance_disable>))? + $""", re.VERBOSE, + ), + "setval": "as-override{{' inheritance-disable' if as_override.inheritance_disable is defined else ''}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "as_override": { + "set": "{{True if as_override is defined " + "and inheritance_disable is not defined}}", + "inheritance_disable": "{{True if inheritance_disable is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "bestpath_origin_as_allow_invalid", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sbestpath\sorigin-as\sallow\sinvalid(?P<invalid>) + $""", re.VERBOSE, + ), + "setval": "bestpath origin-as allow invalid", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "bestpath_origin_as_allow_invalid": "{{ True if invalid is defined}}", + }, + }, + }, + }, + }, + }, + { + "name": "capability_orf_prefix", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \scapability\sorf\sprefix\s(?P<capability_orf_prefix>\S+) + $""", re.VERBOSE, + ), + "setval": "capability orf prefix {{capability_orf_prefix }}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "capability_orf_prefix": "{{capability_orf_prefix}}", + }, + }, + }, + }, + }, + }, + { + "name": "default_originate.set", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s+default-originate(?P<default_originate>) + $""", re.VERBOSE, + ), + "setval": "default-originate", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi}}': { + "default_originate": { + "set": "{{True if default_originate is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "default_originate.route_policy", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s+default-originate(?P<default_originate>) + (\sroute-policy\s(?P<route_policy>\S+))? + $""", re.VERBOSE, + ), + "setval": "default-originate route-policy {{default_originate.route_policy}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi}}': { + "default_originate": { + "route_policy": "{{route_policy}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "default_originate.inheritance_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s+default-originate\s(?P<disable>inheritance-disable) + $""", re.VERBOSE, + ), + "setval": "default-originate inheritance-disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi}}': { + "default_originate": { + "inheritance_disable": "{{true if disable is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "encapsulation_type_srv6", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sencapsulation-type\ssrv6(?P<encapsulation_type_srv6>) + $""", re.VERBOSE, + ), + "setval": "encapsulation-type srv6", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "encapsulation_type_srv6": "{{true if encapsulation_type_srv6 is defined}}", + }, + }, + }, + }, + }, + }, + { + "name": "long_lived_graceful_restart_capable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s+long-lived-graceful-restart + \s(?P<capable>capable) + $""", re.VERBOSE, + ), + "setval": "long-lived-graceful-restart capable", + "compval": "long_lived_graceful_restart.capable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "long_lived_graceful_restart": { + "capable": "{{True if capable is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "long_lived_graceful_restart_stale_time", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s+long-lived-graceful-restart + \s+stale-time\ssend\s(?P<stale_time_send>\d+)\saccept\s(?P<accept>\d+) + $""", re.VERBOSE, + ), + "setval": "long-lived-graceful-restart stale-time send " + "{{stale_time.send}} accept {{stale_time.accept}}", + "compval": "long_lived_graceful_restart.stale_time", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "long_lived_graceful_restart": { + "stale_time": { + "send": "{{stale_time_send}}", + "accept": "{{accept}}", + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "maximum_prefix", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s+maximum-prefix + (\s(?P<maximum_prefix>\d+))? + (\s(?P<threshold_value>\d+))? + (\srestart\s(?P<restart>\d+))? + (\swarning-only\s(?P<warning_only>))? + (\sdiscard-extra-paths\s(?P<discard_extra_paths>))? + $""", re.VERBOSE, + ), + "setval": _tmpl_maximum_prefix, + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "maximum_prefix": { + "max_limit": "{{maximum_prefix}}", + "threshold_value": "{{threshold_value}}", + "restart": "{{restart}}", + "warning_only": "{{ True if warning_only is defined}}", + "discard_extra_paths": "{{ True if discard_extra_paths is defined}}", + }, + }, + }, + }, + }, + }, + }, + + { + "name": "multipath", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \smultipath(?P<multipath>) + $""", re.VERBOSE, + ), + "setval": "multipath", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "multipath": "{{True if multipath is defined}}", + }, + }, + }, + }, + }, + }, + { + "name": "next_hop_self", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \snext-hop-self(?P<next_hop_self>) + (\sinheritance-disable(?P<inheritance_disable>))? + $""", re.VERBOSE, + ), + "setval": "next-hop-self{{' inheritance-disable' if next_hop_self.inheritance_disable is defined else ''}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "next_hop_self": { + "set": "{{True if next_hop_self is defined and" + " inheritance_disable is not defined}}", + "inheritance_disable": "{{True if inheritance_disable is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "next_hop_unchanged.set", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \snext-hop-unchanged(?P<next_hop_unchanged>) + $""", re.VERBOSE, + ), + "setval": "next-hop-unchanged", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi}}': { + "next_hop_unchanged": { + "set": "{{True if next_hop_self is defined }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "next_hop_unchanged.inheritance_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \snext-hop-unchanged(?P<next_hop_unchanged>) + ((?P<inheritance_disable>)\sinheritance-disable)? + $""", re.VERBOSE, + ), + "setval": "next-hop-unchanged inheritance-disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi}}': { + "next_hop_unchanged": { + "inheritance_disable": "{{True if inheritance_disable is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "next_hop_unchanged.multipath", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \snext-hop-unchanged(?P<next_hop_unchanged>) + (?P<multipath>\smultipath)? + $""", re.VERBOSE, + ), + "setval": "next-hop-unchanged multipath", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi}}': { + "next_hop_unchanged": { + "multipath": "{{True if multipath is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "optimal_route_reflection_group_name", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \soptimal-route-reflection\s(?P<group_name>\S+) + $""", re.VERBOSE, + ), + "setval": "optimal-route-reflection {{optimal_route_reflection_group_name}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "optimal_route_reflection_group_name": "{{ group_name}}", + }, + }, + }, + }, + }, + }, + { + "name": "orf_route_policy", + "getval": re.compile( + r""" + \s+(?P<nbr_address>neighbor\s\S+) + \sorf\sroute-policy\s(?P<orf_rr>\S+) + $""", re.VERBOSE, + ), + "setval": "orf route-policy {{orf_route_policy}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "orf_route_policy": "{{orf_rr}}", + }, + }, + }, + }, + }, + }, + { + "name": "origin_as", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sorigin-as\svalidation\sdisable(?P<origin_as>) + $""", re.VERBOSE, + ), + "setval": "origin-as validation disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "origin_as": { + "validation": { + "disable": "{{True if origin_as is defined }}", + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "remove_private_AS.set", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sremove-private-AS(?P<remove_private_AS>) + $""", re.VERBOSE, + ), + "setval": "remove-private-AS", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "remove_private_AS": { + "set": "{{True if remove_private_AS is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "remove_private_AS", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sremove-private-AS(?P<remove_private_AS>) + (\sinbound(?P<inbound>))? + (\sentire-aspath(?P<entire_aspath>))? + (\sinheritance-disable(?P<inheritance_disable>))? + $""", re.VERBOSE, + ), + "setval": _tmpl_remove_private_AS, + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "remove_private_AS": { + "inheritance_disable": "{{True if inheritance_disable is defined}}", + "inbound": "{{True if inbound is defined}}", + "entire_aspath": "{{True if entire_aspath is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "route_policy.inbound", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sroute-policy\s(?P<route_policy>\S+) + \sin + $""", re.VERBOSE, + ), + "setval": "route-policy {{route_policy.inbound}} in", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "route_policy": { + "inbound": "{{route_policy}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "route_policy.outbound", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sroute-policy\s(?P<route_policy>\S+) + \sout + $""", re.VERBOSE, + ), + "setval": "route-policy {{route_policy.outbound}} out", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "route_policy": { + "outbound": "{{route_policy}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "route_reflector_client", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sroute-reflector-client(?P<route_reflector_client>) + (\sinheritance-disable(?P<inheritance_disable>))? + $""", re.VERBOSE, + ), + "setval": "route-reflector-client{{' inheritance-disable' " + "if route_reflector_client.inheritance_disable is defined }}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "route_reflector_client": { + "set": "{{True if route_reflector_client is defined and " + "inheritance_disable is not defined }}", + "inheritance_disable": "{{True if inheritance_disable is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "send_community_ebgp", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \ssend-community-ebgp(?P<send_community_ebgp>) + (\sinheritance-disable(?P<inheritance_disable>))? + $""", re.VERBOSE, + ), + "setval": "send-community-ebgp{{' inheritance-disable' " + "if send_community_ebgp.inheritance_disable is defined else ''}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "send_community_ebgp": { + "set": "{{True if send_community_ebgp is defined and " + "inheritance_disable is not defined}}", + "inheritance_disable": "{{True if inheritance_disable is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "send_community_gshut_ebgp", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \ssend-community-gshut-ebgp(?P<send_community_gshut_ebg>) + (\sinheritance-disable(?P<inheritance_disable>))? + $""", re.VERBOSE, + ), + "setval": "send-community-gshut-ebgp{{' inheritance-disable' " + "if send_community_gshut_ebgp.inheritance_disable is defined else ''}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "send_community_gshut_ebgp": { + "set": "{{True if send_community_gshut_ebg is defined and " + "inheritance_disable is not defined}}", + "inheritance_disable": "{{True if inheritance_disable is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "send_extended_community_ebgp", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \ssend-extended-community-ebgp(?P<send_extended_community_ebgp>) + (\sinheritance-disable(?P<inheritance_disable>))? + $""", re.VERBOSE, + ), + "setval": "send-extended-community-ebgp{{' inheritance-disable' " + "if send_extended_community_ebgp.inheritance_disable is defined else ''}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "send_extended_community_ebgp": { + "set": "{{True if send_extended_community_ebgp is defined and " + "inheritance_disable is not defined}}", + "inheritance_disable": "{{True if inheritance_disable is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "send_multicast_attributes", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s+(?P<send_multicast_attributes>send-multicast-attributes) + (\sdisable(?P<disable>))? + $""", re.VERBOSE, + ), + "setval": "send-multicast-attributes{{' disable' " + "if send_multicast_attributes.disable is defined else ''}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "send_multicast_attributes": { + "set": "{{True if send_multicast_attributes is " + "defined and disable is not defined}}", + "disable": "{{True if disable is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "soft_reconfiguration", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \ssoft-reconfiguration + \sinbound(?P<inbound>) + (\salways(?P<always>))? + (\sinheritance-disable(?P<inheritance_disable>))? + $""", re.VERBOSE, + ), + "setval": _tmpl_soft_reconfiguration, + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "soft_reconfiguration": { + "inbound": { + "set": "{{True if inbound is defined and " + "inheritance_disable is not defined and " + "always is not defined}}", + "always": "{{True if always is defined }}", + "inheritance_disable": "{{True if inheritance_disable is defined}}", + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "weight", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sweight\s(?P<weight>\d+) + $""", re.VERBOSE, + ), + "setval": "weight {{weight}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "weight": "{{weight}}", + }, + }, + }, + }, + }, + }, + { + "name": "use", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \suse\s(?P<af_use>\S+) + $""", re.VERBOSE, + ), + "setval": "weight {{weight}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "use": "{{af_use}}", + }, + }, + }, + }, + }, + }, + { + "name": "update.out_originator_loopcheck_set", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \supdate\sout\soriginator-loopcheck(?P<set>) + $""", re.VERBOSE, + ), + "setval": "update out originator-loopcheck", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "update": { + "out_originator_loopcheck_set": "{{True if set is defined }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "update.out_originator_loopcheck_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \supdate\sout\soriginator-loopcheck(?P<set>) + (\sdisable(?P<disable>))? + $""", re.VERBOSE, + ), + "setval": "update out originator-loopcheck disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "address_family": { + '{{"address_family_" + afi + "_" + safi }}': { + "update": { + "out_originator_loopcheck_disable": "{{True if disable is defined}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "advertisement_interval", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<advertise_in>advertisement-interval\s\d+) + $""", re.VERBOSE, + ), + "setval": "advertisement-interval {{ advertisement_interval }}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "advertisement_interval": "{{ advertise_in.split(" ")[1] }}", + }, + }, + }, + }, + { + "name": "bfd_fast_detect_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sbfd + \sfast-detect + \s(?P<disable>disable) + $""", re.VERBOSE, + ), + "setval": "bfd fast-detect disable", + "compval": "bfd.fast_detect.disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "bfd": { + "fast_detect": {"disable": "{{ True if disable is defined }}"}, + }, + }, + }, + }, + }, + { + "name": "bfd_fast_detect_set", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sbfd + \s(?P<fast_detect>fast-detect) + $""", re.VERBOSE, + ), + "setval": "bfd fast-detect", + "compval": "bfd.fast_detect.set", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "bfd": { + "fast_detect": {"set": "{{ True if fast_detect is defined }}"}, + }, + }, + }, + }, + }, + { + "name": "bfd_fast_detect_strict_mode", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sbfd + \sfast-detect + \s(?P<strict_mode>strict-mode) + $""", re.VERBOSE, + ), + "setval": "bfd fast-detect strict-mode", + "compval": "bfd.fast_detect.strict_mode", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "bfd": { + "fast_detect": {"strict_mode": "{{ True if strict_mode is defined }}"}, + }, + }, + }, + }, + }, + { + "name": "bfd_nbr_multiplier", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sbfd + \s(?P<multiplier>multiplier\s\S+) + $""", re.VERBOSE, + ), + "setval": "bfd multiplier {{ bfd.multiplier}}", + "compval": "bfd.multiplier", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: + { + "bfd": { + "multiplier": "{{multiplier.split(" ")[1]}}", + }, + }, + }, + }, + }, + { + "name": "bfd_nbr_minimum_interval", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sbfd + \s(?P<min_interval>minimum-interval\s\S+) + $""", re.VERBOSE, + ), + "setval": "bfd minimum-interval {{ bfd.minimum_interval}}", + "compval": "bfd.minimum_interval", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "bfd": { + "minimum_interval": "{{min_interval.split(" ")[1]}}", + }, + }, + }, + }, + }, + { + "name": "bmp_activate", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sbmp-activate + \s(?P<bmp_activate>server\s\d+) + $""", re.VERBOSE, + ), + "setval": "bmp-activate server {{bmp_activate.server}}", + "compval": "bmp_activate.serevr", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "bmp_activate": {"server": "{{ bmp_activate.split(" ")[1] }}"}, + }, + }, + }, + }, + { + "name": "neighbor_cluster_id", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<cluster_id>cluster-id\s\d+) + $""", re.VERBOSE, + ), + "setval": "cluster-id {{ cluster_id }}", + "compval": "cluster_id", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: {"cluster_id": "{{ cluster_id.split(" ")[1] }}"}, + }, + }, + }, + { + "name": "neighbor_description", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sdescription\s(?P<description>.+) + $""", re.VERBOSE, + ), + "setval": "description {{ description }}", + "compval": "description", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: {"description": "{{ description }}"}, + }, + }, + }, + { + "name": "dmz_link_bandwidth", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<dmz_link_bandwidth>dmz-link-bandwidth) + $""", re.VERBOSE, + ), + "setval": "dmz-link-bandwidth", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "dmz_link_bandwidth": { + "set": "{{ True if dmz_link_bandwidth is defined }}", + }, + }, + }, + }, + }, + { + "name": "dmz_link_bandwidth_inheritance_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sdmz-link-bandwidth + \s(?P<dmz_link_bandwidth>inheritance_disable) + $""", re.VERBOSE, + ), + "setval": "dmz-link-bandwidth inheritance-disable", + "compval": "dmz_link_bandwidth.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "dmz_link_bandwidth": { + "inheritance_disable": "{{ True if dmz_link_bandwidth is defined }}", + }, + }, + }, + }, + }, + { + "name": "dscp", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<dscp>dscp\s\S+) + $""", re.VERBOSE, + ), + "setval": "dscp {{ dscp }}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "dscp": "{{ dscp.split(" ")[1] }}", + }, + }, + }, + }, + { + "name": "ebgp_multihop_value", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<ebgp_multihop>ebgp-multihop\s\S+) + $""", re.VERBOSE, + ), + "setval": "ebgp-multihop {{ ebgp_multihop.value}}", + "compval": "ebgp_multihop.value", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "ebgp_multihop": { + "value": "{{ ebgp_multihop.split(" ")[1] }}", + }, + }, + }, + }, + }, + { + "name": "ebgp_multihop_mpls", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<ebgp_multihop>ebgp-multihop\s\S*\smpls) + $""", re.VERBOSE, + ), + "setval": "ebgp-multihop mpls", + "compval": "ebgp_multihop.mpls", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "ebgp_multihop": {"mpls": "{{ True if ebgp_multihop is defined }}"}, + }, + }, + }, + }, + { + "name": "ebgp_recv_extcommunity_dmz_set", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<ebgp_recv_extcommunity_dmz>ebgp-recv-extcommunity-dmz) + $""", re.VERBOSE, + ), + "setval": "ebgp-recv-extcommunity-dmz inheritance-disable", + "compval": "ebgp_recv_extcommunity_dm.set", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "ebgp_recv_extcommunity_dmz": { + "set": "{{ True if ebgp_recv_extcommunity_dmz is defined }}", + }, + }, + }, + }, + }, + { + "name": "ebgp_recv_extcommunity_dmz", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<ebgp_recv_extcommunity_dmz>ebgp-recv-extcommunity-dmz\sinheritance-disable) + $""", re.VERBOSE, + ), + "setval": "ebgp-recv-extcommunity-dmz inheritance-disable ", + "compval": "ebgp_recv_extcommunity_dmz.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "ebgp_recv_extcommunity_dmz": { + "inheritance_disable": "{{ True if ebgp_recv_extcommunity_dmz is defined }}", + }, + }, + }, + }, + }, + { + "name": "ebgp_send_extcommunity_dmz", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<ebgp_send_extcommunity_dmz>ebgp-send-extcommunity-dmz\sinheritance-disable) + $""", re.VERBOSE, + ), + "setval": "ebgp-send-extcommunity-dmz inheritance-disable ", + "compval": "ebgp_send_extcommunity_dmz.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "ebgp_send_extcommunity_dmz": { + "inheritance_disable": "{{ True if ebgp_send_extcommunity_dmz is defined }}", + }, + }, + }, + }, + }, + { + "name": "ebgp_send_extcommunity_dmz_set", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<ebgp_send_extcommunity_dmz>ebgp-send-extcommunity-dmz) + $""", re.VERBOSE, + ), + "setval": "ebgp-send-extcommunity-dmz", + "compval": "ebgp_send_extcommunity_dmz.set", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "ebgp_send_extcommunity_dmz": { + "set": "{{ True if ebgp_send_extcommunity_dmz is defined }}", + }, + }, + }, + }, + }, + { + "name": "ebgp_send_extcommunity_dmz_cumulatie", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<ebgp_send_extcommunity_dmz>ebgp-send-extcommunity-dmz\scumulatie) + $""", re.VERBOSE, + ), + "setval": "ebgp-send-extcommunity-dmz cumulatie ", + "compval": "ebgp_send_extcommunity_dmz.cumulatie", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "ebgp_send_extcommunity_dmz": { + "cumulatie": "{{ True if ebgp_send_extcommunity_dmz is defined }}", + }, + }, + }, + }, + }, + { + "name": "egress_engineering", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<egress_engineering>egress-engineering\sinheritance-disable) + $""", re.VERBOSE, + ), + "setval": "egress-engineering inheritance-disable ", + "compval": "egress_engineering.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "egress_engineering": { + "inheritance_disable": "{{ True if egress_engineering is defined }}", + }, + }, + }, + }, + + }, + { + "name": "egress_engineering_set", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<egress_engineering>egress-engineering) + $""", re.VERBOSE, + ), + "setval": "egress-engineering", + "compval": "egress_engineering.set", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "egress_engineering": { + "set": "{{ True if egress_engineering is defined }}", + }, + }, + }, + }, + }, + { + "name": "neighbor_enforce_first_as_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<enforce_first_as_disable>enforce-first-as\sdisable) + $""", re.VERBOSE, + ), + "setval": "enforce-first-as disable", + "compval": "enforce_first_as.disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "enforce_first_as": { + "disable": "{{ True if enforce_first_as_disable is defined }}", + }, + }, + }, + }, + }, + { + "name": "neighbor_graceful_restart_restart_time", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<graceful_restart_restart_time>graceful-restart\srestart-time\s\d+) + $""", re.VERBOSE, + ), + "setval": "graceful-restart restart-time {{ graceful_restart.restart_time}}", + "compval": "graceful_restart.restart_time", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "graceful_restart": { + "restart_time": "{{ graceful_restart_restart_time.split(" ")[2] }}", + }, + }, + }, + }, + }, + { + "name": "neighbor_graceful_restart_stalepath_time", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<graceful_restart_stalepath_time>graceful-restart\sstalepath-time\s\d+) + $""", re.VERBOSE, + ), + "setval": "graceful-restart stalepath-time {{ graceful_restart.stalepath_time}}", + "compval": "graceful_restart.stalepath_time", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "graceful_restart": { + "stalepath_time": "{{ graceful_restart_stalepath_time.split(" ")[2] }}", + }, + }, + }, + }, + }, + { + "name": "neighbor_graceful_maintenance_set", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<graceful_maintenance>graceful-maintenance) + $""", re.VERBOSE, + ), + "setval": "graceful-maintenance", + "compval": "graceful_maintenance.set", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "graceful_maintenance": { + "set": "{{ True if graceful_maintenance is defined }}", + }, + }, + }, + }, + }, + { + "name": "neighbor_graceful_maintenance_activate", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<graceful_maintenance>graceful-maintenance\sactivate) + $""", re.VERBOSE, + ), + "setval": "graceful-maintenance activate", + "compval": "graceful_maintenance.activate.set", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "graceful_maintenance": { + "activate": {"set": "{{ True if graceful_maintenance is defined }}"}, + }, + }, + }, + }, + }, + { + "name": "neighbor_graceful_maintenance_activate_inheritance_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<graceful_maintenance>activate\sinheritance-disable) + $""", re.VERBOSE, + ), + "setval": "graceful-maintenance activate inheritance-disable", + "compval": "graceful_maintenance.activate.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "graceful_maintenance": { + "activate": { + "inheritance_disable": "{{ True if graceful_maintenance is defined }}", + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_graceful_maintenance_as_prepends", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<as_prepends>as-prepends\sinheritance-disable) + $""", re.VERBOSE, + ), + "setval": "graceful-maintenance as-prepends inheritance-disable", + "compval": "graceful_maintenance.as_prepends.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "graceful_maintenance": { + "as_prepends": { + "inheritance_disable": "{{ True if as_prepends is defined }}", + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_graceful_maintenance_local_preference_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<local_preference>local-preference\sinheritance-disable) + $""", re.VERBOSE, + ), + "setval": "graceful-maintenance local-preference inheritance-disable", + "compval": "graceful_maintenance.local_preference.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "graceful_maintenance": { + "local_preference": { + "inheritance_disable": "{{ True if local_preference is defined }}", + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_graceful_maintenance_local_preference", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<local_preference>local-preference\s\d+) + $""", re.VERBOSE, + ), + "setval": "graceful-maintenance local-preference {{ graceful_maintenance.local_preference.value}}", + "compval": "graceful_maintenance.local_preference.value", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "graceful_maintenance": { + "local_preference": { + "value": "{{ local_preference.split(" ")[1]}}", + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_graceful_maintenance_as_prepends_value", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<as_prepends>as-prepends\s\d+) + $""", re.VERBOSE, + ), + "setval": "graceful-maintenance as-prepends {{ graceful_maintenance.as_prepends.value }}", + "compval": "graceful_maintenance.as_prepends.value", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "graceful_maintenance": { + "as_prepends": { + "value": "{{ as_prepends.split(" ")[1]}}", + }, + }, + }, + }, + }, + }, + { + "name": "ignore_connected_check_set", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<ignore_connected_check>ignore-connected-check) + $""", re.VERBOSE, + ), + "setval": "ignore-connected-check", + "compval": "ignore_connected_check.set", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "ignore_connected_check": { + "set": "{{ True if ignore_connected_check is defined }}", + }, + }, + }, + }, + }, + { + "name": "ignore_connected_check", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<ignore_connected_check>ignore-connected-check\sinheritance-disable) + $""", re.VERBOSE, + ), + "setval": "ignore-connected-check inheritance-disable ", + "compval": "ignore_connected_check.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "ignore_connected_check": { + "inheritance_disable": "{{ True if ignore_connected_check is defined }}", + }, + }, + }, + }, + }, + { + "name": "idle_watch_time", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sidle-watch-time(?P<idle_watch_time>\s\S+) + $""", re.VERBOSE, + ), + "setval": "idle-watch-time {{idle_watch_time}} ", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "idle_watch_time": "{{idle_watch_time}}", + }, + }, + }, + }, + { + "name": "internal_vpn_client", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + (?P<internal_vpn_client>\sinternal-vpn-client) + $""", re.VERBOSE, + ), + "setval": "internal-vpn-client", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "internal_vpn_client": "{{true if internal_vpn_client is defined}}", + }, + }, + }, + }, + { + "name": "keychain", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<keychain>keychain\sinheritance-disable) + $""", re.VERBOSE, + ), + "setval": "keychain inheritance-disable ", + "compval": "keychain.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "keychain": { + "inheritance_disable": "{{ True if keychain is defined }}", + }, + }, + }, + }, + + }, + { + "name": "keychain_name", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<keychain>keychain\s\S+) + $""", re.VERBOSE, + ), + "setval": "keychain {{ keychain.name }}", + "compval": "keychain.name", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "keychain": { + "name": "{{ keychain.split(" ")[1] }}", + }, + }, + }, + }, + }, + { + "name": "local_address", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \slocal + \s(?P<local>address\sinheritance-disable) + $""", re.VERBOSE, + ), + "setval": "local address inheritance-disable", + "compval": "local.address.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "local": { + "address": { + "inheritance_disable": "{{ True if local is defined }}", + }, + }, + }, + }, + }, + }, + { + "name": "local", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \slocal + \s(?P<local>address\s\S+) + $""", re.VERBOSE, + ), + "setval": "local address {{ local.address.ipv4_address }}", + "compval": "local.address.ipv4_address", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "local": { + "address": { + "ipv4_address": "{{ local.split(" ")[1] }}", + }, + }, + }, + }, + }, + }, + { + "name": "local_as_inheritance_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<local_as>local-as\sinheritance-disable) + $""", re.VERBOSE, + ), + "setval": "local-as inheritance-disable", + "compval": "local_as.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "local_as": { + "inheritance_disable": "{{ True if local_as is defined }}", + }, + }, + }, + }, + }, + { + "name": "local_as", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<local_as>local-as\s\S+) + (\s(?P<no_prepend>no-prepend))? + (\s(?P<replace_as>replace-as))? + (\s(?P<dual_as>dual-as))? + $""", re.VERBOSE, + ), + "setval": _templ_local_as, + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "local_as": { + "value": "{{ local_as.split(" ")[1] }}", + "no_prepend": { + "set": "{{ True if no_prepend is defined and replace_as is undefined and dual_as is undefined else None}}", + "replace_as": { + "set": "{{ True if replace_as is defined and dual_as is undefined}}", + "dual_as": "{{ not not dual_as}}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "local_address_subnet", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \slocal-address-subnet(?P<local>\s\S+) + $""", re.VERBOSE, + ), + "setval": "local-address-subnet {{local_address_subnet}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "local_address_subnet": "{{local.split(" ")[1]}}", + }, + }, + }, + }, + { + "name": "neighbor_log_message_in_value", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \slog + \smessage + \s(?P<value>in\s\d+) + $""", re.VERBOSE, + ), + "setval": "log message in {{ log.message.in.value}}", + "compval": "log.log_message.in.value", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "log": { + "log_message": { + "in": { + "value": "{{ value.split(" ")[1] }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_log_message_in_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \slog + \smessage + \s(?P<disable>in\sdisable) + $""", re.VERBOSE, + ), + "setval": "log message in disable", + "compval": "log.log_message.in.disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "log": { + "log_message": { + "in": { + "disable": "{{ True if disable is defined }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_log_message_in_inheritance_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \slog + \smessage + \s(?P<disable>in\sinheritance-diable) + $""", re.VERBOSE, + ), + "setval": "log message in inheritance-diable", + "compval": "log.log_message.in.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "log": { + "log_message": { + "in": { + "inheritance_disable": "{{ True if disable is defined }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_log_message_out_value", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \slog + \smessage + \s(?P<value>out\s\d+) + $""", re.VERBOSE, + ), + "setval": "log message out {{ log.message.out.value}}", + "compval": "log.log_message.out.value", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "log": { + "log_message": { + "out": { + "value": "{{ value.split(" ")[1] }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_log_message_out_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \slog + \smessage + \s(?P<disable>out\sdisable) + $""", re.VERBOSE, + ), + "setval": "log message out disable", + "compval": "log.log_message.out.disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "log": { + "log_message": { + "out": { + "disable": "{{ True if disable is defined }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_log_message_out_inheritance_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \slog + \smessage + \s(?P<disable>out\sinheritance-diable) + $""", re.VERBOSE, + ), + "setval": "log message out inheritance-diable", + "compval": "log.log_message.out.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "log": { + "log_message": { + "out": { + "inheritance_disable": "{{ True if disable is defined }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "maximum_peers", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \smaximum-peers(?P<local>\s\S+) + $""", re.VERBOSE, + ), + "setval": "maximum-peers {maximum_peers}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "maximum_peers": "{{local}}", + }, + }, + }, + + }, + { + "name": "password_inheritance_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<password>password\sinheritance-disable) + $""", re.VERBOSE, + ), + "setval": "password inheritance-disable", + "compval": "password.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "password": { + "inheritance_disable": "{{ True if password is defined }}", + }, + }, + }, + }, + }, + { + "name": "password_encrypted", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \spassword\sencrypted + \s(?P<password>\S+) + $""", re.VERBOSE, + ), + "setval": "password encrypted {{password.encrypted}}", + "compval": "password.encrypted", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "password": { + "encrypted": "{{ password }}", + }, + }, + }, + }, + }, + { + "name": "peer_set", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \speer-set(?P<local>\s\S+) + $""", re.VERBOSE, + ), + "setval": "peer-set {peer_set}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "peer_set": "{{local}}", + }, + }, + }, + }, + { + "name": "receive_buffer_size", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<receive_buffer_size>receive-buffer-size\s\d+) + $""", re.VERBOSE, + ), + "setval": "receive-buffer-size {{ receive_buffer_size }}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "receive_buffer_size": "{{ receive_buffer_size.split(" ")[1] }}", + }, + }, + }, + }, + { + "name": "send_buffer_size", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<send_buffer_size>send-buffer-size\s\d+) + $""", re.VERBOSE, + ), + "setval": "send-buffer-size {{ send_buffer_size }}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "send_buffer_size": "{{ send_buffer_size.split(" ")[1] }}", + }, + }, + }, + }, + { + "name": "precedence", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \sprecedence\s(?P<local>\S+) + $""", re.VERBOSE, + ), + "setval": "precedence {{precedence}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "precedence": "{{local}}", + }, + }, + }, + }, + { + "name": "remote_as", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<remote_as>remote-as\s\S+) + $""", re.VERBOSE, + ), + "setval": "remote-as {{ remote_as }}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "remote_as": "{{ remote_as.split(" ")[1] }}", + }, + }, + }, + }, + { + "name": "remote_as_list", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<remote_as>remote-as-list\s\S+) + $""", re.VERBOSE, + ), + "setval": "remote-as-list {{ remote_as_list }}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "remote_as_list": "{{ remote_as.split(" ")[1] }}", + }, + }, + }, + }, + { + "name": "session_open_mode", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<session_open_mode>session-open-mode\s(active-only|both|passive-only)) + $""", re.VERBOSE, + ), + "setval": "session-open-mode {{ session_open_mode }}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "session_open_mode": "{{ session_open_mode.split(" ")[1] }}", + }, + }, + }, + }, + { + "name": "neighbor_shutdown", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<shutdown>shutdown) + $""", re.VERBOSE, + ), + "setval": "shutdown", + "compval": "shutdown", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "shutdown": { + "set": "{{ True if shutdown is defined }}", + }, + }, + }, + }, + }, + { + "name": "neighbor_shutdown_inheritance_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<shutdown>shutdown\sinheritance_disable) + $""", re.VERBOSE, + ), + "setval": "shutdown inheritance-disable", + "compval": "shutdown.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "shutdown": {"inheritance_disable": "{{ True if shutdown is defined }}"}, + }, + }, + }, + }, + { + "name": "neighbor_tcp_mss_inheritance_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<tcp_mss_disable>tcp\smss\sinheritance-disable) + $""", re.VERBOSE, + ), + "setval": "tcp mss inheritance-disable", + "compval": "tcp.mss.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "tcp": { + "mss": { + "inheritance_disable": "{{ True if tcp_mss_disable is defined }}", + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_tcp_mss", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<tcp_mss>tcp\smss\s\d+) + $""", re.VERBOSE, + ), + "setval": "tcp mss {{ tcp.mss.value }}", + "compval": "tcp.mss.value", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "tcp": { + "mss": { + "value": "{{ tcp_mss.split(" ")[2] }}", + }, + }, + }, + }, + }, + + }, + { + "name": "neighbor_timers_keepalive", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<timers_keepalive_time>timers\s\d+) + \s(?P<timers_holdtime>\d+) + $""", re.VERBOSE, + ), + "setval": "timers {{ timers.keepalive_time}} {{ timers.holdtime }}", + "compval": "timers", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "timers": { + "keepalive_time": "{{ timers_keepalive_time.split(" ")[1] }}", + "holdtime": "{{ timers_holdtime.split(" ")[0] }}", + }, + }, + }, + }, + }, + { + "name": "use.neighbor_group", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \suse\sneighbor-group\s(?P<neighbor_group>\S+) + $""", re.VERBOSE, + ), + "setval": "use neighbor-group {{ use.neighbor_group }}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "use": { + "neighbor_group": "{{ neighbor_group }}", + }, + }, + }, + }, + + }, + { + "name": "use.session_group", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \suse\ssession-group\s(?P<session_group>\S+) + $""", re.VERBOSE, + ), + "setval": "use session-group {{ use.session_group }}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "use": { + "session_group": "{{ session_group }}", + }, + }, + }, + }, + }, + { + "name": "update_source", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \supdate-source + \s(?P<update_source>\S+) + $""", re.VERBOSE, + ), + "setval": "update-source {{ update_source}}", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "update_source": "{{ update_source}}", + }, + }, + }, + }, + { + "name": "neighbor_ttl_security_inheritance_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<ttl_security>ttl-security\sinheritance-disable) + $""", re.VERBOSE, + ), + "setval": "ttl-security inheritance-disable", + "compval": "ttl_security.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "ttl_security": { + "inheritance_disable": "{{ True if ttl_security is defined }}", + }, + }, + }, + }, + }, + { + "name": "neighbor_ttl_security", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<ttl_security>ttl-security) + $""", re.VERBOSE, + ), + "setval": "ttl-security", + "compval": "ttl_security.set", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "ttl_security": { + "set": "{{ True if ttl_security is defined }}", + }, + }, + }, + }, + + }, + { + "name": "neighbor_update_in_filtering_attribute_filter_group", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<attribute_filter_group>attribute-filter\sgroup\s\S+) + $""", re.VERBOSE, + ), + "setval": "update in filtering attribute-filter group {{ update.in.filtering.attribute_filter.group }}", + "compval": "update.in.filtering.attribute_filter.group", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "update": { + "in": { + "filtering": { + "attribute_filter": { + "group": "{{ attribute_filter_group.split(" ")[2] }}", + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_update_in_filtering_logging_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<logging_disable>logging\sdisable) + $""", re.VERBOSE, + ), + "setval": "update in filtering logging disable", + "compval": "update.in.filtering.logging.disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "update": { + "in": { + "filtering": { + "logging": { + "disable": "{{True if logging_disable is defined }}", + }, + }, + }, + }, + }, + }, + }, + + }, + { + "name": "neighbor_update_in_filtering_message_buffers", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \s(?P<message_buffers>message\sbuffers\s\d+) + $""", re.VERBOSE, + ), + "setval": "update in filtering message buffers {{ update.in.filtering.message.buffers}}", + "compval": "update.in.filtering.update_message.buffers", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "update": { + "in": { + "filtering": { + "update_message": { + "buffers": "{{ message_buffers.split(" ")[2] }}", + }, + }, + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_capability_additional_paths_send", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \scapability + \sadditional-paths + \s(?P<additional_paths_send>send) + $""", re.VERBOSE, + ), + "setval": "capability additional-paths send", + "compval": "capability.additional_paths.send.set", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "capability": { + "additional_paths": { + "send": { + "set": "{{ True if additional_paths_send is defined }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_capability_additional_paths_send_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \scapability + \sadditional-paths + \s(?P<additional_paths_send>send\sdisable) + $""", re.VERBOSE, + ), + "setval": "capability additional-paths send disable", + "compval": "capability.additional_paths.send.disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "capability": { + "additional_paths": { + "send": { + "disable": "{{ True if additional_paths_send is defined }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_capability_additional_paths_rcv", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \scapability + \sadditional-paths + \s(?P<additional_paths_receive>receive) + $""", re.VERBOSE, + ), + "setval": "capability additional-paths receive", + "compval": "capability.additional_paths.receive.set", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "capability": { + "additional_paths": { + "receive": { + "set": "{{ True if additional_paths_receive is defined }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_capability_additional_paths_rcv_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \scapability + \sadditional-paths + \s(?P<additional_paths_receive_disable>receive\sdisable) + $""", re.VERBOSE, + ), + "setval": "capability additional-paths receive disable", + "compval": "capability.additional_paths.receive.disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "capability": { + "additional_paths": { + "receive": { + "disable": "{{ True if additional_paths_receive_disable is defined }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_capability_suppress_four_byte_AS", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \scapability + \ssuppress + \s(?P<suppress_4_byte_as>4-byte-as) + $""", re.VERBOSE, + ), + "setval": "capability suppress 4-byte-as", + "compval": "capability.suppress.four_byte_AS.set", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "capability": { + "suppress": { + "four_byte_AS": { + "set": "{{ True if suppress_4_byte_as is defined }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_capability_suppress_all", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \scapability + \ssuppress + \s(?P<all>all) + $""", re.VERBOSE, + ), + "setval": "capability suppress all", + "compval": "capability.suppress.all.set", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "capability": { + "suppress": { + "all": { + "set": "{{ True if all is defined }}", + }, + }, + }, + }, + }, + }, + }, + { + "name": "neighbor_capability_suppress_all_inheritance_disable", + "getval": re.compile( + r""" + \s+neighbor-group\s(?P<nbr_address>\S+) + \scapability + \ssuppress + \s(?P<all>all\sinheritance-disable) + $""", re.VERBOSE, + ), + "setval": "capability suppress all inheritance-disable", + "compval": "capability.suppress.all.inheritance_disable", + "result": { + "neighbor": { + UNIQUE_NEIB_ADD: { + "capability": { + "suppress": { + "all": { + "inheritance_disable": "{{ True if all is defined }}", + }, + }, + }, + }, + }, + }, + + }, + + ] + # fmt: on diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv2.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv2.py index e5a54a64f..68937f9bd 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv2.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv2.py @@ -19,11 +19,11 @@ def _tmplt_ospf_default_information(config_data): 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"] + **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"] + **config_data["default_information_originate"], ) return command @@ -35,7 +35,7 @@ def _tmplt_ospf_auto_cost(config_data): command += " disable" if "reference_bandwidth" in config_data["auto_cost"]: command += " reference-bandwidth {reference_bandwidth}".format( - **config_data["auto_cost"] + **config_data["auto_cost"], ) return command @@ -416,11 +416,11 @@ def _tmplt_ospf_area_nssa_def_info_origin(config_data): ) if "metric" in def_info_origin: command += " metric {metric}".format( - **config_data["nssa"]["default_information_originate"] + **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"] + **config_data["nssa"]["default_information_originate"], ) return command @@ -531,11 +531,11 @@ def _tmplt_timers_graceful_shutdown(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"] + **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"] + **config_data["timers"]["graceful-shutdown"], ) return command diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv3.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv3.py index 14e3720be..ea8807206 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv3.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv3.py @@ -19,11 +19,11 @@ def _tmplt_ospf_default_information(config_data): 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"] + **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"] + **config_data["default_information_originate"], ) return command @@ -35,7 +35,7 @@ def _tmplt_ospf_auto_cost(config_data): command += " disable" if "reference_bandwidth" in config_data["auto_cost"]: command += " reference-bandwidth {reference_bandwidth}".format( - **config_data["auto_cost"] + **config_data["auto_cost"], ) return command @@ -413,11 +413,11 @@ def _tmplt_ospf_area_nssa_def_info_origin(config_data): ) if "metric" in def_info_origin: command += " metric {metric}".format( - **config_data["nssa"]["default_information_originate"] + **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"] + **config_data["nssa"]["default_information_originate"], ) return command @@ -528,11 +528,11 @@ def _tmplt_timers_graceful_shutdown(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"] + **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"] + **config_data["timers"]["graceful-shutdown"], ) return command diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/utils.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/utils.py index a4467a487..64c66ca4b 100644 --- a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/utils.py +++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/utils.py @@ -14,12 +14,11 @@ from functools import total_ordering from ansible.module_utils._text import to_text from ansible.module_utils.basic import missing_required_lib +from ansible.module_utils.common.network import is_masklen, to_netmask from ansible.module_utils.six import iteritems from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import ( dict_diff, - is_masklen, search_obj_in_list, - to_netmask, ) @@ -109,7 +108,7 @@ def filter_dict_having_none_value(want, have): 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] + 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: @@ -286,7 +285,7 @@ def normalize_interface(name): if_type = "GigabitEthernet" elif name.lower().startswith("fa"): if_type = "FastEthernet" - elif name.lower().startswith("fo"): + elif name.lower().startswith("for"): if_type = "FortyGigE" elif name.lower().startswith("te"): if_type = "TenGigE" @@ -298,10 +297,16 @@ def normalize_interface(name): if_type = "Vlan" elif name.lower().startswith("lo"): if_type = "Loopback" - elif name.lower().startswith("be"): + elif name.lower().startswith("bundle-e"): if_type = "Bundle-Ether" - elif name.lower().startswith("bp"): + elif name.lower().startswith("bundle-p"): if_type = "Bundle-POS" + elif name.lower().startswith("fif"): + if_type = "FiftyGigE" + elif name.lower().startswith("fou"): + if_type = "FourHundredGigE" + elif name.lower().startswith("two"): + if_type = "TwoHundredGigE" else: if_type = None @@ -310,7 +315,6 @@ def normalize_interface(name): number = number_list[-1].strip() else: number = _get_number(name) - if if_type: proper_interface = if_type + number else: @@ -326,14 +330,16 @@ def get_interface_type(interface): return "GigabitEthernet" elif interface.upper().startswith("FA"): return "FastEthernet" - elif interface.upper().startswith("FO"): + elif interface.upper().startswith("FORT"): return "FortyGigE" elif interface.upper().startswith("ET"): return "Ethernet" elif interface.upper().startswith("LO"): return "Loopback" - elif interface.upper().startswith("BE"): + elif interface.upper().startswith("BUNDLE-E"): return "Bundle-Ether" + elif interface.upper().startswith("BUNDLE-P"): + return "Bundle-POS" elif interface.upper().startswith("NV"): return "nve" elif interface.upper().startswith("TE"): @@ -344,6 +350,16 @@ def get_interface_type(interface): return "HundredGigE" elif interface.upper().startswith("PRE"): return "preconfigure" + elif interface.upper().startswith("FIF"): + return "FiftyGigE" + elif interface.upper().startswith("FOU"): + return "FourHundredGigE" + elif interface.upper().startswith("TWO"): + return "TwoHundredGigE" + elif interface.upper().startswith("MG"): + return "management" + elif interface.upper().startswith("MA"): + return "management" else: return "unknown" @@ -454,3 +470,8 @@ def _coerce(other): if isinstance(other, (int, float)): other = Version(str(other)) return other + + +def netmask_to_cidr(netmask): + # convert netmask to cidr and returns the cidr notation + return str(sum([bin(int(x)).count("1") for x in netmask.split(".")])) |