diff --git a/changelogs/fragments/bgp_address_family.yaml b/changelogs/fragments/bgp_address_family.yaml
new file mode 100644
index 00000000..266c3d81
--- /dev/null
+++ b/changelogs/fragments/bgp_address_family.yaml
@@ -0,0 +1,12 @@
+---
+major_changes:
+ - Aligned with version 1.3+ configuration - aggregate_address, maximum_paths, network, and redistribute
+ moved from `bgp_global` module. These are now Address-family specific.
+ - Many neighbor attributes also moved from `bgp_global` to `bgp_address_family` module.
+ - Redistribute, network stanza - added support for modifiers (metric, backdoor etc as per T6829)
+ - Support for 1.3+ VyOS only
+
+minor_changes:
+ - as_number - Added support for 1.4+ "system-as. 1.3 embedded as_number is still supported"
+ - fix tests for 1.4+ bgp_address_family
+ - updated documentation
diff --git a/changelogs/fragments/bgp_global.yaml b/changelogs/fragments/bgp_global.yaml
new file mode 100644
index 00000000..e528ab39
--- /dev/null
+++ b/changelogs/fragments/bgp_global.yaml
@@ -0,0 +1,10 @@
+---
+minor_changes:
+ - Added support for `solo` neighbor attribute
+ - as_number - Added support for 1.4+ "system-as. 1.3 embedded as_number is still supported"
+ - Fixed tests for 1.4+ bgp_global
+ - updated documentation
+ - Aligned with version 1.3+ configuration - aggregate_address, maximum_paths, network, and redistribute
+ Removed to `bgp_address_family` module.
+ - Many configuration attributes moved from `bgp_global` to `bgp_address_family` module.
+ - Support for 1.3+ VyOS only
diff --git a/docs/vyos.vyos.vyos_bgp_address_family_module.rst b/docs/vyos.vyos.vyos_bgp_address_family_module.rst
index ec4a6398..e17dfdd7 100644
--- a/docs/vyos.vyos.vyos_bgp_address_family_module.rst
+++ b/docs/vyos.vyos.vyos_bgp_address_family_module.rst
@@ -18,6 +18,7 @@ Version added: 1.0.0
Synopsis
--------
- This module manages BGP address family configuration of interfaces on devices running VYOS.
+- Tested against VYOS 1.3, 1.4
diff --git a/docs/vyos.vyos.vyos_bgp_global_module.rst b/docs/vyos.vyos.vyos_bgp_global_module.rst
index 4479124c..64a1b7e0 100644
--- a/docs/vyos.vyos.vyos_bgp_global_module.rst
+++ b/docs/vyos.vyos.vyos_bgp_global_module.rst
@@ -18,6 +18,7 @@ Version added: 1.0.0
Synopsis
--------
- This module manages BGP global configuration of interfaces on devices running VYOS.
+- Tested against VYOS 1.3, 1.4
@@ -50,83 +51,6 @@ Parameters
|
-
-
- aggregate_address
-
-
- list
- / elements=dictionary
-
- |
-
- |
-
- BGP aggregate network.
- |
-
-
- |
- |
-
-
- as_set
-
-
- boolean
-
- |
-
-
- |
-
- Generate AS-set path information for this aggregate address.
- |
-
-
- |
- |
-
-
- prefix
-
-
- string
-
- |
-
- |
-
- BGP aggregate network.
- |
-
-
- |
- |
-
-
- summary_only
-
-
- boolean
-
- |
-
-
- |
-
- Announce the aggregate summary network only.
- |
-
-
-
- |
as_number
@@ -478,7 +402,8 @@ Parameters
|
- Deactivate IPv4 unicast for a peer by default
+ Deactivate IPv4 unicast for a peer by default
+ Deprecated: Unavailable after 1.4
|
@@ -738,58 +663,6 @@ Parameters
-
- |
-
-
- maximum_paths
-
-
- list
- / elements=dictionary
-
- |
-
- |
-
- BGP multipaths
- |
-
-
- |
- |
-
-
- count
-
-
- integer
-
- |
-
- |
-
- No. of paths.
- |
-
-
- |
- |
-
-
- path
-
-
- string
-
- |
-
- |
-
- BGP multipaths
- |
-
-
|
@@ -846,24 +719,25 @@ Parameters
| |
- allowas_in
+ capability
- integer
+ dictionary
|
|
- Number of occurrences of AS number.
+ Advertise capabilities to this neighbor.
|
-
+
|
|
-
+ | |
+
- as_override
+ dynamic
boolean
@@ -876,33 +750,16 @@ Parameters
|
- AS for routes sent to this neighbor to be the local AS.
+ Advertise dynamic capability to this neighbor.
|
|
|
-
-
- attribute_unchanged
-
-
- dictionary
-
- |
-
- |
-
- BGP attributes are sent unchanged.
- |
-
-
- |
- |
|
- as_path
+ extended_nexthop
boolean
@@ -915,78 +772,71 @@ Parameters
|
- as_path
+ Advertise extended nexthop capability to this neighbor.
|
+
|
|
- |
-
+ |
- med
+ default_originate
- boolean
+ string
|
-
|
- med
+ Send default route to this neighbor
|
|
|
- |
-
+ |
- next_hop
+ description
- boolean
+ string
|
-
|
- next_hop
+ Description of the neighbor
|
-
|
|
- capability
+ disable_capability_negotiation
- dictionary
+ boolean
|
+
|
- Advertise capabilities to this neighbor.
+ Disbale capability negotiation with the neighbor
|
-
- |
+
|
|
-
+ |
- dynamic
+ disable_connected_check
boolean
@@ -999,16 +849,15 @@ Parameters
|
- Advertise dynamic capability to this neighbor.
+ Disable check to see if EBGP peer's address is a connected route.
|
|
|
- |
-
+ |
- orf
+ disable_send_community
string
@@ -1016,30 +865,29 @@ Parameters
|
Choices:
- - send
- - receive
+ - extended
+ - standard
|
- Advertise ORF capability to this neighbor.
+ Disable sending community attributes to this neighbor.
|
-
|
|
- default_originate
+ ebgp_multihop
- string
+ integer
|
|
- Send default route to this neighbor
+ Allow this EBGP neighbor to not be on a directly connected network. Specify the number hops.
|
@@ -1047,16 +895,16 @@ Parameters
|
- description
+ local_as
- string
+ integer
|
|
- Description of the neighbor
+ local as number not to be prepended to updates from EBGP peers
|
@@ -1064,7 +912,7 @@ Parameters
|
- disable_capability_negotiation
+ override_capability
boolean
@@ -1077,7 +925,7 @@ Parameters
|
- Disbale capability negotiation with the neighbor
+ Ignore capability negotiation with specified neighbor.
|
@@ -1085,7 +933,7 @@ Parameters
|
- disable_connected_check
+ passive
boolean
@@ -1098,7 +946,7 @@ Parameters
|
- Disable check to see if EBGP peer's address is a connected route.
+ Do not initiate a session with this neighbor
|
@@ -1106,20 +954,16 @@ Parameters
|
- disable_send_community
+ password
string
|
- Choices:
- - extended
- - standard
-
|
- Disable sending community attributes to this neighbor.
+ BGP MD5 password
|
@@ -1127,66 +971,62 @@ Parameters
|
- distribute_list
+ peer_group
- list
- / elements=dictionary
+ boolean
|
+
|
- Access-list to filter route updates to/from this neighbor.
+ True if all the configs under this neighbor key is for peer group template.
|
-
- |
+
|
|
-
+ |
- acl
+ peer_group_name
- integer
+ string
|
|
- Access-list number.
+ IPv4 peer group for this peer
|
|
|
- |
-
+ |
- action
+ port
- string
+ integer
|
- Choices:
- - export
- - import
-
|
- Access-list to filter outgoing/incoming route updates to this neighbor
+ Neighbor's BGP port
|
-
|
|
- ebgp_multihop
+ remote_as
integer
@@ -1195,7 +1035,7 @@ Parameters
|
- Allow this EBGP neighbor to not be on a directly connected network. Specify the number hops.
+ Neighbor BGP AS number
|
|
@@ -1203,433 +1043,7 @@ Parameters
|
- filter_list
-
-
- list
- / elements=dictionary
-
- |
-
- |
-
- As-path-list to filter route updates to/from this neighbor.
- |
-
-
- |
- |
- |
-
-
- action
-
-
- string
-
- |
-
- Choices:
- - export
- - import
-
- |
-
- filter outgoing/incoming route updates
- |
-
-
- |
- |
- |
-
-
- path_list
-
-
- string
-
- |
-
- |
-
- As-path-list to filter
- |
-
-
-
- |
- |
-
-
- local_as
-
-
- integer
-
- |
-
- |
-
- local as number not to be prepended to updates from EBGP peers
- |
-
-
- |
- |
-
-
- maximum_prefix
-
-
- integer
-
- |
-
- |
-
- Maximum number of prefixes to accept from this neighbor nexthop-self Nexthop for routes sent to this neighbor to be the local router.
- |
-
-
- |
- |
-
-
- nexthop_self
-
-
- boolean
-
- |
-
-
- |
-
- Nexthop for routes sent to this neighbor to be the local router.
- |
-
-
- |
- |
-
-
- override_capability
-
-
- boolean
-
- |
-
-
- |
-
- Ignore capability negotiation with specified neighbor.
- |
-
-
- |
- |
-
-
- passive
-
-
- boolean
-
- |
-
-
- |
-
- Do not initiate a session with this neighbor
- |
-
-
- |
- |
-
-
- password
-
-
- string
-
- |
-
- |
-
- BGP MD5 password
- |
-
-
- |
- |
-
-
- peer_group
-
-
- boolean
-
- |
-
-
- |
-
- True if all the configs under this neighbor key is for peer group template.
- |
-
-
- |
- |
-
-
- peer_group_name
-
-
- string
-
- |
-
- |
-
- IPv4 peer group for this peer
- |
-
-
- |
- |
-
-
- port
-
-
- integer
-
- |
-
- |
-
- Neighbor's BGP port
- |
-
-
- |
- |
-
-
- prefix_list
-
-
- list
- / elements=dictionary
-
- |
-
- |
-
- Prefix-list to filter route updates to/from this neighbor.
- |
-
-
- |
- |
- |
-
-
- action
-
-
- string
-
- |
-
- Choices:
- - export
- - import
-
- |
-
- filter outgoing/incoming route updates
- |
-
-
- |
- |
- |
-
-
- prefix_list
-
-
- string
-
- |
-
- |
-
- Prefix-list to filter
- |
-
-
-
- |
- |
-
-
- remote_as
-
-
- integer
-
- |
-
- |
-
- Neighbor BGP AS number
- |
-
-
- |
- |
-
-
- remove_private_as
-
-
- boolean
-
- |
-
-
- |
-
- Remove private AS numbers from AS path in outbound route updates
- |
-
-
- |
- |
-
-
- route_map
-
-
- list
- / elements=dictionary
-
- |
-
- |
-
- Route-map to filter route updates to/from this neighbor.
- |
-
-
- |
- |
- |
-
-
- action
-
-
- string
-
- |
-
- Choices:
- - export
- - import
-
- |
-
- filter outgoing/incoming route updates
- |
-
-
- |
- |
- |
-
-
- route_map
-
-
- string
-
- |
-
- |
-
- route-map to filter
- |
-
-
-
- |
- |
-
-
- route_reflector_client
-
-
- boolean
-
- |
-
-
- |
-
- Neighbor as a route reflector client
- |
-
-
- |
- |
-
-
- route_server_client
-
-
- boolean
-
- |
-
-
- |
-
- Neighbor is route server client
- |
-
-
- |
- |
-
-
- shutdown
+ shutdown
boolean
@@ -1650,7 +1064,7 @@ Parameters
|
- soft_reconfiguration
+ solo
boolean
@@ -1663,7 +1077,7 @@ Parameters
|
- Soft reconfiguration for neighbor
+ Do not send back prefixes learned from the neighbor
|
|
@@ -1773,24 +1187,7 @@ Parameters
|
- Ttl security mechanism for this BGP peer
- |
-
-
- |
- |
-
-
- unsuppress_map
-
-
- string
-
- |
-
- |
-
- Route-map to selectively unsuppress suppressed routes
+ Number of the maximum number of hops to the BGP peer
|
@@ -1810,172 +1207,6 @@ Parameters
Source IP of routing updates
-
- |
- |
-
-
- weight
-
-
- integer
-
- |
-
- |
-
- Default weight for routes from this neighbor
- |
-
-
-
- |
-
-
- network
-
-
- list
- / elements=dictionary
-
- |
-
- |
-
- BGP network
- |
-
-
- |
- |
-
-
- address
-
-
- string
-
- |
-
- |
-
- BGP network address
- |
-
-
- |
- |
-
-
- backdoor
-
-
- boolean
-
- |
-
-
- |
-
- Network as a backdoor route
- |
-
-
- |
- |
-
-
- route_map
-
-
- string
-
- |
-
- |
-
- Route-map to modify route attributes
- |
-
-
-
- |
-
-
- redistribute
-
-
- list
- / elements=dictionary
-
- |
-
- |
-
- Redistribute routes from other protocols into BGP
- |
-
-
- |
- |
-
-
- metric
-
-
- integer
-
- |
-
- |
-
- Metric for redistributed routes.
- |
-
-
- |
- |
-
-
- protocol
-
-
- string
-
- |
-
- Choices:
- - connected
- - kernel
- - ospf
- - rip
- - static
-
- |
-
- types of routes to be redistributed.
- |
-
-
- |
- |
-
-
- route_map
-
-
- string
-
- |
-
- |
-
- Route map to filter redistributed routes
- |
-
|
diff --git a/plugins/module_utils/network/vyos/argspec/bgp_global/bgp_global.py b/plugins/module_utils/network/vyos/argspec/bgp_global/bgp_global.py
index b647ea91..42fb5abf 100644
--- a/plugins/module_utils/network/vyos/argspec/bgp_global/bgp_global.py
+++ b/plugins/module_utils/network/vyos/argspec/bgp_global/bgp_global.py
@@ -36,44 +36,17 @@ class Bgp_globalArgs(object): # pylint: disable=R0903
"type": "dict",
"options": {
"as_number": {"type": "int"},
- "aggregate_address": {
- "type": "list",
- "elements": "dict",
- "options": {
- "prefix": {"type": "str"},
- "as_set": {"type": "bool"},
- "summary_only": {"type": "bool"},
- },
- },
- "maximum_paths": {
- "type": "list",
- "elements": "dict",
- "options": {"path": {"type": "str"}, "count": {"type": "int"}},
- },
"neighbor": {
"type": "list",
"elements": "dict",
"options": {
"address": {"type": "str"},
"advertisement_interval": {"type": "int"},
- "allowas_in": {"type": "int"},
- "as_override": {"type": "bool"},
- "attribute_unchanged": {
- "type": "dict",
- "options": {
- "as_path": {"type": "bool"},
- "med": {"type": "bool"},
- "next_hop": {"type": "bool"},
- },
- },
"capability": {
"type": "dict",
"options": {
"dynamic": {"type": "bool"},
- "orf": {
- "type": "str",
- "choices": ["send", "receive"],
- },
+ "extended_nexthop": {"type": "bool"},
},
},
"default_originate": {"type": "str"},
@@ -84,71 +57,18 @@ class Bgp_globalArgs(object): # pylint: disable=R0903
"type": "str",
"choices": ["extended", "standard"],
},
- "distribute_list": {
- "type": "list",
- "elements": "dict",
- "options": {
- "action": {
- "type": "str",
- "choices": ["export", "import"],
- },
- "acl": {"type": "int"},
- },
- },
"ebgp_multihop": {"type": "int"},
- "filter_list": {
- "type": "list",
- "elements": "dict",
- "options": {
- "action": {
- "type": "str",
- "choices": ["export", "import"],
- },
- "path_list": {"type": "str"},
- },
- },
"local_as": {"type": "int"},
- "maximum_prefix": {"type": "int"},
- "nexthop_self": {"type": "bool"},
"override_capability": {"type": "bool"},
"passive": {"type": "bool"},
"password": {"type": "str", "no_log": True},
"peer_group_name": {"type": "str"},
"peer_group": {"type": "bool"},
"port": {"type": "int"},
- "prefix_list": {
- "type": "list",
- "elements": "dict",
- "options": {
- "action": {
- "type": "str",
- "choices": ["export", "import"],
- },
- "prefix_list": {"type": "str"},
- },
- },
"remote_as": {"type": "int"},
- "remove_private_as": {"type": "bool"},
- "route_map": {
- "type": "list",
- "elements": "dict",
- "options": {
- "action": {
- "type": "str",
- "choices": ["export", "import"],
- },
- "route_map": {"type": "str"},
- },
- },
- "route_reflector_client": {"type": "bool"},
- "route_server_client": {"type": "bool"},
+ "solo": {"type": "bool"},
"shutdown": {"type": "bool"},
- "soft_reconfiguration": {"type": "bool"},
"strict_capability_match": {"type": "bool"},
- "unsuppress_map": {"type": "str"},
- "update_source": {"type": "str"},
- "weight": {"type": "int"},
- "ttl_security": {"type": "int"},
"timers": {
"type": "dict",
"options": {
@@ -157,33 +77,8 @@ class Bgp_globalArgs(object): # pylint: disable=R0903
"keepalive": {"type": "int"},
},
},
- },
- },
- "network": {
- "type": "list",
- "elements": "dict",
- "options": {
- "address": {"type": "str"},
- "backdoor": {"type": "bool"},
- "route_map": {"type": "str"},
- },
- },
- "redistribute": {
- "type": "list",
- "elements": "dict",
- "options": {
- "protocol": {
- "type": "str",
- "choices": [
- "connected",
- "kernel",
- "ospf",
- "rip",
- "static",
- ],
- },
- "route_map": {"type": "str"},
- "metric": {"type": "int"},
+ "ttl_security": {"type": "int"},
+ "update_source": {"type": "str"},
},
},
"timers": {
diff --git a/plugins/module_utils/network/vyos/config/bgp_address_family/bgp_address_family.py b/plugins/module_utils/network/vyos/config/bgp_address_family/bgp_address_family.py
index 1b075adb..0e6bec81 100644
--- a/plugins/module_utils/network/vyos/config/bgp_address_family/bgp_address_family.py
+++ b/plugins/module_utils/network/vyos/config/bgp_address_family/bgp_address_family.py
@@ -33,6 +33,14 @@
Bgp_address_familyTemplate,
)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.bgp_address_family_14 import (
+ Bgp_address_familyTemplate14,
+)
+
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import get_os_version
+
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.version import LooseVersion
+
class Bgp_address_family(ResourceModule):
"""
@@ -49,12 +57,30 @@ def __init__(self, module):
)
self.parsers = []
+ def _validate_template(self):
+ version = get_os_version(self._module)
+ if LooseVersion(version) >= LooseVersion("1.4"):
+ self._tmplt = Bgp_address_familyTemplate14()
+ else:
+ self._tmplt = Bgp_address_familyTemplate()
+
+ def parse(self):
+ """ override parse to check template """
+ self._validate_template()
+ return super().parse()
+
+ def get_parser(self, name):
+ """get_parsers"""
+ self._validate_template()
+ return super().get_parser(name)
+
def execute_module(self):
"""Execute the module
:rtype: A dictionary
:returns: The result from module execution
"""
+ self._validate_template()
if self.state not in ["parsed", "gathered"]:
self.generate_commands()
self.run_commands()
@@ -67,7 +93,9 @@ def generate_commands(self):
wantd = {}
haved = {}
- if self.want.get("as_number") == self.have.get("as_number") or not self.have:
+ if (self.want.get("as_number") == self.have.get("as_number") or
+ not self.have or
+ LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4")):
if self.want:
wantd = {self.want["as_number"]: self.want}
if self.have:
@@ -103,6 +131,9 @@ def _compare(self, want, have):
the `want` and `have` data with the `parsers` defined
for the Bgp_address_family network resource.
"""
+ if LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"):
+ self._compare_asn(want, have)
+
self._compare_af(want, have)
self._compare_neighbors(want, have)
# Do the negation first
@@ -268,13 +299,21 @@ def _compare_neighbors(self, want, have):
def _compare_lists(self, want, have, as_number, afi):
parsers = [
"aggregate_address",
+ "network",
"network.backdoor",
"network.path_limit",
"network.route_map",
+ "redistribute",
"redistribute.metric",
"redistribute.route_map",
"redistribute.table",
]
+
+ if LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"):
+ delete_asn = ""
+ else:
+ delete_asn = " " + str(as_number)
+
for attrib in ["redistribute", "networks", "aggregate_address"]:
wdict = want.pop(attrib, {})
hdict = have.pop(attrib, {})
@@ -300,8 +339,8 @@ def _compare_lists(self, want, have, as_number, afi):
attrib = re.sub("_", "-", attrib)
attrib = re.sub("networks", "network", attrib)
self.commands.append(
- "delete protocols bgp "
- + str(as_number)
+ "delete protocols bgp"
+ + delete_asn
+ " "
+ "address-family "
+ afi
@@ -318,6 +357,19 @@ def _compare_lists(self, want, have, as_number, afi):
"address_family": {"afi": afi, attrib: entry},
},
)
+ # de-duplicate child commands if parent command is present
+ for val in (self.commands):
+ for val2 in self.commands:
+ if val != val2 and val2.startswith(val):
+ self.commands.remove(val2)
+
+ def _compare_asn(self, want, have):
+ if want.get("as_number") and not have.get("as_number"):
+ self.commands.append(
+ "set protocols bgp "
+ + "system-as "
+ + str(want.get("as_number")),
+ )
def _bgp_af_list_to_dict(self, entry):
for name, proc in iteritems(entry):
diff --git a/plugins/module_utils/network/vyos/config/bgp_global/bgp_global.py b/plugins/module_utils/network/vyos/config/bgp_global/bgp_global.py
index c4a85020..91a5af12 100644
--- a/plugins/module_utils/network/vyos/config/bgp_global/bgp_global.py
+++ b/plugins/module_utils/network/vyos/config/bgp_global/bgp_global.py
@@ -17,7 +17,6 @@
necessary to bring the current configuration to its desired end-state is
created.
"""
-import re
from ansible.module_utils.six import iteritems
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module import (
@@ -31,6 +30,13 @@
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.bgp_global import (
Bgp_globalTemplate,
)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.bgp_global_14 import (
+ Bgp_globalTemplate14,
+)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.version import (
+ LooseVersion,
+)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import get_os_version
class Bgp_global(ResourceModule):
@@ -48,12 +54,35 @@ def __init__(self, module):
)
self.parsers = []
+ def _validate_template(self):
+ version = get_os_version(self._module)
+ if LooseVersion(version) >= LooseVersion("1.4"):
+ self._tmplt = Bgp_globalTemplate14()
+ else:
+ self._tmplt = Bgp_globalTemplate()
+
+ def parse(self):
+ """override parse to check template"""
+ self._validate_template()
+ return super().parse()
+
+ def get_parser(self, name):
+ """get_parsers"""
+ self._validate_template()
+ return super().get_parser(name)
+
def execute_module(self):
"""Execute the module
:rtype: A dictionary
:returns: The result from module execution
"""
+ version = get_os_version(self._module)
+ if LooseVersion(version) >= LooseVersion("1.4"):
+ self._asn_mod = ""
+ else:
+ self._asn_mod = " " + str(self.have.get("as_number"))
+ self._validate_template()
if self.state not in ["parsed", "gathered"]:
self.generate_commands()
self.run_commands()
@@ -66,7 +95,11 @@ def generate_commands(self):
wantd = {}
haved = {}
- if self.want.get("as_number") == self.have.get("as_number") or not self.have:
+ if (
+ self.want.get("as_number") == self.have.get("as_number")
+ or not self.have
+ or LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4")
+ ):
if self.want:
wantd = {self.want["as_number"]: self.want}
if self.have:
@@ -105,9 +138,11 @@ def _compare(self, want, have):
the `want` and `have` data with the `parsers` defined
for the Bgp_global network resource.
"""
+ if LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"):
+ self._compare_asn(want, have)
+
parsers = ["maximum_paths", "timers"]
self._compare_neighbor(want, have)
- self._compare_lists(want, have)
self._compare_bgp_params(want, have)
for name, entry in iteritems(want):
if name != "as_number":
@@ -176,12 +211,12 @@ def _compare_neighbor(self, want, have):
"neighbor.weight",
"neighbor.ttl_security",
"neighbor.timers",
- "network.backdoor",
- "network.route_map",
]
+
wneigh = want.pop("neighbor", {})
hneigh = have.pop("neighbor", {})
self._compare_neigh_lists(wneigh, hneigh)
+
for name, entry in iteritems(wneigh):
for k, v in entry.items():
if k == "address":
@@ -207,7 +242,7 @@ def _compare_neighbor(self, want, have):
self._module.fail_json(msg=msg)
else:
self.commands.append(
- "delete protocols bgp " + str(have["as_number"]) + " neighbor " + name,
+ "delete protocols bgp" + self._asn_mod + " neighbor " + name,
)
continue
for k, v in entry.items():
@@ -243,6 +278,7 @@ def _compare_bgp_params(self, want, have):
"bgp_params.routerid",
"bgp_params.scan_time",
]
+
wbgp = want.pop("bgp_params", {})
hbgp = have.pop("bgp_params", {})
for name, entry in iteritems(wbgp):
@@ -287,12 +323,12 @@ def _compare_bgp_params(self, want, have):
},
)
if not wbgp and hbgp:
- self.commands.append("delete protocols bgp " + str(have["as_number"]) + " parameters")
+ self.commands.append("delete protocols bgp" + self._asn_mod + " parameters")
hbgp = {}
for name, entry in iteritems(hbgp):
if name == "confederation":
self.commands.append(
- "delete protocols bgp " + str(have["as_number"]) + " parameters confederation",
+ "delete protocols bgp" + self._asn_mod + " parameters confederation",
)
elif name == "distance":
distance_parsers = [
@@ -317,39 +353,6 @@ def _compare_bgp_params(self, want, have):
},
)
- def _compare_lists(self, want, have):
- parsers = [
- "network.backdoor",
- "network.route_map",
- "redistribute.metric",
- "redistribute.route_map",
- "aggregate_address",
- ]
- for attrib in ["redistribute", "network", "aggregate_address"]:
- wdict = want.pop(attrib, {})
- hdict = have.pop(attrib, {})
- for key, entry in iteritems(wdict):
- if entry != hdict.get(key, {}):
- self.compare(
- parsers=parsers,
- want={"as_number": want["as_number"], attrib: entry},
- have=hdict.pop(key, {}),
- )
- hdict.pop(key, {})
- # remove remaining items in have for replaced
- if not wdict and hdict:
- attrib = re.sub("_", "-", attrib)
- self.commands.append(
- "delete protocols bgp " + str(have["as_number"]) + " " + attrib,
- )
- hdict = {}
- for key, entry in iteritems(hdict):
- self.compare(
- parsers=parsers,
- want={},
- have={"as_number": have["as_number"], attrib: entry},
- )
-
def _compare_neigh_lists(self, want, have):
for attrib in [
"distribute_list",
@@ -392,16 +395,23 @@ def _bgp_global_list_to_dict(self, entry):
redis_dict.update({entry["protocol"]: entry})
proc["redistribute"] = redis_dict
+ def _compare_asn(self, want, have):
+ if want.get("as_number") and not have.get("as_number"):
+ self.commands.append(
+ "set protocols bgp " + "system-as" + " " + str(want.get("as_number")),
+ )
+
def _check_af(self, neighbor):
af_present = False
if self._connection:
config_lines = self._get_config(self._connection).splitlines()
for line in config_lines:
- if "address-family" in line:
- af_present = True
+ if neighbor in line:
+ if "address-family" in line:
+ af_present = True
return af_present
def _get_config(self, connection):
return connection.get(
- 'show configuration commands | match "set protocols bgp .* neighbor"',
+ 'show configuration commands | match "set protocols bgp .*neighbor"',
)
diff --git a/plugins/module_utils/network/vyos/facts/bgp_address_family/bgp_address_family.py b/plugins/module_utils/network/vyos/facts/bgp_address_family/bgp_address_family.py
index 629ffc50..3386bd66 100644
--- a/plugins/module_utils/network/vyos/facts/bgp_address_family/bgp_address_family.py
+++ b/plugins/module_utils/network/vyos/facts/bgp_address_family/bgp_address_family.py
@@ -25,6 +25,13 @@
from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.bgp_address_family import (
Bgp_address_familyTemplate,
)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.bgp_address_family_14 import (
+ Bgp_address_familyTemplate14,
+)
+
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import get_os_version
+
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.version import LooseVersion
class Bgp_address_familyFacts(object):
@@ -55,11 +62,14 @@ def populate_facts(self, connection, ansible_facts, data=None):
data = self.get_device_data(connection)
for resource in data.splitlines():
- if "address-family" in resource:
+ if "address-family" in resource or "system-as" in resource:
config_lines.append(re.sub("'", "", resource))
- # parse native config using the Bgp_address_family template
- bgp_address_family_parser = Bgp_address_familyTemplate(lines=config_lines)
+ # parse native config using the Bgp_address_family template based on version
+ if LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"):
+ bgp_address_family_parser = Bgp_address_familyTemplate14(lines=config_lines)
+ else:
+ bgp_address_family_parser = Bgp_address_familyTemplate(lines=config_lines)
objs = bgp_address_family_parser.parse()
if objs:
if "address_family" in objs:
diff --git a/plugins/module_utils/network/vyos/facts/bgp_global/bgp_global.py b/plugins/module_utils/network/vyos/facts/bgp_global/bgp_global.py
index fe341357..dd793681 100644
--- a/plugins/module_utils/network/vyos/facts/bgp_global/bgp_global.py
+++ b/plugins/module_utils/network/vyos/facts/bgp_global/bgp_global.py
@@ -26,6 +26,14 @@
Bgp_globalTemplate,
)
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.rm_templates.bgp_global_14 import (
+ Bgp_globalTemplate14,
+)
+
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.vyos import get_os_version
+
+from ansible_collections.vyos.vyos.plugins.module_utils.network.vyos.utils.version import LooseVersion
+
class Bgp_globalFacts(object):
"""The vyos bgp_global facts class"""
@@ -58,7 +66,11 @@ def populate_facts(self, connection, ansible_facts, data=None):
if "address-family" not in resource:
config_lines.append(re.sub("'", "", resource))
- bgp_global_parser = Bgp_globalTemplate(lines=config_lines, module=self._module)
+ if LooseVersion(get_os_version(self._module)) >= LooseVersion("1.4"):
+ bgp_global_parser = Bgp_globalTemplate14(lines=config_lines, module=self._module)
+ else:
+ bgp_global_parser = Bgp_globalTemplate(lines=config_lines, module=self._module)
+
objs = bgp_global_parser.parse()
if "neighbor" in objs:
diff --git a/plugins/module_utils/network/vyos/rm_templates/bgp_address_family.py b/plugins/module_utils/network/vyos/rm_templates/bgp_address_family.py
index c996a74a..f8f86cd2 100644
--- a/plugins/module_utils/network/vyos/rm_templates/bgp_address_family.py
+++ b/plugins/module_utils/network/vyos/rm_templates/bgp_address_family.py
@@ -37,44 +37,31 @@ def _tmplt_bgp_af_aggregate_address(config_data):
return command
-def _tmplt_bgp_af_redistribute_metric(config_data):
- if config_data["address_family"]["redistribute"].get("metric"):
- afi = config_data["address_family"]["afi"] + "-unicast"
- command = "protocols bgp {as_number} address-family ".format(**config_data)
- if config_data["address_family"]["redistribute"].get("metric"):
- command += afi + " redistribute {protocol} metric {metric}".format(
- **config_data["address_family"]["redistribute"],
- )
- return command
-
-
-def _tmplt_bgp_af_redistribute_route_map(config_data):
- if config_data["address_family"]["redistribute"].get("route_map"):
- afi = config_data["address_family"]["afi"] + "-unicast"
- command = "protocols bgp {as_number} address-family ".format(**config_data)
- if config_data["address_family"]["redistribute"].get("route_map"):
- command += afi + " redistribute {protocol} route-map {route_map}".format(
- **config_data["address_family"]["redistribute"],
- )
- return command
-
-
-def _tmplt_bgp_af_redistribute_table(config_data):
- if config_data["address_family"]["redistribute"].get("table"):
- afi = config_data["address_family"]["afi"] + "-unicast"
- command = "protocols bgp {as_number} address-family ".format(**config_data)
- if config_data["address_family"]["redistribute"].get("table"):
- command += afi + " table {table}".format(
- **config_data["address_family"]["redistribute"],
- )
- return command
+def _tmplt_bgp_af_redistribute(config_data):
+ afi = config_data["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp {as_number} address-family ".format(**config_data)
+ config_data = config_data["address_family"]["redistribute"]
+ command += afi + " redistribute {protocol}".format(**config_data)
+ if config_data.get("metric"):
+ command += " metric {metric}".format(**config_data)
+ elif config_data.get("route_map"):
+ command += " route-map {route_map}".format(**config_data)
+ elif config_data.get("table"):
+ command += " table {table}".format(**config_data)
+ return command
-def _tmplt_bgp_af_delete_redistribute(config_data):
+def _tmplt_bgp_af_redistribute_delete(config_data):
afi = config_data["address_family"]["afi"] + "-unicast"
command = "protocols bgp {as_number} address-family ".format(**config_data)
- config_data = config_data["address_family"]
- command += afi + " redistribute {protocol}".format(**config_data["redistribute"])
+ config_data = config_data["address_family"]["redistribute"]
+ command += afi + " redistribute {protocol}".format(**config_data)
+ if config_data.get("metric"):
+ command += " metric"
+ elif config_data.get("route_map"):
+ command += " route-map"
+ elif config_data.get("table"):
+ command += " table"
return command
@@ -234,6 +221,30 @@ def _tmplt_bgp_af_neighbor(config_data):
return command
+def _tmplt_bgp_af_network(config_data):
+ afi = config_data["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp {as_number} address-family ".format(**config_data)
+ config_data = config_data["address_family"]["networks"]
+ command += afi + " network {prefix}".format(**config_data)
+ if config_data.get("backdoor"):
+ command += " backdoor"
+ elif config_data.get("route_map"):
+ command += " route-map {route_map}".format(**config_data)
+ return command
+
+
+def _tmplt_bgp_af_network_delete(config_data):
+ afi = config_data["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp {as_number} address-family ".format(**config_data)
+ config_data = config_data["address_family"]["networks"]
+ command += afi + " network {prefix}".format(**config_data)
+ if config_data.get("backdoor"):
+ command += " backdoor"
+ elif config_data.get("route_map"):
+ command += " route_map"
+ return command
+
+
class Bgp_address_familyTemplate(NetworkTemplate):
def __init__(self, lines=None, module=None):
prefix = {"set": "set", "remove": "delete"}
@@ -307,6 +318,38 @@ def __init__(self, lines=None, module=None):
},
},
},
+ {
+ "name": "network",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P\d+)
+ \s+address-family
+ \s+(?P\S+)-unicast
+ \s+network
+ \s+(?P\S+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_network,
+ "remval": "protocols bgp {{ as_number }} address-family {{ address_family.afi }}-unicast network {{ address_family.networks.prefix }}",
+ "compval": "address_family.networks.prefix",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "networks": [
+ {
+ "prefix": "{{ address }}",
+ },
+ ],
+ },
+ },
+ },
+ },
{
"name": "network.backdoor",
"getval": re.compile(
@@ -323,8 +366,8 @@ def __init__(self, lines=None, module=None):
*$""",
re.VERBOSE,
),
- "setval": "protocols bgp {{ as_number }} address-family {{ address_family.afi }}-unicast network {{ address_family.networks.prefix }} backdoor",
- "remval": "protocols bgp {{ as_number }} address-family {{ address_family.afi }}-unicast network {{ address_family.networks.prefix }}",
+ "setval": _tmplt_bgp_af_network,
+ "remval": _tmplt_bgp_af_network_delete,
"compval": "address_family.networks.backdoor",
"result": {
"as_number": "{{ as_num }}",
@@ -358,9 +401,8 @@ def __init__(self, lines=None, module=None):
*$""",
re.VERBOSE,
),
- "setval": "protocols bgp {{ as_number }} address-family {{ address_family.afi }}-unicast network" +
- "{{ address_family.networks.prefix }} path-limit {{ address_family.networks.path_limit }}",
- "remval": "protocols bgp {{ as_number }} address-family {{ address_family.afi }}-unicast network {{ address_family.networks.address }}",
+ "setval": _tmplt_bgp_af_network,
+ "remval": _tmplt_bgp_af_network_delete,
"compval": "address_family.networks.path_limit",
"result": {
"as_number": "{{ as_num }}",
@@ -394,9 +436,8 @@ def __init__(self, lines=None, module=None):
*$""",
re.VERBOSE,
),
- "setval": "protocols bgp {{ as_number }} address-family {{ address_family.afi }}-unicast network" +
- " {{ address_family.networks.prefix }} route-map {{ address_family.networks.route_map }}",
- "remval": "protocols bgp {{ as_number }} address-family {{ address_family.afi }}-unicast network {{ address_family.networks.prefix }}",
+ "setval": _tmplt_bgp_af_network,
+ "remval": _tmplt_bgp_af_network_delete,
"compval": "address_family.networks.route_map",
"result": {
"as_number": "{{ as_num }}",
@@ -413,6 +454,38 @@ def __init__(self, lines=None, module=None):
},
},
},
+ {
+ "name": "redistribute",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+(?P\d+)
+ \s+address-family
+ \s+(?P\S+)-unicast
+ \s+redistribute
+ \s+(?P\S+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_redistribute,
+ "remval": "protocols bgp {{ as_number }} address-family {{ address_family.afi }}-unicast redistribute {{ address_family.redistribute.protocol }}",
+ "compval": "address_family.redistribute.protocol",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "redistribute": [
+ {
+ "protocol": "{{ proto }}",
+ },
+ ],
+ },
+ },
+ },
+ },
{
"name": "redistribute.metric",
"getval": re.compile(
@@ -430,8 +503,8 @@ def __init__(self, lines=None, module=None):
*$""",
re.VERBOSE,
),
- "setval": _tmplt_bgp_af_redistribute_metric,
- "remval": _tmplt_bgp_af_delete_redistribute,
+ "setval": _tmplt_bgp_af_redistribute,
+ "remval": _tmplt_bgp_af_redistribute_delete,
"compval": "address_family.redistribute.metric",
"result": {
"as_number": "{{ as_num }}",
@@ -465,8 +538,8 @@ def __init__(self, lines=None, module=None):
*$""",
re.VERBOSE,
),
- "setval": _tmplt_bgp_af_redistribute_route_map,
- "remval": _tmplt_bgp_af_delete_redistribute,
+ "setval": _tmplt_bgp_af_redistribute,
+ "remval": _tmplt_bgp_af_redistribute_delete,
"compval": "address_family.redistribute.route_map",
"result": {
"as_number": "{{ as_num }}",
@@ -499,8 +572,8 @@ def __init__(self, lines=None, module=None):
*$""",
re.VERBOSE,
),
- "setval": _tmplt_bgp_af_redistribute_table,
- "remval": _tmplt_bgp_af_delete_redistribute,
+ "setval": _tmplt_bgp_af_redistribute,
+ "remval": _tmplt_bgp_af_redistribute_delete,
"compval": "address_family.redistribute.table",
"result": {
"as_number": "{{ as_num }}",
diff --git a/plugins/module_utils/network/vyos/rm_templates/bgp_address_family_14.py b/plugins/module_utils/network/vyos/rm_templates/bgp_address_family_14.py
new file mode 100644
index 00000000..fd4c9de9
--- /dev/null
+++ b/plugins/module_utils/network/vyos/rm_templates/bgp_address_family_14.py
@@ -0,0 +1,1433 @@
+# -*- coding: utf-8 -*-
+# Copyright 2021 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_address_family 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,
+)
+
+
+def _tmplt_bgp_af_aggregate_address(config_data):
+ afi = config_data["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp address-family ".format(**config_data)
+ config_data = config_data["address_family"]
+ if config_data["aggregate_address"].get("as_set"):
+ command += afi + " aggregate-address {prefix} as-set".format(
+ **config_data["aggregate_address"],
+ )
+ if config_data["aggregate_address"].get("summary_only"):
+ command += afi + " aggregate-address {prefix} summary-only".format(
+ **config_data["aggregate_address"],
+ )
+ return command
+
+
+def _tmplt_bgp_af_redistribute(config_data):
+ afi = config_data["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp address-family ".format(**config_data)
+ config_data = config_data["address_family"]["redistribute"]
+ command += afi + " redistribute {protocol}".format(**config_data)
+ if config_data.get("metric"):
+ command += " metric {metric}".format(**config_data)
+ elif config_data.get("route_map"):
+ command += " route-map {route_map}".format(**config_data)
+ elif config_data.get("table"):
+ command += " table {table}".format(**config_data)
+ return command
+
+
+def _tmplt_bgp_af_redistribute_delete(config_data):
+ afi = config_data["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp address-family ".format(**config_data)
+ config_data = config_data["address_family"]["redistribute"]
+ command += afi + " redistribute {protocol}".format(**config_data)
+ if config_data.get("metric"):
+ command += " metric"
+ elif config_data.get("route_map"):
+ command += " route-map"
+ elif config_data.get("table"):
+ command += " table"
+ return command
+
+
+def _tmplt_bgp_af_neighbor_distribute_list(config_data):
+ command = []
+ afi = config_data["neighbors"]["address_family"]["afi"] + "-unicast"
+ cmd = "protocols bgp neighbor ".format(**config_data)
+ cmd += "{neighbor_address} address-family ".format(**config_data["neighbors"])
+ config_data = config_data["neighbors"]["address_family"]
+ for list_el in config_data["distribute_list"]:
+ command.append(
+ cmd + afi + " distribute-list " + list_el["action"] + " " + str(list_el["acl"]),
+ )
+ return command
+
+
+def _tmplt_bgp_af_neighbor_route_map(config_data):
+ command = []
+ afi = config_data["neighbors"]["address_family"]["afi"] + "-unicast"
+ cmd = "protocols bgp neighbor ".format(**config_data)
+ cmd += "{neighbor_address} address-family ".format(**config_data["neighbors"])
+ config_data = config_data["neighbors"]["address_family"]
+ for list_el in config_data["route_map"]:
+ command.append(
+ cmd + afi + " route-map " + list_el["action"] + " " + str(list_el["route_map"]),
+ )
+ return command
+
+
+def _tmplt_bgp_af_neighbor_prefix_list(config_data):
+ command = []
+ afi = config_data["neighbors"]["address_family"]["afi"] + "-unicast"
+ cmd = "protocols bgp neighbor ".format(**config_data)
+ cmd += "{neighbor_address} address-family ".format(**config_data["neighbors"])
+ config_data = config_data["neighbors"]["address_family"]
+ for list_el in config_data["prefix_list"]:
+ command.append(
+ cmd + afi + " prefix-list " + list_el["action"] + " " + str(list_el["prefix_list"]),
+ )
+ return command
+
+
+def _tmplt_bgp_af_neighbor_filter_list(config_data):
+ command = []
+ afi = config_data["neighbors"]["address_family"]["afi"] + "-unicast"
+ cmd = "protocols bgp neighbor ".format(**config_data)
+ cmd += "{neighbor_address} address-family ".format(**config_data["neighbors"])
+ config_data = config_data["neighbors"]["address_family"]
+ for list_el in config_data["filter_list"]:
+ command.append(
+ cmd + afi + " filter-list " + list_el["action"] + " " + str(list_el["path_list"]),
+ )
+ return command
+
+
+def _tmplt_bgp_af_neighbor_attribute(config_data):
+ command = []
+ afi = config_data["neighbors"]["address_family"]["afi"] + "-unicast"
+ cmd = "protocols bgp neighbor ".format(**config_data)
+ cmd += "{neighbor_address} address-family ".format(**config_data["neighbors"])
+ config_data = config_data["neighbors"]["address_family"]
+ for k in config_data["attribute_unchanged"].keys():
+ if config_data["attribute_unchanged"][k]:
+ k = re.sub("_", "-", k)
+ c = cmd + afi + " attribute-unchanged " + k
+ command.append(c)
+ return command
+
+
+def _tmplt_bgp_af_neighbor_delete(config_data):
+ afi = config_data["neighbors"]["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp ".format(**config_data)
+ command += (
+ "neighbor {neighbor_address} address-family ".format(**config_data["neighbors"]) + afi
+ )
+ config_data = config_data["neighbors"]["address_family"]
+ if config_data.get("allowas_in"):
+ command += " allowas-in"
+ elif config_data.get("as_override"):
+ command += " as-override"
+ elif config_data.get("attribute_unchanged"):
+ command += " attribute-unchanged"
+ elif config_data.get("capability"):
+ command += " capability"
+ elif config_data.get("default_originate"):
+ command += " default-originate"
+ elif config_data.get("maximum_prefix"):
+ command += " maximum-prefix"
+ elif config_data.get("nexthop_local"):
+ command += " nexthop-local"
+ elif config_data.get("nexthop_self"):
+ command += " nexthop-self"
+ elif config_data.get("peer_group"):
+ command += " peer-group"
+ elif config_data.get("remote_private_as"):
+ command += " remote-private-as"
+ elif config_data.get("route_reflector_client"):
+ command += " route-reflector-client"
+ elif config_data.get("route_server_client"):
+ command += " route-server-client"
+ elif config_data.get("soft_reconfiguration"):
+ command += " soft-reconfiguration"
+ elif config_data.get("unsuppress_map"):
+ command += " unsuppress-map"
+ elif config_data.get("weight"):
+ command += " weight"
+ elif config_data.get("filter_list"):
+ command += " filter-list"
+ elif config_data.get("prefix_list"):
+ command += " prefix-list"
+ elif config_data.get("distribute_list"):
+ command += " distribute-list"
+ elif config_data.get("route_map"):
+ command += " route-map"
+ return command
+
+
+def _tmplt_bgp_af_neighbor(config_data):
+ afi = config_data["neighbors"]["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp ".format(**config_data)
+ command += (
+ "neighbor {neighbor_address} address-family ".format(**config_data["neighbors"]) + afi
+ )
+ config_data = config_data["neighbors"]["address_family"]
+ if config_data.get("allowas_in"):
+ command += " allowas-in number {allowas_in}".format(**config_data)
+ elif config_data.get("as_override"):
+ command += " as-override"
+ elif config_data.get("capability"):
+ command += " capability "
+ if config_data["capability"].get("dynamic"):
+ command += "dynamic"
+ elif config_data["capability"].get("orf"):
+ command += " prefix-list {orf}".format(**config_data["capability"])
+ elif config_data.get("default_originate"):
+ command += " default-originate route-map {default_originate}".format(**config_data)
+ elif config_data.get("maximum_prefix"):
+ command += " maximum-prefix {maximum_prefix}".format(**config_data)
+ elif config_data.get("nexthop_local"):
+ command += " nexthop-local"
+ elif config_data.get("nexthop_self"):
+ command += " nexthop-self"
+ elif config_data.get("peer_group"):
+ command += " peer-group {peer_group}".format(**config_data)
+ elif config_data.get("remote_private_as"):
+ command += " remote-private-as"
+ elif config_data.get("route_reflector_client"):
+ command += " route-reflector-client"
+ elif config_data.get("route_server_client"):
+ command += " route-server-client"
+ elif config_data.get("soft_reconfiguration"):
+ command += " soft-reconfiguration inbound"
+ elif config_data.get("unsuppress_map"):
+ command += " unsuppress-map {unsuppress_map}".format(**config_data)
+ elif config_data.get("weight"):
+ command += " weight {weight}".format(**config_data)
+ return command
+
+
+def _tmplt_bgp_af_network(config_data):
+ afi = config_data["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp address-family ".format(**config_data)
+ config_data = config_data["address_family"]["networks"]
+ command += afi + " network {prefix}".format(**config_data)
+ if config_data.get("backdoor"):
+ command += " backdoor"
+ elif config_data.get("route_map"):
+ command += " route-map {route_map}".format(**config_data)
+ return command
+
+
+def _tmplt_bgp_af_network_delete(config_data):
+ afi = config_data["address_family"]["afi"] + "-unicast"
+ command = "protocols bgp address-family ".format(**config_data)
+ config_data = config_data["address_family"]["networks"]
+ command += afi + " network {prefix}".format(**config_data)
+ if config_data.get("backdoor"):
+ command += " backdoor"
+ elif config_data.get("route_map"):
+ command += " route_map"
+ return command
+
+
+class Bgp_address_familyTemplate14(NetworkTemplate):
+ def __init__(self, lines=None, module=None):
+ prefix = {"set": "set", "remove": "delete"}
+ super(Bgp_address_familyTemplate14, self).__init__(
+ lines=lines,
+ tmplt=self,
+ prefix=prefix,
+ module=module,
+ )
+
+ # fmt: off
+ PARSERS = [
+ {
+ "name": "system_as",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+system-as
+ \s+(?P\d+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": "protocols bgp system-as {{ as_number }}",
+ "compval": "as_number",
+ "result": {
+ "as_number": "{{ as_num }}",
+ },
+ },
+ {
+ "name": "address_family",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+address-family
+ \s+(?P\S+)-unicast
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": "protocols bgp address-family {{ address_family.afi }}-unicast",
+ "compval": "as_number",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "aggregate_address",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+address-family
+ \s+(?P\S+)-unicast
+ \s+aggregate-address
+ \s+(?P\S+)
+ \s*(?Pas-set)*
+ \s*(?Psummary-only)*
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_aggregate_address,
+ "remval": "protocols bgp address-family {{ address_family.afi }}-unicast aggregate-address" +
+ " {{ address_family.aggregate_address.prefix }}",
+ "compval": "address_family.aggregate_address",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "aggregate_address": [
+ {
+ "prefix": "{{ address }}",
+ "as_set": "{{ True if as_set is defined }}",
+ "summary_only": "{{ True if summary_only is defined }}",
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ "name": "network",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+address-family
+ \s+(?P\S+)-unicast
+ \s+network
+ \s+(?P\S+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_network,
+ "remval": "protocols bgp address-family {{ address_family.afi }}-unicast network {{ address_family.networks.prefix }}",
+ "compval": "address_family.networks.prefix",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "networks": [
+ {
+ "prefix": "{{ address }}",
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ "name": "network.backdoor",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+address-family
+ \s+(?P\S+)-unicast
+ \s+network
+ \s+(?P\S+)
+ \s+backdoor
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_network,
+ "remval": _tmplt_bgp_af_network_delete,
+ "compval": "address_family.networks.backdoor",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "networks": [
+ {
+ "prefix": "{{ address }}",
+ "backdoor": "{{ True }}",
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ "name": "network.path_limit",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+address-family
+ \s+(?P\S+)-unicast
+ \s+network
+ \s+(?P\S+)
+ \s+path-limit
+ \s+(?P\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_bgp_af_network,
+ "remval": _tmplt_bgp_af_network_delete,
+ "compval": "address_family.networks.path_limit",
+ "result": {
+ "as_number": "{{ as_num }}",
+ "address_family": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "networks": [
+ {
+ "prefix": "{{ address }}",
+ "path_limit": "{{ limit|int }}",
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ "name": "network.route_map",
+ "getval": re.compile(
+ r"""
+ ^set
+ \s+protocols
+ \s+bgp
+ \s+address-family
+ \s+(?P\S+)-unicast
+ \s+network
+ \s+(?P\S+)
+ \s+route-map
+ \s+(?P