summaryrefslogtreecommitdiffstats
path: root/ansible_collections/cisco/iosxr/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'ansible_collections/cisco/iosxr/plugins')
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/acl_interfaces.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/acls.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/banner.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/bgp.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/bgp_address_family.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/bgp_global.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/bgp_neighbor_address_family.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/command.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/config.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/facts.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/hostname.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/interface.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/interfaces.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/iosxr.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/l2_interfaces.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/l3_interfaces.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/lacp.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/lacp_interfaces.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/lag_interfaces.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/lldp_global.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/lldp_interfaces.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/logging.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/logging_global.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/netconf.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/ntp_global.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/ospf_interfaces.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/ospfv2.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/ospfv3.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/prefix_lists.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/snmp_server.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/static_routes.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/system.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/action/user.py59
-rw-r--r--ansible_collections/cisco/iosxr/plugins/cliconf/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/cliconf/iosxr.py555
-rw-r--r--ansible_collections/cisco/iosxr/plugins/doc_fragments/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/doc_fragments/iosxr.py20
-rw-r--r--ansible_collections/cisco/iosxr/plugins/filter/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/inventory/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acl_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acl_interfaces/acl_interfaces.py85
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acls/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acls/acls.py560
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_address_family/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_address_family/bgp_address_family.py398
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_global/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_global/bgp_global.py1249
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_neighbor_address_family/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_neighbor_address_family/bgp_neighbor_address_family.py438
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/facts/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/facts/facts.py26
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/hostname/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/hostname/hostname.py50
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/interfaces/interfaces.py65
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/l2_interfaces.py97
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l3_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l3_interfaces/l3_interfaces.py73
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/lacp.py69
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp_interfaces/lacp_interfaces.py77
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lag_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lag_interfaces/lag_interfaces.py88
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/lldp_global.py73
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_interfaces/lldp_interfaces.py77
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/logging_global/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/logging_global/logging_global.py429
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ntp_global/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ntp_global/ntp_global.py231
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospf_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospf_interfaces/ospf_interfaces.py437
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv2/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv2/ospfv2.py825
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv3/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv3/ospfv3.py1439
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ping/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ping/ping.py49
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/prefix_lists/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/prefix_lists/prefix_lists.py79
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/snmp_server/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/snmp_server/snmp_server.py574
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/static_routes/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/static_routes/static_routes.py103
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acl_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acl_interfaces/acl_interfaces.py123
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/acls.py529
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_address_family/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_address_family/bgp_address_family.py243
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_global/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_global/bgp_global.py427
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_neighbor_address_family/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_neighbor_address_family/bgp_neighbor_address_family.py245
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/hostname/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/hostname/hostname.py75
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/interfaces.py311
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/l2_interfaces.py410
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/l3_interfaces.py382
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/lacp.py210
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp_interfaces/lacp_interfaces.py309
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lag_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lag_interfaces/lag_interfaces.py446
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/lldp_global.py223
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_interfaces/lldp_interfaces.py277
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/logging_global/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/logging_global/logging_global.py227
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ntp_global/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ntp_global/ntp_global.py188
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospf_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospf_interfaces/ospf_interfaces.py236
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv2/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv2/ospfv2.py254
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py247
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ping/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ping/ping.py99
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/prefix_lists/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/prefix_lists/prefix_lists.py141
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/snmp_server/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/snmp_server/snmp_server.py397
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/static_routes.py560
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acl_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acl_interfaces/acl_interfaces.py81
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acls/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acls/acls.py471
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_address_family/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_address_family/bgp_address_family.py99
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_global/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_global/bgp_global.py150
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_neighbor_address_family/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_neighbor_address_family/bgp_neighbor_address_family.py111
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/facts.py164
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/hostname/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/hostname/hostname.py75
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/interfaces.py115
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/l2_interfaces.py159
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/l3_interfaces.py131
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp/lacp.py90
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp_interfaces/lacp_interfaces.py120
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lag_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lag_interfaces/lag_interfaces.py151
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/base.py265
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_global/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_global/lldp_global.py106
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_interfaces/lldp_interfaces.py111
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/logging_global/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/logging_global/logging_global.py102
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ntp_global/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ntp_global/ntp_global.py110
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospf_interfaces/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospf_interfaces/ospf_interfaces.py143
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/ospfv2.py165
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/ospfv3.py159
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/prefix_lists/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/prefix_lists/prefix_lists.py78
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/snmp_server/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/snmp_server/snmp_server.py104
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/static_routes/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/static_routes/static_routes.py196
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/iosxr.py588
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/address_family.py133
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/neighbors.py136
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/process.py121
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/module.py71
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/providers.py127
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/acl_interfaces.py64
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_address_family.py1182
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_global.py3133
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_neighbor_address_family.py1038
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/hostname.py48
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/logging_global.py866
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ntp_global.py680
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospf_interfaces.py1416
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv2.py2856
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv3.py2779
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ping.py68
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/prefix_lists.py127
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/snmp_server.py3223
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/utils.py456
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_acl_interfaces.py653
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_acls.py1467
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_banner.py285
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp.py365
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp_address_family.py945
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp_global.py1328
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp_neighbor_address_family.py1197
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_command.py217
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_config.py489
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_facts.py217
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_hostname.py318
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_interfaces.py559
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_l2_interfaces.py706
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_l3_interfaces.py672
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_lacp.py391
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_lacp_interfaces.py653
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_lag_interfaces.py854
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_lldp_global.py490
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_lldp_interfaces.py725
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_logging.py1270
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_logging_global.py1407
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_netconf.py206
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_ntp_global.py1096
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospf_interfaces.py1211
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospfv2.py2545
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospfv3.py2784
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_ping.py176
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_prefix_lists.py1115
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_snmp_server.py2328
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_static_routes.py856
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_system.py748
-rw-r--r--ansible_collections/cisco/iosxr/plugins/modules/iosxr_user.py905
-rw-r--r--ansible_collections/cisco/iosxr/plugins/netconf/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/netconf/iosxr.py378
-rw-r--r--ansible_collections/cisco/iosxr/plugins/sub_plugins/grpc/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/sub_plugins/grpc/iosxr.py200
-rw-r--r--ansible_collections/cisco/iosxr/plugins/sub_plugins/grpc/pb/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py2350
-rw-r--r--ansible_collections/cisco/iosxr/plugins/terminal/__init__.py0
-rw-r--r--ansible_collections/cisco/iosxr/plugins/terminal/iosxr.py61
254 files changed, 71407 insertions, 0 deletions
diff --git a/ansible_collections/cisco/iosxr/plugins/action/__init__.py b/ansible_collections/cisco/iosxr/plugins/action/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/action/acl_interfaces.py b/ansible_collections/cisco/iosxr/plugins/action/acl_interfaces.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/acl_interfaces.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/acls.py b/ansible_collections/cisco/iosxr/plugins/action/acls.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/acls.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/banner.py b/ansible_collections/cisco/iosxr/plugins/action/banner.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/banner.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/bgp.py b/ansible_collections/cisco/iosxr/plugins/action/bgp.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/bgp.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/bgp_address_family.py b/ansible_collections/cisco/iosxr/plugins/action/bgp_address_family.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/bgp_address_family.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/bgp_global.py b/ansible_collections/cisco/iosxr/plugins/action/bgp_global.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/bgp_global.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/bgp_neighbor_address_family.py b/ansible_collections/cisco/iosxr/plugins/action/bgp_neighbor_address_family.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/bgp_neighbor_address_family.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/command.py b/ansible_collections/cisco/iosxr/plugins/action/command.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/command.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/config.py b/ansible_collections/cisco/iosxr/plugins/action/config.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/config.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/facts.py b/ansible_collections/cisco/iosxr/plugins/action/facts.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/facts.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/hostname.py b/ansible_collections/cisco/iosxr/plugins/action/hostname.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/hostname.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/interface.py b/ansible_collections/cisco/iosxr/plugins/action/interface.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/interface.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/interfaces.py b/ansible_collections/cisco/iosxr/plugins/action/interfaces.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/interfaces.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/iosxr.py b/ansible_collections/cisco/iosxr/plugins/action/iosxr.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/iosxr.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/l2_interfaces.py b/ansible_collections/cisco/iosxr/plugins/action/l2_interfaces.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/l2_interfaces.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/l3_interfaces.py b/ansible_collections/cisco/iosxr/plugins/action/l3_interfaces.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/l3_interfaces.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/lacp.py b/ansible_collections/cisco/iosxr/plugins/action/lacp.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/lacp.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/lacp_interfaces.py b/ansible_collections/cisco/iosxr/plugins/action/lacp_interfaces.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/lacp_interfaces.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/lag_interfaces.py b/ansible_collections/cisco/iosxr/plugins/action/lag_interfaces.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/lag_interfaces.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/lldp_global.py b/ansible_collections/cisco/iosxr/plugins/action/lldp_global.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/lldp_global.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/lldp_interfaces.py b/ansible_collections/cisco/iosxr/plugins/action/lldp_interfaces.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/lldp_interfaces.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/logging.py b/ansible_collections/cisco/iosxr/plugins/action/logging.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/logging.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/logging_global.py b/ansible_collections/cisco/iosxr/plugins/action/logging_global.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/logging_global.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/netconf.py b/ansible_collections/cisco/iosxr/plugins/action/netconf.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/netconf.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/ntp_global.py b/ansible_collections/cisco/iosxr/plugins/action/ntp_global.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/ntp_global.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/ospf_interfaces.py b/ansible_collections/cisco/iosxr/plugins/action/ospf_interfaces.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/ospf_interfaces.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/ospfv2.py b/ansible_collections/cisco/iosxr/plugins/action/ospfv2.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/ospfv2.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/ospfv3.py b/ansible_collections/cisco/iosxr/plugins/action/ospfv3.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/ospfv3.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/prefix_lists.py b/ansible_collections/cisco/iosxr/plugins/action/prefix_lists.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/prefix_lists.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/snmp_server.py b/ansible_collections/cisco/iosxr/plugins/action/snmp_server.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/snmp_server.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/static_routes.py b/ansible_collections/cisco/iosxr/plugins/action/static_routes.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/static_routes.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/system.py b/ansible_collections/cisco/iosxr/plugins/action/system.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/system.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/action/user.py b/ansible_collections/cisco/iosxr/plugins/action/user.py
new file mode 100644
index 00000000..d1ba1e15
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/action/user.py
@@ -0,0 +1,59 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.utils.display import Display
+from ansible_collections.ansible.netcommon.plugins.action.network import (
+ ActionModule as ActionNetworkModule,
+)
+
+
+display = Display()
+
+
+class ActionModule(ActionNetworkModule):
+ def run(self, tmp=None, task_vars=None):
+ del tmp # tmp no longer has any effect
+
+ module_name = self._task.action.split(".")[-1]
+ self._config_module = True if module_name in ["iosxr_config", "config"] else False
+ force_cli = module_name in ("iosxr_netconf", "iosxr_config", "iosxr_command", "iosxr_facts")
+ persistent_connection = self._play_context.connection.split(".")[-1]
+ warnings = []
+
+ if (not force_cli and persistent_connection not in ("netconf", "network_cli")) or (
+ force_cli and persistent_connection != "network_cli"
+ ):
+ return {
+ "failed": True,
+ "msg": "Connection type %s is not valid for this module"
+ % self._play_context.connection,
+ }
+
+ result = super(ActionModule, self).run(task_vars=task_vars)
+ if warnings:
+ if "warnings" in result:
+ result["warnings"].extend(warnings)
+ else:
+ result["warnings"] = warnings
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/cliconf/__init__.py b/ansible_collections/cisco/iosxr/plugins/cliconf/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/cliconf/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/cliconf/iosxr.py b/ansible_collections/cisco/iosxr/plugins/cliconf/iosxr.py
new file mode 100644
index 00000000..706bff6e
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/cliconf/iosxr.py
@@ -0,0 +1,555 @@
+#
+# (c) 2017 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+author: Ansible Networking Team (@ansible-network)
+name: iosxr
+short_description: Use iosxr cliconf to run command on Cisco IOS XR platform
+description:
+- This iosxr plugin provides low level abstraction apis for sending and receiving
+ CLI commands from Cisco IOS XR network devices.
+version_added: 1.0.0
+notes:
+- IOSXR commit confirmed command varies with IOSXR version releases,
+ commit_comment and commit_label may or may not
+ be valid together as per the device version.
+options:
+ commit_confirmed:
+ type: boolean
+ default: false
+ description:
+ - enable or disable commit confirmed mode
+ env:
+ - name: ANSIBLE_IOSXR_COMMIT_CONFIRMED
+ vars:
+ - name: ansible_iosxr_commit_confirmed
+ commit_confirmed_timeout:
+ type: int
+ description:
+ - Commits the configuration on a trial basis for the time specified in seconds or minutes.
+ env:
+ - name: ANSIBLE_IOSXR_COMMIT_CONFIRMED_TIMEOUT
+ vars:
+ - name: ansible_iosxr_commit_confirmed_timeout
+ commit_label:
+ type: str
+ description:
+ - Adds label to commit confirmed.
+ env:
+ - name: ANSIBLE_IOSXR_COMMIT_LABEL
+ vars:
+ - name: ansible_iosxr_commit_label
+ commit_comment:
+ type: str
+ description:
+ - Adds comment to commit confirmed..
+ env:
+ - name: ANSIBLE_IOSXR_COMMIT_COMMENT
+ vars:
+ - name: ansible_iosxr_commit_comment
+ config_commands:
+ description:
+ - Specifies a list of commands that can make configuration changes
+ to the target device.
+ - When `ansible_network_single_user_mode` is enabled, if a command sent
+ to the device is present in this list, the existing cache is invalidated.
+ version_added: 2.0.0
+ type: list
+ elements: str
+ default: []
+ vars:
+ - name: ansible_iosxr_config_commands
+ config_mode_exclusive:
+ type: boolean
+ default: false
+ description:
+ - enable or disable config mode exclusive
+ env:
+ - name: ANSIBLE_IOSXR_CONFIG_MODE_EXCLUSIVE
+ vars:
+ - name: ansible_iosxr_config_mode_exclusive
+"""
+
+EXAMPLES = """
+# Use commit confirmed within a task with timeout, label and comment
+
+- name: Commit confirmed with a task
+ vars:
+ ansible_iosxr_commit_confirmed: True
+ ansible_iosxr_commit_confirmed_timeout: 50
+ ansible_iosxr_commit_label: TestLabel
+ ansible_iosxr_commit_comment: I am a test comment
+ cisco.iosxr.iosxr_logging_global:
+ state: merged
+ config:
+ buffered:
+ severity: errors #alerts #informational
+ correlator:
+ buffer_size: 2024
+
+# Commands (cliconf specific)
+# ["commit confirmed 50 label TestLabel comment I am a test comment"]
+
+# Use commit within a task with label
+
+- name: Commit label with a task
+ vars:
+ ansible_iosxr_commit_label: lblTest
+ cisco.iosxr.iosxr_hostname:
+ state: merged
+ config:
+ hostname: R1
+
+# Commands (cliconf specific)
+# ["commit label lblt1"]
+
+# Use commit confirm with timeout and confirm the commit
+
+# NOTE - IOSXR waits for a `commit` when the command
+# executed is `commit confirmed <timeout>` within the timeout
+# period for the config to commit successfully, else a rollback
+# happens.
+
+- name: Example commit confirmed
+ vars:
+ ansible_iosxr_commit_confirmed: True
+ ansible_iosxr_commit_confirmed_timeout: 60
+ tasks:
+ - name: "Commit confirmed with timeout"
+ cisco.iosxr.iosxr_hostname:
+ state: merged
+ config:
+ hostname: R1
+
+ - name: "Confirm the Commit"
+ cisco.iosxr.iosxr_command:
+ commands:
+ - commit
+
+# Commands (cliconf specific)
+# ["commit confirmed 60"]
+
+# Use exclusive mode with a task
+
+- name: Configure exclusive mode with a task
+ vars:
+ ansible_iosxr_config_mode_exclusive: True
+ cisco.iosxr.iosxr_interfaces:
+ state: merged
+ config:
+ - name: GigabitEthernet0/0/0/2
+ description: Configured via Ansible
+ - name: GigabitEthernet0/0/0/3
+ description: Configured via Ansible
+
+# Commands (cliconf specific)
+# ["configure exclusive"]
+
+# Use Replace option with commit confirmed
+
+# NOTE - IOSXR waits for a `commit` when the command
+# executed is `commit replace confirmed <timeout>` within the timeout
+# period for the config to commit successfully, else a rollback
+# happens.
+# This option is supported by only iosxr_config module
+
+- name: Example replace config with commit confirmed
+ vars:
+ ansible_iosxr_commit_confirmed: True
+ ansible_iosxr_commit_confirmed_timeout: 60
+ tasks:
+ - name: "Replace config with Commit confirmed"
+ cisco.iosxr.iosxr_config:
+ src: 'replace_running_cfg_iosxr.txt'
+ replace: config
+
+ - name: "Confirm the Commit"
+ cisco.iosxr.iosxr_command:
+ commands:
+ - commit
+"""
+
+import json
+import re
+
+from ansible.errors import AnsibleConnectionFailure
+from ansible.module_utils._text import to_text
+from ansible.module_utils.common._collections_compat import Mapping
+from ansible.module_utils.connection import ConnectionError
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import (
+ NetworkConfig,
+ dumps,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
+from ansible_collections.ansible.netcommon.plugins.plugin_utils.cliconf_base import CliconfBase
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ mask_config_blocks_from_diff,
+ sanitize_config,
+)
+
+
+class Cliconf(CliconfBase):
+ def __init__(self, *args, **kwargs):
+ self._device_info = {}
+ super(Cliconf, self).__init__(*args, **kwargs)
+
+ def get_command_output(self, command):
+ reply = self.get(command)
+ data = to_text(reply, errors="surrogate_or_strict").strip()
+ return data
+
+ def get_device_info(self):
+ if not self._device_info:
+ device_info = dict()
+ device_info["network_os"] = "iosxr"
+ data = self.get_command_output("show version | utility head -n 20")
+ match = re.search(r"Version (\S+)$", data, re.M)
+ if match:
+ device_info["network_os_version"] = match.group(1)
+ else:
+ match = re.search(r"Version (\S+ \S+)$", data, re.M)
+ if match:
+ device_info["network_os_version"] = match.group(1)
+
+ match = re.search(r'image file is "(.+)"', data)
+ if match:
+ device_info["network_os_image"] = match.group(1)
+
+ model_search_strs = [
+ r"^[Cc]isco (.+) \(\) processor",
+ r"^[Cc]isco ([A-Z0-9\-]+) processor",
+ r"^[Cc]isco (.+) \(revision",
+ r"^[Cc]isco (\S+ \S+).+bytes of .*memory",
+ ]
+ for item in model_search_strs:
+ match = re.search(item, data, re.M)
+ if match:
+ device_info["network_os_model"] = match.group(1)
+ break
+
+ hostname = self.get_command_output("show running-config hostname")
+ match = re.search(r"hostname\s(\S+)$", hostname, re.M)
+ if match:
+ device_info["network_os_hostname"] = match.group(1)
+
+ self._device_info = device_info
+
+ return self._device_info
+
+ def configure(self, admin=False, exclusive=False):
+ prompt = to_text(self._connection.get_prompt(), errors="surrogate_or_strict").strip()
+ if not prompt.endswith(")#"):
+ if admin and "admin-" not in prompt:
+ self.send_command("admin")
+ if exclusive or self.get_option("config_mode_exclusive"):
+ self.send_command("configure exclusive")
+ return
+ self.send_command("configure terminal")
+
+ def abort(self, admin=False):
+ prompt = to_text(self._connection.get_prompt(), errors="surrogate_or_strict").strip()
+ if prompt.endswith(")#"):
+ self.send_command("abort")
+ if admin and "admin-" in prompt:
+ self.send_command("exit")
+
+ def get_config(self, source="running", format="text", flags=None):
+ if source not in ["running"]:
+ raise ValueError("fetching configuration from %s is not supported" % source)
+
+ lookup = {"running": "running-config"}
+
+ cmd = "show {0} ".format(lookup[source])
+ cmd += " ".join(to_list(flags))
+ cmd = cmd.strip()
+
+ return self.send_command(cmd)
+
+ def edit_config(
+ self,
+ candidate=None,
+ commit=True,
+ admin=False,
+ exclusive=False,
+ replace=None,
+ comment=None,
+ label=None,
+ ):
+ operations = self.get_device_operations()
+ self.check_edit_config_capability(operations, candidate, commit, replace, comment)
+
+ resp = {}
+ results = []
+ requests = []
+
+ self.configure(admin=admin, exclusive=exclusive)
+
+ if replace:
+ candidate = "load {0}".format(replace)
+
+ for line in to_list(candidate):
+ if not isinstance(line, Mapping):
+ line = {"command": line}
+ cmd = line["command"]
+ results.append(self.send_command(**line))
+ requests.append(cmd)
+
+ # Before any commit happened, we can get a real configuration
+ # diff from the device and make it available by the iosxr_config module.
+ # This information can be useful either in check mode or normal mode.
+ resp["show_commit_config_diff"] = self.get("show commit changes diff")
+
+ if commit:
+ try:
+ self.commit(comment=comment, label=label, replace=replace)
+ except AnsibleConnectionFailure as exc:
+ error_msg = to_text(exc, errors="surrogate_or_strict").strip()
+ if "Invalid input detected" in error_msg and "comment" in error_msg:
+ msg = (
+ "value of comment option '%s' is ignored as it in not supported by IOSXR"
+ % comment
+ )
+ self._connection.queue_message("warning", msg)
+ comment = None
+ self.commit(comment=comment, label=label, replace=replace)
+ else:
+ raise ConnectionError(error_msg)
+
+ else:
+ self.discard_changes()
+
+ if not self.get_option("commit_confirmed"):
+ self.abort(admin=admin)
+
+ resp["request"] = requests
+ resp["response"] = results
+ return resp
+
+ def get_diff(
+ self,
+ candidate=None,
+ running=None,
+ diff_match="line",
+ diff_ignore_lines=None,
+ path=None,
+ diff_replace="line",
+ ):
+ diff = {}
+ device_operations = self.get_device_operations()
+ option_values = self.get_option_values()
+
+ if candidate is None and device_operations["supports_generate_diff"]:
+ raise ValueError("candidate configuration is required to generate diff")
+
+ if diff_match not in option_values["diff_match"]:
+ raise ValueError(
+ "'match' value %s in invalid, valid values are %s"
+ % (diff_match, ", ".join(option_values["diff_match"])),
+ )
+
+ if diff_replace not in option_values["diff_replace"]:
+ raise ValueError(
+ "'replace' value %s in invalid, valid values are %s"
+ % (diff_replace, ", ".join(option_values["diff_replace"])),
+ )
+
+ # prepare candidate configuration
+ sanitized_candidate = sanitize_config(candidate)
+ candidate_obj = NetworkConfig(indent=1, comment_tokens=["!"])
+ candidate_obj.load(sanitized_candidate)
+
+ if running and diff_match != "none":
+ # running configuration
+ running = mask_config_blocks_from_diff(running, candidate, "ansible")
+ running = sanitize_config(running)
+
+ running_obj = NetworkConfig(
+ indent=1,
+ contents=running,
+ ignore_lines=diff_ignore_lines,
+ comment_tokens=["!"],
+ )
+ configdiffobjs = candidate_obj.difference(
+ running_obj,
+ path=path,
+ match=diff_match,
+ replace=diff_replace,
+ )
+
+ else:
+ configdiffobjs = candidate_obj.items
+
+ diff["config_diff"] = dumps(configdiffobjs, "commands") if configdiffobjs else ""
+ return diff
+
+ def get(
+ self,
+ command=None,
+ prompt=None,
+ answer=None,
+ sendonly=False,
+ newline=True,
+ output=None,
+ check_all=False,
+ ):
+ if output:
+ raise ValueError("'output' value %s is not supported for get" % output)
+ return self.send_command(
+ command=command,
+ prompt=prompt,
+ answer=answer,
+ sendonly=sendonly,
+ newline=newline,
+ check_all=check_all,
+ )
+
+ def commit(self, comment=None, label=None, replace=None):
+ """Implements commit functionality of config module
+ and commit confirmed functionality of cliconf module
+
+ Args:
+ comment (str, optional): commit comment. Defaults to None.
+ label (str, optional): commit label. Defaults to None.
+ replace (bool, optional): Flag to replace commit. Defaults to None.
+ """
+
+ cmd_obj = {}
+ if replace:
+ cmd_obj["command"] = "commit replace"
+ if self.get_option("commit_confirmed"):
+ cmd_obj["command"] = "commit replace confirmed"
+ if self.get_option("commit_confirmed_timeout"):
+ cmd_obj["command"] += " {0}".format(self.get_option("commit_confirmed_timeout"))
+
+ cmd_obj[
+ "prompt"
+ ] = "This commit will replace or remove the entire running configuration"
+ cmd_obj["answer"] = "yes"
+
+ elif self.get_option("commit_confirmed"):
+ cmd_obj["command"] = "commit confirmed"
+ if self.get_option("commit_confirmed_timeout"):
+ cmd_obj["command"] += " {0}".format(self.get_option("commit_confirmed_timeout"))
+ if self.get_option("commit_label"):
+ cmd_obj["command"] += " label {0}".format(self.get_option("commit_label"))
+ if self.get_option("commit_comment"):
+ cmd_obj["command"] += " comment {0}".format(self.get_option("commit_comment"))
+
+ else:
+ label = label or self.get_option("commit_label")
+ comment = comment or self.get_option("commit_comment")
+
+ if comment or label:
+ cmd_obj["command"] = "commit"
+ if label:
+ cmd_obj["command"] += " label {0}".format(label)
+ if comment:
+ cmd_obj["command"] += " comment {0}".format(comment)
+
+ else:
+ cmd_obj["command"] = "commit show-error"
+ # In some cases even a normal commit, i.e., !replace,
+ # throws a prompt and we need to handle it before
+ # proceeding further
+ cmd_obj["prompt"] = "(C|c)onfirm"
+ cmd_obj["answer"] = "y"
+ self.send_command(**cmd_obj)
+
+ def run_commands(self, commands=None, check_rc=True):
+ if commands is None:
+ raise ValueError("'commands' value is required")
+ responses = list()
+ for cmd in to_list(commands):
+ if not isinstance(cmd, Mapping):
+ cmd = {"command": cmd}
+
+ output = cmd.pop("output", None)
+ if output:
+ raise ValueError("'output' value %s is not supported for run_commands" % output)
+
+ try:
+ out = self.send_command(**cmd)
+ except AnsibleConnectionFailure as e:
+ if check_rc:
+ raise
+ out = getattr(e, "err", e)
+
+ if out is not None:
+ try:
+ out = to_text(out, errors="surrogate_or_strict").strip()
+ except UnicodeError:
+ raise ConnectionError(
+ message="Failed to decode output from %s: %s" % (cmd, to_text(out)),
+ )
+
+ try:
+ out = json.loads(out)
+ except ValueError:
+ pass
+
+ responses.append(out)
+ return responses
+
+ def discard_changes(self):
+ self.send_command("abort")
+
+ def get_device_operations(self):
+ return {
+ "supports_diff_replace": True,
+ "supports_commit": True,
+ "supports_rollback": False,
+ "supports_defaults": False,
+ "supports_onbox_diff": False,
+ "supports_commit_comment": True,
+ "supports_multiline_delimiter": False,
+ "supports_diff_match": True,
+ "supports_diff_ignore_lines": True,
+ "supports_generate_diff": True,
+ "supports_replace": True,
+ "supports_admin": True,
+ "supports_commit_label": True,
+ }
+
+ def get_option_values(self):
+ return {
+ "format": ["text"],
+ "diff_match": ["line", "strict", "exact", "none"],
+ "diff_replace": ["line", "block", "config"],
+ "output": [],
+ }
+
+ def get_capabilities(self):
+ result = super(Cliconf, self).get_capabilities()
+ result["rpc"] += ["commit", "discard_changes", "get_diff", "configure", "exit"]
+ result["device_operations"] = self.get_device_operations()
+ result.update(self.get_option_values())
+ return json.dumps(result)
+
+ def set_cli_prompt_context(self):
+ """
+ Make sure we are in the operational cli mode
+ :return: None
+ """
+ if self._connection.connected and not self.get_option("commit_confirmed"):
+ self._update_cli_prompt_context(config_context=")#", exit_command="abort")
diff --git a/ansible_collections/cisco/iosxr/plugins/doc_fragments/__init__.py b/ansible_collections/cisco/iosxr/plugins/doc_fragments/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/doc_fragments/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/doc_fragments/iosxr.py b/ansible_collections/cisco/iosxr/plugins/doc_fragments/iosxr.py
new file mode 100644
index 00000000..5049db81
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/doc_fragments/iosxr.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+# Copyright: (c) 2015, Peter Sprygada <psprygada@ansible.com>
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+
+class ModuleDocFragment(object):
+
+ # Standard files documentation fragment
+ DOCUMENTATION = r"""options: {}
+notes:
+- For more information on using Ansible to manage network devices see the :ref:`Ansible
+ Network Guide <network_guide>`
+- For more information on using Ansible to manage Cisco devices see the `Cisco integration
+ page <https://www.ansible.com/integrations/networks/cisco>`_.
+"""
diff --git a/ansible_collections/cisco/iosxr/plugins/filter/__init__.py b/ansible_collections/cisco/iosxr/plugins/filter/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/filter/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/inventory/__init__.py b/ansible_collections/cisco/iosxr/plugins/inventory/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/inventory/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acl_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acl_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acl_interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acl_interfaces/acl_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acl_interfaces/acl_interfaces.py
new file mode 100644
index 00000000..58ff82be
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acl_interfaces/acl_interfaces.py
@@ -0,0 +1,85 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_acl_interfaces module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+class Acl_interfacesArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_acl_interfaces module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "running_config": {"type": "str"},
+ "config": {
+ "elements": "dict",
+ "options": {
+ "access_groups": {
+ "elements": "dict",
+ "options": {
+ "acls": {
+ "elements": "dict",
+ "options": {
+ "direction": {
+ "choices": ["in", "out"],
+ "type": "str",
+ "required": True,
+ },
+ "name": {"type": "str", "required": True},
+ },
+ "type": "list",
+ },
+ "afi": {
+ "choices": ["ipv4", "ipv6"],
+ "type": "str",
+ "required": True,
+ },
+ },
+ "type": "list",
+ },
+ "name": {"type": "str", "required": True},
+ },
+ "type": "list",
+ },
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "parsed",
+ "rendered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acls/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acls/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acls/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acls/acls.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acls/acls.py
new file mode 100644
index 00000000..e8cb5f9c
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/acls/acls.py
@@ -0,0 +1,560 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_acls module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+class AclsArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_acls module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "running_config": {"type": "str"},
+ "config": {
+ "elements": "dict",
+ "options": {
+ "acls": {
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "aces": {
+ "elements": "dict",
+ "mutually_exclusive": [
+ ["grant", "remark", "line"],
+ ],
+ "options": {
+ "destination": {
+ "mutually_exclusive": [
+ [
+ "address",
+ "any",
+ "host",
+ "prefix",
+ "net_group",
+ "port_group",
+ ],
+ [
+ "wildcard_bits",
+ "any",
+ "host",
+ "prefix",
+ "net_group",
+ "port_group",
+ ],
+ ],
+ "options": {
+ "host": {"type": "str"},
+ "net_group": {"type": "str"},
+ "port_group": {"type": "str"},
+ "address": {"type": "str"},
+ "any": {"type": "bool"},
+ "prefix": {"type": "str"},
+ "port_protocol": {
+ "mutually_exclusive": [
+ [
+ "eq",
+ "gt",
+ "lt",
+ "neq",
+ "range",
+ ],
+ ],
+ "options": {
+ "eq": {"type": "str"},
+ "gt": {"type": "str"},
+ "lt": {"type": "str"},
+ "neq": {"type": "str"},
+ "range": {
+ "options": {
+ "end": {"type": "str"},
+ "start": {
+ "type": "str",
+ },
+ },
+ "required_together": [
+ ["start", "end"],
+ ],
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "wildcard_bits": {"type": "str"},
+ },
+ "required_together": [
+ ["address", "wildcard_bits"],
+ ],
+ "type": "dict",
+ },
+ "dscp": {
+ "mutually_exclusive": [
+ ["eq", "gt", "lt", "neq", "range"],
+ ],
+ "type": "dict",
+ "options": {
+ "eq": {"type": "str"},
+ "gt": {"type": "str"},
+ "lt": {"type": "str"},
+ "neq": {"type": "str"},
+ "range": {
+ "options": {
+ "end": {"type": "str"},
+ "start": {"type": "str"},
+ },
+ "required_together": [
+ ["start", "end"],
+ ],
+ "type": "dict",
+ },
+ },
+ },
+ "fragments": {"type": "bool"},
+ "capture": {"type": "bool"},
+ "destopts": {"type": "bool"},
+ "authen": {"type": "bool"},
+ "routing": {"type": "bool"},
+ "hop_by_hop": {"type": "bool"},
+ "grant": {
+ "type": "str",
+ "choices": ["permit", "deny"],
+ },
+ "icmp_off": {"type": "bool"},
+ "log": {"type": "bool"},
+ "log_input": {"type": "bool"},
+ "line": {"type": "str", "aliases": ["ace"]},
+ "packet_length": {
+ "mutually_exclusive": [
+ ["eq", "lt", "neq", "range"],
+ ["eq", "gt", "neq", "range"],
+ ],
+ "options": {
+ "eq": {"type": "int"},
+ "gt": {"type": "int"},
+ "lt": {"type": "int"},
+ "neq": {"type": "int"},
+ "range": {
+ "options": {
+ "end": {"type": "int"},
+ "start": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "precedence": {"type": "str"},
+ "protocol": {"type": "str"},
+ "protocol_options": {
+ "mutually_exclusive": [
+ ["icmp", "tcp", "igmp", "icmpv6"],
+ ],
+ "options": {
+ "icmpv6": {
+ "type": "dict",
+ "options": {
+ "address_unreachable": {
+ "type": "bool",
+ },
+ "administratively_prohibited": {
+ "type": "bool",
+ },
+ "beyond_scope_of_source_address": {
+ "type": "bool",
+ },
+ "destination_unreachable": {
+ "type": "bool",
+ },
+ "echo": {"type": "bool"},
+ "echo_reply": {"type": "bool"},
+ "erroneous_header_field": {
+ "type": "bool",
+ },
+ "group_membership_query": {
+ "type": "bool",
+ },
+ "group_membership_report": {
+ "type": "bool",
+ },
+ "group_membership_termination": {
+ "type": "bool",
+ },
+ "host_unreachable": {
+ "type": "bool",
+ },
+ "nd_na": {"type": "bool"},
+ "nd_ns": {"type": "bool"},
+ "neighbor_redirect": {
+ "type": "bool",
+ },
+ "no_route_to_destination": {
+ "type": "bool",
+ },
+ "node_information_request_is_refused": {
+ "type": "bool",
+ },
+ "node_information_successful_reply": {
+ "type": "bool",
+ },
+ "packet_too_big": {
+ "type": "bool",
+ },
+ "parameter_problem": {
+ "type": "bool",
+ },
+ "port_unreachable": {
+ "type": "bool",
+ },
+ "query_subject_is_IPv4address": {
+ "type": "bool",
+ },
+ "query_subject_is_IPv6address": {
+ "type": "bool",
+ },
+ "query_subject_is_domainname": {
+ "type": "bool",
+ },
+ "reassembly_timeout": {
+ "type": "bool",
+ },
+ "redirect": {"type": "bool"},
+ "router_advertisement": {
+ "type": "bool",
+ },
+ "router_renumbering": {
+ "type": "bool",
+ },
+ "router_solicitation": {
+ "type": "bool",
+ },
+ "rr_command": {"type": "bool"},
+ "rr_result": {"type": "bool"},
+ "rr_seqnum_reset": {
+ "type": "bool",
+ },
+ "time_exceeded": {
+ "type": "bool",
+ },
+ "ttl_exceeded": {
+ "type": "bool",
+ },
+ "unknown_query_type": {
+ "type": "bool",
+ },
+ "unreachable": {
+ "type": "bool",
+ },
+ "unrecognized_next_header": {
+ "type": "bool",
+ },
+ "unrecognized_option": {
+ "type": "bool",
+ },
+ "whoareyou_reply": {
+ "type": "bool",
+ },
+ "whoareyou_request": {
+ "type": "bool",
+ },
+ },
+ },
+ "icmp": {
+ "options": {
+ "administratively_prohibited": {
+ "type": "bool",
+ },
+ "alternate_address": {
+ "type": "bool",
+ },
+ "conversion_error": {
+ "type": "bool",
+ },
+ "dod_host_prohibited": {
+ "type": "bool",
+ },
+ "dod_net_prohibited": {
+ "type": "bool",
+ },
+ "echo": {"type": "bool"},
+ "echo_reply": {"type": "bool"},
+ "general_parameter_problem": {
+ "type": "bool",
+ },
+ "host_isolated": {
+ "type": "bool",
+ },
+ "host_precedence_unreachable": {
+ "type": "bool",
+ },
+ "host_redirect": {
+ "type": "bool",
+ },
+ "host_tos_redirect": {
+ "type": "bool",
+ },
+ "host_tos_unreachable": {
+ "type": "bool",
+ },
+ "host_unknown": {
+ "type": "bool",
+ },
+ "host_unreachable": {
+ "type": "bool",
+ },
+ "information_reply": {
+ "type": "bool",
+ },
+ "information_request": {
+ "type": "bool",
+ },
+ "mask_reply": {"type": "bool"},
+ "mask_request": {
+ "type": "bool",
+ },
+ "mobile_redirect": {
+ "type": "bool",
+ },
+ "net_redirect": {
+ "type": "bool",
+ },
+ "net_tos_redirect": {
+ "type": "bool",
+ },
+ "net_tos_unreachable": {
+ "type": "bool",
+ },
+ "net_unreachable": {
+ "type": "bool",
+ },
+ "network_unknown": {
+ "type": "bool",
+ },
+ "no_room_for_option": {
+ "type": "bool",
+ },
+ "option_missing": {
+ "type": "bool",
+ },
+ "packet_too_big": {
+ "type": "bool",
+ },
+ "parameter_problem": {
+ "type": "bool",
+ },
+ "port_unreachable": {
+ "type": "bool",
+ },
+ "precedence_unreachable": {
+ "type": "bool",
+ },
+ "protocol_unreachable": {
+ "type": "bool",
+ },
+ "reassembly_timeout": {
+ "type": "bool",
+ },
+ "redirect": {"type": "bool"},
+ "router_advertisement": {
+ "type": "bool",
+ },
+ "router_solicitation": {
+ "type": "bool",
+ },
+ "source_quench": {
+ "type": "bool",
+ },
+ "source_route_failed": {
+ "type": "bool",
+ },
+ "time_exceeded": {
+ "type": "bool",
+ },
+ "timestamp_reply": {
+ "type": "bool",
+ },
+ "timestamp_request": {
+ "type": "bool",
+ },
+ "traceroute": {"type": "bool"},
+ "ttl_exceeded": {
+ "type": "bool",
+ },
+ "unreachable": {
+ "type": "bool",
+ },
+ },
+ "type": "dict",
+ },
+ "igmp": {
+ "options": {
+ "dvmrp": {"type": "bool"},
+ "host_query": {"type": "bool"},
+ "host_report": {
+ "type": "bool",
+ },
+ "mtrace": {"type": "bool"},
+ "mtrace_response": {
+ "type": "bool",
+ },
+ "pim": {"type": "bool"},
+ "trace": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "tcp": {
+ "options": {
+ "ack": {"type": "bool"},
+ "established": {
+ "type": "bool",
+ },
+ "fin": {"type": "bool"},
+ "psh": {"type": "bool"},
+ "rst": {"type": "bool"},
+ "syn": {"type": "bool"},
+ "urg": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "remark": {"type": "str"},
+ "sequence": {"type": "int"},
+ "source": {
+ "mutually_exclusive": [
+ [
+ "address",
+ "any",
+ "host",
+ "prefix",
+ "net_group",
+ "port_group",
+ ],
+ [
+ "wildcard_bits",
+ "any",
+ "host",
+ "prefix",
+ "net_group",
+ "port_group",
+ ],
+ ],
+ "options": {
+ "host": {"type": "str"},
+ "net_group": {"type": "str"},
+ "port_group": {"type": "str"},
+ "address": {"type": "str"},
+ "any": {"type": "bool"},
+ "prefix": {"type": "str"},
+ "port_protocol": {
+ "mutually_exclusive": [
+ [
+ "eq",
+ "gt",
+ "lt",
+ "neq",
+ "range",
+ ],
+ ],
+ "options": {
+ "eq": {"type": "str"},
+ "gt": {"type": "str"},
+ "lt": {"type": "str"},
+ "neq": {"type": "str"},
+ "range": {
+ "options": {
+ "end": {"type": "str"},
+ "start": {
+ "type": "str",
+ },
+ },
+ "required_together": [
+ ["start", "end"],
+ ],
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "wildcard_bits": {"type": "str"},
+ },
+ "required_together": [
+ ["address", "wildcard_bits"],
+ ],
+ "type": "dict",
+ },
+ "ttl": {
+ "mutually_exclusive": [
+ ["eq", "gt", "lt", "neq", "range"],
+ ],
+ "options": {
+ "eq": {"type": "int"},
+ "gt": {"type": "int"},
+ "lt": {"type": "int"},
+ "neq": {"type": "int"},
+ "range": {
+ "options": {
+ "end": {"type": "int"},
+ "start": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ },
+ "type": "list",
+ },
+ },
+ "type": "list",
+ },
+ "afi": {
+ "choices": ["ipv4", "ipv6"],
+ "required": True,
+ "type": "str",
+ },
+ },
+ "type": "list",
+ },
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "rendered",
+ "parsed",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_address_family/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_address_family/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_address_family/__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
new file mode 100644
index 00000000..7413c1ad
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_address_family/bgp_address_family.py
@@ -0,0 +1,398 @@
+# -*- 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
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the
+# cli_rm_builder.
+#
+# Manually editing this file is not advised.
+#
+# To update the argspec make the desired changes
+# in the module docstring and re-run
+# cli_rm_builder.
+#
+#############################################
+
+"""
+The arg spec for the iosxr_bgp_address_family module
+"""
+
+
+class Bgp_address_familyArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_bgp_address_family module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "type": "dict",
+ "options": {
+ "as_number": {"type": "str"},
+ "address_family": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "afi": {
+ "type": "str",
+ "choices": [
+ "ipv4",
+ "ipv6",
+ "l2vpn",
+ "link-state",
+ "vpnv4",
+ "vpnv6",
+ ],
+ },
+ "safi": {
+ "type": "str",
+ "choices": [
+ "flowspec",
+ "mdt",
+ "multicast",
+ "mvpn",
+ "rt-filter",
+ "tunnel",
+ "unicast",
+ "evpn",
+ "mspw",
+ "vpls-vpws",
+ "link-state",
+ ],
+ },
+ "vrf": {"type": "str"},
+ "additional_paths": {
+ "type": "str",
+ "choices": ["send", "receive"],
+ },
+ "advertise_best_external": {"type": "bool"},
+ "aggregate_address": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "value": {"type": "str"},
+ "as_set": {"type": "bool"},
+ "as_confed_set": {"type": "bool"},
+ "summary_only": {"type": "bool"},
+ "route_policy": {"type": "str"},
+ },
+ },
+ "allocate_label": {
+ "type": "dict",
+ "options": {
+ "all": {"type": "bool"},
+ "route_policy": {"type": "str"},
+ },
+ },
+ "as_path_loopcheck_out_disable": {"type": "bool"},
+ "bgp": {
+ "type": "dict",
+ "options": {
+ "attribute_download": {"type": "bool"},
+ "bestpath": {
+ "type": "dict",
+ "options": {
+ "origin_as": {
+ "type": "dict",
+ "options": {
+ "use": {
+ "type": "dict",
+ "options": {
+ "validity": {
+ "type": "bool",
+ },
+ },
+ },
+ "allow": {
+ "type": "dict",
+ "options": {
+ "invalid": {
+ "type": "bool",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "client_to_client": {
+ "type": "dict",
+ "options": {
+ "reflection": {
+ "type": "dict",
+ "options": {
+ "cluster_id_disable": {
+ "type": "dict",
+ "options": {
+ "cluster_id": {
+ "type": "str",
+ },
+ "disable": {
+ "type": "bool",
+ },
+ },
+ },
+ "disable": {"type": "bool"},
+ },
+ },
+ },
+ },
+ "dampening": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "value": {"type": "int"},
+ "route_policy": {"type": "str"},
+ },
+ },
+ "label_delay": {
+ "type": "dict",
+ "options": {
+ "delay_second_parts": {"type": "int"},
+ "delay_ms_parts": {"type": "int"},
+ },
+ },
+ "import_delay": {
+ "type": "dict",
+ "options": {
+ "delay_second_parts": {"type": "int"},
+ "delay_ms_parts": {"type": "int"},
+ },
+ },
+ "origin_as": {
+ "type": "dict",
+ "options": {
+ "validation": {
+ "type": "dict",
+ "options": {
+ "disable": {"type": "bool"},
+ "signal": {
+ "type": "dict",
+ "options": {
+ "ibgp": {
+ "type": "bool",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "scan_time": {"type": "int"},
+ },
+ },
+ "default_martian_check_disable": {"type": "bool"},
+ "distance": {
+ "type": "dict",
+ "options": {
+ "routes_external_to_as": {"type": "int"},
+ "routes_internal_to_as": {"type": "int"},
+ "local_routes": {"type": "int"},
+ },
+ },
+ "dynamic_med": {"type": "int"},
+ "maximum_paths": {
+ "type": "dict",
+ "options": {
+ "ibgp": {
+ "type": "dict",
+ "options": {
+ "max_path_value": {"type": "int"},
+ "order_igp_metric": {"type": "bool"},
+ "selective_order_igp_metric": {
+ "type": "bool",
+ },
+ "unequal_cost": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "order_igp_metric": {
+ "type": "bool",
+ },
+ "selective_order_igp_metric": {
+ "type": "bool",
+ },
+ },
+ },
+ },
+ },
+ "ebgp": {
+ "type": "dict",
+ "options": {
+ "max_path_value": {"type": "int"},
+ "order_igp_metric": {"type": "bool"},
+ "selective_order_igp_metric": {
+ "type": "bool",
+ },
+ },
+ },
+ "eibgp": {
+ "type": "dict",
+ "options": {
+ "max_path_value": {"type": "int"},
+ "order_igp_metric": {"type": "bool"},
+ "selective_order_igp_metric": {
+ "type": "bool",
+ },
+ },
+ },
+ },
+ },
+ "networks": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "network": {"type": "str"},
+ "backdoor_route_policy": {"type": "str"},
+ "route_policy": {"type": "str"},
+ },
+ },
+ "nexthop": {
+ "type": "dict",
+ "options": {
+ "resolution_prefix_length_minimum": {
+ "type": "int",
+ "choices": [0, 32],
+ },
+ "route_policy": {"type": "str"},
+ "trigger_delay_critical": {"type": "int"},
+ "trigger_delay_non_critical": {"type": "int"},
+ },
+ },
+ "optimal_route_reflection": {
+ "type": "dict",
+ "options": {
+ "group_name": {"type": "str"},
+ "primary_address": {"type": "str"},
+ "secondary_address": {"type": "str"},
+ },
+ },
+ "permanent_network_route_policy": {"type": "str"},
+ "retain_local_label": {"type": "int"},
+ "table_policy": {"type": "str"},
+ "update": {
+ "type": "dict",
+ "options": {
+ "limit": {
+ "type": "dict",
+ "options": {
+ "sub_group": {
+ "type": "dict",
+ "options": {
+ "ibgp": {"type": "int"},
+ "ebgp": {"type": "int"},
+ },
+ },
+ "address_family": {"type": "int"},
+ },
+ },
+ "wait_install": {"type": "bool"},
+ },
+ },
+ "redistribute": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "protocol": {
+ "type": "str",
+ "choices": [
+ "ospf",
+ "application",
+ "eigrp",
+ "isis",
+ "static",
+ "connected",
+ "lisp",
+ "mobile",
+ "rip",
+ "subscriber",
+ ],
+ "required": True,
+ },
+ "id": {"type": "str"},
+ "metric": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "internal": {"type": "bool"},
+ "external": {"type": "bool"},
+ "level": {
+ "type": "str",
+ "choices": ["1", "2", "1-inter-area"],
+ },
+ "nssa_external": {"type": "bool"},
+ "external_ospf": {
+ "type": "int",
+ "choices": [1, 2],
+ },
+ },
+ },
+ "inter_as_install": {"type": "bool"},
+ "segmented_multicast": {"type": "bool"},
+ "global_table_multicast": {"type": "bool"},
+ "vrf_all_conf": {
+ "type": "dict",
+ "options": {
+ "source_rt_import_policy": {"type": "bool"},
+ "table_policy": {"type": "str"},
+ "label_mode": {
+ "type": "dict",
+ "options": {
+ "per_ce": {"type": "bool"},
+ "per_vrf": {"type": "bool"},
+ "route_policy": {"type": "str"},
+ },
+ },
+ },
+ },
+ "weight": {
+ "type": "dict",
+ "options": {
+ "reset_on_import_disable": {"type": "bool"},
+ "reset_on_import": {"type": "bool"},
+ },
+ },
+ "allow_vpn_default_originate": {"type": "bool"},
+ "label_mode": {
+ "type": "dict",
+ "options": {
+ "per_ce": {"type": "bool"},
+ "per_vrf": {"type": "bool"},
+ "route_policy": {"type": "str"},
+ "per_prefix": {"type": "bool"},
+ },
+ },
+ "mvpn_single_forwarder_selection_all": {
+ "type": "bool",
+ },
+ "mvpn_single_forwarder_selection_highest_ip_address": {
+ "type": "bool",
+ },
+ "route_target_download": {"type": "bool"},
+ },
+ },
+ },
+ },
+ "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/bgp_global/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_global/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_global/__init__.py
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
new file mode 100644
index 00000000..051e2699
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_global/bgp_global.py
@@ -0,0 +1,1249 @@
+# -*- 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
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the
+# cli_rm_builder.
+#
+# Manually editing this file is not advised.
+#
+# To update the argspec make the desired changes
+# in the module docstring and re-run
+# cli_rm_builder.
+#
+#############################################
+
+"""
+The arg spec for the iosxr_bgp_global module
+"""
+
+
+class Bgp_globalArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_bgp_global module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "type": "dict",
+ "options": {
+ "as_number": {"type": "str"},
+ "bfd": {
+ "type": "dict",
+ "options": {
+ "minimum_interval": {"type": "int"},
+ "multiplier": {"type": "int"},
+ },
+ },
+ "bgp": {
+ "type": "dict",
+ "options": {
+ "as_path_loopcheck": {"type": "bool"},
+ "auto_policy_soft_reset": {
+ "type": "dict",
+ "options": {"disable": {"type": "bool"}},
+ },
+ "bestpath": {
+ "type": "dict",
+ "options": {
+ "as_path": {
+ "type": "dict",
+ "options": {
+ "ignore": {"type": "bool"},
+ "multipath_relax": {"type": "bool"},
+ },
+ },
+ "aigp": {
+ "type": "dict",
+ "options": {"ignore": {"type": "bool"}},
+ },
+ "med": {
+ "type": "dict",
+ "options": {
+ "always": {"type": "bool"},
+ "confed": {"type": "bool"},
+ "missing_as_worst": {"type": "bool"},
+ },
+ },
+ "compare_routerid": {"type": "bool"},
+ "cost_community": {
+ "type": "dict",
+ "options": {"ignore": {"type": "bool"}},
+ },
+ "origin_as": {
+ "type": "dict",
+ "options": {
+ "use": {
+ "type": "dict",
+ "options": {
+ "validity": {"type": "bool"},
+ },
+ },
+ "allow": {
+ "type": "dict",
+ "options": {
+ "invalid": {"type": "bool"},
+ },
+ },
+ },
+ },
+ },
+ },
+ "cluster_id": {"type": "str"},
+ "confederation": {
+ "type": "dict",
+ "options": {
+ "identifier": {"type": "int"},
+ "peers": {"type": "list", "elements": "int"},
+ },
+ },
+ "default": {
+ "type": "dict",
+ "options": {"local_preference": {"type": "int"}},
+ },
+ "enforce_first_as": {
+ "type": "dict",
+ "options": {"disable": {"type": "bool"}},
+ },
+ "fast_external_fallover": {
+ "type": "dict",
+ "options": {"disable": {"type": "bool"}},
+ },
+ "graceful_restart": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "graceful_reset": {"type": "bool"},
+ "restart_time": {"type": "int"},
+ "purge_time": {"type": "int"},
+ "stalepath_time": {"type": "int"},
+ },
+ },
+ "install": {
+ "type": "dict",
+ "options": {"diversion": {"type": "bool"}},
+ },
+ "log": {
+ "type": "dict",
+ "options": {
+ "log_message": {
+ "type": "dict",
+ "options": {"disable": {"type": "bool"}},
+ },
+ "neighbor": {
+ "type": "dict",
+ "options": {
+ "changes": {
+ "type": "dict",
+ "options": {
+ "detail": {"type": "bool"},
+ "disable": {"type": "bool"},
+ },
+ },
+ },
+ },
+ },
+ },
+ "maximum": {
+ "type": "dict",
+ "options": {"neighbor": {"type": "int"}},
+ },
+ "multipath": {
+ "type": "dict",
+ "options": {
+ "as_path": {
+ "type": "dict",
+ "options": {
+ "ignore": {
+ "type": "dict",
+ "options": {
+ "onwards": {"type": "bool"},
+ },
+ },
+ },
+ },
+ },
+ },
+ "origin_as": {
+ "type": "dict",
+ "options": {
+ "validation": {
+ "type": "dict",
+ "options": {
+ "disable": {"type": "bool"},
+ "signal": {
+ "type": "dict",
+ "options": {
+ "ibgp": {"type": "bool"},
+ },
+ },
+ "time": {
+ "type": "dict",
+ "options": {
+ "time_off": {"type": "bool"},
+ "time_in_second": {
+ "type": "int",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "redistribute_internal": {"type": "bool"},
+ "router_id": {"type": "str"},
+ "scan_time": {"type": "int"},
+ "unsafe_ebgp_policy": {"type": "bool"},
+ "update_delay": {"type": "int"},
+ },
+ },
+ "default_information": {
+ "type": "dict",
+ "options": {"originate": {"type": "bool"}},
+ },
+ "default_metric": {"type": "int"},
+ "graceful_maintenance": {
+ "type": "dict",
+ "options": {
+ "activate": {
+ "type": "str",
+ "choices": [
+ "all-neighbors",
+ "retain-routes",
+ "all-neighbors retain-routes",
+ "",
+ ],
+ },
+ },
+ },
+ "ibgp": {
+ "type": "dict",
+ "options": {
+ "policy": {
+ "type": "dict",
+ "options": {
+ "out": {
+ "type": "dict",
+ "options": {
+ "enforce_modifications": {
+ "type": "bool",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "mpls": {
+ "type": "dict",
+ "options": {
+ "activate": {
+ "type": "dict",
+ "options": {"interface": {"type": "str"}},
+ },
+ },
+ },
+ "mvpn": {"type": "bool"},
+ "neighbors": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "neighbor_address": {
+ "type": "str",
+ "aliases": ["neighbor"],
+ "required": True,
+ },
+ "advertisement_interval": {"type": "int"},
+ "bfd": {
+ "type": "dict",
+ "options": {
+ "fast_detect": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "disable": {"type": "bool"},
+ "strict_mode": {"type": "bool"},
+ },
+ },
+ "multiplier": {"type": "int"},
+ "minimum_interval": {"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"},
+ },
+ },
+ "keychain": {
+ "type": "dict",
+ "no_log": False,
+ "options": {
+ "name": {"type": "str"},
+ "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"},
+ "inheritance_disable": {"type": "bool"},
+ },
+ },
+ "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",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "origin_as": {
+ "type": "dict",
+ "options": {
+ "validation": {
+ "type": "dict",
+ "options": {"disable": {"type": "bool"}},
+ },
+ },
+ },
+ "receive_buffer_size": {"type": "int"},
+ "remote_as": {"type": "int"},
+ "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"},
+ },
+ },
+ "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"},
+ },
+ },
+ "nsr": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "disable": {"type": "bool"},
+ },
+ },
+ "socket": {
+ "type": "dict",
+ "options": {
+ "receive_buffer_size": {"type": "int"},
+ "send_buffer_size": {"type": "int"},
+ },
+ },
+ "timers": {
+ "type": "dict",
+ "options": {
+ "keepalive_time": {"type": "int"},
+ "holdtime": {"type": "int"},
+ },
+ },
+ "update": {
+ "type": "dict",
+ "options": {
+ "in": {
+ "type": "dict",
+ "options": {
+ "error_handling": {
+ "type": "dict",
+ "options": {
+ "basic": {
+ "type": "dict",
+ "options": {
+ "ebgp": {
+ "type": "dict",
+ "options": {
+ "disable": {
+ "type": "bool",
+ },
+ },
+ },
+ "ibgp": {
+ "type": "dict",
+ "options": {
+ "disable": {
+ "type": "bool",
+ },
+ },
+ },
+ },
+ },
+ "extended": {
+ "type": "dict",
+ "options": {
+ "ebgp": {"type": "bool"},
+ "ibgp": {"type": "bool"},
+ },
+ },
+ },
+ },
+ },
+ },
+ "out": {
+ "type": "dict",
+ "options": {"logging": {"type": "bool"}},
+ },
+ "limit": {"type": "int"},
+ },
+ },
+ "rpki": {
+ "type": "dict",
+ "options": {
+ "route": {
+ "type": "dict",
+ "options": {
+ "value": {"type": "str"},
+ "max": {"type": "int"},
+ "origin": {"type": "int"},
+ },
+ },
+ "servers": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "purge_time": {"type": "int"},
+ "refresh_time": {
+ "type": "dict",
+ "options": {
+ "value": {"type": "int"},
+ "time_off": {"type": "bool"},
+ },
+ },
+ "response_time": {
+ "type": "dict",
+ "options": {
+ "value": {"type": "int"},
+ "time_off": {"type": "bool"},
+ },
+ },
+ "shutdown": {"type": "bool"},
+ "transport": {
+ "type": "dict",
+ "options": {
+ "ssh": {
+ "type": "dict",
+ "options": {
+ "port": {"type": "int"},
+ },
+ },
+ "tcp": {
+ "type": "dict",
+ "options": {
+ "port": {"type": "int"},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "vrfs": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "vrf": {"type": "str"},
+ "bfd": {
+ "type": "dict",
+ "options": {
+ "minimum_interval": {"type": "int"},
+ "multiplier": {"type": "int"},
+ },
+ },
+ "bgp": {
+ "type": "dict",
+ "options": {
+ "auto_policy_soft_reset": {
+ "type": "dict",
+ "options": {"disable": {"type": "bool"}},
+ },
+ "bestpath": {
+ "type": "dict",
+ "options": {
+ "as_path": {
+ "type": "dict",
+ "options": {
+ "ignore": {"type": "bool"},
+ "multipath_relax": {
+ "type": "bool",
+ },
+ },
+ },
+ "aigp": {
+ "type": "dict",
+ "options": {
+ "ignore": {"type": "bool"},
+ },
+ },
+ "med": {
+ "type": "dict",
+ "options": {
+ "always": {"type": "bool"},
+ "confed": {"type": "bool"},
+ "missing_as_worst": {
+ "type": "bool",
+ },
+ },
+ },
+ "compare_routerid": {"type": "bool"},
+ "cost_community": {
+ "type": "dict",
+ "options": {
+ "ignore": {"type": "bool"},
+ },
+ },
+ "origin_as": {
+ "type": "dict",
+ "options": {
+ "use": {
+ "type": "dict",
+ "options": {
+ "validity": {
+ "type": "bool",
+ },
+ },
+ },
+ "allow": {
+ "type": "dict",
+ "options": {
+ "invalid": {
+ "type": "bool",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "default": {
+ "type": "dict",
+ "options": {
+ "local_preference": {"type": "int"},
+ },
+ },
+ "enforce_first_as": {
+ "type": "dict",
+ "options": {"disable": {"type": "bool"}},
+ },
+ "fast_external_fallover": {
+ "type": "dict",
+ "options": {"disable": {"type": "bool"}},
+ },
+ "log": {
+ "type": "dict",
+ "options": {
+ "log_message": {
+ "type": "dict",
+ "options": {
+ "disable": {"type": "bool"},
+ },
+ },
+ "neighbor": {
+ "type": "dict",
+ "options": {
+ "changes": {
+ "type": "dict",
+ "options": {
+ "detail": {
+ "type": "bool",
+ },
+ "disable": {
+ "type": "bool",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "multipath": {
+ "type": "dict",
+ "options": {
+ "as_path": {
+ "type": "dict",
+ "options": {
+ "ignore": {
+ "type": "dict",
+ "options": {
+ "onwards": {
+ "type": "bool",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "redistribute_internal": {"type": "bool"},
+ "router_id": {"type": "str"},
+ "unsafe_ebgp_policy": {"type": "bool"},
+ },
+ },
+ "default_information": {
+ "type": "dict",
+ "options": {"originate": {"type": "bool"}},
+ },
+ "default_metric": {"type": "int"},
+ "mpls": {
+ "type": "dict",
+ "options": {
+ "activate": {
+ "type": "dict",
+ "options": {"interface": {"type": "str"}},
+ },
+ },
+ },
+ "neighbors": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "neighbor_address": {
+ "type": "str",
+ "aliases": ["neighbor"],
+ "required": True,
+ },
+ "advertisement_interval": {"type": "int"},
+ "bfd": {
+ "type": "dict",
+ "options": {
+ "fast_detect": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "disable": {"type": "bool"},
+ "strict_mode": {
+ "type": "bool",
+ },
+ },
+ },
+ "multiplier": {"type": "int"},
+ "minimum_interval": {"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"},
+ },
+ },
+ "keychain": {
+ "type": "dict",
+ "no_log": False,
+ "options": {
+ "name": {"type": "str"},
+ "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"},
+ "inheritance_disable": {
+ "type": "bool",
+ },
+ },
+ },
+ "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",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "origin_as": {
+ "type": "dict",
+ "options": {
+ "validation": {
+ "type": "dict",
+ "options": {
+ "disable": {"type": "bool"},
+ },
+ },
+ },
+ },
+ "receive_buffer_size": {"type": "int"},
+ "remote_as": {"type": "int"},
+ "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"},
+ },
+ },
+ "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"},
+ },
+ },
+ "rd": {
+ "type": "dict",
+ "options": {"auto": {"type": "bool"}},
+ },
+ "socket": {
+ "type": "dict",
+ "options": {
+ "receive_buffer_size": {"type": "int"},
+ "send_buffer_size": {"type": "int"},
+ },
+ },
+ "timers": {
+ "type": "dict",
+ "options": {
+ "keepalive_time": {"type": "int"},
+ "holdtime": {"type": "int"},
+ },
+ },
+ },
+ },
+ },
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "type": "str",
+ "choices": [
+ "deleted",
+ "merged",
+ "replaced",
+ "gathered",
+ "rendered",
+ "parsed",
+ "purged",
+ ],
+ "default": "merged",
+ },
+ } # pylint: disable=C0301
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_neighbor_address_family/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_neighbor_address_family/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_neighbor_address_family/__init__.py
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
new file mode 100644
index 00000000..a720860b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/bgp_neighbor_address_family/bgp_neighbor_address_family.py
@@ -0,0 +1,438 @@
+# -*- 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
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the
+# cli_rm_builder.
+#
+# Manually editing this file is not advised.
+#
+# To update the argspec make the desired changes
+# in the module docstring and re-run
+# cli_rm_builder.
+#
+#############################################
+
+"""
+The arg spec for the iosxr_bgp_neighbor_address_family module
+"""
+
+
+class Bgp_neighbor_address_familyArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_bgp_neighbor_address_family module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "type": "dict",
+ "options": {
+ "as_number": {"type": "str"},
+ "neighbors": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "neighbor_address": {"type": "str", "required": True},
+ "address_family": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "afi": {
+ "type": "str",
+ "choices": [
+ "ipv4",
+ "ipv6",
+ "l2vpn",
+ "link-state",
+ "vpnv4",
+ "vpnv6",
+ ],
+ },
+ "safi": {
+ "type": "str",
+ "choices": [
+ "flowspec",
+ "mdt",
+ "multicast",
+ "mvpn",
+ "rt-filter",
+ "tunnel",
+ "unicast",
+ "labeled-unicast",
+ ],
+ },
+ "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"},
+ },
+ },
+ "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"},
+ "validation": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "redirect": {"type": "bool"},
+ "disable": {"type": "bool"},
+ },
+ },
+ },
+ },
+ },
+ },
+ "vrfs": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "vrf": {"type": "str"},
+ "neighbors": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "neighbor_address": {"type": "str", "required": True},
+ "address_family": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "afi": {"type": "str", "choices": ["ipv4", "ipv6"]},
+ "safi": {
+ "type": "str",
+ "choices": [
+ "flowspec",
+ "multicast",
+ "mvpn",
+ "unicast",
+ "labeled-unicast",
+ ],
+ },
+ "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",
+ "aliases": ["as_overrride"],
+ "options": {
+ "set": {"type": "bool"},
+ "inheritance_disable": {"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"},
+ },
+ },
+ "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"},
+ "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"},
+ },
+ },
+ "soft_reconfiguration": {
+ "type": "dict",
+ "options": {
+ "inbound": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "always": {"type": "bool"},
+ "inheritance_disable": {"type": "bool"},
+ },
+ },
+ },
+ },
+ "site_of_origin": {"type": "str"},
+ "weight": {"type": "int"},
+ "validation": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "redirect": {"type": "bool"},
+ "disable": {"type": "bool"},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "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/facts/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/facts/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/facts/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/facts/facts.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/facts/facts.py
new file mode 100644
index 00000000..478b9181
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/facts/facts.py
@@ -0,0 +1,26 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The arg spec for the iosxr facts module.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+class FactsArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr facts module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "gather_subset": dict(default=["min"], type="list", elements="str"),
+ "gather_network_resources": dict(type="list", elements="str"),
+ "available_network_resources": {"type": "bool", "default": False},
+ }
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/hostname/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/hostname/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/hostname/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/hostname/hostname.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/hostname/hostname.py
new file mode 100644
index 00000000..04acd8a3
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/hostname/hostname.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+# Copyright 2022 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the
+# cli_rm_builder.
+#
+# Manually editing this file is not advised.
+#
+# To update the argspec make the desired changes
+# in the module docstring and re-run
+# cli_rm_builder.
+#
+#############################################
+
+"""
+The arg spec for the iosxr_hostname module
+"""
+
+
+class HostnameArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_hostname module"""
+
+ argument_spec = {
+ "config": {"type": "dict", "options": {"hostname": {"type": "str"}}},
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "deleted",
+ "merged",
+ "overridden",
+ "replaced",
+ "gathered",
+ "rendered",
+ "parsed",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/interfaces/interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/interfaces/interfaces.py
new file mode 100644
index 00000000..67b5c88c
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/interfaces/interfaces.py
@@ -0,0 +1,65 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the ios_interfaces module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+class InterfacesArgs(object):
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str", "required": True},
+ "description": {"type": "str"},
+ "enabled": {"default": True, "type": "bool"},
+ "speed": {"type": "int"},
+ "mtu": {"type": "int"},
+ "duplex": {"type": "str", "choices": ["full", "half"]},
+ },
+ "type": "list",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "parsed",
+ "rendered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ }
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/__init__.py
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
new file mode 100644
index 00000000..e58ddebb
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l2_interfaces/l2_interfaces.py
@@ -0,0 +1,97 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_l2_interfaces module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+class L2_InterfacesArgs(object):
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str", "required": True},
+ "native_vlan": {"type": "int"},
+ "l2transport": {"type": "bool"},
+ "l2protocol": {
+ "elements": "dict",
+ "options": {
+ "cdp": {
+ "type": "str",
+ "choices": ["drop", "forward", "tunnel"],
+ },
+ "pvst": {
+ "type": "str",
+ "choices": ["drop", "forward", "tunnel"],
+ },
+ "stp": {
+ "type": "str",
+ "choices": ["drop", "forward", "tunnel"],
+ },
+ "vtp": {
+ "type": "str",
+ "choices": ["drop", "forward", "tunnel"],
+ },
+ "cpsv": {
+ "type": "str",
+ "choices": ["drop", "reverse-tunnel", "tunnel"],
+ },
+ },
+ "type": "list",
+ },
+ "q_vlan": {"type": "list", "elements": "int"},
+ "propagate": {"type": "bool"},
+ "encapsulation": {
+ "type": "dict",
+ "options": {
+ "dot1q": {"type": "int"},
+ "second_dot1q": {"type": "int"},
+ },
+ },
+ },
+ "type": "list",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "parsed",
+ "rendered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ }
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l3_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l3_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l3_interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l3_interfaces/l3_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l3_interfaces/l3_interfaces.py
new file mode 100644
index 00000000..bf506750
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/l3_interfaces/l3_interfaces.py
@@ -0,0 +1,73 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the ios_l3_interfaces module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+class L3_InterfacesArgs(object):
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str", "required": True},
+ "ipv4": {
+ "elements": "dict",
+ "type": "list",
+ "options": {
+ "address": {"type": "str"},
+ "secondary": {"type": "bool"},
+ },
+ },
+ "ipv6": {
+ "elements": "dict",
+ "type": "list",
+ "options": {"address": {"type": "str"}},
+ },
+ },
+ "type": "list",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "parsed",
+ "rendered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ }
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/__init__.py
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
new file mode 100644
index 00000000..2bdda177
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp/lacp.py
@@ -0,0 +1,69 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_lacp module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+class LacpArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_lacp module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "options": {
+ "system": {
+ "options": {
+ "mac": {
+ "type": "dict",
+ "options": {"address": {"type": "str"}},
+ },
+ "priority": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "deleted",
+ "parsed",
+ "rendered",
+ "gathered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp_interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp_interfaces/lacp_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp_interfaces/lacp_interfaces.py
new file mode 100644
index 00000000..55cdfda8
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lacp_interfaces/lacp_interfaces.py
@@ -0,0 +1,77 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_lacp_interfaces module
+"""
+
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+class Lacp_interfacesArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_lacp_interfaces module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "elements": "dict",
+ "options": {
+ "churn_logging": {
+ "choices": ["actor", "partner", "both"],
+ "type": "str",
+ },
+ "collector_max_delay": {"type": "int"},
+ "name": {"type": "str"},
+ "period": {"type": "int"},
+ "switchover_suppress_flaps": {"type": "int"},
+ "system": {
+ "options": {
+ "mac": {"type": "str"},
+ "priority": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "list",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "deleted",
+ "overridden",
+ "parsed",
+ "rendered",
+ "gathered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lag_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lag_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lag_interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lag_interfaces/lag_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lag_interfaces/lag_interfaces.py
new file mode 100644
index 00000000..09498c57
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lag_interfaces/lag_interfaces.py
@@ -0,0 +1,88 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_lag_interfaces module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+class Lag_interfacesArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_lag_interfaces module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "elements": "dict",
+ "options": {
+ "links": {
+ "options": {
+ "max_active": {"type": "int"},
+ "min_active": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "load_balancing_hash": {
+ "choices": ["dst-ip", "src-ip"],
+ "type": "str",
+ },
+ "members": {
+ "elements": "dict",
+ "options": {
+ "member": {"type": "str"},
+ "mode": {
+ "choices": ["on", "active", "passive", "inherit"],
+ "type": "str",
+ },
+ },
+ "type": "list",
+ },
+ "mode": {
+ "choices": ["on", "active", "passive"],
+ "type": "str",
+ },
+ "name": {"required": True, "type": "str"},
+ },
+ "type": "list",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "parsed",
+ "rendered",
+ "gathered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ }
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/__init__.py
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
new file mode 100644
index 00000000..6c6c3947
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_global/lldp_global.py
@@ -0,0 +1,73 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_lldp_global module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+class Lldp_globalArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_lldp module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "options": {
+ "holdtime": {"type": "int"},
+ "reinit": {"type": "int"},
+ "subinterfaces": {"type": "bool"},
+ "timer": {"type": "int"},
+ "tlv_select": {
+ "options": {
+ "management_address": {"type": "bool"},
+ "port_description": {"type": "bool"},
+ "system_capabilities": {"type": "bool"},
+ "system_description": {"type": "bool"},
+ "system_name": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "deleted",
+ "parsed",
+ "rendered",
+ "gathered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_interfaces/lldp_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_interfaces/lldp_interfaces.py
new file mode 100644
index 00000000..7eb13de6
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/lldp_interfaces/lldp_interfaces.py
@@ -0,0 +1,77 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_lldp_interfaces module
+"""
+
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+class Lldp_interfacesArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_lldp_interfaces module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "elements": "dict",
+ "options": {
+ "destination": {
+ "type": "dict",
+ "options": {
+ "mac_address": {
+ "type": "str",
+ "choices": [
+ "ieee-nearest-bridge",
+ "ieee-nearest-non-tmpr-bridge",
+ ],
+ },
+ },
+ },
+ "name": {"type": "str"},
+ "receive": {"type": "bool"},
+ "transmit": {"type": "bool"},
+ },
+ "type": "list",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "deleted",
+ "overridden",
+ "parsed",
+ "rendered",
+ "gathered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/logging_global/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/logging_global/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/logging_global/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/logging_global/logging_global.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/logging_global/logging_global.py
new file mode 100644
index 00000000..339ffc7e
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/logging_global/logging_global.py
@@ -0,0 +1,429 @@
+# -*- 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
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the
+# cli_rm_builder.
+#
+# Manually editing this file is not advised.
+#
+# To update the argspec make the desired changes
+# in the module docstring and re-run
+# cli_rm_builder.
+#
+#############################################
+
+"""
+The arg spec for the iosxr_logging_global module
+"""
+
+
+class Logging_globalArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_logging_global module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "type": "dict",
+ "options": {
+ "archive": {
+ "type": "dict",
+ "options": {
+ "device": {"type": "str"},
+ "archive_length": {"type": "int"},
+ "archive_size": {"type": "int"},
+ "file_size": {"type": "int"},
+ "frequency": {
+ "type": "str",
+ "choices": ["daily", "weekly"],
+ },
+ "severity": {
+ "type": "str",
+ "choices": [
+ "alerts",
+ "critical",
+ "debugging",
+ "emergencies",
+ "errors",
+ "informational",
+ "notifications",
+ "warnings",
+ ],
+ },
+ "threshold": {"type": "int"},
+ },
+ },
+ "buffered": {
+ "type": "dict",
+ "options": {
+ "size": {"type": "int"},
+ "severity": {
+ "type": "str",
+ "choices": [
+ "alerts",
+ "critical",
+ "debugging",
+ "emergencies",
+ "errors",
+ "informational",
+ "notifications",
+ "warnings",
+ ],
+ },
+ "discriminator": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "match_params": {
+ "type": "str",
+ "choices": [
+ "match1",
+ "match2",
+ "match3",
+ "nomatch1",
+ "nomatch2",
+ "nomatch3",
+ ],
+ },
+ "name": {"type": "str"},
+ },
+ },
+ },
+ },
+ "console": {
+ "type": "dict",
+ "options": {
+ "state": {
+ "type": "str",
+ "choices": ["enabled", "disabled"],
+ },
+ "severity": {
+ "type": "str",
+ "choices": [
+ "alerts",
+ "critical",
+ "debugging",
+ "emergencies",
+ "errors",
+ "informational",
+ "notifications",
+ "warning",
+ ],
+ },
+ "discriminator": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "match_params": {
+ "type": "str",
+ "choices": [
+ "match1",
+ "match2",
+ "match3",
+ "nomatch1",
+ "nomatch2",
+ "nomatch3",
+ ],
+ },
+ "name": {"type": "str"},
+ },
+ },
+ },
+ },
+ "correlator": {
+ "type": "dict",
+ "options": {
+ "buffer_size": {"type": "int"},
+ "rules": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "rule_name": {"type": "str"},
+ "rule_type": {
+ "type": "str",
+ "choices": ["stateful", "nonstateful"],
+ },
+ "timeout": {"type": "int"},
+ "timeout_rootcause": {"type": "int"},
+ "context_correlation": {"type": "bool"},
+ "reissue_nonbistate": {"type": "bool"},
+ "reparent": {"type": "bool"},
+ },
+ },
+ "rule_sets": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "rulename": {
+ "type": "list",
+ "elements": "str",
+ },
+ },
+ },
+ },
+ },
+ "events": {
+ "type": "dict",
+ "options": {
+ "buffer_size": {"type": "int"},
+ "display_location": {"type": "bool"},
+ "filter_match": {"type": "list", "elements": "str"},
+ "severity": {
+ "type": "str",
+ "choices": [
+ "alerts",
+ "critical",
+ "debugging",
+ "emergencies",
+ "errors",
+ "informational",
+ "notifications",
+ "warnings",
+ ],
+ },
+ "threshold": {"type": "int"},
+ },
+ },
+ "facility": {
+ "type": "str",
+ "choices": [
+ "auth",
+ "cron",
+ "daemon",
+ "kern",
+ "local0",
+ "local1",
+ "local2",
+ "local3",
+ "local4",
+ "local5",
+ "local6",
+ "local7",
+ "lpr",
+ "mail",
+ "news",
+ "sys10",
+ "sys11",
+ "sys12",
+ "sys13",
+ "sys14",
+ "sys9",
+ "syslog",
+ "user",
+ "uucp",
+ ],
+ },
+ "files": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "path": {"type": "str"},
+ "maxfilesize": {"type": "int"},
+ "severity": {
+ "type": "str",
+ "choices": [
+ "alerts",
+ "critical",
+ "debugging",
+ "emergencies",
+ "errors",
+ "info",
+ "notifications",
+ "warning",
+ ],
+ },
+ },
+ },
+ "format": {"type": "bool"},
+ "history": {
+ "type": "dict",
+ "options": {
+ "state": {
+ "type": "str",
+ "choices": ["enabled", "disabled"],
+ },
+ "size": {"type": "int"},
+ "severity": {
+ "type": "str",
+ "choices": [
+ "alerts",
+ "critical",
+ "debugging",
+ "emergencies",
+ "errors",
+ "informational",
+ "notifications",
+ "warnings",
+ ],
+ },
+ },
+ },
+ "hostnameprefix": {"type": "str"},
+ "ipv4": {
+ "type": "dict",
+ "options": {
+ "dscp": {"type": "str"},
+ "precedence": {"type": "str"},
+ },
+ },
+ "ipv6": {
+ "type": "dict",
+ "options": {
+ "dscp": {"type": "str"},
+ "precedence": {"type": "str"},
+ },
+ },
+ "localfilesize": {"type": "int"},
+ "monitor": {
+ "type": "dict",
+ "options": {
+ "state": {
+ "type": "str",
+ "choices": ["enabled", "disabled"],
+ },
+ "discriminator": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "match_params": {
+ "type": "str",
+ "choices": [
+ "match1",
+ "match2",
+ "match3",
+ "nomatch1",
+ "nomatch2",
+ "nomatch3",
+ ],
+ },
+ "name": {"type": "str"},
+ },
+ },
+ "severity": {
+ "type": "str",
+ "choices": [
+ "alerts",
+ "critical",
+ "debugging",
+ "emergencies",
+ "errors",
+ "informational",
+ "notifications",
+ "warning",
+ ],
+ },
+ },
+ },
+ "source_interfaces": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "interface": {"type": "str"},
+ "vrf": {"type": "str"},
+ },
+ },
+ "suppress": {
+ "type": "dict",
+ "options": {
+ "apply_rule": {"type": "str"},
+ "duplicates": {"type": "bool"},
+ },
+ },
+ "tls_servers": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "severity": {
+ "type": "str",
+ "choices": [
+ "alerts",
+ "critical",
+ "debugging",
+ "emergencies",
+ "errors",
+ "informational",
+ "notifications",
+ "warnings",
+ ],
+ },
+ "tls_hostname": {"type": "str"},
+ "trustpoint": {"type": "str"},
+ "vrf": {"type": "str"},
+ },
+ },
+ "trap": {
+ "type": "dict",
+ "options": {
+ "state": {
+ "type": "str",
+ "choices": ["enabled", "disabled"],
+ },
+ "severity": {
+ "type": "str",
+ "choices": [
+ "alerts",
+ "critical",
+ "debugging",
+ "emergencies",
+ "errors",
+ "informational",
+ "notifications",
+ "warning",
+ ],
+ },
+ },
+ },
+ "hosts": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "severity": {
+ "type": "str",
+ "choices": [
+ "alerts",
+ "critical",
+ "debugging",
+ "emergencies",
+ "error",
+ "info",
+ "notifications",
+ "warning",
+ ],
+ },
+ "host": {"type": "str"},
+ "port": {"type": "str", "default": "default"},
+ "vrf": {"type": "str", "default": "default"},
+ },
+ },
+ },
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "parsed",
+ "rendered",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ntp_global/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ntp_global/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ntp_global/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ntp_global/ntp_global.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ntp_global/ntp_global.py
new file mode 100644
index 00000000..2c44713a
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ntp_global/ntp_global.py
@@ -0,0 +1,231 @@
+# -*- 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
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the
+# cli_rm_builder.
+#
+# Manually editing this file is not advised.
+#
+# To update the argspec make the desired changes
+# in the module docstring and re-run
+# cli_rm_builder.
+#
+#############################################
+
+"""
+The arg spec for the iosxr_ntp_global module
+"""
+
+
+class Ntp_globalArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_ntp_global module"""
+
+ argument_spec = {
+ "config": {
+ "type": "dict",
+ "options": {
+ "access_group": {
+ "type": "dict",
+ "options": {
+ "ipv4": {
+ "type": "dict",
+ "options": {
+ "peer": {"type": "str"},
+ "query_only": {"type": "str"},
+ "serve": {"type": "str"},
+ "serve_only": {"type": "str"},
+ },
+ },
+ "ipv6": {
+ "type": "dict",
+ "options": {
+ "peer": {"type": "str"},
+ "query_only": {"type": "str"},
+ "serve": {"type": "str"},
+ "serve_only": {"type": "str"},
+ },
+ },
+ "vrfs": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "ipv4": {
+ "type": "dict",
+ "options": {
+ "peer": {"type": "str"},
+ "query_only": {"type": "str"},
+ "serve": {"type": "str"},
+ "serve_only": {"type": "str"},
+ },
+ },
+ "ipv6": {
+ "type": "dict",
+ "options": {
+ "peer": {"type": "str"},
+ "query_only": {"type": "str"},
+ "serve": {"type": "str"},
+ "serve_only": {"type": "str"},
+ },
+ },
+ },
+ },
+ },
+ },
+ "authenticate": {"type": "bool"},
+ "authentication_keys": {
+ "type": "list",
+ "elements": "dict",
+ "no_log": False,
+ "options": {
+ "id": {"type": "int"},
+ "key": {"type": "str", "no_log": True},
+ "encryption": {"type": "bool"},
+ },
+ },
+ "broadcastdelay": {"type": "int"},
+ "drift": {
+ "type": "dict",
+ "options": {
+ "aging_time": {"type": "int"},
+ "file": {"type": "str"},
+ },
+ },
+ "interfaces": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "vrf": {"type": "str"},
+ "broadcast_client": {"type": "bool"},
+ "broadcast_destination": {"type": "str"},
+ "broadcast_key": {"type": "int", "no_log": False},
+ "broadcast_version": {"type": "int"},
+ "multicast_key": {"type": "int", "no_log": False},
+ "multicast_ttl": {"type": "int"},
+ "multicast_client": {"type": "str"},
+ "multicast_destination": {"type": "str"},
+ "multicast_version": {"type": "int"},
+ },
+ },
+ "ipv4": {
+ "type": "dict",
+ "options": {
+ "dscp": {"type": "str"},
+ "precedence": {
+ "type": "str",
+ "choices": [
+ "critical",
+ "flash",
+ "flash-override",
+ "immediate",
+ "internet",
+ "network",
+ "priority",
+ "routine",
+ ],
+ },
+ },
+ },
+ "ipv6": {
+ "type": "dict",
+ "options": {
+ "dscp": {"type": "str"},
+ "precedence": {
+ "type": "str",
+ "choices": [
+ "critical",
+ "flash",
+ "flash-override",
+ "immediate",
+ "internet",
+ "network",
+ "priority",
+ "routine",
+ ],
+ },
+ },
+ },
+ "log_internal_sync": {"type": "bool"},
+ "master": {
+ "type": "dict",
+ "options": {"stratum": {"type": "int"}},
+ },
+ "max_associations": {"type": "int"},
+ "passive": {"type": "bool"},
+ "trusted_keys": {
+ "type": "list",
+ "elements": "dict",
+ "no_log": False,
+ "options": {"key_id": {"type": "int"}},
+ },
+ "update_calendar": {"type": "bool"},
+ "source_interface": {"type": "str"},
+ "source_vrfs": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "vrf": {"type": "str"},
+ },
+ },
+ "servers": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "vrf": {"type": "str"},
+ "server": {"type": "str", "required": True},
+ "burst": {"type": "bool"},
+ "iburst": {"type": "bool"},
+ "key_id": {"type": "int"},
+ "source": {"type": "str"},
+ "maxpoll": {"type": "int"},
+ "minpoll": {"type": "int"},
+ "prefer": {"type": "bool"},
+ "version": {"type": "int"},
+ },
+ },
+ "peers": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "vrf": {"type": "str"},
+ "peer": {"type": "str", "required": True},
+ "burst": {"type": "bool"},
+ "iburst": {"type": "bool"},
+ "key_id": {"type": "int"},
+ "source": {"type": "str"},
+ "maxpoll": {"type": "int"},
+ "minpoll": {"type": "int"},
+ "prefer": {"type": "bool"},
+ "version": {"type": "int"},
+ },
+ },
+ },
+ },
+ "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/ospf_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospf_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospf_interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospf_interfaces/ospf_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospf_interfaces/ospf_interfaces.py
new file mode 100644
index 00000000..c74bde95
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospf_interfaces/ospf_interfaces.py
@@ -0,0 +1,437 @@
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the
+# cli_rm_builder.
+#
+# Manually editing this file is not advised.
+#
+# To update the argspec make the desired changes
+# in the module docstring and re-run
+# cli_rm_builder.
+#
+#############################################
+
+"""
+The arg spec for the iosxr_ospf_interfaces module
+"""
+
+
+class Ospf_interfacesArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_ospf_interfaces module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "running_config": {"type": "str"},
+ "config": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str", "required": True},
+ "type": {"type": "str", "required": True},
+ "address_family": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "afi": {
+ "type": "str",
+ "choices": ["ipv4", "ipv6"],
+ "required": True,
+ },
+ "processes": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "process_id": {
+ "type": "str",
+ "required": True,
+ },
+ "area": {
+ "type": "dict",
+ "options": {"area_id": {"type": "str"}},
+ },
+ },
+ },
+ "apply_group_option": {
+ "type": "dict",
+ "options": {
+ "group_name": {"type": "str"},
+ "operation": {
+ "type": "str",
+ "choices": ["add", "remove", "append"],
+ },
+ },
+ },
+ "authentication": {
+ "no_log": False,
+ "type": "dict",
+ "options": {
+ "message_digest": {
+ "no_log": False,
+ "type": "dict",
+ "options": {
+ "keychain": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ },
+ "null_auth": {"type": "bool"},
+ },
+ },
+ "authentication_key": {
+ "type": "dict",
+ "no_log": True,
+ "options": {
+ "password": {"type": "str", "no_log": True},
+ "clear": {"type": "str"},
+ "encrypted": {"type": "str"},
+ },
+ },
+ "bfd": {
+ "type": "dict",
+ "options": {
+ "fast_detect": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "strict_mode": {"type": "bool"},
+ },
+ },
+ "minimum_interval": {"type": "int"},
+ "multiplier": {"type": "int"},
+ },
+ },
+ "cost": {"type": "int"},
+ "cost_fallback": {
+ "type": "dict",
+ "options": {
+ "cost": {"type": "int"},
+ "threshold": {"type": "int"},
+ },
+ },
+ "database_filter": {
+ "type": "dict",
+ "options": {"all_outgoing_lsa": {"type": "bool"}},
+ },
+ "dead_interval": {"type": "int"},
+ "demand_circuit": {"type": "bool"},
+ "fast_reroute": {
+ "type": "dict",
+ "options": {
+ "disabled": {"type": "bool"},
+ "per_link": {
+ "type": "dict",
+ "options": {
+ "information_type": {
+ "type": "str",
+ "choices": [
+ "exclude",
+ "lfa_candidate",
+ ],
+ },
+ "use_candidate_only": {"type": "bool"},
+ "interface": {
+ "type": "dict",
+ "options": {
+ "bvi": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "int",
+ },
+ },
+ },
+ "bundle_ether": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "int",
+ },
+ },
+ },
+ "pos_int": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "int",
+ },
+ },
+ },
+ "fast_ethernet": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "str",
+ },
+ },
+ },
+ "fiftygige": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "str",
+ },
+ },
+ },
+ "fortygige": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "str",
+ },
+ },
+ },
+ "fourhundredgige": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "str",
+ },
+ },
+ },
+ "gigabitethernet": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "str",
+ },
+ },
+ },
+ "hundredgige": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "str",
+ },
+ },
+ },
+ "mgmteth": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "str",
+ },
+ },
+ },
+ "multilink": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "str",
+ },
+ },
+ },
+ "pw_ether": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "int",
+ },
+ },
+ },
+ "pw_iw": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "int",
+ },
+ },
+ },
+ "srp": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "str",
+ },
+ },
+ },
+ "serial": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "str",
+ },
+ },
+ },
+ "tengige": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "str",
+ },
+ },
+ },
+ "twentyfivegige": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "str",
+ },
+ },
+ },
+ "twohundredgige": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "str",
+ },
+ },
+ },
+ "nve": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "int",
+ },
+ },
+ },
+ "tunnel_ip": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "int",
+ },
+ },
+ },
+ "tunnel_ipsec": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "int",
+ },
+ },
+ },
+ "tunnel_mte": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "int",
+ },
+ },
+ },
+ "tunnel_mpls": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {
+ "type": "str",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "flood_reduction": {"type": "bool"},
+ "hello_interval": {"type": "int"},
+ "link_down_fast_detect": {"type": "bool"},
+ "message_digest_key": {
+ "type": "dict",
+ "no_log": False,
+ "options": {
+ "id": {"type": "int", "required": True},
+ "md5": {
+ "type": "dict",
+ "required": True,
+ "options": {
+ "password": {
+ "type": "str",
+ "no_log": True,
+ },
+ "clear": {"type": "bool"},
+ "encrypted": {"type": "bool"},
+ },
+ },
+ },
+ },
+ "mpls_ldp_sync": {"type": "bool"},
+ "mtu_ignore": {"type": "bool"},
+ "network": {
+ "type": "str",
+ "choices": [
+ "broadcast",
+ "non-broadcast",
+ "point-to-multipoint",
+ "point-to-point",
+ ],
+ },
+ "neighbors": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "neighbor_id": {"type": "str"},
+ "cost": {"type": "int"},
+ "db_filter_all_out": {"type": "bool"},
+ "poll_interval": {"type": "int"},
+ "priority": {"type": "int"},
+ },
+ },
+ "packet_size": {"type": "int"},
+ "passive": {"type": "bool"},
+ "prefix_suppression": {"type": "bool"},
+ "priority": {"type": "int"},
+ "retransmit_interval": {"type": "int"},
+ "security_ttl": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "hops": {"type": "int"},
+ },
+ },
+ "transmit_delay": {"type": "int"},
+ },
+ },
+ },
+ },
+ "state": {
+ "type": "str",
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "parsed",
+ "rendered",
+ ],
+ "default": "merged",
+ },
+ } # pylint: disable=C0301
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv2/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv2/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv2/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv2/ospfv2.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv2/ospfv2.py
new file mode 100644
index 00000000..b9b45461
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv2/ospfv2.py
@@ -0,0 +1,825 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_ospfv2 module
+"""
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+class Ospfv2Args(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_ospfv2 module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "options": {
+ "processes": {
+ "elements": "dict",
+ "options": {
+ "address_family_unicast": {"type": "bool"},
+ "adjacency_stagger": {
+ "options": {
+ "disable": {"type": "bool"},
+ "max_adjacency": {"type": "int"},
+ "min_adjacency": {"type": "int"},
+ },
+ "required_together": [
+ ["min_adjacency", "max_adjacency"],
+ ],
+ "type": "dict",
+ },
+ "apply_weight": {
+ "mutually_exclusive": [
+ ["bandwidth", "default_weight"],
+ ],
+ "options": {
+ "bandwidth": {"type": "int"},
+ "default_weight": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "areas": {
+ "elements": "dict",
+ "options": {
+ "area_id": {"required": True, "type": "str"},
+ "authentication": {
+ "mutually_exclusive": [
+ [
+ "keychain",
+ "message_digest",
+ "no_auth",
+ ],
+ ],
+ "options": {
+ "keychain": {
+ "type": "str",
+ "no_log": False,
+ },
+ "message_digest": {
+ "options": {
+ "keychain": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ "type": "dict",
+ },
+ "no_auth": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "authentication_key": {
+ "mutually_exclusive": [
+ ["clear", "encrypted"],
+ ],
+ "options": {
+ "clear": {"type": "str"},
+ "encrypted": {"type": "str"},
+ "password": {
+ "type": "str",
+ "no_log": True,
+ },
+ },
+ "type": "dict",
+ "no_log": True,
+ },
+ "bfd": {
+ "options": {
+ "fast_detect": {
+ "options": {
+ "set": {"type": "bool"},
+ "strict_mode": {
+ "type": "bool",
+ },
+ },
+ "type": "dict",
+ },
+ "minimum_interval": {"type": "int"},
+ "multiplier": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "cost": {"type": "int"},
+ "dead_interval": {"type": "int"},
+ "default_cost": {"type": "int"},
+ "hello_interval": {"type": "int"},
+ "mpls": {
+ "options": {
+ "ldp": {
+ "options": {
+ "auto_config": {
+ "type": "bool",
+ },
+ "sync": {"type": "bool"},
+ "sync_igp_shortcuts": {
+ "type": "bool",
+ },
+ },
+ "type": "dict",
+ },
+ "traffic_eng": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "mtu_ignore": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "nssa": {
+ "options": {
+ "default_information_originate": {
+ "options": {
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "no_redistribution": {"type": "bool"},
+ "no_summary": {"type": "bool"},
+ "set": {"type": "bool"},
+ "translate": {
+ "options": {
+ "type7": {
+ "options": {
+ "always": {
+ "type": "bool",
+ },
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "ranges": {
+ "elements": "dict",
+ "mutually_exclusive": [
+ ["advertise", "not_advertise"],
+ ],
+ "options": {
+ "address": {
+ "required": True,
+ "type": "str",
+ },
+ "advertise": {"type": "bool"},
+ "not_advertise": {"type": "bool"},
+ },
+ "type": "list",
+ },
+ "route_policy": {
+ "elements": "dict",
+ "options": {
+ "direction": {
+ "choices": ["in", "out"],
+ "type": "str",
+ },
+ "parameters": {
+ "elements": "str",
+ "type": "list",
+ },
+ },
+ "type": "list",
+ },
+ "stub": {
+ "options": {
+ "no_summary": {"type": "bool"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "transmit_delay": {"type": "int"},
+ "virtual_link": {
+ "elements": "dict",
+ "options": {
+ "authentication": {
+ "mutually_exclusive": [
+ [
+ "keychain",
+ "message_digest",
+ "no_auth",
+ ],
+ ],
+ "options": {
+ "keychain": {
+ "type": "str",
+ "no_log": False,
+ },
+ "message_digest": {
+ "options": {
+ "keychain": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ "type": "dict",
+ },
+ "no_auth": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "authentication_key": {
+ "mutually_exclusive": [
+ ["clear", "encrypted"],
+ ],
+ "options": {
+ "clear": {"type": "str"},
+ "encrypted": {"type": "str"},
+ "password": {
+ "type": "str",
+ "no_log": True,
+ },
+ },
+ "type": "dict",
+ "no_log": True,
+ },
+ "dead_interval": {"type": "int"},
+ "hello_interval": {"type": "int"},
+ "id": {
+ "required": True,
+ "type": "str",
+ },
+ "message_digest_key": {
+ "options": {
+ "id": {
+ "required": True,
+ "type": "int",
+ },
+ "md5": {
+ "mutually_exclusive": [
+ ["clear", "encrypted"],
+ ],
+ "options": {
+ "clear": {
+ "type": "bool",
+ },
+ "encrypted": {
+ "type": "bool",
+ },
+ "password": {
+ "type": "str",
+ "no_log": True,
+ },
+ },
+ "type": "dict",
+ "no_log": False,
+ },
+ },
+ "type": "dict",
+ "no_log": False,
+ },
+ "retransmit_interval": {"type": "int"},
+ "transmit_delay": {"type": "int"},
+ },
+ "type": "list",
+ },
+ },
+ "type": "list",
+ },
+ "authentication": {
+ "mutually_exclusive": [
+ ["keychain", "message_digest", "no_auth"],
+ ],
+ "options": {
+ "keychain": {"type": "str", "no_log": False},
+ "message_digest": {
+ "options": {
+ "keychain": {
+ "type": "str",
+ "no_log": False,
+ },
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "no_auth": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "authentication_key": {
+ "mutually_exclusive": [["clear", "encrypted"]],
+ "options": {
+ "clear": {"type": "bool"},
+ "encrypted": {"type": "bool"},
+ "password": {"type": "str", "no_log": True},
+ },
+ "type": "dict",
+ "no_log": True,
+ },
+ "auto_cost": {
+ "mutually_exclusive": [
+ ["reference_bandwidth", "disable"],
+ ],
+ "options": {
+ "disable": {"type": "bool"},
+ "reference_bandwidth": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "bfd": {
+ "options": {
+ "fast_detect": {
+ "options": {
+ "set": {"type": "bool"},
+ "strict_mode": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "minimum_interval": {"type": "int"},
+ "multiplier": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "capability": {
+ "options": {
+ "opaque": {
+ "mutually_exclusive": [["set", "disable"]],
+ "options": {
+ "disable": {"type": "bool"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "type7": {"type": "str"},
+ },
+ "type": "dict",
+ },
+ "cost": {"type": "int"},
+ "database_filter": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "dead_interval": {"type": "int"},
+ "default_information_originate": {
+ "options": {
+ "always": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "default_metric": {"type": "int"},
+ "demand_circuit": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "distance": {
+ "options": {
+ "admin_distance": {
+ "elements": "dict",
+ "options": {
+ "access_list": {"type": "str"},
+ "source": {"type": "str"},
+ "value": {"type": "int"},
+ "wildcard": {"type": "str"},
+ },
+ "required_together": [
+ ["value", "source", "wildcard"],
+ ],
+ "type": "list",
+ },
+ "ospf_distance": {
+ "options": {
+ "external": {"type": "int"},
+ "inter_area": {"type": "int"},
+ "intra_area": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "distribute_bgp_ls": {
+ "options": {
+ "instance_id": {"type": "int"},
+ "throttle": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "distribute_link_state": {
+ "options": {
+ "instance_id": {"type": "int"},
+ "throttle": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "distribute_list": {
+ "elements": "dict",
+ "mutually_exclusive": [
+ ["access_list", "route_policy"],
+ ],
+ "options": {
+ "access_list": {"type": "str"},
+ "direction": {
+ "choices": ["in", "out"],
+ "type": "str",
+ },
+ "outgoing_params": {
+ "options": {
+ "id": {"type": "str"},
+ "route_type": {
+ "choices": [
+ "bgp",
+ "connected",
+ "dagr",
+ "ospf",
+ "static",
+ ],
+ "type": "str",
+ },
+ },
+ "type": "dict",
+ },
+ "route_policy": {"type": "str"},
+ },
+ "type": "list",
+ },
+ "external_out": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "flood_reduction": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "hello_interval": {"type": "int"},
+ "ignore_lsa_mospf": {"type": "bool"},
+ "link_down_fast_detect": {"type": "bool"},
+ "log_adjacency_changes": {
+ "options": {
+ "detail": {"type": "bool"},
+ "disable": {"type": "bool"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "loopback_stub_network": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "max_lsa": {
+ "options": {
+ "ignore_count": {"type": "int"},
+ "ignore_time": {"type": "int"},
+ "reset_time": {"type": "int"},
+ "threshold": {"type": "int"},
+ "warning_only": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "max_metric": {
+ "options": {
+ "router_lsa": {
+ "options": {
+ "external_lsa": {
+ "options": {
+ "max_metric_value": {
+ "type": "int",
+ },
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "include_stub": {"type": "bool"},
+ "on_startup": {
+ "options": {
+ "set": {"type": "bool"},
+ "wait_for_bgp_asn": {
+ "type": "int",
+ },
+ "wait_period": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "set": {"type": "bool"},
+ "summary_lsa": {
+ "options": {
+ "max_metric_value": {
+ "type": "int",
+ },
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "message_digest_key": {
+ "options": {
+ "id": {"required": True, "type": "int"},
+ "md5": {
+ "mutually_exclusive": [
+ ["clear", "encrypted"],
+ ],
+ "options": {
+ "clear": {"type": "bool"},
+ "encrypted": {"type": "bool"},
+ "password": {
+ "type": "str",
+ "no_log": True,
+ },
+ },
+ "required": True,
+ "type": "dict",
+ "no_log": False,
+ },
+ },
+ "type": "dict",
+ "no_log": False,
+ },
+ "microloop_avoidance": {
+ "mutually_exclusive": [
+ [
+ "protected",
+ "rib_update_delay",
+ "segment_routing",
+ ],
+ ],
+ "options": {
+ "protected": {"type": "bool"},
+ "rib_update_delay": {"type": "int"},
+ "segment_routing": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "monitor_convergence": {
+ "options": {
+ "prefix_list": {"type": "str"},
+ "track_external_routes": {"type": "bool"},
+ "track_ip_frr": {"type": "bool"},
+ "track_summary_routes": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "mpls": {
+ "options": {
+ "ldp": {
+ "options": {
+ "auto_config": {"type": "bool"},
+ "sync": {"type": "bool"},
+ "sync_igp_shortcuts": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "traffic_eng": {
+ "options": {
+ "autoroute_exclude": {
+ "options": {
+ "parameters": {
+ "elements": "str",
+ "type": "list",
+ },
+ "route_policy": {
+ "type": "str",
+ },
+ },
+ "type": "dict",
+ },
+ "igp_intact": {"type": "bool"},
+ "ldp_sync_update": {"type": "bool"},
+ "multicast_intact": {"type": "bool"},
+ "router_id": {"type": "str"},
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "mtu_ignore": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "network": {
+ "options": {
+ "broadcast": {"type": "bool"},
+ "non_broadcast": {"type": "bool"},
+ "point_to_multipoint": {"type": "bool"},
+ "point_to_point": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "nsf": {
+ "options": {
+ "cisco": {
+ "options": {
+ "enforce_global": {"type": "bool"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "flush_delay_time": {"type": "int"},
+ "ietf": {
+ "options": {
+ "helper_disable": {"type": "bool"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "interval": {"type": "int"},
+ "lifetime": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "nsr": {"type": "bool"},
+ "packet_size": {"type": "int"},
+ "passive": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "prefix_suppression": {
+ "options": {
+ "secondary_address": {"type": "bool"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "priority": {"type": "int"},
+ "process_id": {"required": True, "type": "str"},
+ "protocol_shutdown": {
+ "options": {
+ "host_mode": {"type": "bool"},
+ "limit": {
+ "options": {
+ "high": {"type": "int"},
+ "low": {"type": "int"},
+ "medium": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "on_reload": {"type": "bool"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "redistribute": {
+ "options": {
+ "id": {"type": "str"},
+ "level": {
+ "choices": [1, 2, 12],
+ "type": "int",
+ },
+ "lsa_type_summary": {"type": "bool"},
+ "match": {"type": "str"},
+ "metric": {"type": "int"},
+ "metric_type": {
+ "choices": [1, 2],
+ "type": "int",
+ },
+ "nssa_only": {"type": "bool"},
+ "preserve_med": {"type": "bool"},
+ "route_policy": {
+ "options": {
+ "name": {"type": "str"},
+ "parameters": {
+ "elements": "str",
+ "type": "list",
+ },
+ },
+ "type": "dict",
+ },
+ "route_type": {
+ "choices": [
+ "application",
+ "bgp",
+ "connected",
+ "dagr",
+ "eigrp",
+ "isis",
+ "mobile",
+ "ospf",
+ "rip",
+ "static",
+ "subscriber",
+ ],
+ "type": "str",
+ },
+ "tag": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "retransmit_interval": {"type": "int"},
+ "router_id": {"type": "str"},
+ "security_ttl": {
+ "options": {
+ "hops": {"type": "int"},
+ "set": {"type": "bool"},
+ },
+ "type": "dict",
+ },
+ "summary_in": {
+ "choices": ["enable", "disable"],
+ "type": "str",
+ },
+ "summary_prefix": {
+ "elements": "dict",
+ "options": {
+ "not_advertise": {"type": "bool"},
+ "prefix": {"required": True, "type": "str"},
+ "tag": {"type": "int"},
+ },
+ "type": "list",
+ },
+ "timers": {
+ "options": {
+ "graceful_shutdown": {
+ "options": {
+ "initial_delay": {"type": "int"},
+ "retain_routes": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "lsa": {
+ "options": {
+ "group_pacing": {"type": "int"},
+ "min_arrival": {"type": "int"},
+ "refresh": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "pacing_flood": {"type": "int"},
+ "throttle": {
+ "options": {
+ "fast_reroute": {"type": "int"},
+ "lsa_all": {
+ "options": {
+ "initial_delay": {
+ "type": "int",
+ },
+ "max_delay": {"type": "int"},
+ "min_delay": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "spf": {
+ "options": {
+ "change_delay": {
+ "type": "int",
+ },
+ "max_wait": {"type": "int"},
+ "second_delay": {
+ "type": "int",
+ },
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ },
+ "type": "dict",
+ },
+ "transmit_delay": {"type": "int"},
+ "weight": {"type": "int"},
+ },
+ "type": "list",
+ },
+ },
+ "type": "dict",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "rendered",
+ "parsed",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv3/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv3/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv3/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv3/ospfv3.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv3/ospfv3.py
new file mode 100644
index 00000000..a72599b9
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ospfv3/ospfv3.py
@@ -0,0 +1,1439 @@
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The arg spec for the iosxr_ospfv3 module
+"""
+
+
+class Ospfv3Args(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_ospfv3 module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "running_config": {"type": "str"},
+ "config": {
+ "type": "dict",
+ "options": {
+ "processes": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "process_id": {"type": "str", "required": True},
+ "address_family_unicast": {"type": "bool"},
+ "authentication": {
+ "type": "dict",
+ "options": {
+ "disable": {"type": "bool", "default": False},
+ "ipsec": {
+ "type": "dict",
+ "options": {
+ "spi": {"type": "int"},
+ "algorithim_type": {
+ "type": "str",
+ "choices": ["md5", "sha1"],
+ },
+ "key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "clear_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "password_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ },
+ },
+ },
+ "auto_cost": {
+ "type": "dict",
+ "options": {
+ "reference_bandwidth": {"type": "int"},
+ "disable": {"type": "bool"},
+ },
+ },
+ "bfd": {
+ "type": "dict",
+ "options": {
+ "fast_detect": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "strict_mode": {"type": "bool"},
+ },
+ },
+ "minimum_interval": {"type": "int"},
+ "multiplier": {"type": "int"},
+ },
+ },
+ "areas": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "area_id": {"type": "str", "required": True},
+ "authentication": {
+ "type": "dict",
+ "options": {
+ "disable": {
+ "type": "bool",
+ "default": False,
+ },
+ "ipsec": {
+ "type": "dict",
+ "options": {
+ "spi": {"type": "int"},
+ "algorithim_type": {
+ "type": "str",
+ "choices": ["md5", "sha1"],
+ },
+ "key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "clear_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "password_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ },
+ },
+ },
+ "bfd": {
+ "type": "dict",
+ "options": {
+ "fast_detect": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "strict_mode": {
+ "type": "bool",
+ },
+ },
+ },
+ "minimum_interval": {"type": "int"},
+ "multiplier": {"type": "int"},
+ },
+ },
+ "cost": {"type": "int"},
+ "database_filter": {
+ "type": "dict",
+ "options": {
+ "all_outgoing_lsa": {"type": "bool"},
+ },
+ },
+ "dead_interval": {"type": "int"},
+ "default_cost": {"type": "int"},
+ "demand_circuit": {"type": "bool"},
+ "distrinbute_rib_prefix_list_name": {
+ "type": "str",
+ },
+ "fast_reroute": {
+ "type": "dict",
+ "options": {
+ "disabled": {"type": "bool"},
+ "per_link": {
+ "type": "dict",
+ "options": {
+ "information_type": {
+ "type": "str",
+ "choices": [
+ "exclude",
+ "lfa_candidate",
+ ],
+ },
+ "use_candidate_only": {
+ "type": "bool",
+ },
+ "interface": {
+ "type": "dict",
+ "options": {
+ "bvi": {
+ "type": "list",
+ "elements": "int",
+ },
+ "bundle_ether": {
+ "type": "list",
+ "elements": "int",
+ },
+ "pos_int": {
+ "type": "list",
+ "elements": "int",
+ },
+ "fast_ethernet": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fiftygige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fortygige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fourhundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "gigabitethernet": {
+ "type": "list",
+ "elements": "str",
+ },
+ "hundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "mgmteth": {
+ "type": "list",
+ "elements": "str",
+ },
+ "multilink": {
+ "type": "list",
+ "elements": "str",
+ },
+ "pw_ether": {
+ "type": "list",
+ "elements": "int",
+ },
+ "pw_iw": {
+ "type": "list",
+ "elements": "int",
+ },
+ "srp": {
+ "type": "list",
+ "elements": "str",
+ },
+ "serial": {
+ "type": "list",
+ "elements": "str",
+ },
+ "tengige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "twentyfivegige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "twohundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "nve": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_ip": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_ipsec": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_mte": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_mpls": {
+ "type": "int",
+ },
+ },
+ },
+ },
+ },
+ "per_prefix": {
+ "type": "dict",
+ "options": {
+ "information_type": {
+ "type": "str",
+ "choices": [
+ "exclude",
+ "lfa_candidate",
+ ],
+ },
+ "use_candidate_only": {
+ "type": "bool",
+ },
+ "interface": {
+ "type": "dict",
+ "options": {
+ "bvi": {
+ "type": "list",
+ "elements": "int",
+ },
+ "bundle_ether": {
+ "type": "list",
+ "elements": "int",
+ },
+ "pos_int": {
+ "type": "list",
+ "elements": "int",
+ },
+ "fast_ethernet": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fiftygige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fortygige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fourhundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "gigabitethernet": {
+ "type": "list",
+ "elements": "str",
+ },
+ "hundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "mgmteth": {
+ "type": "list",
+ "elements": "str",
+ },
+ "multilink": {
+ "type": "list",
+ "elements": "str",
+ },
+ "pw_ether": {
+ "type": "list",
+ "elements": "int",
+ },
+ "pw_iw": {
+ "type": "list",
+ "elements": "int",
+ },
+ "srp": {
+ "type": "list",
+ "elements": "str",
+ },
+ "serial": {
+ "type": "list",
+ "elements": "str",
+ },
+ "tengige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "twentyfivegige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "twohundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "nve": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_ip": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_ipsec": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_mte": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_mpls": {
+ "type": "int",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "flood_reduction": {"type": "bool"},
+ "hello_interval": {"type": "int"},
+ "instance_id": {"type": "int"},
+ "mtu_ignore": {"type": "bool"},
+ "mpls_ldp_sync": {"type": "bool"},
+ "network": {
+ "type": "str",
+ "choices": [
+ "broadcast",
+ "non-broadcast",
+ "point-to-multipoint",
+ "point-to-point",
+ ],
+ },
+ "nssa": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "default_information_originate": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ },
+ },
+ "no_redistribution": {"type": "bool"},
+ "no_summary": {"type": "bool"},
+ "translate": {
+ "type": "dict",
+ "options": {
+ "type7": {
+ "type": "dict",
+ "options": {
+ "always": {
+ "type": "bool",
+ "required": True,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "packet_size": {"type": "int"},
+ "passive": {"type": "bool"},
+ "prefix_suppression": {"type": "bool"},
+ "priority": {"type": "int"},
+ "ranges": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "address": {
+ "type": "str",
+ "required": True,
+ },
+ "cost": {"type": "int"},
+ "advertise": {"type": "bool"},
+ "not_advertise": {"type": "bool"},
+ },
+ },
+ "retransmit_interval": {"type": "int"},
+ "stub": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "no_summary": {"type": "bool"},
+ },
+ },
+ "transmit_delay": {"type": "int"},
+ "virtual_link": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "id": {
+ "type": "str",
+ "required": True,
+ },
+ "authentication": {
+ "type": "dict",
+ "options": {
+ "disable": {
+ "type": "bool",
+ "default": False,
+ },
+ "ipsec": {
+ "type": "dict",
+ "options": {
+ "spi": {"type": "int"},
+ "algorithim_type": {
+ "type": "str",
+ "choices": [
+ "md5",
+ "sha1",
+ ],
+ },
+ "key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "clear_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "password_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ },
+ },
+ },
+ "dead_interval": {"type": "int"},
+ "hello_interval": {"type": "int"},
+ "retransmit_interval": {"type": "int"},
+ "transmit_delay": {"type": "int"},
+ "encryption": {
+ "type": "dict",
+ "options": {
+ "disable": {
+ "type": "bool",
+ "default": False,
+ },
+ "ipsec": {
+ "type": "dict",
+ "options": {
+ "spi": {"type": "int"},
+ "esp": {
+ "type": "dict",
+ "options": {
+ "triple_des": {
+ "type": "dict",
+ "options": {
+ "key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "clear_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "password_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ },
+ "aes": {
+ "type": "dict",
+ "options": {
+ "algorithim_type": {
+ "type": "str",
+ "choices": [
+ "192",
+ "256",
+ ],
+ },
+ "key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "clear_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "password_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ },
+ "des": {
+ "type": "dict",
+ "options": {
+ "key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "clear_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "password_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ },
+ "null_encryption": {
+ "type": "dict",
+ "options": {
+ "authentication": {
+ "type": "dict",
+ "options": {
+ "algorithim_type": {
+ "type": "str",
+ "choices": [
+ "md5",
+ "sha1",
+ ],
+ },
+ "key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "clear_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "password_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "encryption": {
+ "type": "dict",
+ "options": {
+ "disable": {
+ "type": "bool",
+ "default": False,
+ },
+ "ipsec": {
+ "type": "dict",
+ "options": {
+ "spi": {"type": "int"},
+ "esp": {
+ "type": "dict",
+ "options": {
+ "triple_des": {
+ "type": "dict",
+ "options": {
+ "key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "clear_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "password_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ },
+ "aes": {
+ "type": "dict",
+ "options": {
+ "algorithim_type": {
+ "type": "str",
+ "choices": [
+ "192",
+ "256",
+ ],
+ },
+ "key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "clear_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "password_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ },
+ "des": {
+ "type": "dict",
+ "options": {
+ "key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "clear_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "password_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ },
+ "null_encryption": {
+ "type": "dict",
+ "options": {
+ "authentication": {
+ "type": "dict",
+ "options": {
+ "algorithim_type": {
+ "type": "str",
+ "choices": [
+ "md5",
+ "sha1",
+ ],
+ },
+ "key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "clear_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "password_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "capability": {
+ "type": "dict",
+ "options": {
+ "type7": {
+ "type": "dict",
+ "options": {
+ "prefer": {"type": "bool"},
+ "translate": {"type": "bool"},
+ },
+ },
+ },
+ },
+ "cost": {"type": "int"},
+ "database_filter": {
+ "type": "dict",
+ "options": {"all_outgoing_lsa": {"type": "bool"}},
+ },
+ "dead_interval": {"type": "int"},
+ "default_information_originate": {
+ "type": "dict",
+ "options": {
+ "always": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ "set": {"type": "bool"},
+ },
+ },
+ "default_metric": {"type": "int"},
+ "demand_circuit": {"type": "bool"},
+ "distance": {
+ "type": "dict",
+ "options": {
+ "admin_distance": {"type": "int"},
+ "ospfv3_distance": {
+ "type": "dict",
+ "options": {
+ "external": {"type": "int"},
+ "inter_area": {"type": "int"},
+ "intra_area": {"type": "int"},
+ },
+ },
+ },
+ },
+ "distribute_list": {
+ "type": "dict",
+ "options": {
+ "prefix_list": {
+ "type": "list",
+ "elements": "str",
+ "options": {
+ "name": {"type": "str"},
+ "in": {"type": "bool"},
+ "out": {"type": "bool"},
+ },
+ },
+ },
+ },
+ "encryption": {
+ "type": "dict",
+ "options": {
+ "disable": {"type": "bool", "default": False},
+ "ipsec": {
+ "type": "dict",
+ "options": {
+ "spi": {"type": "int"},
+ "esp": {
+ "type": "dict",
+ "options": {
+ "triple_des": {
+ "type": "dict",
+ "options": {
+ "key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "clear_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "password_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ },
+ "aes": {
+ "type": "dict",
+ "options": {
+ "algorithim_type": {
+ "type": "str",
+ "choices": [
+ "192",
+ "256",
+ ],
+ },
+ "key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "clear_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "password_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ },
+ "des": {
+ "type": "dict",
+ "options": {
+ "key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "clear_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "password_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ },
+ "null_encryption": {
+ "type": "dict",
+ "options": {
+ "authentication": {
+ "type": "dict",
+ "options": {
+ "algorithim_type": {
+ "type": "str",
+ "choices": [
+ "md5",
+ "sha1",
+ ],
+ },
+ "key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "clear_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ "password_key": {
+ "type": "str",
+ "no_log": False,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "fast_reroute": {
+ "type": "dict",
+ "options": {
+ "disabled": {"type": "bool"},
+ "per_link": {
+ "type": "dict",
+ "options": {
+ "information_type": {
+ "type": "str",
+ "choices": [
+ "exclude",
+ "lfa_candidate",
+ ],
+ },
+ "use_candidate_only": {"type": "bool"},
+ "interface": {
+ "type": "dict",
+ "options": {
+ "bvi": {
+ "type": "list",
+ "elements": "int",
+ },
+ "bundle_ether": {
+ "type": "list",
+ "elements": "int",
+ },
+ "pos_int": {
+ "type": "list",
+ "elements": "int",
+ },
+ "fast_ethernet": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fiftygige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fortygige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fourhundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "gigabitethernet": {
+ "type": "list",
+ "elements": "str",
+ },
+ "hundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "mgmteth": {
+ "type": "list",
+ "elements": "str",
+ },
+ "multilink": {
+ "type": "list",
+ "elements": "str",
+ },
+ "pw_ether": {
+ "type": "list",
+ "elements": "int",
+ },
+ "pw_iw": {
+ "type": "list",
+ "elements": "int",
+ },
+ "srp": {
+ "type": "list",
+ "elements": "str",
+ },
+ "serial": {
+ "type": "list",
+ "elements": "str",
+ },
+ "tengige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "twentyfivegige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "twohundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "nve": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_ip": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_ipsec": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_mte": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_mpls": {"type": "int"},
+ },
+ },
+ },
+ },
+ "per_prefix": {
+ "type": "dict",
+ "options": {
+ "information_type": {
+ "type": "str",
+ "choices": [
+ "exclude",
+ "lfa_candidate",
+ ],
+ },
+ "use_candidate_only": {"type": "bool"},
+ "interface": {
+ "type": "dict",
+ "options": {
+ "bvi": {
+ "type": "list",
+ "elements": "int",
+ },
+ "bundle_ether": {
+ "type": "list",
+ "elements": "int",
+ },
+ "post_int": {
+ "type": "list",
+ "elements": "int",
+ },
+ "fast_ethernet": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fiftygige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fortygige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "fourhundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "gigabitethernet": {
+ "type": "list",
+ "elements": "str",
+ },
+ "hundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "mgmteth": {
+ "type": "list",
+ "elements": "str",
+ },
+ "multilink": {
+ "type": "list",
+ "elements": "str",
+ },
+ "pw_ether": {
+ "type": "list",
+ "elements": "int",
+ },
+ "pw_iw": {
+ "type": "list",
+ "elements": "int",
+ },
+ "srp": {
+ "type": "list",
+ "elements": "str",
+ },
+ "serial": {
+ "type": "list",
+ "elements": "str",
+ },
+ "tengige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "twentyfivegige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "twohundredgige": {
+ "type": "list",
+ "elements": "str",
+ },
+ "nve": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_ip": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_ipsec": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_mte": {
+ "type": "list",
+ "elements": "int",
+ },
+ "tunnel_mpls": {"type": "int"},
+ },
+ },
+ },
+ },
+ },
+ },
+ "flood_reduction": {"type": "bool"},
+ "graceful_restart": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "helper_disable": {"type": "bool"},
+ "min_interval": {"type": "int"},
+ "max_interval": {"type": "int"},
+ },
+ },
+ "hello_interval": {"type": "int"},
+ "ignore_mospf_type6_lsa": {"type": "bool"},
+ "instance_id": {"type": "int"},
+ "log_adjacency_changes": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "disable": {"type": "bool"},
+ "detail": {"type": "bool"},
+ },
+ },
+ "maximum": {
+ "type": "dict",
+ "options": {
+ "interfaces": {"type": "int"},
+ "paths": {"type": "int"},
+ "redistributed_prefixes": {"type": "int"},
+ },
+ },
+ "mpls_ldp_sync": {"type": "bool"},
+ "mtu_ignore": {"type": "bool"},
+ "network": {
+ "type": "str",
+ "choices": [
+ "broadcast",
+ "non-broadcast",
+ "point-to-multipoint",
+ "point-to-point",
+ ],
+ },
+ "nsr": {"type": "bool"},
+ "packet_size": {"type": "int"},
+ "passive": {"type": "bool"},
+ "prefix_suppression": {"type": "bool"},
+ "priority": {"type": "int"},
+ "protocol_shutdown": {"type": "bool"},
+ "redistribute": {
+ "type": "dict",
+ "options": {
+ "application": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "id": {
+ "type": "str",
+ "required": True,
+ },
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ "bgp": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "id": {
+ "type": "int",
+ "required": True,
+ },
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "preserved_med": {"type": "str"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ "connected": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ "eigrp": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "id": {
+ "type": "int",
+ "required": True,
+ },
+ "set": {"type": "bool"},
+ "match": {
+ "type": "str",
+ "choices": [
+ "external",
+ "internal",
+ ],
+ },
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ "isis": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "id": {
+ "type": "str",
+ "required": True,
+ },
+ "set": {"type": "bool"},
+ "level": {
+ "type": "str",
+ "choices": [
+ "level-1",
+ "level-1-2",
+ "level-2",
+ ],
+ },
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ "mobile": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ "ospfv3": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "id": {
+ "type": "str",
+ "required": True,
+ },
+ "set": {"type": "bool"},
+ "match": {
+ "type": "dict",
+ "options": {
+ "external": {
+ "type": "int",
+ "choices": ["1", "2"],
+ },
+ "nssa_external": {
+ "type": "int",
+ "choices": ["1", "2"],
+ },
+ "internal": {"type": "bool"},
+ },
+ },
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ "static": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ "subscriber": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ "metric_type": {"type": "int"},
+ "route_policy": {"type": "str"},
+ "tag": {"type": "int"},
+ },
+ },
+ },
+ },
+ "retransmit_interval": {"type": "int"},
+ "router_id": {"type": "str"},
+ "spf_prefix_priority": {
+ "type": "dict",
+ "options": {
+ "disable": {"type": "bool"},
+ "route_policy": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "value": {"type": "str"},
+ },
+ },
+ },
+ },
+ "stub_router": {
+ "type": "dict",
+ "options": {
+ "router_lsa": {
+ "type": "dict",
+ "options": {
+ "advertise_with": {
+ "type": "str",
+ "choices": [
+ "max-metric",
+ "r-bit",
+ "v6-bit",
+ ],
+ },
+ "always": {"type": "bool"},
+ "external_lsa": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ },
+ },
+ "include_stub": {"type": "bool"},
+ "on_proc_migration": {"type": "int"},
+ "on_proc_restart": {"type": "int"},
+ "on_startup": {
+ "type": "dict",
+ "options": {
+ "time": {"type": "int"},
+ "wait_for_bgp": {
+ "type": "bool",
+ },
+ },
+ },
+ "on_switchover": {"type": "int"},
+ "summary_lsa": {
+ "type": "dict",
+ "options": {
+ "set": {"type": "bool"},
+ "metric": {"type": "int"},
+ },
+ },
+ },
+ },
+ },
+ },
+ "summary_prefix": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "prefix": {"type": "str", "required": True},
+ "not_advertise": {"type": "bool"},
+ "tag": {"type": "int"},
+ },
+ },
+ "timers": {
+ "type": "dict",
+ "options": {
+ "lsa_arrival": {"type": "int"},
+ "pacing": {
+ "type": "dict",
+ "options": {
+ "flood": {"type": "int"},
+ "lsa_group": {"type": "int"},
+ "retransmission": {"type": "int"},
+ },
+ },
+ "throttle": {
+ "type": "dict",
+ "options": {
+ "lsa": {
+ "type": "dict",
+ "options": {
+ "all_lsa_initial": {
+ "type": "int",
+ },
+ "all_lsa_minimum": {
+ "type": "int",
+ },
+ },
+ },
+ "spf": {
+ "type": "dict",
+ "options": {
+ "spf_initial": {"type": "int"},
+ "spf_minimum": {"type": "int"},
+ },
+ },
+ },
+ },
+ },
+ },
+ "trace": {
+ "type": "dict",
+ "options": {
+ "size": {"type": "str"},
+ "value": {"type": "int"},
+ },
+ },
+ "transmit_delay": {"type": "int"},
+ },
+ },
+ },
+ },
+ "state": {
+ "type": "str",
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "rendered",
+ "parsed",
+ ],
+ "default": "merged",
+ },
+ } # pylint: disable=C0301
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ping/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ping/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ping/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ping/ping.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ping/ping.py
new file mode 100644
index 00000000..6b0f04ce
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/ping/ping.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+# Copyright 2022 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the
+# cli_rm_builder.
+#
+# Manually editing this file is not advised.
+#
+# To update the argspec make the desired changes
+# in the module docstring and re-run
+# cli_rm_builder.
+#
+#############################################
+
+"""
+The arg spec for the iosxr_ping module
+"""
+
+
+class PingArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_ping module"""
+
+ argument_spec = {
+ "count": {"type": "int"},
+ "afi": {"choices": ["ipv4", "ipv6"], "default": "ipv4", "type": "str"},
+ "dest": {"required": True, "type": "str"},
+ "df_bit": {"default": False, "type": "bool"},
+ "sweep": {"default": False, "type": "bool"},
+ "validate": {"default": False, "type": "bool"},
+ "source": {"type": "str"},
+ "size": {"type": "int"},
+ "state": {
+ "choices": ["absent", "present"],
+ "default": "present",
+ "type": "str",
+ },
+ "vrf": {"type": "str"},
+ } # pylint: disable=C0301
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/prefix_lists/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/prefix_lists/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/prefix_lists/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/prefix_lists/prefix_lists.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/prefix_lists/prefix_lists.py
new file mode 100644
index 00000000..f8e5a1da
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/prefix_lists/prefix_lists.py
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+# Copyright 2022 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the
+# cli_rm_builder.
+#
+# Manually editing this file is not advised.
+#
+# To update the argspec make the desired changes
+# in the module docstring and re-run
+# cli_rm_builder.
+#
+#############################################
+
+"""
+The arg spec for the iosxr_prefix_lists module
+"""
+
+
+class Prefix_listsArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_prefix_lists module"""
+
+ argument_spec = {
+ "running_config": {"type": "str"},
+ "config": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "afi": {"type": "str", "choices": ["ipv4", "ipv6"]},
+ "prefix_lists": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "entries": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "sequence": {"type": "int"},
+ "action": {
+ "type": "str",
+ "choices": ["permit", "deny", "remark"],
+ },
+ "description": {"type": "str"},
+ "prefix": {"type": "str"},
+ "eq": {"type": "int"},
+ "ge": {"type": "int"},
+ "le": {"type": "int"},
+ },
+ },
+ },
+ },
+ },
+ },
+ "state": {
+ "type": "str",
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "parsed",
+ "gathered",
+ "rendered",
+ ],
+ "default": "merged",
+ },
+ } # pylint: disable=C0301
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/snmp_server/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/snmp_server/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/snmp_server/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/snmp_server/snmp_server.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/snmp_server/snmp_server.py
new file mode 100644
index 00000000..a51f04c0
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/snmp_server/snmp_server.py
@@ -0,0 +1,574 @@
+# -*- coding: utf-8 -*-
+# Copyright 2022 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the
+# cli_rm_builder.
+#
+# Manually editing this file is not advised.
+#
+# To update the argspec make the desired changes
+# in the module docstring and re-run
+# cli_rm_builder.
+#
+#############################################
+
+"""
+The arg spec for the iosxr_snmp_server module
+"""
+
+
+class Snmp_serverArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_snmp_server module"""
+
+ argument_spec = {
+ "config": {
+ "type": "dict",
+ "options": {
+ "chassis_id": {"type": "str"},
+ "communities": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "acl_v4": {"type": "str"},
+ "acl_v6": {"type": "str"},
+ "ro": {"type": "bool"},
+ "rw": {"type": "bool"},
+ "sdrowner": {"type": "bool"},
+ "systemowner": {"type": "bool"},
+ "v4_acl": {"type": "str"},
+ },
+ },
+ "community_maps": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "context": {"type": "str"},
+ "security_name": {"type": "str"},
+ "target_list": {"type": "str"},
+ },
+ },
+ "correlator": {
+ "type": "dict",
+ "options": {
+ "buffer_size": {"type": "int"},
+ "rules": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "rule_name": {"type": "str"},
+ "timeout": {"type": "int"},
+ },
+ },
+ "rule_sets": {
+ "type": "list",
+ "elements": "dict",
+ "options": {"name": {"type": "str"}},
+ },
+ },
+ },
+ "contact": {"type": "str"},
+ "context": {"type": "list", "elements": "str"},
+ "drop": {
+ "type": "dict",
+ "options": {
+ "unknown_user": {"type": "bool"},
+ "report_IPv4": {"type": "str"},
+ "report_IPv6": {"type": "str"},
+ },
+ },
+ "engineid": {
+ "type": "dict",
+ "options": {"local": {"type": "str"}},
+ },
+ "groups": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "group": {"type": "str"},
+ "version": {
+ "type": "str",
+ "choices": ["v1", "v3", "v2c"],
+ },
+ "context": {"type": "str"},
+ "notify": {"type": "str"},
+ "read": {"type": "str"},
+ "write": {"type": "str"},
+ "acl_v4": {"type": "str", "aliases": ["Ipv4_acl"]},
+ "acl_v6": {"type": "str", "aliases": ["Ipv6_acl"]},
+ "v4_acl": {"type": "str"},
+ },
+ },
+ "hosts": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "host": {"type": "str"},
+ "community": {"type": "str"},
+ "udp_port": {"type": "int"},
+ "informs": {"type": "bool"},
+ "traps": {"type": "bool"},
+ "version": {
+ "type": "str",
+ "choices": ["1", "2c", "3"],
+ },
+ },
+ },
+ "ifindex": {"type": "bool"},
+ "ifmib": {
+ "type": "dict",
+ "options": {
+ "ifalias_long": {"type": "bool"},
+ "internal_cache_max_duration": {"type": "int"},
+ "ipsubscriber": {"type": "bool"},
+ "stats": {"type": "bool"},
+ },
+ },
+ "inform": {
+ "options": {
+ "pending": {"type": "int"},
+ "retries": {"type": "int"},
+ "timeout": {"type": "int"},
+ },
+ "type": "dict",
+ },
+ "interfaces": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "notification_linkupdown_disable": {"type": "bool"},
+ "index_persistent": {"type": "bool"},
+ },
+ },
+ "ipv4": {
+ "type": "dict",
+ "options": {
+ "dscp": {"type": "str"},
+ "precedence": {"type": "str"},
+ },
+ },
+ "ipv6": {
+ "type": "dict",
+ "options": {
+ "dscp": {"type": "str"},
+ "precedence": {"type": "str"},
+ },
+ },
+ "location": {"type": "str"},
+ "logging_threshold_oid_processing": {"type": "int"},
+ "logging_threshold_pdu_processing": {"type": "int"},
+ "mib_bulkstat_max_procmem_size": {"type": "int"},
+ "mib_object_lists": {"type": "list", "elements": "str"},
+ "mib_schema": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "object_list": {"type": "str"},
+ "poll_interval": {"type": "int"},
+ },
+ },
+ "mib_bulkstat_transfer_ids": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "buffer_size": {"type": "int"},
+ "enable": {"type": "bool"},
+ "format_schemaASCI": {"type": "bool"},
+ "retain": {"type": "int"},
+ "retry": {"type": "int"},
+ "schema": {"type": "str"},
+ "transfer_interval": {"type": "int"},
+ },
+ },
+ "mroutemib_send_all_vrf": {"type": "bool"},
+ "notification_log_mib": {
+ "type": "dict",
+ "options": {
+ "GlobalSize": {"type": "int"},
+ "default": {"type": "bool"},
+ "disable": {"type": "bool"},
+ "size": {"type": "int"},
+ },
+ },
+ "oid_poll_stats": {"type": "bool"},
+ "overload_control": {
+ "type": "dict",
+ "options": {
+ "overload_drop_time": {"type": "int"},
+ "overload_throttle_rate": {"type": "int"},
+ },
+ },
+ "packetsize": {"type": "int"},
+ "queue_length": {"type": "int"},
+ "targets": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "name": {"type": "str"},
+ "host": {"type": "str"},
+ "vrf": {"type": "str"},
+ },
+ },
+ "throttle_time": {"type": "int"},
+ "timeouts": {
+ "type": "dict",
+ "options": {
+ "duplicate": {"type": "int"},
+ "inQdrop": {"type": "int"},
+ "pdu_stats": {"type": "int"},
+ "subagent": {"type": "int"},
+ "threshold": {"type": "int"},
+ },
+ },
+ "trap": {
+ "type": "dict",
+ "options": {
+ "authentication_vrf_disable": {"type": "bool"},
+ "link_ietf": {"type": "bool"},
+ "throttle_time": {"type": "int"},
+ },
+ },
+ "trap_source": {"type": "str"},
+ "trap_timeout": {"type": "int"},
+ "traps": {
+ "type": "dict",
+ "options": {
+ "addrpool": {
+ "type": "dict",
+ "options": {
+ "low": {"type": "bool"},
+ "high": {"type": "bool"},
+ },
+ },
+ "bfd": {"type": "bool"},
+ "bgp": {
+ "type": "dict",
+ "options": {
+ "cbgp2": {"type": "bool"},
+ "updown": {"type": "bool"},
+ },
+ },
+ "bulkstat_collection": {"type": "bool"},
+ "bulkstat_transfer": {"type": "bool"},
+ "bridgemib": {"type": "bool"},
+ "copy_complete": {"type": "bool"},
+ "cisco_entity_ext": {"type": "bool"},
+ "config": {"type": "bool"},
+ "diameter": {
+ "type": "dict",
+ "options": {
+ "peerdown": {"type": "bool"},
+ "peerup": {"type": "bool"},
+ "permanentfail": {"type": "bool"},
+ "protocolerror": {"type": "bool"},
+ "transientfail": {"type": "bool"},
+ },
+ },
+ "entity": {"type": "bool"},
+ "entity_redundancy": {
+ "type": "dict",
+ "options": {
+ "all": {"type": "bool"},
+ "status": {"type": "bool"},
+ "switchover": {"type": "bool"},
+ },
+ },
+ "entity_state": {
+ "type": "dict",
+ "options": {
+ "operstatus": {"type": "bool"},
+ "switchover": {"type": "bool"},
+ },
+ },
+ "flash": {
+ "type": "dict",
+ "options": {
+ "insertion": {"type": "bool"},
+ "removal": {"type": "bool"},
+ },
+ },
+ "fru_ctrl": {"type": "bool"},
+ "hsrp": {"type": "bool"},
+ "ipsla": {"type": "bool"},
+ "ipsec": {
+ "type": "dict",
+ "options": {
+ "start": {"type": "bool"},
+ "stop": {"type": "bool"},
+ },
+ },
+ "isakmp": {
+ "type": "dict",
+ "options": {
+ "start": {"type": "bool"},
+ "stop": {"type": "bool"},
+ },
+ },
+ "isis": {
+ "type": "dict",
+ "options": {
+ "adjacency_change": {"type": "bool"},
+ "all": {"type": "bool"},
+ "area_mismatch": {"type": "bool"},
+ "attempt_to_exceed_max_sequence": {
+ "type": "bool",
+ },
+ "authentication_failure": {"type": "bool"},
+ "authentication_type_failure": {
+ "type": "bool",
+ },
+ "corrupted_lsp_detected": {"type": "bool"},
+ "database_overload": {"type": "bool"},
+ "id_len_mismatch": {"type": "bool"},
+ "lsp_error_detected": {"type": "bool"},
+ "lsp_too_large_to_propagate": {"type": "bool"},
+ "manual_address_drops": {"type": "bool"},
+ "max_area_addresses_mismatch": {
+ "type": "bool",
+ },
+ "orig_lsp_buff_size_mismatch": {
+ "type": "bool",
+ },
+ "version_skew": {"type": "bool"},
+ "own_lsp_purge": {"type": "bool"},
+ "rejected_adjacency": {"type": "bool"},
+ "protocols_supported_mismatch": {
+ "type": "bool",
+ },
+ "sequence_number_skip": {"type": "bool"},
+ },
+ },
+ "l2tun": {
+ "type": "dict",
+ "options": {
+ "pseudowire_status": {"type": "bool"},
+ "sessions": {"type": "bool"},
+ "tunnel_down": {"type": "bool"},
+ "tunnel_up": {"type": "bool"},
+ },
+ },
+ "l2vpn": {
+ "type": "dict",
+ "options": {
+ "all": {"type": "bool"},
+ "cisco": {"type": "bool"},
+ "vc_down": {"type": "bool"},
+ "vc_up": {"type": "bool"},
+ },
+ },
+ "msdp_peer_state_change": {"type": "bool"},
+ "ntp": {"type": "bool"},
+ "ospf": {
+ "type": "dict",
+ "options": {
+ "errors": {
+ "type": "dict",
+ "options": {
+ "bad_packet": {"type": "bool"},
+ "authentication_failure": {
+ "type": "bool",
+ },
+ "config_error": {"type": "bool"},
+ "virt_bad_packet": {"type": "bool"},
+ "virt_authentication_failure": {
+ "type": "bool",
+ },
+ "virt_config_error": {"type": "bool"},
+ },
+ },
+ "lsa": {
+ "type": "dict",
+ "options": {
+ "lsa_maxage": {"type": "bool"},
+ "lsa_originate": {"type": "bool"},
+ },
+ },
+ "retransmit": {
+ "type": "dict",
+ "options": {
+ "packets": {"type": "bool"},
+ "virt_packets": {"type": "bool"},
+ },
+ },
+ "state_change": {
+ "type": "dict",
+ "options": {
+ "if_state_change": {"type": "bool"},
+ "neighbor_state_change": {
+ "type": "bool",
+ },
+ "virtif_state_change": {
+ "type": "bool",
+ },
+ "virtneighbor_state_change": {
+ "type": "bool",
+ },
+ },
+ },
+ },
+ },
+ "ospfv3": {
+ "type": "dict",
+ "options": {
+ "errors": {
+ "type": "dict",
+ "options": {
+ "bad_packet": {"type": "bool"},
+ "config_error": {"type": "bool"},
+ "virt_bad_packet": {"type": "bool"},
+ "virt_config_error": {"type": "bool"},
+ },
+ },
+ "state_change": {
+ "type": "dict",
+ "options": {
+ "if_state_change": {"type": "bool"},
+ "neighbor_state_change": {
+ "type": "bool",
+ },
+ "virtif_state_change": {
+ "type": "bool",
+ },
+ "virtneighbor_state_change": {
+ "type": "bool",
+ },
+ "nssa_state_change": {"type": "bool"},
+ "restart_status_change": {
+ "type": "bool",
+ },
+ "restart_helper_status_change": {
+ "type": "bool",
+ },
+ "restart_virtual_helper_status_change": {
+ "type": "bool",
+ },
+ },
+ },
+ },
+ },
+ "power": {"type": "bool"},
+ "rf": {"type": "bool"},
+ "pim": {
+ "type": "dict",
+ "options": {
+ "interface_state_change": {"type": "bool"},
+ "invalid_message_received": {"type": "bool"},
+ "neighbor_change": {"type": "bool"},
+ "rp_mapping_change": {"type": "bool"},
+ },
+ },
+ "rsvp": {
+ "type": "dict",
+ "options": {
+ "all": {"type": "bool"},
+ "lost_flow": {"type": "bool"},
+ "new_flow": {"type": "bool"},
+ },
+ },
+ "selective_vrf_download_role_change": {"type": "bool"},
+ "sensor": {"type": "bool"},
+ "snmp": {
+ "type": "dict",
+ "options": {
+ "authentication": {"type": "bool"},
+ "linkdown": {"type": "bool"},
+ "linkup": {"type": "bool"},
+ "warmstart": {"type": "bool"},
+ "coldstart": {"type": "bool"},
+ },
+ },
+ "vrrp_events": {"type": "bool"},
+ "syslog": {"type": "bool"},
+ "subscriber": {
+ "type": "dict",
+ "options": {
+ "session_agg_access_interface": {
+ "type": "bool",
+ },
+ "session_agg_node": {"type": "bool"},
+ },
+ },
+ "system": {"type": "bool"},
+ "vpls": {
+ "type": "dict",
+ "options": {
+ "all": {"type": "bool"},
+ "full_clear": {"type": "bool"},
+ "full_raise": {"type": "bool"},
+ "status": {"type": "bool"},
+ },
+ },
+ },
+ },
+ "users": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "user": {"type": "str"},
+ "group": {"type": "str"},
+ "acl_v4": {"type": "str", "aliases": ["Ipv4_acl"]},
+ "acl_v6": {"type": "str", "aliases": ["Ipv6_acl"]},
+ "SDROwner": {"type": "bool"},
+ "SystemOwner": {"type": "bool"},
+ "v4_acl": {"type": "str"},
+ "version": {
+ "type": "str",
+ "choices": ["v1", "v2c", "v3"],
+ },
+ },
+ },
+ "vrfs": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "vrf": {"type": "str"},
+ "context": {"type": "list", "elements": "str"},
+ "hosts": {
+ "type": "list",
+ "elements": "dict",
+ "options": {
+ "host": {"type": "str"},
+ "community": {"type": "str"},
+ "udp_port": {"type": "int"},
+ "informs": {"type": "bool"},
+ "traps": {"type": "bool"},
+ "version": {
+ "type": "str",
+ "choices": ["1", "2c", "3"],
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "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/static_routes/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/static_routes/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/static_routes/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/static_routes/static_routes.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/static_routes/static_routes.py
new file mode 100644
index 00000000..7b2cd025
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/argspec/static_routes/static_routes.py
@@ -0,0 +1,103 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+"""
+The arg spec for the iosxr_static_routes module
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+class Static_routesArgs(object): # pylint: disable=R0903
+ """The arg spec for the iosxr_static_routes module"""
+
+ def __init__(self, **kwargs):
+ pass
+
+ argument_spec = {
+ "config": {
+ "elements": "dict",
+ "options": {
+ "vrf": {"type": "str"},
+ "address_families": {
+ "elements": "dict",
+ "options": {
+ "afi": {
+ "choices": ["ipv4", "ipv6"],
+ "required": True,
+ "type": "str",
+ },
+ "safi": {
+ "choices": ["unicast", "multicast"],
+ "required": True,
+ "type": "str",
+ },
+ "routes": {
+ "elements": "dict",
+ "options": {
+ "dest": {"required": True, "type": "str"},
+ "next_hops": {
+ "elements": "dict",
+ "options": {
+ "admin_distance": {"type": "int"},
+ "description": {"type": "str"},
+ "dest_vrf": {"type": "str"},
+ "forward_router_address": {
+ "type": "str",
+ },
+ "interface": {"type": "str"},
+ "metric": {"type": "int"},
+ "tag": {"type": "int"},
+ "track": {"type": "str"},
+ "tunnel_id": {"type": "int"},
+ "vrflabel": {"type": "int"},
+ },
+ "type": "list",
+ },
+ },
+ "type": "list",
+ },
+ },
+ "type": "list",
+ },
+ },
+ "type": "list",
+ },
+ "running_config": {"type": "str"},
+ "state": {
+ "choices": [
+ "merged",
+ "replaced",
+ "overridden",
+ "deleted",
+ "gathered",
+ "rendered",
+ "parsed",
+ ],
+ "default": "merged",
+ "type": "str",
+ },
+ } # pylint: disable=C0301
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acl_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acl_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acl_interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acl_interfaces/acl_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acl_interfaces/acl_interfaces.py
new file mode 100644
index 00000000..4f21c181
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acl_interfaces/acl_interfaces.py
@@ -0,0 +1,123 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_acl_interfaces class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible_collections.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.acl_interfaces import (
+ Acl_interfacesTemplate,
+)
+
+
+class Acl_interfaces(ResourceModule):
+ """
+ The iosxr_acl_interfaces class
+ """
+
+ def __init__(self, module):
+ super(Acl_interfaces, self).__init__(
+ empty_fact_val={},
+ facts_module=Facts(module),
+ module=module,
+ resource="acl_interfaces",
+ tmplt=Acl_interfacesTemplate(),
+ )
+
+ def execute_module(self):
+ """Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ if self.state not in ["parsed", "gathered"]:
+ self.gen_config()
+ self.run_commands()
+ return self.result
+
+ def gen_config(self):
+ """Select the appropriate function based on the state provided
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ # convert list of dicts to dicts of dicts
+ wantd = {entry["name"]: entry for entry in self.want}
+ haved = {entry["name"]: entry for entry in self.have}
+
+ # turn all lists of dicts into dicts prior to merge
+ for entry in wantd, haved:
+ self._list_to_dict(entry)
+
+ # if state is merged, merge want onto have and then compare
+ if self.state == "merged":
+ wantd = dict_merge(haved, wantd)
+
+ # if state is deleted, empty out wantd and set haved to wantd
+ if self.state == "deleted":
+ haved = {k: v for k, v in haved.items() if k in wantd or not wantd}
+ wantd = {}
+
+ # remove superfluous config
+ if self.state in ["overridden", "deleted"]:
+ for k, have in haved.items():
+ if k not in wantd:
+ self._compare(want={}, have=have)
+
+ for k, want in wantd.items():
+ self._compare(want=want, have=haved.pop(k, {}))
+
+ def _compare(self, want, have):
+ begin = len(self.commands)
+ self._compare_lists(want=want, have=have)
+ if len(self.commands) != begin:
+ self.commands.insert(
+ begin,
+ self._tmplt.render(want or have, "interface", False),
+ )
+
+ def _compare_lists(self, want, have):
+ wdict = want.get("access_groups", {})
+ hdict = have.get("access_groups", {})
+
+ for afi in ("ipv4", "ipv6"):
+ wacls = wdict.pop(afi, {}).pop("acls", {})
+ hacls = hdict.pop(afi, {}).pop("acls", {})
+
+ for key, entry in wacls.items():
+ if entry != hacls.pop(key, {}):
+ entry["afi"] = afi
+ self.addcmd(entry, "access_groups", False)
+ # remove remaining items in have for replaced
+ for entry in hacls.values():
+ entry["afi"] = afi
+ self.addcmd(entry, "access_groups", True)
+
+ def _list_to_dict(self, entry):
+ for item in entry.values():
+ for ag in item.get("access_groups", []):
+ ag["acls"] = {subentry["direction"]: subentry for subentry in ag.get("acls", [])}
+ item["access_groups"] = {
+ subentry["afi"]: subentry for subentry in item.get("access_groups", [])
+ }
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/__init__.py
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
new file mode 100644
index 00000000..9f9b1ea6
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/acls/acls.py
@@ -0,0 +1,529 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_acls class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import (
+ ConfigBase,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ dict_diff,
+ remove_empties,
+ search_obj_in_list,
+ to_list,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import Facts
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ flatten_dict,
+ is_ipv4_address,
+ prefix_to_address_wildcard,
+)
+
+
+class Acls(ConfigBase):
+ """
+ The iosxr_acls class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["acls"]
+
+ def __init__(self, module):
+ super(Acls, self).__init__(module)
+
+ def get_acls_facts(self, data=None):
+ """Get the 'facts' (the current configuration)
+
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset,
+ self.gather_network_resources,
+ data=data,
+ )
+ acls_facts = facts["ansible_network_resources"].get("acls")
+ if not acls_facts:
+ return []
+ return acls_facts
+
+ def execute_module(self):
+ """Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_acls_facts = self.get_acls_facts()
+ else:
+ existing_acls_facts = []
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_acls_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_acls_facts = self.get_acls_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed",
+ )
+ result["parsed"] = self.get_acls_facts(data=running_config)
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_acls_facts
+ if result["changed"]:
+ result["after"] = changed_acls_facts
+
+ elif self.state == "gathered":
+ result["gathered"] = changed_acls_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_acls_facts):
+ """Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ have = existing_acls_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """Select the appropriate function based on the state provided
+
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ state = self._module.params["state"]
+ commands = []
+
+ if state in ("overridden", "merged", "replaced", "rendered") and not want:
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ state,
+ ),
+ )
+
+ if state == "overridden":
+ commands.extend(self._state_overridden(want, have))
+
+ elif state == "deleted":
+ commands.extend(self._state_deleted(want, have))
+
+ else:
+ # Instead of passing entire want and have
+ # list of dictionaries to the respective
+ # _state_* methods we are passing the want
+ # and have dictionaries per AFI
+ for item in want:
+ afi = item["afi"]
+ obj_in_have = search_obj_in_list(afi, have, key="afi") or {}
+
+ if state == "merged" or self.state == "rendered":
+ commands.extend(
+ self._state_merged(remove_empties(item), obj_in_have),
+ )
+
+ elif state == "replaced":
+ commands.extend(
+ self._state_replaced(
+ remove_empties(item),
+ obj_in_have,
+ ),
+ )
+
+ return commands
+
+ def _state_replaced(self, want, have):
+ """The command generator when state is replaced
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ for want_acl in want["acls"]:
+ have_acl = search_obj_in_list(want_acl["name"], have.get("acls", [])) or {}
+ acl_updates = []
+
+ for have_ace in have_acl.get("aces", []):
+ want_ace = (
+ search_obj_in_list(
+ have_ace["sequence"],
+ want_acl["aces"],
+ key="sequence",
+ )
+ or {}
+ )
+ if not want_ace:
+ acl_updates.append("no {0}".format(have_ace["sequence"]))
+
+ for want_ace in want_acl.get("aces", []):
+ have_ace = (
+ search_obj_in_list(
+ want_ace.get("sequence"),
+ have_acl.get("aces", []),
+ key="sequence",
+ )
+ or {}
+ )
+ set_cmd = self._set_commands(want_ace, have_ace)
+ if set_cmd:
+ acl_updates.append(set_cmd)
+
+ if acl_updates:
+ acl_updates.insert(
+ 0,
+ "{0} access-list {1}".format(
+ want["afi"],
+ want_acl["name"],
+ ),
+ )
+ commands.extend(acl_updates)
+
+ return commands
+
+ def _state_overridden(self, want, have):
+ """The command generator when state is overridden
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ # Remove extraneous AFI that are present in config but not
+ # specified in `want`
+ for have_afi in have:
+ want_afi = search_obj_in_list(have_afi["afi"], want, key="afi") or {}
+ if not want_afi:
+ for acl in have_afi.get("acls", []):
+ commands.append(
+ "no {0} access-list {1}".format(
+ have_afi["afi"],
+ acl["name"],
+ ),
+ )
+
+ # First we remove the extraneous ACLs from the AFIs that
+ # are present both in `want` and in `have` and then
+ # we call `_state_replaced` to update the ACEs within those ACLs
+ for want_afi in want:
+ want_afi = remove_empties(want_afi)
+ have_afi = search_obj_in_list(want_afi["afi"], have, key="afi") or {}
+ if have_afi:
+ for have_acl in have_afi.get("acls", []):
+ want_acl = (
+ search_obj_in_list(
+ have_acl["name"],
+ want_afi.get("acls", []),
+ )
+ or {}
+ )
+ if not want_acl:
+ commands.append(
+ "no {0} access-list {1}".format(
+ have_afi["afi"],
+ have_acl["name"],
+ ),
+ )
+
+ commands.extend(self._state_replaced(want_afi, have_afi))
+
+ return commands
+
+ def _state_merged(self, want, have):
+ """The command generator when state is merged
+
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+ if not have:
+ have = {}
+
+ for want_acl in want["acls"]:
+ have_acl = search_obj_in_list(want_acl["name"], have.get("acls", {})) or {}
+
+ acl_updates = []
+ for want_ace in want_acl["aces"]:
+ have_ace = (
+ search_obj_in_list(
+ want_ace.get("sequence"),
+ have_acl.get("aces", []),
+ key="sequence",
+ )
+ or {}
+ )
+ set_cmd = self._set_commands(want_ace, have_ace)
+ if set_cmd:
+ acl_updates.append(set_cmd)
+
+ if acl_updates:
+ acl_updates.insert(
+ 0,
+ "{0} access-list {1}".format(
+ want["afi"],
+ want_acl["name"],
+ ),
+ )
+ commands.extend(acl_updates)
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """The command generator when state is deleted
+
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+
+ if not want:
+ want = [{"afi": "ipv4"}, {"afi": "ipv6"}]
+
+ for item in want:
+ item = remove_empties(item)
+ have_item = search_obj_in_list(item["afi"], have, key="afi") or {}
+ if "acls" not in item:
+ if have_item:
+ for acl in have_item["acls"]:
+ commands.append(
+ "no {0} access-list {1}".format(
+ have_item["afi"],
+ acl["name"],
+ ),
+ )
+ else:
+ for want_acl in item["acls"]:
+ have_acl = (
+ search_obj_in_list(
+ want_acl["name"],
+ have_item.get("acls", []),
+ )
+ or {}
+ )
+ if have_acl:
+ commands.append(
+ "no {0} access-list {1}".format(
+ have_item["afi"],
+ have_acl["name"],
+ ),
+ )
+
+ return commands
+
+ def _compute_commands(self, want_ace):
+ """This command creates an ACE line from an ACE dictionary
+
+ :rtype: A string
+ :returns: An ACE generated from a structured ACE dictionary
+ """
+
+ def _compute_src_dest(dir_dict):
+ cmd = ""
+ if "any" in dir_dict:
+ cmd += "any "
+ elif "host" in dir_dict:
+ cmd += "host {0} ".format(dir_dict["host"])
+ elif "net_group" in dir_dict:
+ cmd += "net-group {0} ".format(dir_dict["net_group"])
+ elif "port_group" in dir_dict:
+ cmd += "port-group {0} ".format(dir_dict["port_group"])
+ elif "prefix" in dir_dict:
+ cmd += "{0} ".format(dir_dict["prefix"])
+ else:
+ cmd += "{0} {1} ".format(
+ dir_dict["address"],
+ dir_dict["wildcard_bits"],
+ )
+
+ if "port_protocol" in dir_dict:
+ protocol_range = dir_dict["port_protocol"].get("range")
+ if protocol_range:
+ cmd += "range {0} {1} ".format(
+ protocol_range["start"],
+ protocol_range["end"],
+ )
+ else:
+ for key, value in iteritems(dir_dict["port_protocol"]):
+ cmd += "{0} {1} ".format(key, value)
+
+ return cmd
+
+ def _compute_protocol_options(protocol_dict):
+ cmd = ""
+ for value in protocol_options.values():
+ for subkey, subvalue in iteritems(value):
+ if subvalue:
+ cmd += "{0} ".format(subkey.replace("_", "-"))
+ return cmd
+
+ def _compute_match_options(want_ace):
+ cmd = ""
+
+ if "precedence" in want_ace:
+ cmd += "precedence {0} ".format(want_ace["precedence"])
+
+ for x in ["dscp", "packet_length", "ttl"]:
+ if x in want_ace:
+ opt_range = want_ace[x].get("range")
+ if opt_range:
+ cmd += "{0} range {1} {2} ".format(
+ x.replace("_", "-"),
+ opt_range["start"],
+ opt_range["end"],
+ )
+ else:
+ for key, value in iteritems(want_ace[x]):
+ cmd += "{0} {1} {2} ".format(
+ x.replace("_", "-"),
+ key,
+ value,
+ )
+
+ for x in (
+ "authen",
+ "capture",
+ "fragments",
+ "routing",
+ "log",
+ "log_input",
+ "icmp_off",
+ "destopts",
+ "hop_by_hop",
+ ):
+ if x in want_ace:
+ cmd += "{0} ".format(x.replace("_", "-"))
+
+ return cmd
+
+ cmd = ""
+ if "sequence" in want_ace:
+ cmd += "{0} ".format(want_ace["sequence"])
+
+ if "remark" in want_ace:
+ cmd += "remark {0}".format(want_ace["remark"])
+
+ elif "line" in want_ace:
+ cmd += want_ace["line"]
+
+ else:
+ cmd += "{0} ".format(want_ace["grant"])
+ if "protocol" in want_ace:
+ cmd += "{0} ".format(want_ace["protocol"])
+
+ cmd += _compute_src_dest(want_ace["source"])
+ cmd += _compute_src_dest(want_ace["destination"])
+
+ protocol_options = want_ace.get("protocol_options", {})
+ if protocol_options:
+ cmd += _compute_protocol_options(protocol_options)
+
+ cmd += _compute_match_options(want_ace)
+
+ return cmd.strip()
+
+ def _set_commands(self, want_ace, have_ace):
+ """A helped method that checks if there is
+ a delta between the `have_ace` and `want_ace`.
+ If there is a delta then it calls `_compute_commands`
+ to create the ACE line.
+
+ :rtype: A string
+ :returns: An ACE generated from a structured ACE dictionary
+ via a call to `_compute_commands`
+ """
+
+ if "line" in want_ace:
+ if want_ace["line"] != have_ace.get("line"):
+ return self._compute_commands(want_ace)
+
+ else:
+ if ("prefix" in want_ace.get("source", {})) or (
+ "prefix" in want_ace.get("destination", {})
+ ):
+ self._prepare_for_diff(want_ace)
+
+ protocol_opt_delta = {}
+ delta = dict_diff(have_ace, want_ace)
+
+ # `dict_diff` doesn't work properly for `protocol_options` diff,
+ # so we need to handle it separately
+ if want_ace.get("protocol_options", {}):
+ protocol_opt_delta = set(
+ flatten_dict(have_ace.get("protocol_options", {})),
+ ) ^ set(flatten_dict(want_ace.get("protocol_options", {})))
+
+ if delta or protocol_opt_delta:
+ want_ace = self._dict_merge(have_ace, want_ace)
+ return self._compute_commands(want_ace)
+
+ def _prepare_for_diff(self, ace):
+ """This method prepares the want ace dict
+ for diff calculation against the have ace dict.
+
+ :param ace: The want ace to prepare for diff calculation
+ """
+ # Convert prefixes to "address wildcard bits" format for IPv4 addresses
+ # Not valid for IPv6 addresses because those can only be specified as prefixes
+ # and are always rendered in running-config as prefixes too
+ for x in ["source", "destination"]:
+ prefix = ace.get(x, {}).get("prefix")
+ if prefix and is_ipv4_address(prefix):
+ del ace[x]["prefix"]
+ (
+ ace[x]["address"],
+ ace[x]["wildcard_bits"],
+ ) = prefix_to_address_wildcard(prefix)
+
+ def _dict_merge(self, have_ace, want_ace):
+ for x in want_ace:
+ have_ace[x] = want_ace[x]
+ return have_ace
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_address_family/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_address_family/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_address_family/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_address_family/bgp_address_family.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_address_family/bgp_address_family.py
new file mode 100644
index 00000000..6f090192
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_address_family/bgp_address_family.py
@@ -0,0 +1,243 @@
+#
+# -*- 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 iosxr_bgp_address_family config file.
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to its desired end-state is
+created.
+"""
+
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.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_address_family import (
+ Bgp_address_familyTemplate,
+)
+
+
+class Bgp_address_family(ResourceModule):
+ """
+ The iosxr_bgp_address_family config class
+ """
+
+ def __init__(self, module):
+ super(Bgp_address_family, self).__init__(
+ empty_fact_val={},
+ facts_module=Facts(module),
+ module=module,
+ resource="bgp_address_family",
+ tmplt=Bgp_address_familyTemplate(),
+ )
+ self.parsers = [
+ "router",
+ "address_family",
+ "advertise_best_external",
+ "additional_paths",
+ "allocate_label",
+ "as_path_loopcheck_out_disable",
+ "bgp_attribute_download",
+ "bgp_bestpath_origin_as_use",
+ "bgp_bestpath_origin_as_allow",
+ "bgp_client_to_client_reflection_cluster_id",
+ "bgp_reflection_disable",
+ "bgp_dampening",
+ "bgp_label_delay",
+ "bgp_import_delay",
+ "bgp_origin_as_validation",
+ "bgp_scan_time",
+ "default_martian_check_disable",
+ "distance",
+ "dynamic_med",
+ "maximum_paths_ibgp",
+ "maximum_paths_ebgp",
+ "maximum_paths_eibgp",
+ "optimal_route_reflection",
+ "nexthop",
+ "permanent_network_route_policy",
+ "retain_local_label",
+ "update",
+ "global_table_multicast",
+ "segmented_multicast",
+ "inter_as_install",
+ "vrf_all_conf",
+ "weight",
+ "route_target_download",
+ "label_mode",
+ "mvpn_single_forwarder_selection_highest_ip_address",
+ "mvpn_single_forwarder_selection_all",
+ "table_policy",
+ ]
+
+ def execute_module(self):
+ """Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ if self.state not in ["parsed", "gathered"]:
+ self.generate_commands()
+ self.run_commands()
+ return self.result
+
+ def generate_commands(self):
+ """Generate configuration commands to send based on
+ want, have and desired state.
+ """
+ wantd = self.want
+ haved = self.have
+ for entry in self.want, self.have:
+ self._bgp_list_to_dict(entry)
+
+ # if state is deleted, clean up global params
+ if self.state == "deleted":
+ if wantd:
+ to_del = {"address_family": self._set_to_delete(haved, wantd)}
+ haved.update(to_del)
+
+ wantd = {"as_number": haved.get("as_number")}
+
+ else:
+ wantd = self.want
+ # if state is merged, merge want onto have and then compare
+ if self.state == "merged":
+ wantd = dict_merge(self.have, self.want)
+
+ self._compare(want=wantd, have=haved)
+
+ def _compare(self, want, have):
+ """Leverages the base class `compare()` method and
+ populates the list of commands to be run by comparing
+ the `want` and `have` data with the `parsers` defined
+ for the Bgp_global network resource.
+ """
+
+ self._compare_af(want=want, have=have)
+ if self.commands and "router bgp" not in self.commands[0]:
+ self.commands.insert(
+ 0,
+ self._tmplt.render(
+ {"as_number": want["as_number"]},
+ "router",
+ 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", {})
+ vrf_want_have = []
+ for name, entry in iteritems(wafs):
+ begin = len(self.commands)
+ af_have = hafs.pop(name, {})
+ if "vrf" in entry:
+ vrf_want_have.append((entry, af_have))
+
+ else:
+ self.compare(parsers=self.parsers, want=entry, have=af_have)
+ self._compare_lists(want=entry, have=af_have)
+ if len(self.commands) != begin:
+ self.commands.insert(
+ begin,
+ self._tmplt.render(
+ {
+ "afi": entry.get("afi"),
+ "safi": entry.get("safi"),
+ },
+ "address_family",
+ False,
+ ),
+ )
+
+ # compare af under vrf separately to ensure correct generation of commands
+ for waf, haf in vrf_want_have:
+ begin = len(self.commands)
+ self.compare(parsers=self.parsers, want=waf, have=haf)
+ self._compare_lists(want=waf, have=haf)
+ if len(self.commands) != begin:
+ self.commands.insert(
+ begin,
+ self._tmplt.render(
+ {"afi": waf.get("afi"), "safi": waf.get("safi")},
+ "address_family",
+ False,
+ ),
+ )
+ self.commands.insert(
+ begin,
+ self._tmplt.render({"vrf": waf.get("vrf")}, "vrf", False),
+ )
+
+ # for deleted and overridden state
+ if self.state != "replaced":
+ for name, entry in iteritems(hafs):
+ if "vrf" in entry:
+ self.addcmd({"vrf": entry.get("vrf")}, "vrf", False)
+ self.addcmd(
+ {"afi": entry.get("afi"), "safi": entry.get("safi")},
+ "address_family",
+ True,
+ )
+
+ def _compare_lists(self, want, have):
+ for attrib in ["aggregate_address", "networks", "redistribute"]:
+ wdict = want.get(attrib, {})
+ hdict = have.get(attrib, {})
+ for key, entry in iteritems(wdict):
+ if entry != hdict.pop(key, {}):
+ self.addcmd(entry, attrib.format(attrib), False)
+
+ # remove remaining items in have for replaced
+ for entry in hdict.values():
+ self.addcmd(entry, attrib.format(attrib), True)
+
+ def _bgp_list_to_dict(self, entry):
+ """Convert list of items to dict of items
+ for efficient diff calculation.
+ :params entry: data dictionary
+ """
+ for item in entry.get("address_family", []):
+ item["aggregate_address"] = {x["value"]: x for x in item.get("aggregate_address", [])}
+ item["networks"] = {x["network"]: x for x in item.get("networks", [])}
+ item["redistribute"] = {
+ (x.get("id"), x["protocol"]): x for x in item.get("redistribute", [])
+ }
+
+ if "address_family" in entry:
+ entry["address_family"] = {
+ "address_family_" + x["afi"] + "_" + x["safi"] + "_vrf_" + x.get("vrf", ""): x
+ for x in entry.get("address_family", [])
+ }
+
+ def _get_config(self):
+ return self._connection.get("show running-config router bgp")
+
+ def _set_to_delete(self, haved, wantd):
+ afs_to_del = {}
+ h_addrs = haved.get("address_family", {})
+ w_addrs = wantd.get("address_family", {})
+ for af, h_addr in iteritems(h_addrs):
+ if af in w_addrs:
+ afs_to_del[af] = h_addr
+ return afs_to_del
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_global/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_global/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_global/__init__.py
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
new file mode 100644
index 00000000..69b752be
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_global/bgp_global.py
@@ -0,0 +1,427 @@
+#
+# -*- 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 iosxr_bgp_global config file.
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to its desired end-state is
+created.
+"""
+
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.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_global import (
+ Bgp_globalTemplate,
+)
+
+
+class Bgp_global(ResourceModule):
+ """
+ The iosxr_bgp_global config class
+ """
+
+ def __init__(self, module):
+ super(Bgp_global, self).__init__(
+ empty_fact_val={},
+ facts_module=Facts(module),
+ module=module,
+ resource="bgp_global",
+ tmplt=Bgp_globalTemplate(),
+ )
+ self.parsers = [
+ "router",
+ "bfd_multiplier",
+ "bfd_minimum_interval",
+ "bgp_auto_policy_soft_reset",
+ "bgp_as_path_loopcheck",
+ "bgp_cluster_id",
+ "bgp_default_local_preference",
+ "bgp_enforce_first_as_disable",
+ "bgp_fast_external_fallover_disable",
+ "bgp_install_diversion",
+ "bgp_max_neighbors",
+ "bgp_redistribute_internal",
+ "bgp_router_id",
+ "bgp_scan_time",
+ "bgp_unsafe_ebgp_policy",
+ "bgp_update_delay",
+ "bgp_bestpath_aigp",
+ "bgp_bestpath_as_path_ignore",
+ "bgp_bestpath_as_path_multipath_relax",
+ "bgp_bestpath_med_always",
+ "bgp_bestpath_med_confed",
+ "bgp_bestpath_med_missing_as_worst",
+ "bgp_bestpath_compare_routerid",
+ "bgp_bestpath_cost_community_ignore",
+ "bgp_bestpath_origin_as_use",
+ "bgp_bestpath_origin_as_allow",
+ "bgp_confederation_identifier",
+ "bgp_graceful_restart_set",
+ "bgp_graceful_restart_graceful_reset",
+ "bgp_graceful_restart_restart_time",
+ "bgp_graceful_restart_purge_time",
+ "bgp_graceful_restart_stalepath_time",
+ "bgp_log_message",
+ "bgp_log_neighbor_changes_detail",
+ "bgp_log_neighbor_changes_disable",
+ "bgp_multipath_as_path_ignore_onwards",
+ "bgp_origin_as_validation_disable",
+ "bgp_origin_as_validation_signal_ibgp",
+ "bgp_origin_as_validation_time_off",
+ "bgp_origin_as_validation_time",
+ "bgp_default_information_originate",
+ "bgp_default_metric",
+ "bgp_graceful_maintenance",
+ "ibgp_policy_out_enforce_modifications",
+ "mpls_activate_interface",
+ "mvpn",
+ "nsr_set",
+ "nsr_disable",
+ "socket_receive_buffer_size",
+ "socket_send_buffer_size",
+ "update_in_error_handling_basic_ebgp_disable",
+ "update_in_error_handling_basic_ibgp_disable",
+ "update_in_error_handling_extended_ebgp",
+ "update_in_error_handling_extended_ibgp",
+ "update_out_logging",
+ "update_limit",
+ "rpki_route_value",
+ "rd_auto",
+ "timers_keepalive",
+ ]
+
+ 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.
+ """
+ if self.state in ["merged", "replaced"]:
+ w_asn = self.want.get("as_number")
+ h_asn = self.have.get("as_number")
+
+ if h_asn and w_asn != h_asn:
+ self._module.fail_json(
+ msg="BGP is already configured with ASN {0}. "
+ "Please remove it with state purged before "
+ "configuring new as_number".format(h_asn),
+ )
+ for entry in self.want, self.have:
+ self._bgp_list_to_dict(entry)
+
+ # if state is deleted, clean up global params
+ if self.state == "deleted":
+ if not self.want or (self.have.get("as_number") == self.want.get("as_number")):
+ self._compare(
+ want={"as_number": self.want.get("as_number")},
+ have=self.have,
+ )
+ elif self.state == "purged":
+ if not self.want or (self.have.get("as_number") == self.want.get("as_number")):
+ self.addcmd(self.have or {}, "router", True)
+
+ else:
+ wantd = self.want
+ # if state is merged, merge want onto have and then compare
+ if self.state == "merged":
+ wantd = dict_merge(self.have, self.want)
+
+ self._compare(want=wantd, have=self.have)
+
+ def _compare(self, want, have):
+ """Leverages the base class `compare()` method and
+ populates the list of commands to be run by comparing
+ the `want` and `have` data with the `parsers` defined
+ for the Bgp_global network resource.
+ """
+
+ self.compare(parsers=self.parsers, want=want, have=have)
+ self._compare_rpki_server(want=want, have=self.have)
+ self._compare_confederation_peers(want=want, have=have)
+ self._compare_neighbors(want=want, have=self.have)
+ self._vrfs_compare(want=want, have=have)
+ if self.commands and "router bgp" not in self.commands[0]:
+ self.commands.insert(
+ 0,
+ self._tmplt.render(
+ {"as_number": want["as_number"]},
+ "router",
+ False,
+ ),
+ )
+
+ def _compare_rpki_server(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 rpki servers resource.
+ """
+ rpki_server_parsers = [
+ "rpki_server_purge_time",
+ "rpki_server_refresh_time",
+ "rpki_server_refresh_time_off",
+ "rpki_server_response_time",
+ "rpki_server_response_time_off",
+ "rpki_server_shutdown",
+ "rpki_server_transport_ssh",
+ "rpki_server_transport_tcp",
+ ]
+ want = want.get("rpki", {}).get("servers", {})
+ have = have.get("rpki", {}).get("servers", {})
+ for name, entry in iteritems(want):
+ new_have = have.pop(name, {})
+ begin = len(self.commands)
+ self.compare(
+ parsers=rpki_server_parsers,
+ want=entry,
+ have=new_have,
+ )
+ rpki_server_name = entry.get("name")
+ if len(self.commands) != begin:
+ self.commands.insert(
+ begin,
+ self._tmplt.render(
+ {"name": rpki_server_name},
+ "rpki_server_name",
+ False,
+ ),
+ )
+ for name, entry in iteritems(have):
+ self.addcmd(entry, "rpki_server_name", True)
+
+ def _compare_confederation_peers(self, want, have):
+ """Custom handling of confederation.peers option
+ :params want: the want BGP dictionary
+ :params have: the have BGP dictionary
+ """
+ w_cpeers = want.get("bgp", {}).get("confederation", {}).get("peers", [])
+ h_cpeers = have.get("bgp", {}).get("confederation", {}).get("peers", [])
+
+ if set(w_cpeers) != set(h_cpeers):
+ if self.state in ["replaced", "deleted"]:
+ # if there are peers already configured
+ # we need to remove those before we pass
+ # the new ones otherwise the device appends
+ # them to the existing ones
+ if h_cpeers:
+ self.addcmd(have, "bgp_confederation_peers", True)
+ if w_cpeers:
+ self.addcmd(want, "bgp_confederation_peers", False)
+
+ def _compare_neighbors(self, want, have, vrf=None):
+ """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 = [
+ "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",
+ "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",
+ "remote_as",
+ "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("neighbors", {})
+ have_nbr = have.get("neighbors", {})
+ 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)
+ neighbor_address = entry.get("neighbor_address", "")
+ if len(self.commands) != begin:
+ self.commands.insert(
+ begin,
+ self._tmplt.render(
+ {"neighbor_address": neighbor_address},
+ "neighbor_address",
+ False,
+ ),
+ )
+ for name, entry in iteritems(have_nbr):
+ if self._check_af("neighbor_address", name):
+ self._module.fail_json(
+ msg="Neighbor {0} has address-family configurations. "
+ "Please use the iosxr_bgp_neighbor_address_family module to remove those first.".format(
+ name,
+ ),
+ )
+ else:
+ self.addcmd(entry, "neighbor_address", True)
+
+ def _vrfs_compare(self, want, have):
+ """Custom handling of VRFs option
+ :params want: the want BGP dictionary
+ :params have: the have BGP dictionary
+ """
+ wvrfs = want.get("vrfs", {})
+ hvrfs = have.get("vrfs", {})
+ for name, entry in iteritems(wvrfs):
+ begin = len(self.commands)
+ vrf_have = hvrfs.pop(name, {})
+ self._compare_rpki_server(want=entry, have=vrf_have)
+ self._compare_neighbors(want=entry, have=vrf_have)
+ self.compare(parsers=self.parsers, want=entry, have=vrf_have)
+ if len(self.commands) != begin:
+ self.commands.insert(
+ begin,
+ self._tmplt.render(
+ {"vrf": entry.get("vrf")},
+ "vrf",
+ False,
+ ),
+ )
+ # cleanup remaining VRFs
+ # but do not negate it entirely
+ # instead remove only those attributes
+ # that this module manages
+ for name, entry in iteritems(hvrfs):
+ if self._check_af("vrf", name):
+ self._module.fail_json(
+ msg="VRF {0} has address-family configurations. "
+ "Please use the iosxr_bgp_address_family module to remove those first.".format(
+ name,
+ ),
+ )
+ else:
+ self.addcmd(entry, "vrf", True)
+
+ def _bgp_list_to_dict(self, entry):
+ """Convert list of items to dict of items
+ for efficient diff calculation.
+ :params entry: data dictionary
+ """
+
+ def _build_key(x):
+ """Build primary key for path_attribute
+ option.
+ :params x: path_attribute dictionary
+ :returns: primary key as tuple
+ """
+ key_1 = "start_{0}".format(x.get("range", {}).get("start", ""))
+ key_2 = "end_{0}".format(x.get("range", {}).get("end", ""))
+ key_3 = "type_{0}".format(x.get("type", ""))
+ key_4 = x["action"]
+
+ return (key_1, key_2, key_3, key_4)
+
+ if "servers" in entry.get("rpki", {}):
+ entry["rpki"]["servers"] = {
+ x["name"]: x for x in entry.get("rpki", {}).get("servers", [])
+ }
+ if "neighbors" in entry:
+ entry["neighbors"] = {x["neighbor_address"]: x for x in entry.get("neighbors", [])}
+
+ if "vrfs" in entry:
+ entry["vrfs"] = {x["vrf"]: x for x in entry.get("vrfs", [])}
+ for _k, vrf in iteritems(entry["vrfs"]):
+ self._bgp_list_to_dict(vrf)
+
+ def _get_config(self):
+ return self._connection.get("show running-config router bgp")
+
+ def _check_af(self, context, context_name):
+ af_present = False
+ if self._connection:
+ config_lines = self._get_config().splitlines()
+ index = [i + 1 for i, el in enumerate(config_lines) if context_name in el]
+ if index:
+ # had to do this to escape flake8 and black errors
+ ind = index[0]
+ for line in config_lines[ind:]:
+ if context in line:
+ break
+ if "address-family" in line:
+ af_present = True
+ break
+ return af_present
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_neighbor_address_family/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_neighbor_address_family/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_neighbor_address_family/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_neighbor_address_family/bgp_neighbor_address_family.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_neighbor_address_family/bgp_neighbor_address_family.py
new file mode 100644
index 00000000..8f72127d
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/bgp_neighbor_address_family/bgp_neighbor_address_family.py
@@ -0,0 +1,245 @@
+#
+# -*- 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 iosxr_bgp_neighbor_address_family config file.
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to its desired end-state is
+created.
+"""
+
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.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_neighbor_address_family import (
+ Bgp_neighbor_address_familyTemplate,
+)
+
+
+class Bgp_neighbor_address_family(ResourceModule):
+ """
+ The iosxr_bgp_neighbor_address_family config class
+ """
+
+ def __init__(self, module):
+ super(Bgp_neighbor_address_family, self).__init__(
+ empty_fact_val={},
+ facts_module=Facts(module),
+ module=module,
+ resource="bgp_neighbor_address_family",
+ tmplt=Bgp_neighbor_address_familyTemplate(),
+ )
+ self.parsers = [
+ "router",
+ "aigp",
+ "allowas_in",
+ "as_override",
+ "bestpath_origin_as_allow_invalid",
+ "capability_orf_prefix",
+ "default_originate",
+ "long_lived_graceful_restart_capable",
+ "long_lived_graceful_restart_stale_time",
+ "maximum_prefix",
+ "multipath",
+ "next_hop_self",
+ "next_hop_unchanged",
+ "optimal_route_reflection_group_name",
+ "origin_as",
+ "remove_private_AS",
+ "route_reflector_client",
+ "send_community_ebgp",
+ "send_community_gshut_ebgp",
+ "send_extended_community_ebgp",
+ "send_multicast_attributes",
+ "soft_reconfiguration",
+ "weight",
+ "site_of_origin",
+ "validation",
+ "route_policy.inbound",
+ "route_policy.outbound",
+ ]
+
+ 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.
+ """
+
+ for entry in self.want, self.have:
+ self._bgp_list_to_dict(entry)
+
+ wantd = self.want
+ haved = self.have
+ # if state is merged, merge want onto have and then compare
+ if self.state == "merged":
+ wantd = dict_merge(self.have, self.want)
+
+ # if state is deleted, empty out wantd and set haved to elements to delete
+ if self.state == "deleted":
+ if wantd:
+ to_del = {
+ "neighbors": self._set_to_delete(haved, wantd),
+ "vrfs": {},
+ }
+
+ for k, hvrf in iteritems(haved.get("vrfs", {})):
+ wvrf = wantd.get("vrfs", {}).get(k, {})
+ to_del["vrfs"][k] = {
+ "neighbors": self._set_to_delete(hvrf, wvrf),
+ "vrf": k,
+ }
+ haved.update(to_del)
+
+ wantd = {"as_number": haved.get("as_number")}
+
+ self._compare(want=wantd, have=haved)
+
+ def _compare(self, want, have):
+ """Leverages the base class `compare()` method and
+ populates the list of commands to be run by comparing
+ the `want` and `have` data with the `parsers` defined
+ for the Bgp_global network resource.
+ """
+
+ self._compare_neighbors(want=want, have=have)
+ self._compare_vrf(want=want, have=have)
+ if self.commands and "router bgp" not in self.commands[0]:
+ self.commands.insert(
+ 0,
+ self._tmplt.render(
+ {"as_number": want["as_number"]},
+ "router",
+ False,
+ ),
+ )
+
+ def _compare_neighbors(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.
+ """
+ want_nbr = want.get("neighbors", {})
+ have_nbr = have.get("neighbors", {})
+ for name, entry in iteritems(want_nbr):
+ have = have_nbr.pop(name, {})
+ begin = len(self.commands)
+ self._compare_af(want=entry, have=have)
+ if len(self.commands) != begin:
+ self.commands.insert(begin, "neighbor {0}".format(name))
+
+ # for deleted and overridden state
+ if self.state != "replaced":
+ for name, entry in iteritems(have_nbr):
+ begin = len(self.commands)
+ self._compare_af(want={}, have=entry)
+ if len(self.commands) != begin:
+ self.commands.insert(begin, "neighbor {0}".format(name))
+
+ 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 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 _compare_vrf(self, want, have):
+ """Custom handling of VRFs option
+ :params want: the want BGP dictionary
+ :params have: the have BGP dictionary
+ """
+ wvrfs = want.get("vrfs", {})
+ hvrfs = have.get("vrfs", {})
+ for name, entry in iteritems(wvrfs):
+ begin = len(self.commands)
+ vrf_have = hvrfs.pop(name, {})
+ self._compare_neighbors(want=entry, have=vrf_have)
+ if len(self.commands) != begin:
+ self.commands.insert(begin, "vrf {0}".format(name))
+ # for deleted and replaced state
+ for name, entry in iteritems(hvrfs):
+ begin = len(self.commands)
+ self._compare_neighbors(want={}, have=entry)
+ if len(self.commands) != begin:
+ self.commands.insert(begin, "vrf {0}".format(name))
+
+ def _bgp_list_to_dict(self, data):
+ if "neighbors" in data:
+ for nbr in data["neighbors"]:
+ if "address_family" in nbr:
+ nbr["address_family"] = {
+ (x["afi"], x.get("safi")): x for x in nbr["address_family"]
+ }
+ data["neighbors"] = {x["neighbor_address"]: x for x in data["neighbors"]}
+
+ if "vrfs" in data:
+ for vrf in data["vrfs"]:
+ self._bgp_list_to_dict(vrf)
+ data["vrfs"] = {x["vrf"]: x for x in data["vrfs"]}
+
+ def _set_to_delete(self, haved, wantd):
+ neighbors = {}
+ h_nbrs = haved.get("neighbors", {})
+ w_nbrs = wantd.get("neighbors", {})
+
+ for k, h_nbr in iteritems(h_nbrs):
+ w_nbr = w_nbrs.pop(k, {})
+ if w_nbr:
+ neighbors[k] = h_nbr
+ afs_to_del = {}
+ h_addrs = h_nbr.get("address_family", {})
+ w_addrs = w_nbr.get("address_family", {})
+ for af, h_addr in iteritems(h_addrs):
+ if af in w_addrs:
+ afs_to_del[af] = h_addr
+ neighbors[k]["address_family"] = afs_to_del
+
+ return neighbors
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/hostname/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/hostname/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/hostname/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/hostname/hostname.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/hostname/hostname.py
new file mode 100644
index 00000000..deb6ea05
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/hostname/hostname.py
@@ -0,0 +1,75 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2022 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_hostname config file.
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to its desired end-state is
+created.
+"""
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.resource_module import (
+ ResourceModule,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import Facts
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.hostname import (
+ HostnameTemplate,
+)
+
+
+class Hostname(ResourceModule):
+ """
+ The iosxr_hostname config class
+ """
+
+ def __init__(self, module):
+ super(Hostname, self).__init__(
+ empty_fact_val={},
+ facts_module=Facts(module),
+ module=module,
+ resource="hostname",
+ tmplt=HostnameTemplate(),
+ )
+ self.parsers = ["hostname"]
+
+ def execute_module(self):
+ """Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ if self.state not in ["parsed", "gathered"]:
+ self.generate_commands()
+ self.run_commands()
+ return self.result
+
+ def generate_commands(self):
+ """Generate configuration commands to send based on
+ want, have and desired state.
+ """
+ wantd = self.want
+ haved = self.have
+
+ if self.state == "deleted":
+ wantd = {}
+
+ self._compare(want=wantd, have=haved)
+
+ def _compare(self, want, have):
+ """Leverages the base class `compare()` method and
+ populates the list of commands to be run by comparing
+ the `want` and `have` data with the `parsers` defined
+ for the Hostname network resource.
+ """
+ self.compare(parsers=self.parsers, want=want, have=have)
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/__init__.py
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
new file mode 100644
index 00000000..2a0c1885
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/interfaces/interfaces.py
@@ -0,0 +1,311 @@
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat Inc.
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_interfaces class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import (
+ ConfigBase,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import Facts
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ add_command_to_config_list,
+ dict_to_set,
+ filter_dict_having_none_value,
+ get_interface_type,
+ normalize_interface,
+ remove_command_from_config_list,
+ remove_duplicate_interface,
+)
+
+
+class Interfaces(ConfigBase):
+ """
+ The iosxr_interfaces class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["interfaces"]
+
+ params = ("description", "mtu", "speed", "duplex")
+
+ def __init__(self, module):
+ super(Interfaces, self).__init__(module)
+
+ def get_interfaces_facts(self, data=None):
+ """Get the 'facts' (the current configuration)
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset,
+ self.gather_network_resources,
+ data=data,
+ )
+ interfaces_facts = facts["ansible_network_resources"].get("interfaces")
+ if not interfaces_facts:
+ return []
+ return interfaces_facts
+
+ def execute_module(self):
+ """Execute the module
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_interfaces_facts = self.get_interfaces_facts()
+ else:
+ existing_interfaces_facts = []
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_interfaces_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_interfaces_facts = self.get_interfaces_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed",
+ )
+ result["parsed"] = self.get_interfaces_facts(data=running_config)
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_interfaces_facts
+ if result["changed"]:
+ result["after"] = changed_interfaces_facts
+
+ elif self.state == "gathered":
+ result["gathered"] = changed_interfaces_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_interfaces_facts):
+ """Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ have = existing_interfaces_facts
+ resp = self.set_state(want, have)
+
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """Select the appropriate function based on the state provided
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ if self.state in ("overridden", "merged", "replaced", "rendered") and not want:
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ self.state,
+ ),
+ )
+
+ if self.state == "overridden":
+ commands = self._state_overridden(want, have)
+ elif self.state == "deleted":
+ commands = self._state_deleted(want, have)
+ elif self.state in ("merged", "rendered"):
+ commands = self._state_merged(want, have)
+ elif self.state == "replaced":
+ commands = self._state_replaced(want, have)
+
+ return commands
+
+ def _state_replaced(self, want, have):
+ """The command generator when state is replaced
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ for interface in want:
+ for each in have:
+ if each["name"] == interface["name"] or interface["name"] in each["name"]:
+ break
+ else:
+ continue
+ have_dict = filter_dict_having_none_value(interface, each)
+ want = dict()
+ commands.extend(self._clear_config(want, have_dict))
+ commands.extend(self._set_config(interface, each))
+ # Remove the duplicate interface call
+ commands = remove_duplicate_interface(commands)
+
+ return commands
+
+ def _state_overridden(self, want, have):
+ """The command generator when state is overridden
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ for each in have:
+ for interface in want:
+ if each["name"] == interface["name"] or interface["name"] in each["name"]:
+ break
+ else:
+ # We didn't find a matching desired state, which means we can
+ # pretend we received an empty desired state.
+ interface = dict(name=each["name"])
+ commands.extend(self._clear_config(interface, each))
+ continue
+ have_dict = filter_dict_having_none_value(interface, each)
+ want = dict()
+ commands.extend(self._clear_config(want, have_dict))
+ commands.extend(self._set_config(interface, each))
+ # Remove the duplicate interface call
+ commands = remove_duplicate_interface(commands)
+
+ return commands
+
+ def _state_merged(self, want, have):
+ """The command generator when state is merged
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+ flag = 0
+ for interface in want:
+ if self.state == "rendered":
+ commands.extend(self._set_config(interface, dict()))
+ else:
+ for each in have:
+ if each["name"] == interface["name"] or interface["name"] in each["name"]:
+ flag = 1
+ break
+ if flag == 1:
+ commands.extend(self._set_config(interface, each))
+ else:
+ commands.extend(self._set_config(interface, dict()))
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """The command generator when state is deleted
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+
+ if want:
+ for interface in want:
+ for each in have:
+ if each["name"] == interface["name"] or interface["name"] in each["name"]:
+ break
+ else:
+ continue
+ interface = dict(name=interface["name"])
+ commands.extend(self._clear_config(interface, each))
+ else:
+ for each in have:
+ want = dict()
+ commands.extend(self._clear_config(want, each))
+
+ return commands
+
+ def _set_config(self, want, have):
+ # Set the interface config based on the want and have config
+ commands = []
+ want["name"] = normalize_interface(want["name"])
+ interface = "interface " + want["name"]
+ # Get the diff b/w want and have
+ want_dict = dict_to_set(want)
+ have_dict = dict_to_set(have)
+ diff = want_dict - have_dict
+
+ if diff:
+ diff = dict(diff)
+ for item in self.params:
+ if diff.get(item):
+ cmd = item + " " + str(want.get(item))
+ add_command_to_config_list(interface, cmd, commands)
+ if diff.get("enabled"):
+ add_command_to_config_list(interface, "no shutdown", commands)
+ elif diff.get("enabled") is False:
+ add_command_to_config_list(interface, "shutdown", commands)
+
+ return commands
+
+ def _clear_config(self, want, have):
+ # Delete the interface config based on the want and have config
+ commands = []
+
+ if want.get("name"):
+ interface_type = get_interface_type(want["name"])
+ interface = "interface " + want["name"]
+ else:
+ interface_type = get_interface_type(have["name"])
+ interface = "interface " + have["name"]
+
+ if have.get("description") and want.get("description") != have.get(
+ "description",
+ ):
+ remove_command_from_config_list(interface, "description", commands)
+ if not have.get("enabled") and want.get("enabled") != have.get(
+ "enabled",
+ ):
+ # if enable is False set enable as True which is the default behavior
+ remove_command_from_config_list(interface, "shutdown", commands)
+
+ if interface_type.lower() == "gigabitethernet":
+ if (
+ have.get("speed")
+ and have.get("speed") != "auto"
+ and want.get("speed") != have.get("speed")
+ ):
+ remove_command_from_config_list(interface, "speed", commands)
+ if (
+ have.get("duplex")
+ and have.get("duplex") != "auto"
+ and want.get("duplex") != have.get("duplex")
+ ):
+ remove_command_from_config_list(interface, "duplex", commands)
+ if have.get("mtu") and want.get("mtu") != have.get("mtu"):
+ remove_command_from_config_list(interface, "mtu", commands)
+
+ return commands
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/__init__.py
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
new file mode 100644
index 00000000..c571d3fa
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l2_interfaces/l2_interfaces.py
@@ -0,0 +1,410 @@
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat Inc.
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_l2_interfaces class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import (
+ ConfigBase,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ remove_empties,
+ to_list,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import Facts
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import get_os_version
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ Version,
+ add_command_to_config_list,
+ dict_diff,
+ filter_dict_having_none_value,
+ normalize_interface,
+ remove_command_from_config_list,
+ remove_duplicate_interface,
+)
+
+
+class L2_Interfaces(ConfigBase):
+ """
+ The iosxr_interfaces class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["l2_interfaces"]
+
+ def get_l2_interfaces_facts(self, data=None):
+ """Get the 'facts' (the current configuration)
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset,
+ self.gather_network_resources,
+ data=data,
+ )
+ l2_interfaces_facts = facts["ansible_network_resources"].get(
+ "l2_interfaces",
+ )
+ if not l2_interfaces_facts:
+ return []
+ return l2_interfaces_facts
+
+ def execute_module(self):
+ """Execute the module
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_l2_interfaces_facts = self.get_l2_interfaces_facts()
+ else:
+ existing_l2_interfaces_facts = []
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_l2_interfaces_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_l2_interfaces_facts = self.get_l2_interfaces_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed",
+ )
+ result["parsed"] = self.get_l2_interfaces_facts(
+ data=running_config,
+ )
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_l2_interfaces_facts
+ if result["changed"]:
+ result["after"] = changed_l2_interfaces_facts
+
+ elif self.state == "gathered":
+ result["gathered"] = changed_l2_interfaces_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_l2_interfaces_facts):
+ """Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ have = existing_l2_interfaces_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """Select the appropriate function based on the state provided
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ if self.state in ("overridden", "merged", "replaced", "rendered") and not want:
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ self.state,
+ ),
+ )
+
+ if self.state == "overridden":
+ commands = self._state_overridden(want, have, self._module)
+ elif self.state == "deleted":
+ commands = self._state_deleted(want, have)
+ elif self.state in ("merged", "rendered"):
+ commands = self._state_merged(want, have, self._module)
+ elif self.state == "replaced":
+ commands = self._state_replaced(want, have, self._module)
+
+ return commands
+
+ def _state_replaced(self, want, have, module):
+ """The command generator when state is replaced
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ for interface in want:
+ interface["name"] = normalize_interface(interface["name"])
+ for each in have:
+ if each["name"] == interface["name"] or interface["name"] in each["name"]:
+ break
+ else:
+ commands.extend(self._set_config(interface, {}, module))
+ continue
+ interface = remove_empties(interface)
+ have_dict = filter_dict_having_none_value(interface, each)
+ commands.extend(self._clear_config(dict(), have_dict))
+ commands.extend(self._set_config(interface, each, module))
+ # Remove the duplicate interface call
+ commands = remove_duplicate_interface(commands)
+
+ return commands
+
+ def _state_overridden(self, want, have, module):
+ """The command generator when state is overridden
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ not_in_have = set()
+ in_have = set()
+ for each in have:
+ for interface in want:
+ interface["name"] = normalize_interface(interface["name"])
+ if each["name"] == interface["name"]:
+ in_have.add(interface["name"])
+ break
+ if interface["name"] != each["name"]:
+ not_in_have.add(interface["name"])
+ else:
+ # We didn't find a matching desired state, which means we can
+ # pretend we received an empty desired state.
+ interface = dict(name=each["name"])
+ commands.extend(self._clear_config(interface, each))
+ continue
+ interface = remove_empties(interface)
+ have_dict = filter_dict_having_none_value(interface, each)
+ commands.extend(self._clear_config(dict(), have_dict))
+ commands.extend(self._set_config(interface, each, module))
+ # Add the want interface that's not already configured in have interface
+ for each in not_in_have - in_have:
+ for every in want:
+ interface = "interface {0}".format(every["name"])
+ if each and interface not in commands:
+ commands.extend(self._set_config(every, {}, module))
+
+ # Remove the duplicate interface call
+ commands = remove_duplicate_interface(commands)
+
+ return commands
+
+ def _state_merged(self, want, have, module):
+ """The command generator when state is merged
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+
+ for interface in want:
+ interface["name"] = normalize_interface(interface["name"])
+ interface = remove_empties(interface)
+ for each in have:
+ if each["name"] == interface["name"] or interface["name"] in each["name"]:
+ break
+ else:
+ commands.extend(self._set_config(interface, {}, module))
+ continue
+ commands.extend(self._set_config(interface, each, module))
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """The command generator when state is deleted
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+
+ if want:
+ for interface in want:
+ interface["name"] = normalize_interface(interface["name"])
+ for each in have:
+ if each["name"] == interface["name"] or interface["name"] in each["name"]:
+ break
+ else:
+ continue
+ interface = dict(name=interface["name"])
+ commands.extend(self._clear_config(interface, each))
+ else:
+ for each in have:
+ want = dict()
+ commands.extend(self._clear_config(want, each))
+
+ return commands
+
+ def _set_config(self, want, have, module):
+ # Set the interface config based on the want and have config
+ commands = []
+ interface = "interface " + want["name"]
+ l2_protocol_bool = False
+ # Get the diff b/w want and have
+ diff = dict_diff(have, want)
+ if diff:
+ # For merging with already configured l2protocol
+ if have.get("l2protocol") and len(have.get("l2protocol")) > 1:
+ l2_protocol_diff = []
+ for each in want.get("l2protocol"):
+ for every in have.get("l2protocol"):
+ if every == each:
+ break
+ if each not in have.get("l2protocol"):
+ l2_protocol_diff.append(each)
+ l2_protocol_bool = True
+ l2protocol = tuple(l2_protocol_diff)
+ else:
+ l2protocol = {}
+
+ wants_native = diff.get("native_vlan")
+ l2transport = diff.get("l2transport")
+ q_vlan = diff.get("q_vlan")
+ encapsulation = diff.get("encapsulation")
+ propagate = diff.get("propagate")
+ if l2_protocol_bool is False:
+ l2protocol = diff.get("l2protocol")
+
+ os_version = get_os_version(self._module)
+ if os_version and Version(os_version) < Version("7.0.0"):
+ if wants_native:
+ cmd = "dot1q native vlan {0}".format(wants_native)
+ add_command_to_config_list(interface, cmd, commands)
+
+ if l2transport or l2protocol:
+ for each in l2protocol:
+ each = dict(each)
+ if isinstance(each, dict) and list(each.keys())[0] != "cpsv":
+ cmd = "l2transport l2protocol {0} {1}".format(
+ list(each.keys())[0],
+ list(each.values())[0],
+ )
+ 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"):
+ 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(),
+ ):
+ cmd = "l2transport l2protocol {0} {1}".format(
+ "cpsv",
+ each.get("cpsv"),
+ )
+ add_command_to_config_list(
+ interface,
+ cmd,
+ commands,
+ )
+ break
+ if encapsulation:
+ encapsulation = dict(encapsulation)
+ if encapsulation.get("dot1q"):
+ if encapsulation.get("second_dot1q"):
+ cmd = "encapsulation dot1q {0} second-dot1q {1}".format(
+ encapsulation.get("dot1q"),
+ encapsulation.get("second_dot1q"),
+ )
+ else:
+ cmd = "encapsulation dot1q {0}".format(
+ encapsulation.get("dot1q"),
+ )
+ add_command_to_config_list(interface, cmd, commands)
+
+ if l2transport or l2protocol:
+ if propagate and not have.get("propagate"):
+ cmd = "l2transport propagate remote-status"
+ add_command_to_config_list(interface, cmd, commands)
+ elif want.get("l2transport") is False and (
+ want.get("l2protocol") or want.get("propagate")
+ ):
+ module.fail_json(
+ msg="L2transport L2protocol or Propagate can only be configured when "
+ "L2transport set to True!",
+ )
+
+ return commands
+
+ def _clear_config(self, want, have):
+ # Delete the interface config based on the want and have config
+ commands = []
+
+ if want.get("name"):
+ interface = "interface " + want["name"]
+ else:
+ interface = "interface " + have["name"]
+ os_version = get_os_version(self._module)
+ if os_version and Version(os_version) < Version("7.0.0"):
+ if have.get("native_vlan"):
+ remove_command_from_config_list(
+ interface,
+ "dot1q native vlan",
+ commands,
+ )
+
+ if have.get("q_vlan"):
+ remove_command_from_config_list(
+ interface,
+ "encapsulation dot1q",
+ commands,
+ )
+ else:
+ if have.get("encapsulation"):
+ remove_command_from_config_list(
+ interface,
+ "encapsulation dot1q",
+ commands,
+ )
+
+ if have.get("l2protocol") and (
+ want.get("l2protocol") is None or want.get("propagate") is None
+ ):
+ if "no l2transport" not in commands:
+ remove_command_from_config_list(
+ interface,
+ "l2transport",
+ commands,
+ )
+ elif have.get("l2transport") and have.get("l2transport") != want.get(
+ "l2transport",
+ ):
+ if "no l2transport" not in commands:
+ remove_command_from_config_list(
+ interface,
+ "l2transport",
+ commands,
+ )
+ return commands
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/__init__.py
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
new file mode 100644
index 00000000..98b7c596
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/l3_interfaces/l3_interfaces.py
@@ -0,0 +1,382 @@
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat Inc.
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_l3_interfaces class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import (
+ ConfigBase,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import Facts
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ add_command_to_config_list,
+ dict_to_set,
+ filter_dict_having_none_value,
+ normalize_interface,
+ remove_command_from_config_list,
+ remove_duplicate_interface,
+ validate_ipv6,
+ validate_n_expand_ipv4,
+)
+
+
+class L3_Interfaces(ConfigBase):
+ """
+ The iosxr_l3_interfaces class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["l3_interfaces"]
+
+ def get_l3_interfaces_facts(self, data=None):
+ """Get the 'facts' (the current configuration)
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset,
+ self.gather_network_resources,
+ data=data,
+ )
+ l3_interfaces_facts = facts["ansible_network_resources"].get(
+ "l3_interfaces",
+ )
+ if not l3_interfaces_facts:
+ return []
+ return l3_interfaces_facts
+
+ def execute_module(self):
+ """Execute the module
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_l3_interfaces_facts = self.get_l3_interfaces_facts()
+ else:
+ existing_l3_interfaces_facts = []
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_l3_interfaces_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_l3_interfaces_facts = self.get_l3_interfaces_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed",
+ )
+ result["parsed"] = self.get_l3_interfaces_facts(
+ data=running_config,
+ )
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_l3_interfaces_facts
+ if result["changed"]:
+ result["after"] = changed_l3_interfaces_facts
+
+ elif self.state == "gathered":
+ result["gathered"] = changed_l3_interfaces_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_l3_interfaces_facts):
+ """Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ have = existing_l3_interfaces_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """Select the appropriate function based on the state provided
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ if self.state in ("overridden", "merged", "replaced", "rendered") and not want:
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ self.state,
+ ),
+ )
+
+ if self.state == "overridden":
+ commands = self._state_overridden(want, have, self._module)
+ elif self.state == "deleted":
+ commands = self._state_deleted(want, have)
+ elif self.state in ("merged", "rendered"):
+ commands = self._state_merged(want, have, self._module)
+ elif self.state == "replaced":
+ commands = self._state_replaced(want, have, self._module)
+
+ return commands
+
+ def _state_replaced(self, want, have, module):
+ """The command generator when state is replaced
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ for interface in want:
+ interface["name"] = normalize_interface(interface["name"])
+ for each in have:
+ if each["name"] == interface["name"]:
+ break
+ else:
+ commands.extend(self._set_config(interface, dict(), module))
+ continue
+ have_dict = filter_dict_having_none_value(interface, each)
+ commands.extend(self._clear_config(dict(), have_dict))
+ commands.extend(self._set_config(interface, each, module))
+ # Remove the duplicate interface call
+ commands = remove_duplicate_interface(commands)
+
+ return commands
+
+ def _state_overridden(self, want, have, module):
+ """The command generator when state is overridden
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ not_in_have = set()
+ in_have = set()
+
+ for each in have:
+ for interface in want:
+ interface["name"] = normalize_interface(interface["name"])
+ if each["name"] == interface["name"]:
+ in_have.add(interface["name"])
+ break
+ if interface["name"] != each["name"]:
+ not_in_have.add(interface["name"])
+ else:
+ # We didn't find a matching desired state, which means we can
+ # pretend we received an empty desired state.
+ interface = dict(name=each["name"])
+ kwargs = {"want": interface, "have": each}
+ commands.extend(self._clear_config(**kwargs))
+ continue
+ have_dict = filter_dict_having_none_value(interface, each)
+ commands.extend(self._clear_config(dict(), have_dict))
+ commands.extend(self._set_config(interface, each, module))
+ # Add the want interface that's not already configured in have interface
+ for each in not_in_have - in_have:
+ for every in want:
+ interface = "interface {0}".format(every["name"])
+ if each and interface not in commands:
+ commands.extend(self._set_config(every, {}, module))
+ # Remove the duplicate interface call
+ commands = remove_duplicate_interface(commands)
+
+ return commands
+
+ def _state_merged(self, want, have, module):
+ """The command generator when state is merged
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+
+ for interface in want:
+ interface["name"] = normalize_interface(interface["name"])
+ if self.state == "rendered":
+ commands.extend(self._set_config(interface, dict(), module))
+ else:
+ for each in have:
+ if each["name"] == interface["name"]:
+ break
+ else:
+ commands.extend(
+ self._set_config(interface, dict(), module),
+ )
+ continue
+ commands.extend(self._set_config(interface, each, module))
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """The command generator when state is deleted
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+
+ if want:
+ for interface in want:
+ interface["name"] = normalize_interface(interface["name"])
+ for each in have:
+ if each["name"] == interface["name"] or interface["name"] in each["name"]:
+ break
+ else:
+ continue
+ interface = dict(name=interface["name"])
+ commands.extend(self._clear_config(interface, each))
+ else:
+ for each in have:
+ want = dict()
+ commands.extend(self._clear_config(want, each))
+
+ return commands
+
+ def verify_diff_again(self, want, have):
+ """
+ Verify the IPV4 difference again as sometimes due to
+ change in order of set, set difference may result into change,
+ when there's actually no difference between want and have
+ :param want: want_dict IPV4
+ :param have: have_dict IPV4
+ :return: diff
+ """
+ diff = False
+ for each in want:
+ each_want = dict(each)
+ for every in have:
+ every_have = dict(every)
+
+ if each_want.get("address") == every_have.get("address"):
+ if len(each_want.keys()) == len(every_have.keys()) and (
+ each_want.get("secondary") == every_have.get("secondary")
+ ):
+ diff = False
+ break
+ if not each_want.get("secondary") and not every_have.get(
+ "secondary",
+ ):
+ diff = False
+ break
+
+ diff = True
+ else:
+ diff = True
+ if diff:
+ break
+
+ return diff
+
+ def _set_config(self, want, have, module):
+ # Set the interface config based on the want and have config
+ commands = []
+ interface = "interface " + want["name"]
+
+ # To handle L3 IPV4 configuration
+ if want.get("ipv4"):
+ for each in want.get("ipv4"):
+ if each.get("address") != "dhcp":
+ ip_addr_want = validate_n_expand_ipv4(module, each)
+ each["address"] = ip_addr_want
+
+ # Get the diff b/w want and have
+ want_dict = dict_to_set(want)
+ have_dict = dict_to_set(have)
+
+ # To handle L3 IPV4 configuration
+ want_ipv4 = dict(want_dict).get("ipv4")
+ have_ipv4 = dict(have_dict).get("ipv4")
+ if want_ipv4:
+ if have_ipv4:
+ diff_ipv4 = set(want_ipv4) - set(dict(have_dict).get("ipv4"))
+ if diff_ipv4:
+ diff_ipv4 = diff_ipv4 if self.verify_diff_again(want_ipv4, have_ipv4) else ()
+ else:
+ diff_ipv4 = set(want_ipv4)
+ for each in diff_ipv4:
+ ipv4_dict = dict(each)
+ if ipv4_dict.get("address") != "dhcp":
+ cmd = "ipv4 address {0}".format(ipv4_dict["address"])
+ if ipv4_dict.get("secondary"):
+ cmd += " secondary"
+ add_command_to_config_list(interface, cmd, commands)
+
+ # To handle L3 IPV6 configuration
+ want_ipv6 = dict(want_dict).get("ipv6")
+ have_ipv6 = dict(have_dict).get("ipv6")
+ if want_ipv6:
+ if have_ipv6:
+ diff_ipv6 = set(want_ipv6) - set(have_ipv6)
+ else:
+ diff_ipv6 = set(want_ipv6)
+ for each in diff_ipv6:
+ ipv6_dict = dict(each)
+ validate_ipv6(ipv6_dict.get("address"), module)
+ cmd = "ipv6 address {0}".format(ipv6_dict.get("address"))
+ add_command_to_config_list(interface, cmd, commands)
+
+ return commands
+
+ def _clear_config(self, want, have):
+ # Delete the interface config based on the want and have config
+ count = 0
+ commands = []
+ if want.get("name"):
+ interface = "interface " + want["name"]
+ else:
+ interface = "interface " + have["name"]
+
+ if have.get("ipv4") and want.get("ipv4"):
+ for each in have.get("ipv4"):
+ if each.get("secondary") and not (want.get("ipv4")[count].get("secondary")):
+ cmd = "ipv4 address {0} secondary".format(
+ each.get("address"),
+ )
+ remove_command_from_config_list(interface, cmd, commands)
+ count += 1
+ if have.get("ipv4") and not (want.get("ipv4")):
+ remove_command_from_config_list(
+ interface,
+ "ipv4 address",
+ commands,
+ )
+ if have.get("ipv6") and not (want.get("ipv6")):
+ remove_command_from_config_list(
+ interface,
+ "ipv6 address",
+ commands,
+ )
+
+ return commands
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/__init__.py
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
new file mode 100644
index 00000000..8a6744e5
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp/lacp.py
@@ -0,0 +1,210 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_lacp class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import (
+ ConfigBase,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ dict_diff,
+ remove_empties,
+ to_list,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import Facts
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ flatten_dict,
+)
+
+
+class Lacp(ConfigBase):
+ """
+ The iosxr_lacp class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["lacp"]
+
+ def __init__(self, module):
+ super(Lacp, self).__init__(module)
+
+ def get_lacp_facts(self, data=None):
+ """Get the 'facts' (the current configuration)
+
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset,
+ self.gather_network_resources,
+ data=data,
+ )
+ lacp_facts = facts["ansible_network_resources"].get("lacp")
+ if not lacp_facts:
+ return {}
+ return lacp_facts
+
+ def execute_module(self):
+ """Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_lacp_facts = self.get_lacp_facts()
+ else:
+ existing_lacp_facts = {}
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_lacp_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_lacp_facts = self.get_lacp_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed",
+ )
+ result["parsed"] = self.get_lacp_facts(data=running_config)
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_lacp_facts
+ if result["changed"]:
+ result["after"] = changed_lacp_facts
+
+ elif self.state == "gathered":
+ result["gathered"] = changed_lacp_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_lacp_facts):
+ """Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params.get("config")
+ if not want:
+ want = {}
+ have = existing_lacp_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """Select the appropriate function based on the state provided
+
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ if self.state in ("merged", "replaced", "rendered") and not want:
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ self.state,
+ ),
+ )
+
+ if self.state == "deleted":
+ commands = self._state_deleted(want, have)
+ elif self.state in ("merged", "rendered"):
+ commands = self._state_merged(want, have)
+ elif self.state == "replaced":
+ commands = self._state_replaced(want, have)
+
+ return commands
+
+ def _state_replaced(self, want, have):
+ """The command generator when state is replaced
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ commands.extend(self._state_deleted(want, have))
+
+ commands.extend(self._state_merged(want, have))
+
+ return commands
+
+ def _state_merged(self, want, have):
+ """The command generator when state is merged
+
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+
+ updates = dict_diff(have, want)
+ if self.state == "rendered":
+ updates = want
+ if updates:
+ for key, value in iteritems(
+ flatten_dict(remove_empties(updates["system"])),
+ ):
+ commands.append(
+ "lacp system {0} {1}".format(
+ key.replace("address", "mac"),
+ value,
+ ),
+ )
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """The command generator when state is deleted
+
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+
+ for x in [
+ k for k in have.get("system", {}) if k not in remove_empties(want.get("system", {}))
+ ]:
+ commands.append("no lacp system {0}".format(x))
+
+ return commands
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp_interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp_interfaces/lacp_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp_interfaces/lacp_interfaces.py
new file mode 100644
index 00000000..a438726f
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lacp_interfaces/lacp_interfaces.py
@@ -0,0 +1,309 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_lacp_interfaces class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import (
+ ConfigBase,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ dict_diff,
+ remove_empties,
+ search_obj_in_list,
+ to_list,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import Facts
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ dict_delete,
+ flatten_dict,
+ pad_commands,
+)
+
+
+class Lacp_interfaces(ConfigBase):
+ """
+ The iosxr_lacp_interfaces class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["lacp_interfaces"]
+
+ def __init__(self, module):
+ super(Lacp_interfaces, self).__init__(module)
+
+ def get_lacp_interfaces_facts(self, data=None):
+ """Get the 'facts' (the current configuration)
+
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset,
+ self.gather_network_resources,
+ data=data,
+ )
+ lacp_interfaces_facts = facts["ansible_network_resources"].get(
+ "lacp_interfaces",
+ )
+ if not lacp_interfaces_facts:
+ return []
+ return lacp_interfaces_facts
+
+ def execute_module(self):
+ """Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ commands = list()
+ warnings = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_lacp_interfaces_facts = self.get_lacp_interfaces_facts()
+ else:
+ existing_lacp_interfaces_facts = []
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_lacp_interfaces_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_lacp_interfaces_facts = self.get_lacp_interfaces_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed",
+ )
+ result["parsed"] = self.get_lacp_interfaces_facts(
+ data=running_config,
+ )
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_lacp_interfaces_facts
+ if result["changed"]:
+ result["after"] = changed_lacp_interfaces_facts
+ elif self.state == "gathered":
+ result["gathered"] = changed_lacp_interfaces_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_lacp_interfaces_facts):
+ """Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ have = existing_lacp_interfaces_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """Select the appropriate function based on the state provided
+
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ state = self._module.params["state"]
+
+ if state in ("overridden", "merged", "replaced", "rendered") and not want:
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ state,
+ ),
+ )
+
+ if state == "overridden":
+ commands.extend(Lacp_interfaces._state_overridden(want, have))
+
+ elif state == "deleted":
+ if not want:
+ for intf in have:
+ commands.extend(
+ Lacp_interfaces._state_deleted(
+ {"name": intf["name"]},
+ intf,
+ ),
+ )
+ else:
+ for item in want:
+ obj_in_have = search_obj_in_list(item["name"], have)
+ commands.extend(
+ Lacp_interfaces._state_deleted(item, obj_in_have),
+ )
+
+ else:
+ for item in want:
+ name = item["name"]
+ obj_in_have = search_obj_in_list(name, have)
+
+ if state in ("merged", "rendered"):
+ commands.extend(
+ Lacp_interfaces._state_merged(item, obj_in_have),
+ )
+
+ elif state == "replaced":
+ commands.extend(
+ Lacp_interfaces._state_replaced(item, obj_in_have),
+ )
+
+ return commands
+
+ @staticmethod
+ def _state_replaced(want, have):
+ """The command generator when state is replaced
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ replaced_commands = []
+ merged_commands = []
+
+ if have:
+ replaced_commands = Lacp_interfaces._state_deleted(want, have)
+
+ merged_commands = Lacp_interfaces._state_merged(want, have)
+
+ if merged_commands and replaced_commands:
+ del merged_commands[0]
+
+ commands.extend(replaced_commands)
+ commands.extend(merged_commands)
+
+ return commands
+
+ @staticmethod
+ def _state_overridden(want, have):
+ """The command generator when state is overridden
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ for intf in have:
+ intf_in_want = search_obj_in_list(intf["name"], want)
+ if not intf_in_want:
+ commands.extend(
+ Lacp_interfaces._state_deleted(
+ {"name": intf["name"]},
+ intf,
+ ),
+ )
+
+ for intf in want:
+ intf_in_have = search_obj_in_list(intf["name"], have)
+ commands.extend(
+ Lacp_interfaces._state_replaced(intf, intf_in_have),
+ )
+
+ return commands
+
+ @staticmethod
+ def _state_merged(want, have):
+ """The command generator when state is merged
+
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+
+ if not have:
+ have = {"name": want["name"]}
+
+ for key, value in iteritems(
+ flatten_dict(remove_empties(dict_diff(have, want))),
+ ):
+ commands.append(Lacp_interfaces._compute_commands(key, value))
+
+ if commands:
+ pad_commands(commands, want["name"])
+
+ return commands
+
+ @staticmethod
+ def _state_deleted(want, have):
+ """The command generator when state is deleted
+
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+
+ for key, value in iteritems(
+ flatten_dict(dict_delete(have, remove_empties(want))),
+ ):
+ commands.append(
+ Lacp_interfaces._compute_commands(key, value, remove=True),
+ )
+
+ if commands:
+ pad_commands(commands, have["name"])
+
+ return commands
+
+ @staticmethod
+ def _compute_commands(key, value, remove=False):
+ if key == "churn_logging":
+ cmd = "lacp churn logging {0}".format(value)
+
+ elif key == "collector_max_delay":
+ cmd = "lacp collector-max-delay {0}".format(value)
+
+ elif key == "period":
+ cmd = "lacp period {0}".format(value)
+
+ elif key == "switchover_suppress_flaps":
+ cmd = "lacp switchover suppress-flaps {0}".format(value)
+
+ elif key == "mac":
+ cmd = "lacp system mac {0}".format(value)
+
+ elif key == "priority":
+ cmd = "lacp system priority {0}".format(value)
+
+ if remove:
+ cmd = "no " + cmd
+
+ return cmd
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lag_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lag_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lag_interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lag_interfaces/lag_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lag_interfaces/lag_interfaces.py
new file mode 100644
index 00000000..69422604
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lag_interfaces/lag_interfaces.py
@@ -0,0 +1,446 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_lag_interfaces class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from copy import deepcopy
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import (
+ ConfigBase,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ dict_diff,
+ param_list_to_dict,
+ remove_empties,
+ search_obj_in_list,
+ to_list,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import Facts
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import get_os_version
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ Version,
+ dict_delete,
+ diff_list_of_dicts,
+ flatten_dict,
+ normalize_interface,
+ pad_commands,
+)
+
+
+class Lag_interfaces(ConfigBase):
+ """
+ The iosxr_lag_interfaces class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["lag_interfaces"]
+
+ def __init__(self, module):
+ super(Lag_interfaces, self).__init__(module)
+
+ def get_lag_interfaces_facts(self, data=None):
+ """Get the 'facts' (the current configuration)
+
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset,
+ self.gather_network_resources,
+ data=data,
+ )
+ lag_interfaces_facts = facts["ansible_network_resources"].get(
+ "lag_interfaces",
+ )
+ if not lag_interfaces_facts:
+ return []
+ return lag_interfaces_facts
+
+ def execute_module(self):
+ """Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+ if self.state in self.ACTION_STATES:
+ existing_lag_interfaces_facts = self.get_lag_interfaces_facts()
+ else:
+ existing_lag_interfaces_facts = {}
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_lag_interfaces_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_lag_interfaces_facts = self.get_lag_interfaces_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed",
+ )
+ result["parsed"] = self.get_lag_interfaces_facts(
+ data=running_config,
+ )
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_lag_interfaces_facts
+ if result["changed"]:
+ result["after"] = changed_lag_interfaces_facts
+
+ elif self.state == "gathered":
+ result["gathered"] = changed_lag_interfaces_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_lag_interfaces_facts):
+ """Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ if want:
+ for item in want:
+ item["name"] = normalize_interface(item["name"])
+ if "members" in want and want["members"]:
+ for item in want["members"]:
+ item.update(
+ {
+ "member": normalize_interface(item["member"]),
+ "mode": item["mode"],
+ },
+ )
+ have = existing_lag_interfaces_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """Select the appropriate function based on the state provided
+
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ state = self._module.params["state"]
+ commands = []
+
+ if self.state in ("merged", "replaced", "overridden", "rendered") and not want:
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ state,
+ ),
+ )
+
+ if state == "overridden":
+ commands.extend(self._state_overridden(want, have))
+
+ elif state == "deleted":
+ commands.extend(self._state_deleted(want, have))
+
+ else:
+ # Instead of passing entire want and have
+ # list of dictionaries to the respective
+ # _state_* methods we are passing the want
+ # and have dictionaries per interface
+ for item in want:
+ name = item["name"]
+ obj_in_have = search_obj_in_list(name, have)
+
+ if state in ("merged", "rendered"):
+ commands.extend(self._state_merged(item, obj_in_have))
+
+ elif state == "replaced":
+ commands.extend(self._state_replaced(item, obj_in_have))
+
+ return commands
+
+ def _state_replaced(self, want, have):
+ """The command generator when state is replaced
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ if have:
+ commands.extend(self._render_bundle_del_commands(want, have))
+ commands.extend(self._render_bundle_updates(want, have))
+
+ if commands or have == {}:
+ pad_commands(commands, want["name"])
+
+ if have:
+ commands.extend(self._render_interface_del_commands(want, have))
+ commands.extend(self._render_interface_updates(want, have))
+
+ return commands
+
+ def _state_overridden(self, want, have):
+ """The command generator when state is overridden
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ for have_intf in have:
+ intf_in_want = search_obj_in_list(have_intf["name"], want)
+ if not intf_in_want:
+ commands.extend(self._purge_attribs(have_intf))
+
+ for intf in want:
+ intf_in_have = search_obj_in_list(intf["name"], have)
+ commands.extend(self._state_replaced(intf, intf_in_have))
+
+ return commands
+
+ def _state_merged(self, want, have):
+ """The command generator when state is merged
+
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+ commands.extend(self._render_bundle_updates(want, have))
+
+ if commands or have == {}:
+ pad_commands(commands, want["name"])
+
+ commands.extend(self._render_interface_updates(want, have))
+ return commands
+
+ def _state_deleted(self, want, have):
+ """The command generator when state is deleted
+
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+
+ if not want:
+ for item in have:
+ commands.extend(self._purge_attribs(intf=item))
+ else:
+ for item in want:
+ name = item["name"]
+ obj_in_have = search_obj_in_list(name, have)
+ if not obj_in_have:
+ self._module.fail_json(
+ msg=("interface {0} does not exist".format(name)),
+ )
+ commands.extend(self._purge_attribs(intf=obj_in_have))
+
+ return commands
+
+ def _render_bundle_updates(self, want, have):
+ """The command generator for updates to bundles
+ :rtype: A list
+ :returns: the commands necessary to update bundles
+ """
+ commands = []
+ if not have:
+ have = {"name": want["name"]}
+
+ want_copy = deepcopy(want)
+ have_copy = deepcopy(have)
+
+ want_copy.pop("members", [])
+ have_copy.pop("members", [])
+
+ bundle_updates = dict_diff(have_copy, want_copy)
+
+ if bundle_updates:
+ for key, value in iteritems(
+ flatten_dict(remove_empties(bundle_updates)),
+ ):
+ commands.append(self._compute_commands(key=key, value=value))
+
+ return commands
+
+ def _render_interface_updates(self, want, have):
+ """The command generator for updates to member
+ interfaces
+ :rtype: A list
+ :returns: the commands necessary to update member
+ interfaces
+ """
+ commands = []
+
+ if not have:
+ have = {"name": want["name"]}
+
+ member_diff = diff_list_of_dicts(
+ want["members"],
+ have.get("members", []),
+ )
+
+ for diff in member_diff:
+ diff_cmd = []
+ bundle_cmd = "bundle id {0}".format(
+ want["name"].split("Bundle-Ether")[1],
+ )
+ if diff.get("mode"):
+ bundle_cmd += " mode {0}".format(diff.get("mode"))
+ diff_cmd.append(bundle_cmd)
+ pad_commands(diff_cmd, diff["member"])
+ commands.extend(diff_cmd)
+
+ return commands
+
+ def _render_bundle_del_commands(self, want, have):
+ """The command generator for delete commands
+ w.r.t bundles
+ :rtype: A list
+ :returns: the commands necessary to update member
+ interfaces
+ """
+ commands = []
+ if not want:
+ want = {"name": have["name"]}
+
+ want_copy = deepcopy(want)
+ have_copy = deepcopy(have)
+ want_copy.pop("members", [])
+ have_copy.pop("members", [])
+
+ to_delete = dict_delete(have_copy, remove_empties(want_copy))
+ if to_delete:
+ for key, value in iteritems(
+ flatten_dict(remove_empties(to_delete)),
+ ):
+ commands.append(
+ self._compute_commands(key=key, value=value, remove=True),
+ )
+
+ return commands
+
+ def _render_interface_del_commands(self, want, have):
+ """The command generator for delete commands
+ w.r.t member interfaces
+ :rtype: A list
+ :returns: the commands necessary to update member
+ interfaces
+ """
+ commands = []
+ if not want:
+ want = {}
+ have_members = have.get("members")
+
+ if have_members:
+ have_members = param_list_to_dict(
+ deepcopy(have_members),
+ unique_key="member",
+ )
+ want_members = param_list_to_dict(
+ deepcopy(want).get("members", []),
+ unique_key="member",
+ )
+
+ for key in have_members:
+ if key not in want_members:
+ member_cmd = ["no bundle id"]
+ pad_commands(member_cmd, key)
+ commands.extend(member_cmd)
+
+ return commands
+
+ def _purge_attribs(self, intf):
+ """The command generator for purging attributes
+ :rtype: A list
+ :returns: the commands necessary to purge attributes
+ """
+ commands = []
+ have_copy = deepcopy(intf)
+ members = have_copy.pop("members", [])
+
+ to_delete = dict_delete(
+ have_copy,
+ remove_empties({"name": have_copy["name"]}),
+ )
+ if to_delete:
+ for key, value in iteritems(
+ flatten_dict(remove_empties(to_delete)),
+ ):
+ commands.append(
+ self._compute_commands(key=key, value=value, remove=True),
+ )
+
+ if commands:
+ pad_commands(commands, intf["name"])
+
+ if members:
+ members = param_list_to_dict(
+ deepcopy(members),
+ unique_key="member",
+ )
+ for key in members:
+ member_cmd = ["no bundle id"]
+ pad_commands(member_cmd, key)
+ commands.extend(member_cmd)
+
+ return commands
+
+ def _compute_commands(self, key, value, remove=False):
+ """The method generates LAG commands based on the
+ key, value passed. When remove is set to True,
+ the command is negated.
+ :rtype: str
+ :returns: a command based on the `key`, `value` pair
+ passed and the value of `remove`
+ """
+ if key == "mode":
+ cmd = "lacp mode {0}".format(value)
+
+ elif key == "load_balancing_hash":
+ os_version = get_os_version(self._module)
+ if os_version and Version(os_version) < Version("7.0.0"):
+ cmd = "bundle load-balancing hash {0}".format(value)
+
+ elif key == "max_active":
+ cmd = "bundle maximum-active links {0}".format(value)
+
+ elif key == "min_active":
+ cmd = "bundle minimum-active links {0}".format(value)
+
+ if remove:
+ cmd = "no {0}".format(cmd)
+
+ return cmd
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/__init__.py
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
new file mode 100644
index 00000000..e4fda3c7
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_global/lldp_global.py
@@ -0,0 +1,223 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_lldp_global class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import (
+ ConfigBase,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ dict_diff,
+ remove_empties,
+ to_list,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import Facts
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ dict_delete,
+ flatten_dict,
+)
+
+
+class Lldp_global(ConfigBase):
+ """
+ The iosxr_lldp class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["lldp_global"]
+
+ def __init__(self, module):
+ super(Lldp_global, self).__init__(module)
+
+ def get_lldp_global_facts(self, data=None):
+ """Get the 'facts' (the current configuration)
+
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset,
+ self.gather_network_resources,
+ data=data,
+ )
+ lldp_facts = facts["ansible_network_resources"].get("lldp_global")
+ if not lldp_facts:
+ return {}
+ return lldp_facts
+
+ def execute_module(self):
+ """Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+ if self.state in self.ACTION_STATES:
+ existing_lldp_global_facts = self.get_lldp_global_facts()
+ else:
+ existing_lldp_global_facts = {}
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_lldp_global_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_lldp_global_facts = self.get_lldp_global_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed",
+ )
+ result["parsed"] = self.get_lldp_global_facts(data=running_config)
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_lldp_global_facts
+ if result["changed"]:
+ result["after"] = changed_lldp_global_facts
+ elif self.state == "gathered":
+ result["gathered"] = changed_lldp_global_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_lldp_global_facts):
+ """Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ if not want and self._module.params["state"] == "deleted":
+ want = {}
+ have = existing_lldp_global_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """Select the appropriate function based on the state provided
+
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ state = self._module.params["state"]
+ if state in ("merged", "replaced", "rendered") and not want:
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ state,
+ ),
+ )
+
+ if state == "deleted":
+ commands = self._state_deleted(want, have)
+ elif state in ("merged", "rendered"):
+ commands = self._state_merged(want, have)
+ elif state == "replaced":
+ commands = self._state_replaced(want, have)
+
+ return commands
+
+ def _state_replaced(self, want, have):
+ """The command generator when state is replaced
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ commands.extend(self._state_deleted(want, have))
+
+ commands.extend(self._state_merged(want, have))
+
+ return commands
+
+ def _state_merged(self, want, have):
+ """The command generator when state is merged
+
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+ updates = dict_diff(have, want)
+ if updates:
+ for key, value in iteritems(flatten_dict(remove_empties(updates))):
+ commands.append(self._compute_commands(key, value))
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """The command generator when state is deleted
+
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+ for key, value in iteritems(
+ flatten_dict(dict_delete(have, remove_empties(want))),
+ ):
+ cmd = self._compute_commands(key, value, remove=True)
+ if cmd:
+ commands.append(cmd)
+
+ return commands
+
+ def _compute_commands(self, key, value=None, remove=False):
+ if key in ["holdtime", "reinit", "timer"]:
+ cmd = "lldp {0} {1}".format(key, value)
+ if remove:
+ return "no {0}".format(cmd)
+ else:
+ return cmd
+
+ elif key == "subinterfaces":
+ cmd = "lldp subinterfaces enable"
+ if value and not remove:
+ return cmd
+ elif (not value and not remove) or (value and remove):
+ return "no {0}".format(cmd)
+
+ else:
+ cmd = "lldp tlv-select {0} disable".format(key.replace("_", "-"))
+ if not value and not remove:
+ return cmd
+ elif (value and not remove) or (not value and remove):
+ return "no {0}".format(cmd)
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_interfaces/lldp_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_interfaces/lldp_interfaces.py
new file mode 100644
index 00000000..93dc42f4
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/lldp_interfaces/lldp_interfaces.py
@@ -0,0 +1,277 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_lldp_interfaces class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import (
+ ConfigBase,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ dict_diff,
+ remove_empties,
+ search_obj_in_list,
+ to_list,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import Facts
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ dict_delete,
+ flatten_dict,
+ pad_commands,
+)
+
+
+class Lldp_interfaces(ConfigBase):
+ """
+ The iosxr_lldp_interfaces class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["lldp_interfaces"]
+
+ def __init__(self, module):
+ super(Lldp_interfaces, self).__init__(module)
+
+ def get_lldp_interfaces_facts(self, data=None):
+ """Get the 'facts' (the current configuration)
+
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset,
+ self.gather_network_resources,
+ data=data,
+ )
+ lldp_interfaces_facts = facts["ansible_network_resources"].get(
+ "lldp_interfaces",
+ )
+ if not lldp_interfaces_facts:
+ return []
+ return lldp_interfaces_facts
+
+ def execute_module(self):
+ """Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_lldp_interfaces_facts = self.get_lldp_interfaces_facts()
+ else:
+ existing_lldp_interfaces_facts = []
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_lldp_interfaces_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_lldp_interfaces_facts = self.get_lldp_interfaces_facts()
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed",
+ )
+ result["parsed"] = self.get_lldp_interfaces_facts(
+ data=running_config,
+ )
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_lldp_interfaces_facts
+ if result["changed"]:
+ result["after"] = changed_lldp_interfaces_facts
+ elif self.state == "gathered":
+ result["gathered"] = changed_lldp_interfaces_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_lldp_interfaces_facts):
+ """Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ have = existing_lldp_interfaces_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """Select the appropriate function based on the state provided
+
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ state = self._module.params["state"]
+ commands = []
+ if state in ("overridden", "merged", "replaced", "rendered") and not want:
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ state,
+ ),
+ )
+
+ if state == "overridden":
+ commands.extend(self._state_overridden(want, have))
+
+ elif state == "deleted":
+ if not want:
+ for intf in have:
+ commands.extend(
+ self._state_deleted({"name": intf["name"]}, intf),
+ )
+ else:
+ for item in want:
+ obj_in_have = search_obj_in_list(item["name"], have)
+ commands.extend(self._state_deleted(item, obj_in_have))
+
+ else:
+ for item in want:
+ name = item["name"]
+ obj_in_have = search_obj_in_list(name, have)
+
+ if state in ("merged", "rendered"):
+ commands.extend(self._state_merged(item, obj_in_have))
+
+ elif state == "replaced":
+ commands.extend(self._state_replaced(item, obj_in_have))
+
+ return commands
+
+ def _state_replaced(self, want, have):
+ """The command generator when state is replaced
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+ replaced_commands = []
+ merged_commands = []
+
+ if have:
+ replaced_commands = self._state_deleted(want, have)
+
+ merged_commands = self._state_merged(want, have)
+
+ if merged_commands and replaced_commands:
+ del merged_commands[0]
+
+ commands.extend(replaced_commands)
+ commands.extend(merged_commands)
+
+ return commands
+
+ def _state_overridden(self, want, have):
+ """The command generator when state is overridden
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ for intf in have:
+ intf_in_want = search_obj_in_list(intf["name"], want)
+ if not intf_in_want:
+ commands.extend(
+ self._state_deleted({"name": intf["name"]}, intf),
+ )
+
+ for intf in want:
+ intf_in_have = search_obj_in_list(intf["name"], have)
+ commands.extend(self._state_replaced(intf, intf_in_have))
+
+ return commands
+
+ def _state_merged(self, want, have):
+ """The command generator when state is merged
+
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+ if not have:
+ have = {"name": want["name"]}
+
+ for key, value in iteritems(
+ flatten_dict(remove_empties(dict_diff(have, want))),
+ ):
+ commands.append(self._compute_commands(key, value))
+
+ if commands:
+ pad_commands(commands, want["name"])
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """The command generator when state is deleted
+
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+
+ for key, value in iteritems(
+ flatten_dict(dict_delete(have, remove_empties(want))),
+ ):
+ commands.append(self._compute_commands(key, value, remove=True))
+
+ if commands:
+ pad_commands(commands, have["name"])
+
+ return commands
+
+ def _compute_commands(self, key, value=None, remove=False):
+ if key == "mac_address":
+ cmd = "lldp destination mac-address {0}".format(value)
+ if remove:
+ return "no {0}".format(cmd)
+ else:
+ return cmd
+
+ else:
+ cmd = "lldp {0} disable".format(key)
+ if not value and not remove:
+ return cmd
+ elif (value and not remove) or (not value and remove):
+ return "no {0}".format(cmd)
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/logging_global/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/logging_global/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/logging_global/__init__.py
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
new file mode 100644
index 00000000..ff790e54
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/logging_global/logging_global.py
@@ -0,0 +1,227 @@
+#
+# -*- 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 iosxr_logging_global 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_diff,
+ 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.logging_global import (
+ Logging_globalTemplate,
+)
+
+
+class Logging_global(ResourceModule):
+ """
+ The iosxr_logging_global config class
+ """
+
+ def __init__(self, module):
+ super(Logging_global, self).__init__(
+ empty_fact_val={},
+ facts_module=Facts(module),
+ module=module,
+ resource="logging_global",
+ tmplt=Logging_globalTemplate(),
+ )
+ self.parsers = [
+ "archive.device",
+ "archive.frequency",
+ "archive.severity",
+ "archive.archive_size",
+ "archive.archive_length",
+ "archive.file_size",
+ "buffered.size",
+ "buffered.severity",
+ "buffered.discriminator",
+ "console.severity",
+ "correlator.buffer_size",
+ "events.threshold",
+ "events.buffer_size",
+ "events.display_location",
+ "events.severity",
+ "facility",
+ "hostnameprefix",
+ "format",
+ "ipv4.dscp",
+ "ipv6.dscp",
+ "ipv4.precedence",
+ "ipv6.precedence",
+ "localfilesize",
+ "suppress.duplicates",
+ "suppress.apply_rule",
+ "monitor.severity",
+ "monitor.discriminator",
+ "history.size",
+ "history.severity",
+ "trap.severity",
+ "trap.state",
+ "monitor.state",
+ "history.state",
+ "console.state",
+ ]
+
+ def execute_module(self):
+ """Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ if self.state not in ["parsed", "gathered"]:
+ self.generate_commands()
+ self.run_commands()
+ return self.result
+
+ def generate_commands(self):
+ """Generate configuration commands to send based on
+ want, have and desired state.
+ """
+ wantd = self.list_to_dict(self.want)
+ haved = self.list_to_dict(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":
+ wantd = {}
+
+ self._compare(want=wantd, have=haved)
+ if self.state in ["overridden", "replaced"]:
+ self.commands = [each for each in self.commands if "no" in each] + [
+ each for each in self.commands if "no" not in each
+ ]
+
+ def _compare(self, want, have):
+ """Leverages the base class `compare()` method and
+ populates the list of commands to be run by comparing
+ the `want` and `have` data with the `parsers` defined
+ for the Logging_global network resource.
+ """
+ self.compare(parsers=self.parsers, want=want, have=have)
+ self._compare_lists(want, have)
+
+ def _compare_lists(self, want, have):
+ """
+ Handles list attributes from config_data
+ """
+ for x in [
+ "hosts",
+ "files",
+ "source_interfaces",
+ "tls_servers",
+ "correlator.rule_sets",
+ "correlator.rules",
+ "events.filter_match",
+ "buffered.discriminator",
+ "monitor.discriminator",
+ "console.discriminator",
+ ]:
+ wantx = want.get(x, {})
+ havex = have.get(x, {})
+ if "." in x:
+ complex_parser = x.split(".")
+ wantx = want.get(complex_parser[0], {}).get(
+ complex_parser[1],
+ {},
+ )
+ havex = have.get(complex_parser[0], {}).get(
+ complex_parser[1],
+ {},
+ )
+
+ if x in ["tls_servers", "correlator.rules"]:
+ # handling complex parsers for replaced and overridden state
+
+ for key, wentry in iteritems(wantx):
+ hentry = havex.pop(key, {})
+ updates = dict_diff(hentry, wentry)
+ if updates and x == "tls_servers":
+ updates.update(name=wentry["name"])
+ self.addcmd(updates, x)
+ elif updates and x == "correlator.rules":
+ updates.update(rule_type=wentry["rule_type"])
+ updates.update(rule_name=wentry["rule_name"])
+ self.addcmd(updates, x)
+ else:
+ for key, wentry in iteritems(wantx):
+ hentry = havex.pop(key, {})
+ if wentry != hentry:
+ self.addcmd(wentry, x)
+
+ for key, hentry in iteritems(havex):
+ 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"]}
+
+ if "source_interfaces" in data:
+ data["source_interfaces"] = {
+ x["interface"] + "_" + x.get("vrf", ""): x for x in data["source_interfaces"]
+ }
+
+ if "files" in data:
+ data["files"] = {x["name"]: x for x in data["files"]}
+
+ if "hosts" in data:
+ data["hosts"] = {x["host"]: x for x in data["hosts"]}
+ if "events" in data:
+ if "filter_match" in data["events"]:
+ data["events"]["filter_match"] = {
+ x: {"match": x} for x in data["events"]["filter_match"]
+ }
+
+ if "correlator" in data:
+ if "rules" in data["correlator"]:
+ data["correlator"]["rules"] = {
+ x["rule_name"]: x for x in data["correlator"]["rules"]
+ }
+ if "rule_sets" in data["correlator"]:
+ rule_sets = deepcopy(data["correlator"]["rule_sets"])
+ data["correlator"]["rule_sets"] = dict()
+ for x in rule_sets:
+ if len(x.get("rulename", [])) > 0:
+ for y in x.get("rulename"):
+ new_data = {"rulename": y, "name": x["name"]}
+ data["correlator"]["rule_sets"].update(
+ {x["name"] + "_" + y: new_data},
+ )
+
+ else:
+ data["correlator"]["rule_sets"].update({x["name"]: x})
+
+ for x in ["buffered", "monitor", "console"]:
+ if x in data:
+ if "discriminator" in data[x]:
+ data[x]["discriminator"] = {
+ x["match_params"] + "_" + x["name"]: x for x in data[x]["discriminator"]
+ }
+ return data
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ntp_global/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ntp_global/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ntp_global/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ntp_global/ntp_global.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ntp_global/ntp_global.py
new file mode 100644
index 00000000..5ec1789b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ntp_global/ntp_global.py
@@ -0,0 +1,188 @@
+#
+# -*- 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 iosxr_ntp_global 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_diff,
+ 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.ntp_global import (
+ Ntp_globalTemplate,
+)
+
+
+class Ntp_global(ResourceModule):
+ """
+ The iosxr_ntp_global config class
+ """
+
+ def __init__(self, module):
+ super(Ntp_global, self).__init__(
+ empty_fact_val={},
+ facts_module=Facts(module),
+ module=module,
+ resource="ntp_global",
+ tmplt=Ntp_globalTemplate(),
+ )
+ self.parsers = [
+ "access_group.ipv4.peer",
+ "access_group.ipv4.serve",
+ "access_group.ipv4.serve_only",
+ "access_group.ipv4.query_only",
+ "access_group.ipv6.peer",
+ "access_group.ipv6.serve",
+ "access_group.ipv6.serve_only",
+ "access_group.ipv6.query_only",
+ "authenticate",
+ "log_internal_sync",
+ "broadcastdelay",
+ "drift.aging_time",
+ "drift.file",
+ "ipv4.dscp",
+ "ipv4.precedence",
+ "ipv6.dscp",
+ "ipv6.precedence",
+ "max_associations",
+ "master.stratum",
+ "passive",
+ "update_calendar",
+ "source_interface",
+ ]
+
+ def execute_module(self):
+ """Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ if self.state not in ["parsed", "gathered"]:
+ self.generate_commands()
+ self.run_commands()
+ return self.result
+
+ def generate_commands(self):
+ """Generate configuration commands to send based on
+ want, have and desired state.
+ """
+ wantd = self._ntp_list_to_dict(self.want)
+ haved = self._ntp_list_to_dict(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
+ if self.state == "deleted":
+ wantd = {}
+
+ self._compare(want=wantd, have=haved)
+ if self.state in ["overridden", "replaced"]:
+ self.commands = [each for each in self.commands if "no" in each] + [
+ each for each in self.commands if "no" not in each
+ ]
+
+ def _compare(self, want, have):
+ """Leverages the base class `compare()` method and
+ populates the list of commands to be run by comparing
+ the `want` and `have` data with the `parsers` defined
+ for the Ntp_global network resource.
+ """
+ self._compare_lists(want=want, have=have)
+ self.compare(parsers=self.parsers, want=want, have=have)
+
+ def _compare_lists(self, want, have):
+ keys = [
+ "authentication_keys",
+ "peers",
+ "servers",
+ "trusted_keys",
+ "interfaces",
+ "source_vrfs",
+ "access_group.vrfs",
+ ]
+ for x in keys:
+ if "." in x:
+ ag_vrf_list = x.split(".")
+ wantx = want.get(ag_vrf_list[0], {}).get(ag_vrf_list[1], {})
+ havex = have.get(ag_vrf_list[0], {}).get(ag_vrf_list[1], {})
+ x = ag_vrf_list[1]
+ else:
+ wantx = want.get(x, {})
+ havex = have.get(x, {})
+
+ for wkey, wentry in iteritems(wantx):
+ hentry = havex.pop(wkey, {})
+ if wentry != hentry:
+ if x == "interfaces":
+ updates = dict_diff(hentry, wentry)
+ updates.update(name=wentry.get("name"))
+ updates.update(vrf=wentry.get("vrf", ""))
+ self.addcmd(updates, x)
+ else:
+ self.addcmd(wentry, x)
+
+ # remove superfluos config
+ for _hkey, hentry in iteritems(havex):
+ if x == "interfaces":
+ if "vrf" in hentry:
+ self.commands.append(
+ "no ntp interface {0} vrf {1}".format(
+ _hkey.split("_")[0],
+ _hkey.split("_")[1],
+ ),
+ )
+ else:
+ self.commands.append(
+ "no ntp interface {0}".format(_hkey.split("_")[0]),
+ )
+ else:
+ self.addcmd(hentry, x, negate=True)
+
+ def _ntp_list_to_dict(self, data):
+ """Convert all list to dicts to dicts
+ of dicts
+ """
+ tmp = deepcopy(data)
+ if "access_group" in tmp:
+ if "vrfs" in tmp["access_group"]:
+ tmp["access_group"]["vrfs"] = {i["name"]: i for i in tmp["access_group"]["vrfs"]}
+ if "interfaces" in tmp:
+ tmp["interfaces"] = {i["name"] + "_" + i.get("vrf", ""): i for i in tmp["interfaces"]}
+ if "peers" in tmp:
+ tmp["peers"] = {i["peer"] + "_" + i.get("vrf", ""): i for i in tmp["peers"]}
+ if "servers" in tmp:
+ tmp["servers"] = {i["server"] + "_" + i.get("vrf", ""): i for i in tmp["servers"]}
+
+ pkey = {
+ "authentication_keys": "id",
+ "trusted_keys": "key_id",
+ "source_vrfs": "vrf",
+ }
+ for k in pkey.keys():
+ if k in tmp:
+ tmp[k] = {i[pkey[k]]: i for i in tmp[k]}
+ return tmp
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospf_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospf_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospf_interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospf_interfaces/ospf_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospf_interfaces/ospf_interfaces.py
new file mode 100644
index 00000000..a80fe215
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospf_interfaces/ospf_interfaces.py
@@ -0,0 +1,236 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+"""
+The iosxr_ospf_interfaces config file.
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to its desired end-state is
+created.
+"""
+
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.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.ospf_interfaces import (
+ Ospf_interfacesTemplate,
+)
+
+
+class Ospf_interfaces(ResourceModule):
+ """
+ The iosxr_ospf_interfaces config class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["ospf_interfaces"]
+
+ def __init__(self, module):
+ super(Ospf_interfaces, self).__init__(
+ empty_fact_val=[],
+ facts_module=Facts(module),
+ module=module,
+ resource="ospf_interfaces",
+ tmplt=Ospf_interfacesTemplate(),
+ )
+ self.parsers = [
+ "authentication.message_digest",
+ "authentication.null_auth",
+ "authentication.message_digest.keychain",
+ "authentication_key",
+ "bfd.minimum_interval",
+ "bfd.multiplier",
+ "bfd.fast_detect.set",
+ "bfd.fast_detect.disable",
+ "bfd.fast_detect.strict_mode",
+ "cost",
+ "cost_fallback",
+ "dead_interval",
+ "demand_circuit",
+ "flood_reduction",
+ "hello_interval",
+ "link_down.set",
+ "link_down.disable",
+ "message_digest_key",
+ "mpls.set_ldp",
+ "mpls.ldp_sync",
+ "mpls.ldp_sync_disable",
+ "mtu_ignore",
+ "network",
+ "packet_size",
+ "passive",
+ "prefix_suppression.disable",
+ "prefix_suppression.secondary_address",
+ "priority",
+ "retransmit_interval",
+ "security.ttl_hops",
+ "security.ttl",
+ "transmit_delay",
+ ]
+
+ def execute_module(self):
+ """Execute the module
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ if self.state not in ["parsed", "gathered"]:
+ self.generate_commands()
+ self.run_commands()
+ return self.result
+
+ def generate_commands(self):
+ """Generate configuration commands to send based on
+ want, have and desired state.
+ """
+ wantd = {entry["name"]: entry for entry in self.want}
+ haved = {entry["name"]: entry for entry in self.have}
+
+ # turn all lists of dicts into dicts prior to merge
+ for entry in wantd, haved:
+ self._ospf_int_list_to_dict(entry)
+
+ # if state is merged, merge want onto have and then compare
+ if self.state == "merged":
+ wantd = dict_merge(haved, wantd)
+
+ # if state is deleted, empty out wantd and set haved to wantd
+ if self.state == "deleted":
+ haved = {k: v for k, v in iteritems(haved) if k in wantd or not wantd}
+ have_int = []
+ if wantd == {}:
+ for k, have in iteritems(haved):
+ self._remove_ospf_int(have)
+
+ for k, have in iteritems(haved):
+ if k in wantd:
+ have_int.append(k)
+ self._remove_ospf_int(have)
+ wantd = {}
+
+ # remove superfluous config for overridden and deleted
+ if self.state == "overridden":
+ for k, have in iteritems(haved):
+ if k not in wantd:
+ self._remove_ospf_int(have)
+ if self.state != "deleted":
+ for k, want in iteritems(wantd):
+ self._compare(want=want, have=haved.pop(k, {}))
+
+ def _remove_ospf_int(self, entry):
+ int_name = entry.get("name", {})
+ int_addr = entry.get("address_family", {})
+ for k, addr in iteritems(int_addr):
+ for key, value in addr["processes"].items():
+ rem_entry = {
+ "name": int_name,
+ "afi": addr["afi"],
+ "process": value["process_id"],
+ "area": value["area"],
+ }
+ self.addcmd(rem_entry, "name", True)
+
+ def _compare(self, want, have):
+ """Leverages the base class `compare()` method and
+ populates the list of commands to be run by comparing
+ the `want` and `have` data with the `parsers` defined
+ for the Ospf_interfaces network resource.
+ """
+ self._compare_interface(want=want, have=have)
+
+ self._compare_addr_family(want=want, have=have)
+
+ def _compare_interface(self, want, have):
+ wdict = want.get("address_family", {})
+ hdict = have.get("address_family", {})
+ wname = want.get("name")
+ hname = have.get("name")
+ h_value = {}
+
+ for key, w_value in iteritems(wdict):
+ if hdict and hdict.get(key):
+ h_value = hdict[key]
+ else:
+ h_value = None
+ w = {
+ "name": wname,
+ "type": w_value["afi"],
+ "address_family": w_value,
+ }
+ if h_value is not None:
+ h = {
+ "name": hname,
+ "type": h_value["afi"],
+ "address_family": h_value,
+ }
+ else:
+ h = {}
+ self.compare(parsers="name", want=w, have=h)
+
+ def _compare_addr_family(self, want, have):
+ wdict = want.get("address_family", {})
+ hdict = have.get("address_family", {})
+ wname = want.get("name")
+ hname = have.get("name")
+ # Fetch the area info as that would be common to all the attributes per interface
+ for name, entry in iteritems(wdict):
+ w_process = {}
+ h_process = {}
+ for key, value in iteritems(entry):
+ if key == "processes":
+ for pname, pentry in iteritems(value):
+ w_process = pentry
+ for key, param in iteritems(entry):
+ w_addr = {"afi": name, key: param, "processes": w_process}
+ h_addr = {}
+ if hdict.get(name):
+ hdict_entry = hdict.get(name)
+ for item, value in iteritems(hdict_entry):
+ if item == "processes":
+ for pname, pentry in iteritems(value):
+ h_process = pentry
+ h_addr = {
+ "afi": name,
+ key: hdict[name].pop(key, {}),
+ "processes": h_process,
+ }
+ w = {"name": wname, "address_family": w_addr}
+ h = {"name": hname, "address_family": h_addr}
+ self.compare(parsers=self.parsers, want=w, have=h)
+ for name, entry in iteritems(hdict):
+ for key, param in iteritems(entry):
+ h_addr = {"afi": name, key: param}
+ w_addr = {}
+ w = {"name": wname, "address_family": w_addr}
+ h = {"name": hname, "address_family": h_addr}
+ self.compare(parsers=self.parsers, want=w, have=h)
+
+ def _ospf_int_list_to_dict(self, entry):
+ for name, family in iteritems(entry):
+ if "address_family" in family:
+ family["address_family"] = {
+ entry["afi"]: entry for entry in family.get("address_family", [])
+ }
+ self._ospf_int_list_to_dict(family["address_family"])
+ for name, ospf_processes in iteritems(entry):
+ if "processes" in ospf_processes:
+ ospf_processes["processes"] = {
+ entry["process_id"]: entry for entry in ospf_processes.get("processes", [])
+ }
+ self._ospf_int_list_to_dict(ospf_processes["processes"])
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv2/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv2/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv2/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv2/ospfv2.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv2/ospfv2.py
new file mode 100644
index 00000000..4b2d15f7
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv2/ospfv2.py
@@ -0,0 +1,254 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_ospfv2 class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from copy import deepcopy
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.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.ospfv2 import (
+ Ospfv2Template,
+)
+
+
+class Ospfv2(ResourceModule):
+ """
+ The ios_ospfv2 class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["ospfv2"]
+
+ def __init__(self, module):
+ super(Ospfv2, self).__init__(
+ empty_fact_val={},
+ facts_module=Facts(module),
+ module=module,
+ resource="ospfv2",
+ tmplt=Ospfv2Template(),
+ )
+
+ def execute_module(self):
+ """Execute the module
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ self.gen_config()
+ self.run_commands()
+
+ return self.result
+
+ def gen_config(self):
+ """Select the appropriate function based on the state provided
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ if self.want:
+ wantd = {
+ (entry["process_id"], entry.get("vrf")): entry
+ for entry in self.want.get("processes", [])
+ }
+ else:
+ wantd = {}
+ if self.have:
+ haved = {
+ (entry["process_id"], entry.get("vrf")): entry
+ for entry in self.have.get("processes", [])
+ }
+ else:
+ haved = {}
+
+ # turn all lists of dicts into dicts prior to merge
+ for thing in wantd, haved:
+ for _pid, proc in iteritems(thing):
+ for area in proc.get("areas", []):
+ virtual_link = {entry["id"]: entry for entry in area.get("virtual_link", [])}
+ if bool(virtual_link):
+ area["virtual_link"] = virtual_link
+ ranges = {entry["address"]: entry for entry in area.get("ranges", [])}
+ if bool(ranges):
+ area["ranges"] = ranges
+
+ proc["areas"] = {entry["area_id"]: entry for entry in proc.get("areas", [])}
+ if proc.get("distribute_list"):
+ if "acls" in proc.get("distribute_list"):
+ proc["distribute_list"]["acls"] = {
+ entry["name"]: entry
+ for entry in proc["distribute_list"].get(
+ "acls",
+ [],
+ )
+ }
+
+ # if state is merged, merge want onto have
+ if self.state == "merged":
+ wantd = dict_merge(haved, wantd)
+
+ # if state is deleted, limit the have to anything in want
+ # set want to nothing
+ if self.state == "deleted":
+ haved = {k: v for k, v in iteritems(haved) if k in wantd or not wantd}
+ wantd = {}
+
+ # delete processes first so we do run into "more than one" errors
+ if self.state == "deleted":
+ haved_del = deepcopy(haved)
+ want_process = {}
+ for k, t_want in iteritems(haved_del):
+ want_process["process_id"] = t_want.get("process_id")
+ if not (len(t_want) == 2 and not t_want.get("areas")):
+ self._compare(want=want_process, have=haved_del.get(k, {}))
+ if self.state == "overridden":
+ haved_del = deepcopy(haved)
+ want = {}
+ for k, t_want in iteritems(haved_del):
+ if k not in wantd:
+ want["process_id"] = t_want.get("process_id")
+ if not (len(t_want) == 2 and not t_want.get("areas")):
+ self._compare(want=want, have=haved_del.get(k, {}))
+
+ for k, want in iteritems(wantd):
+ self._compare(want=want, have=haved.pop(k, {}))
+
+ def _compare(self, want, have):
+ parsers = [
+ "bfd",
+ "cost",
+ "weight",
+ "passive",
+ "priority",
+ "protocol",
+ "auto_cost",
+ "bandwidth",
+ "flood_reduction",
+ "default_metric",
+ "default_weight",
+ "router_id",
+ "demand_circuit",
+ "packet_size",
+ "transmit_delay",
+ "summary_in",
+ "external_out",
+ "dead_interval",
+ "hello_interval",
+ "authentication",
+ "adjacency_stagger",
+ "retransmit_interval",
+ "mtu_ignore",
+ "bfd.fast_detect",
+ "capability",
+ "capability.opaque",
+ "admin_distance",
+ "ospf_distance",
+ "address_family_unicast",
+ "loopback_stub_network",
+ "authentication.message_digest",
+ "default_information_originate",
+ "link_down_fast_detect",
+ "nsr",
+ "database_filter",
+ "log_adjacency_changes",
+ "distribute_bgp_ls",
+ "distribute_link_state",
+ "max_lsa",
+ "max_metric",
+ "mpls_ldp",
+ "mpls_traffic_eng",
+ "microloop_avoidance",
+ "prefix_suppression",
+ "protocol_shutdown",
+ "timers.lsa",
+ "timers.graceful_shutdown",
+ "throttle.lsa_all",
+ "throttle.spf",
+ "throttle.fast_reroute",
+ "timers.pacing_flood",
+ ]
+
+ if want != have:
+ self.addcmd(want or have, "pid", False)
+ self.compare(parsers, want, have)
+ self._areas_compare(want, have)
+
+ def _areas_compare(self, want, have):
+ wareas = want.get("areas", {})
+ hareas = have.get("areas", {})
+ for name, entry in iteritems(wareas):
+ self._area_compare(want=entry, have=hareas.pop(name, {}))
+ for name, entry in iteritems(hareas):
+ self._area_compare(want={}, have=entry)
+
+ def _area_compare(self, want, have):
+ parsers = [
+ "area.authentication",
+ "area.authentication_key",
+ "area.authentication.message_digest",
+ "area.mpls_traffic_eng",
+ "area.mpls_ldp",
+ "area.bfd",
+ "area.bfd.fast_detect",
+ "area.nssa",
+ "area.nssa.default_information_originate",
+ "area.nssa.translate",
+ "area.default_cost",
+ "area.stub",
+ "area.ranges",
+ "area.cost",
+ "area.dead_interval",
+ "area.hello_interval",
+ "area.transmit_delay",
+ "area.mtu_ignore",
+ "area.packet_size",
+ "area.priority",
+ "area.weight",
+ "area.external_out",
+ "area.summary_in",
+ "area.demand_circuit",
+ "area.passive",
+ ]
+ self.compare(parsers=parsers, want=want, have=have)
+ self._areas_compare_virtual_link(want, have)
+
+ def _areas_compare_virtual_link(self, want, have):
+ wvlinks = want.get("virtual_link", {})
+ hvlinks = have.get("virtual_link", {})
+ for name, entry in iteritems(wvlinks):
+ self._area_compare_virtual_link(
+ want=entry,
+ have=hvlinks.pop(name, {}),
+ )
+ for name, entry in iteritems(hvlinks):
+ self._area_compare_virtual_link(want={}, have=entry)
+
+ def _area_compare_virtual_link(self, want, have):
+ parsers = [
+ "virtual_link.authentication",
+ "virtual_link.authentication_key",
+ "virtual_link.authentication.message_digest",
+ "virtual_link.hello_interval",
+ "virtual_link.dead_interval",
+ "virtual_link.retransmit_interval",
+ ]
+ self.compare(parsers=parsers, want=want, have=have)
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/__init__.py
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
new file mode 100644
index 00000000..05ce4247
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ospfv3/ospfv3.py
@@ -0,0 +1,247 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from copy import deepcopy
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.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.ospfv3 import (
+ Ospfv3Template,
+)
+
+
+class Ospfv3(ResourceModule):
+ """
+ The ios_ospfv3 class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["ospfv3"]
+
+ def __init__(self, module):
+ super(Ospfv3, self).__init__(
+ empty_fact_val={},
+ facts_module=Facts(module),
+ module=module,
+ resource="ospfv3",
+ tmplt=Ospfv3Template(),
+ )
+
+ def execute_module(self):
+ """Execute the module
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ self.gen_config()
+ self.run_commands()
+
+ return self.result
+
+ def gen_config(self):
+ """Select the appropriate function based on the state provided
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ if self.want:
+ wantd = {
+ (entry["process_id"], entry.get("vrf")): entry
+ for entry in self.want.get("processes", [])
+ }
+ else:
+ wantd = {}
+ if self.have:
+ haved = {
+ (entry["process_id"], entry.get("vrf")): entry
+ for entry in self.have.get("processes", [])
+ }
+ else:
+ haved = {}
+
+ # turn all lists of dicts into dicts prior to merge
+ for thing in wantd, haved:
+ for _pid, proc in iteritems(thing):
+ for area in proc.get("areas", []):
+ virtual_link = {entry["id"]: entry for entry in area.get("virtual_link", [])}
+ if bool(virtual_link):
+ area["virtual_link"] = virtual_link
+ ranges = {entry["address"]: entry for entry in area.get("ranges", [])}
+ if bool(ranges):
+ area["ranges"] = ranges
+
+ proc["areas"] = {entry["area_id"]: entry for entry in proc.get("areas", [])}
+ if proc.get("distribute_list"):
+ if "acls" in proc.get("distribute_list"):
+ proc["distribute_list"]["acls"] = {
+ entry["name"]: entry
+ for entry in proc["distribute_list"].get(
+ "acls",
+ [],
+ )
+ }
+
+ # if state is merged, merge want onto have
+ if self.state == "merged":
+ wantd = dict_merge(haved, wantd)
+
+ # if state is deleted, limit the have to anything in want
+ # set want to nothing
+ if self.state == "deleted":
+ haved = {k: v for k, v in iteritems(haved) if k in wantd or not wantd}
+ wantd = {}
+
+ # delete processes first so we do run into "more than one" errors
+ if self.state == "deleted":
+ haved_del = deepcopy(haved)
+ want_process = {}
+ for k, t_want in iteritems(haved_del):
+ want_process["process_id"] = t_want.get("process_id")
+ if not (len(t_want) == 2 and not t_want.get("areas")):
+ self._compare(want=want_process, have=haved_del.get(k, {}))
+ if self.state == "overridden":
+ haved_del = deepcopy(haved)
+ want = {}
+ for k, t_want in iteritems(haved_del):
+ if k not in wantd:
+ want["process_id"] = t_want.get("process_id")
+ if not (len(t_want) == 2 and not t_want.get("areas")):
+ self._compare(want=want, have=haved_del.get(k, {}))
+
+ for k, want in iteritems(wantd):
+ self._compare(want=want, have=haved.pop(k, {}))
+
+ def _compare(self, want, have):
+ parsers = [
+ "bfd.minimum_interval",
+ "bfd.multiplier",
+ "cost",
+ "weight",
+ "passive",
+ "priority",
+ "protocol",
+ "auto_cost",
+ "bandwidth",
+ "flood_reduction",
+ "default_metric",
+ "default_weight",
+ "router_id",
+ "demand_circuit",
+ "packet_size",
+ "transmit_delay",
+ "dead_interval",
+ "hello_interval",
+ "authentication",
+ "retransmit_interval",
+ "mtu_ignore",
+ "bfd.fast_detect",
+ "capability",
+ "capability.opaque",
+ "admin_distance",
+ "ospf_distance",
+ "address_family_unicast",
+ "loopback_stub_network",
+ "authentication.ipsec",
+ "default_information_originate",
+ "link_down_fast_detect",
+ "nsr",
+ "database_filter",
+ "log_adjacency",
+ "distribute_bgp_ls",
+ "distribute_link_state",
+ "max_lsa",
+ "max_metric",
+ "mpls_ldp",
+ "mpls_traffic_eng",
+ "microloop_avoidance",
+ "prefix_suppression",
+ "protocol_shutdown",
+ "timers.lsa",
+ "timers.graceful_shutdown",
+ "throttle.lsa_all",
+ "throttle.spf",
+ "throttle.fast_reroute",
+ "timers.pacing_flood",
+ ]
+
+ if want != have:
+ self.addcmd(want or have, "pid", False)
+ self.compare(parsers, want, have)
+ self._areas_compare(want, have)
+
+ def _areas_compare(self, want, have):
+ wareas = want.get("areas", {})
+ hareas = have.get("areas", {})
+ for name, entry in iteritems(wareas):
+ self._area_compare(want=entry, have=hareas.pop(name, {}))
+ for name, entry in iteritems(hareas):
+ self._area_compare(want={}, have=entry)
+
+ def _area_compare(self, want, have):
+ parsers = [
+ "area.authentication",
+ "area.authentication.ipsec",
+ "area.mpls_traffic_eng",
+ "area.mpls_ldp",
+ "area.bfd.minimum_interval",
+ "area.bfd.multiplier",
+ "area.bfd.fast_detect",
+ "area.nssa",
+ "area.nssa.default_information_originate",
+ "area.nssa.translate",
+ "area.default_cost",
+ "area.stub",
+ "area.ranges",
+ "area.cost",
+ "area.dead_interval",
+ "area.hello_interval",
+ "area.transmit_delay",
+ "area.mtu_ignore",
+ "area.packet_size",
+ "area.priority",
+ "area.weight",
+ "area.external_out",
+ "area.summary_in",
+ "area.demand_circuit",
+ "area.passive",
+ ]
+ self.compare(parsers=parsers, want=want, have=have)
+ self._areas_compare_virtual_link(want, have)
+
+ def _areas_compare_virtual_link(self, want, have):
+ wvlinks = want.get("virtual_link", {})
+ hvlinks = have.get("virtual_link", {})
+ for name, entry in iteritems(wvlinks):
+ self._area_compare_virtual_link(
+ want=entry,
+ have=hvlinks.pop(name, {}),
+ )
+ for name, entry in iteritems(hvlinks):
+ self._area_compare_virtual_link(want={}, have=entry)
+
+ def _area_compare_virtual_link(self, want, have):
+ parsers = [
+ "virtual_link.authentication",
+ "virtual_link.authentication_key",
+ "virtual_link.authentication.message_digest",
+ "virtual_link.hello_interval",
+ "virtual_link.dead_interval",
+ "virtual_link.retransmit_interval",
+ ]
+ self.compare(parsers=parsers, want=want, have=have)
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ping/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ping/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ping/__init__.py
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
new file mode 100644
index 00000000..ce2a5229
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/ping/ping.py
@@ -0,0 +1,99 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2022 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_ping config file.
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to its desired end-state is
+created.
+"""
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import run_commands
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.ping import (
+ PingTemplate,
+)
+
+
+class Ping:
+ """
+ The iosxr_ping config class
+ """
+
+ def __init__(self, module):
+ self.module = module
+ self.result = {}
+
+ def execute_module(self):
+ """Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ self.generate_command()
+ res = self.run_command()
+ return self.process_result(res)
+
+ def build_ping(self, params):
+ tmplt = PingTemplate()
+ params = utils.remove_empties(params)
+ cmd = tmplt.render(params, "rate", False)
+ return cmd
+
+ def validate_results(self, module, loss, results):
+ """
+ This function is used to validate whether the ping results were unexpected per "state" param.
+ """
+ state = module.params["state"]
+ if state == "present" and loss == 100:
+ module.fail_json(msg="Ping failed unexpectedly", **results)
+ elif state == "absent" and loss < 100:
+ module.fail_json(msg="Ping succeeded unexpectedly", **results)
+
+ def generate_command(self):
+ """Generate configuration commands to send based on
+ want, have and desired state.
+ """
+ warnings = list()
+ if warnings:
+ self.result["warnings"] = warnings
+ self.result["commands"] = self.build_ping(self.module.params)
+
+ def run_command(self):
+ ping_results = run_commands(
+ self.module,
+ commands=self.result["commands"],
+ )
+ return ping_results
+
+ def process_result(self, ping_results):
+ """
+ Function used to parse the statistical information from the ping response.
+ Example: "Success rate is 100 percent (5/5), round-trip min/avg/max = 1/2/8 ms"
+ Returns the percent of packet loss, received packets, transmitted packets, and RTT data.
+ """
+
+ if type(ping_results) == list:
+ ping_results = ping_results[0]
+
+ ping_data = PingTemplate(lines=ping_results.splitlines())
+ obj = list(ping_data.parse().values())
+
+ self.result["packet_loss"] = obj[0].get("loss_percentage")
+ self.result["packets_rx"] = obj[0].get("rx")
+ self.result["packets_tx"] = obj[0].get("tx")
+ self.result["rtt"] = obj[0].get("rtt")
+ loss = obj[0].get("loss")
+ self.validate_results(self.module, loss, self.result)
+ return self.result
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/prefix_lists/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/prefix_lists/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/prefix_lists/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/prefix_lists/prefix_lists.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/prefix_lists/prefix_lists.py
new file mode 100644
index 00000000..03ef3f11
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/prefix_lists/prefix_lists.py
@@ -0,0 +1,141 @@
+#
+# -*- 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 iosxr_prefix_lists config file.
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to its desired end-state is
+created.
+"""
+
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.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.prefix_lists import (
+ Prefix_listsTemplate,
+)
+
+
+class Prefix_lists(ResourceModule):
+ """
+ The iosxr_prefix_lists config class
+ """
+
+ def __init__(self, module):
+ super(Prefix_lists, self).__init__(
+ empty_fact_val=[],
+ facts_module=Facts(module),
+ module=module,
+ resource="prefix_lists",
+ tmplt=Prefix_listsTemplate(),
+ )
+ self.parsers = ["prefix", "description", "prefix_list"]
+
+ def execute_module(self):
+ """Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ if self.state not in ["parsed", "gathered"]:
+ self.generate_commands()
+ self.run_commands()
+ return self.result
+
+ def generate_commands(self):
+ """Generate configuration commands to send based on
+ want, have and desired state.
+ """
+ wantd = {entry["afi"]: entry for entry in self.want}
+ haved = {entry["afi"]: entry for entry in self.have}
+
+ self._prefix_list_to_dict(wantd)
+ self._prefix_list_to_dict(haved)
+
+ # 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 = {}
+
+ # remove superfluous config for overridden and deleted
+ if self.state in ["overridden", "deleted"]:
+ for k, have in iteritems(haved):
+ if k not in wantd:
+ self._compare(want={}, have=have)
+
+ for k, want in iteritems(wantd):
+ self._compare(want=want, have=haved.pop(k, {}))
+ # alligning cmd with negate cmd 1st followed by config cmd
+ if self.state in ["overridden", "replaced"]:
+ self.commands = [each for each in self.commands if "no" in each] + [
+ each for each in self.commands if "no" not in each
+ ]
+
+ def _compare(self, want, have):
+ """Leverages the base class `compare()` method and
+ populates the list of commands to be run by comparing
+ the `want` and `have` data with the `parsers` defined
+ for the Prefix_lists network resource.
+ """
+ self._compare_plists(
+ want.get("prefix_lists", {}),
+ have.get("prefix_lists", {}),
+ )
+
+ def _compare_plists(self, want, have):
+ for wk, wentry in iteritems(want):
+ hentry = have.pop(wk, {})
+ # compare sequences
+ self._compare_seqs(
+ wentry.pop("entries", {}),
+ hentry.pop("entries", {}),
+ )
+
+ # remove remaining prefix lists
+ for h in have.values():
+ self.commands.append(
+ "no {0} prefix-list {1}".format(h["afi"], h["name"]),
+ )
+
+ def _compare_seqs(self, want, have):
+ for wseq, wentry in iteritems(want):
+ hentry = have.pop(wseq, {})
+ self.compare(parsers=self.parsers, want=wentry, have=hentry)
+
+ # remove remaining entries from have prefix list
+ for hseq in have.values():
+ self.compare(parsers=self.parsers, want={}, have=hseq)
+
+ def _prefix_list_to_dict(self, entry):
+ for afi, value in iteritems(entry):
+ if "prefix_lists" in value:
+ for plist in value["prefix_lists"]:
+ plist.update({"afi": afi})
+ if "entries" in plist:
+ for seq in plist["entries"]:
+ seq.update({"afi": afi, "name": plist["name"]})
+ plist["entries"] = {x["sequence"]: x for x in plist["entries"]}
+ value["prefix_lists"] = {
+ (entry["name"], afi): entry for entry in value["prefix_lists"]
+ }
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/snmp_server/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/snmp_server/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/snmp_server/__init__.py
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
new file mode 100644
index 00000000..9ee3e1a1
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/snmp_server/snmp_server.py
@@ -0,0 +1,397 @@
+#
+# -*- 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 iosxr_snmp_server 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_diff,
+ 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.snmp_server import (
+ Snmp_serverTemplate,
+)
+
+
+class Snmp_server(ResourceModule):
+ """
+ The iosxr_snmp_server config class
+ """
+
+ def __init__(self, module):
+ super(Snmp_server, self).__init__(
+ empty_fact_val={},
+ facts_module=Facts(module),
+ module=module,
+ resource="snmp_server",
+ tmplt=Snmp_serverTemplate(),
+ )
+ self.parsers = [
+ "chassis_id",
+ "correlator.buffer_size",
+ "contact",
+ "ifindex",
+ "ipv4.dscp",
+ "ipv6.dscp",
+ "ipv4.precedence",
+ "ipv6.precedence",
+ "location",
+ "logging_threshold_oid_processing",
+ "logging_threshold_pdu_processing",
+ "mib_bulkstat_max_procmem_size",
+ "mroutemib_send_all_vrf",
+ "oid_poll_stats",
+ "overload_control",
+ "packetsize",
+ "queue_length",
+ "throttle_time",
+ "trap_source",
+ "trap_timeout",
+ "drop.report_IPv4",
+ "drop.report_IPv6",
+ "drop.unknown_user",
+ "ifmib.internal_cache_max_duration",
+ "ifmib.ipsubscriber",
+ "ifmib.stats",
+ "ifmib.ifalias_long",
+ "inform.timeout",
+ "inform.retries",
+ "inform.pending",
+ "notification_log_mib.size",
+ "notification_log_mib.default",
+ "notification_log_mib.disable",
+ "notification_log_mib.GlobalSize",
+ "trap.link_ietf",
+ "trap.authentication_vrf_disable",
+ "trap.throttle_time",
+ "timeouts.threshold",
+ "timeouts.pdu_stats",
+ "timeouts.subagent",
+ "timeouts.inQdrop",
+ "timeouts.duplicate",
+ "traps.addrpool.low",
+ "traps.addrpool.high",
+ "traps.bfd",
+ "traps.bgp.cbgp2",
+ "traps.bgp.updown",
+ "traps.bulkstat_collection",
+ "traps.bulkstat_transfer",
+ "traps.bridgemib",
+ "traps.copy_complete",
+ "traps.cisco_entity_ext",
+ "traps.config",
+ "traps.diameter.peerdown",
+ "traps.diameter.peerup",
+ "traps.diameter.protocolerror",
+ "traps.diameter.permanentfail",
+ "traps.diameter.transientfail",
+ "traps.entity",
+ "traps.entity_redundancy.all",
+ "traps.entity_redundancy.status",
+ "traps.entity_redundancy.switchover",
+ "traps.entity_state.operstatus",
+ "traps.entity_state.switchover",
+ "traps.flash.removal",
+ "traps.flash.insertion",
+ "traps.fru_ctrl",
+ "traps.hsrp",
+ "traps.ipsla",
+ "traps.ipsec.start",
+ "traps.ipsec.stop",
+ "traps.isakmp.start",
+ "traps.isakmp.stop",
+ "traps.isis",
+ "traps.l2tun.pseudowire_status",
+ "traps.l2tun.sessions",
+ "traps.l2tun.tunnel_up",
+ "traps.l2tun.tunnel_down",
+ "traps.l2vpn.all",
+ "traps.l2vpn.cisco",
+ "traps.l2vpn.vc_up",
+ "traps.l2vpn.vc_down",
+ "traps.msdp_peer_state_change",
+ "traps.ospf.retransmit.virt_packets",
+ "traps.ospf.retransmit.packets",
+ "traps.ospf.lsa.lsa_originate",
+ "traps.ospf.lsa.lsa_maxage",
+ "traps.ospf.errors.bad_packet",
+ "traps.ospf.errors.authentication_failure",
+ "traps.ospf.errors.config_error",
+ "traps.ospf.errors.virt_bad_packet",
+ "traps.ospf.errors.virt_authentication_failure",
+ "traps.ospf.errors.virt_config_error",
+ "traps.ospf.state_change.if_state_change",
+ "traps.ospf.state_change.neighbor_state_change",
+ "traps.ospf.state_change.virtif_state_change",
+ "traps.ospf.state_change.virtneighbor_state_change",
+ "traps.ospfv3.errors.bad_packet",
+ "traps.ospfv3.errors.authentication_failure",
+ "traps.ospfv3.errors.config_error",
+ "traps.ospfv3.errors.virt_config_error",
+ "traps.ospfv3.errors.virt_bad_packet",
+ "traps.ospfv3.state_change.neighbor_state_change",
+ "traps.ospfv3.state_change.virtif_state_change",
+ "traps.ospfv3.state_change.virtneighbor_state_change",
+ "traps.ospfv3.state_change.restart_status_change",
+ "traps.ospfv3.state_change.restart_helper_status_change",
+ "traps.ospfv3.state_change.restart_virtual_helper_status_change",
+ "traps.ospfv3.state_change.nssa_state_change",
+ "traps.power",
+ "traps.rf",
+ "traps.pim.neighbor_change",
+ "traps.pim.invalid_message_received",
+ "traps.pim.rp_mapping_change",
+ "traps.pim.interface_state_change",
+ "traps.rsvp.lost_flow",
+ "traps.rsvp.new_flow",
+ "traps.rsvp.all",
+ "traps.selective_vrf_download_role_change",
+ "traps.sensor",
+ "traps.vrrp_events",
+ "traps.syslog",
+ "traps.system",
+ "traps.subscriber.session_agg_access_interface",
+ "traps.subscriber.session_agg_node",
+ "traps.vpls.all",
+ "traps.vpls.full_clear",
+ "traps.vpls.full_raise",
+ "traps.vpls.status",
+ "traps.snmp.linkup",
+ "traps.snmp.linkdown",
+ "traps.snmp.coldstart",
+ "traps.snmp.warmstart",
+ "traps.snmp.authentication",
+ ]
+
+ 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 handle_alieses(self, want):
+ for x in [want.get("groups", []), want.get("users", [])]:
+ for y in x:
+ if y.get("Ipv4_acl"):
+ del y["Ipv4_acl"]
+ if y.get("Ipv6_acl"):
+ del y["Ipv6_acl"]
+ return want
+
+ def generate_commands(self):
+ """Generate configuration commands to send based on
+ want, have and desired state.
+ """
+
+ self.want = self.handle_alieses(self.want)
+ wantd = self.list_to_dict(self.want)
+ haved = self.list_to_dict(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":
+ wantd = {}
+
+ self._compare(want=wantd, have=haved)
+ if self.state in ["overridden", "replaced"]:
+ self.commands = [each for each in self.commands if "no" in each] + [
+ each for each in self.commands if "no" not in each
+ ]
+
+ def _compare(self, want, have):
+ """Leverages the base class `compare()` method and
+ populates the list of commands to be run by comparing
+ the `want` and `have` data with the `parsers` defined
+ for the Logging_global network resource.
+ """
+ self.compare(parsers=self.parsers, want=want, have=have)
+ self._compare_lists(want, have)
+ self._compare_vrfs(want, have)
+
+ def _remove_snmp_server(self, begin):
+ for i in range(begin, len(self.commands)):
+ self.commands[i] = self.commands[i].replace("snmp-server ", "")
+
+ def _compare_vrfs(self, want, have):
+ wvrfs = want.get("vrfs", {})
+ hvrfs = have.get("vrfs", {})
+ for name, entry in iteritems(wvrfs):
+ begin = len(self.commands)
+ vrf_have = hvrfs.pop(name, {})
+ self._compare_lists(want=entry, have=vrf_have)
+ if len(self.commands) != begin:
+ self._remove_snmp_server(begin)
+ self.commands.insert(
+ begin,
+ self._tmplt.render(
+ {"vrf": entry.get("vrf")},
+ "vrfs",
+ False,
+ ),
+ )
+ for name, entry in iteritems(hvrfs):
+ self.addcmd(entry, "vrfs", True)
+
+ def _compare_lists(self, want, have):
+ """
+ Handles list attributes from config_data
+ """
+ for x in [
+ "communities",
+ "community_maps",
+ "correlator.rule_sets",
+ "correlator.rules",
+ "context",
+ "groups",
+ "hosts",
+ "interfaces",
+ "mib_object_lists",
+ "mib_schema",
+ "mib_bulkstat_transfer_ids",
+ "users",
+ "targets",
+ ]:
+
+ wantx = want.get(x, {})
+ havex = have.get(x, {})
+ if "." in x:
+ complex_parser = x.split(".")
+ wantx = want.get(complex_parser[0], {}).get(
+ complex_parser[1],
+ {},
+ )
+ havex = have.get(complex_parser[0], {}).get(
+ complex_parser[1],
+ {},
+ )
+
+ if x in [
+ "interfaces",
+ "correlator.rules",
+ "mib_schema",
+ "mib_bulkstat_transfer_ids",
+ ]:
+ # handling complex parsers for replaced and overridden state
+
+ for key, wentry in iteritems(wantx):
+ hentry = havex.pop(key, {})
+ updates = dict_diff(hentry, wentry)
+ if updates and x in [
+ "interfaces",
+ "mib_schema",
+ "mib_bulkstat_transfer_ids",
+ ]:
+ updates.update(name=wentry["name"])
+ self.addcmd(updates, x)
+ elif updates and x == "correlator.rules":
+ updates.update(rule_name=wentry["rule_name"])
+ self.addcmd(updates, x)
+ else:
+ for key, wentry in iteritems(wantx):
+ hentry = havex.pop(key, {})
+ if wentry != hentry:
+ self.addcmd(wentry, x)
+
+ for key, hentry in iteritems(havex):
+ self.addcmd(hentry, x, negate=True)
+
+ def _host_list_to_dict(self, data):
+ host_dict = {}
+ host_data = deepcopy(data)
+ for el in host_data["hosts"]:
+ tr = ""
+ inf = ""
+ if el.get("traps"):
+ tr = "traps"
+ if el.get("informs"):
+ inf = "informs"
+ host_dict.update(
+ {
+ (
+ el.get("host"),
+ el.get("community"),
+ el.get("version"),
+ inf,
+ tr,
+ el.get("udp_port"),
+ ): el,
+ },
+ )
+ return host_dict
+
+ def list_to_dict(self, config):
+
+ data = deepcopy(config)
+
+ if data.get("vrfs"):
+ for x in data["vrfs"]:
+ if "context" in x:
+ x["context"] = {y: {"name": y} for y in x["context"]}
+ if "hosts" in x:
+ x["hosts"] = self._host_list_to_dict(x)
+
+ pkey = {
+ "communities": "name",
+ "community_maps": "name",
+ "interfaces": "name",
+ "mib_schema": "name",
+ "groups": "group",
+ "mib_bulkstat_transfer_ids": "name",
+ "users": "user",
+ "vrfs": "vrf",
+ }
+ for k in pkey.keys():
+ if k in data:
+ data[k] = {i[pkey[k]]: i for i in data[k]}
+
+ if "correlator" in data:
+ if "rules" in data["correlator"]:
+ data["correlator"]["rules"] = {
+ x["rule_name"]: x for x in data["correlator"]["rules"]
+ }
+ if "rule_sets" in data["correlator"]:
+ data["correlator"]["rule_sets"] = {
+ x["name"]: x for x in data["correlator"]["rule_sets"]
+ }
+
+ if "context" in data:
+ data["context"] = {x: {"name": x} for x in data["context"]}
+ if "mib_object_lists" in data:
+ data["mib_object_lists"] = {x: {"mib_object": x} for x in data["mib_object_lists"]}
+ if "targets" in data:
+ data["targets"] = {
+ x["name"] + x.get("vrf", "") + x.get("host", ""): x for x in data["targets"]
+ }
+ if "hosts" in data:
+ data["hosts"] = self._host_list_to_dict(data)
+ return data
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/__init__.py
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
new file mode 100644
index 00000000..b558f01a
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/config/static_routes/static_routes.py
@@ -0,0 +1,560 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_static_routes class
+It is in this file where the current configuration (as dict)
+is compared to the provided configuration (as dict) and the command set
+necessary to bring the current configuration to it's desired end-state is
+created
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.cfg.base import (
+ ConfigBase,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ dict_diff,
+ dict_merge,
+ remove_empties,
+ search_obj_in_list,
+ to_list,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import Facts
+
+
+class Static_routes(ConfigBase):
+ """
+ The iosxr_static_routes class
+ """
+
+ gather_subset = ["!all", "!min"]
+
+ gather_network_resources = ["static_routes"]
+
+ def __init__(self, module):
+ super(Static_routes, self).__init__(module)
+
+ def get_static_routes_facts(self, data=None):
+ """Get the 'facts' (the current configuration)
+
+ :rtype: A dictionary
+ :returns: The current configuration as a dictionary
+ """
+ facts, _warnings = Facts(self._module).get_facts(
+ self.gather_subset,
+ self.gather_network_resources,
+ data=data,
+ )
+ static_routes_facts = facts["ansible_network_resources"].get(
+ "static_routes",
+ )
+ if not static_routes_facts:
+ return []
+ return static_routes_facts
+
+ def execute_module(self):
+ """Execute the module
+
+ :rtype: A dictionary
+ :returns: The result from module execution
+ """
+ result = {"changed": False}
+ warnings = list()
+ commands = list()
+
+ if self.state in self.ACTION_STATES:
+ existing_static_routes_facts = self.get_static_routes_facts()
+ else:
+ existing_static_routes_facts = []
+
+ if self.state in self.ACTION_STATES or self.state == "rendered":
+ commands.extend(self.set_config(existing_static_routes_facts))
+
+ if commands and self.state in self.ACTION_STATES:
+ if not self._module.check_mode:
+ self._connection.edit_config(commands)
+ result["changed"] = True
+
+ if self.state in self.ACTION_STATES:
+ result["commands"] = commands
+
+ if self.state in self.ACTION_STATES or self.state == "gathered":
+ changed_static_routes_facts = self.get_static_routes_facts()
+
+ elif self.state == "rendered":
+ result["rendered"] = commands
+
+ elif self.state == "parsed":
+ running_config = self._module.params["running_config"]
+ if not running_config:
+ self._module.fail_json(
+ msg="value of running_config parameter must not be empty for state parsed",
+ )
+ result["parsed"] = self.get_static_routes_facts(
+ data=running_config,
+ )
+
+ if self.state in self.ACTION_STATES:
+ result["before"] = existing_static_routes_facts
+ if result["changed"]:
+ result["after"] = changed_static_routes_facts
+
+ elif self.state == "gathered":
+ result["gathered"] = changed_static_routes_facts
+
+ result["warnings"] = warnings
+ return result
+
+ def set_config(self, existing_static_routes_facts):
+ """Collect the configuration from the args passed to the module,
+ collect the current configuration (as a dict from facts)
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ want = self._module.params["config"]
+ have = existing_static_routes_facts
+ resp = self.set_state(want, have)
+ return to_list(resp)
+
+ def set_state(self, want, have):
+ """Select the appropriate function based on the state provided
+
+ :param want: the desired configuration as a dictionary
+ :param have: the current configuration as a dictionary
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ state = self._module.params["state"]
+ commands = []
+
+ if state in ("overridden", "merged", "replaced", "rendered") and not want:
+ self._module.fail_json(
+ msg="value of config parameter must not be empty for state {0}".format(
+ state,
+ ),
+ )
+
+ if state == "overridden":
+ commands.extend(self._state_overridden(want, have))
+
+ elif state == "deleted":
+ if not want:
+ if len(have) >= 1:
+ return "no router static"
+
+ else:
+ for w_item in want:
+ obj_in_have = self._find_vrf(w_item, have)
+ if obj_in_have:
+ commands.extend(
+ self._state_deleted(
+ remove_empties(w_item),
+ obj_in_have,
+ ),
+ )
+
+ else:
+ for w_item in want:
+ obj_in_have = self._find_vrf(w_item, have)
+ if state == "merged" or self.state == "rendered":
+ commands.extend(
+ self._state_merged(
+ remove_empties(w_item),
+ obj_in_have,
+ ),
+ )
+
+ elif state == "replaced":
+ commands.extend(
+ self._state_replaced(
+ remove_empties(w_item),
+ obj_in_have,
+ ),
+ )
+
+ if commands:
+ commands.insert(0, "router static")
+
+ return commands
+
+ def _state_replaced(self, want, have):
+ """The command generator when state is replaced
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ for want_afi in want.get("address_families", []):
+ have_afi = (
+ self.find_af_context(
+ want_afi,
+ have.get("address_families", []),
+ )
+ or {}
+ )
+ update_commands = []
+ for want_route in want_afi.get("routes", []):
+ have_route = (
+ search_obj_in_list(
+ want_route["dest"],
+ have_afi.get("routes", []),
+ key="dest",
+ )
+ or {}
+ )
+
+ rotated_have_next_hops = self.rotate_next_hops(
+ have_route.get("next_hops", {}),
+ )
+ rotated_want_next_hops = self.rotate_next_hops(
+ want_route.get("next_hops", {}),
+ )
+
+ for key in rotated_have_next_hops.keys():
+ if key not in rotated_want_next_hops:
+ cmd = "no {0}".format(want_route["dest"])
+ for item in key:
+ if "." in item or ":" in item or "/" in item:
+ cmd += " {0}".format(item)
+ else:
+ cmd += " vrf {0}".format(item)
+ update_commands.append(cmd)
+
+ for key, value in iteritems(rotated_want_next_hops):
+ if key in rotated_have_next_hops:
+ existing = True
+ have_exit_point_attribs = rotated_have_next_hops[key]
+
+ else:
+ existing = False
+ have_exit_point_attribs = {}
+
+ updates = dict_diff(have_exit_point_attribs, value)
+
+ if updates or not existing:
+ update_commands.append(
+ self._compute_commands(
+ dest=want_route["dest"],
+ next_hop=key,
+ updates=updates,
+ ),
+ )
+
+ if update_commands:
+ update_commands.insert(
+ 0,
+ "address-family {0} {1}".format(
+ want_afi["afi"],
+ want_afi["safi"],
+ ),
+ )
+ commands.extend(update_commands)
+
+ if "vrf" in want and update_commands:
+ commands.insert(0, "vrf {0}".format(want["vrf"]))
+
+ return commands
+
+ def _state_overridden(self, want, have):
+ """The command generator when state is overridden
+
+ :rtype: A list
+ :returns: the commands necessary to migrate the current configuration
+ to the desired configuration
+ """
+ commands = []
+
+ # Iterate through all the entries, i.e., VRFs and Global entry in have
+ # and fully remove the ones that are not present in want and then call
+ # replaced
+
+ for h_item in have:
+ w_item = self._find_vrf(h_item, want)
+
+ # Delete all the top-level keys (VRFs/Global Route Entry) that are
+ # not specified in want.
+ if not w_item:
+ if "vrf" in h_item:
+ commands.append("no vrf {0}".format(h_item["vrf"]))
+ else:
+ for have_afi in h_item.get("address_families", []):
+ commands.append(
+ "no address-family {0} {1}".format(
+ have_afi["afi"],
+ have_afi["safi"],
+ ),
+ )
+
+ # For VRFs/Global Entry present in want, we also need to delete extraneous routes
+ # from them. We cannot reuse `_state_replaced` for this purpose since its scope is
+ # limited to replacing a single `dest`.
+ else:
+ del_cmds = []
+ for have_afi in h_item.get("address_families", []):
+ want_afi = (
+ self.find_af_context(
+ have_afi,
+ w_item.get("address_families", []),
+ )
+ or {}
+ )
+ update_commands = []
+ for h_route in have_afi.get("routes", []):
+ w_route = (
+ search_obj_in_list(
+ h_route["dest"],
+ want_afi.get("routes", []),
+ key="dest",
+ )
+ or {}
+ )
+ if not w_route:
+ update_commands.append(
+ "no {0}".format(h_route["dest"]),
+ )
+
+ if update_commands:
+ update_commands.insert(
+ 0,
+ "address-family {0} {1}".format(
+ want_afi["afi"],
+ want_afi["safi"],
+ ),
+ )
+ del_cmds.extend(update_commands)
+
+ if "vrf" in want and update_commands:
+ del_cmds.insert(0, "vrf {0}".format(want["vrf"]))
+
+ commands.extend(del_cmds)
+
+ # We finally call `_state_replaced` to replace exiting `dest` entries
+ # or add new ones as specified in want.
+ for w_item in want:
+ h_item = self._find_vrf(w_item, have)
+ commands.extend(
+ self._state_replaced(remove_empties(w_item), h_item),
+ )
+
+ return commands
+
+ def _state_merged(self, want, have):
+ """The command generator when state is merged
+
+ :rtype: A list
+ :returns: the commands necessary to merge the provided into
+ the current configuration
+ """
+ commands = []
+
+ for want_afi in want.get("address_families", []):
+ have_afi = (
+ self.find_af_context(
+ want_afi,
+ have.get("address_families", []),
+ )
+ or {}
+ )
+
+ update_commands = []
+ for want_route in want_afi.get("routes", []):
+ have_route = (
+ search_obj_in_list(
+ want_route["dest"],
+ have_afi.get("routes", []),
+ key="dest",
+ )
+ or {}
+ )
+
+ # convert the next_hops list of dictionaries to dictionary of
+ # dictionaries with (`dest_vrf`, `forward_router_address`, `interface`) tuple
+ # being the key for each dictionary.
+ # a combination of these 3 attributes uniquely identifies a route entry.
+ # in case `dest_vrf` is not specified, `forward_router_address` and `interface`
+ # become the unique identifier
+ rotated_have_next_hops = self.rotate_next_hops(
+ have_route.get("next_hops", {}),
+ )
+ rotated_want_next_hops = self.rotate_next_hops(
+ want_route.get("next_hops", {}),
+ )
+
+ # for every dict in the want next_hops dictionaries, if the key
+ # is present in `rotated_have_next_hops`, we set `existing` to True,
+ # which means the the given want exit point exists and we run dict_diff
+ # on `value` which is basically all the other attributes of the exit point
+ # if the key is not present, it means that this is a new exit point
+ for key, value in iteritems(rotated_want_next_hops):
+ if key in rotated_have_next_hops:
+ existing = True
+ have_exit_point_attribs = rotated_have_next_hops[key]
+
+ else:
+ existing = False
+ have_exit_point_attribs = {}
+
+ updates = dict_diff(have_exit_point_attribs, value)
+ if updates or not existing:
+ update_commands.append(
+ self._compute_commands(
+ dest=want_route["dest"],
+ next_hop=key,
+ # dict_merge() is necessary to make sure that we
+ # don't end up overridding the entry and also to
+ # allow incremental updates
+ updates=dict_merge(
+ rotated_have_next_hops.get(key, {}),
+ updates,
+ ),
+ ),
+ )
+
+ if update_commands:
+ update_commands.insert(
+ 0,
+ "address-family {0} {1}".format(
+ want_afi["afi"],
+ want_afi["safi"],
+ ),
+ )
+ commands.extend(update_commands)
+
+ if "vrf" in want and update_commands:
+ commands.insert(0, "vrf {0}".format(want["vrf"]))
+
+ return commands
+
+ def _state_deleted(self, want, have):
+ """The command generator when state is deleted
+
+ :rtype: A list
+ :returns: the commands necessary to remove the current configuration
+ of the provided objects
+ """
+ commands = []
+ if "address_families" not in want:
+ return ["no vrf {0}".format(want["vrf"])]
+
+ else:
+ for want_afi in want.get("address_families", []):
+ have_afi = (
+ self.find_af_context(
+ want_afi,
+ have.get("address_families", []),
+ )
+ or {}
+ )
+ if have_afi:
+ commands.append(
+ "no address-family {0} {1}".format(
+ have_afi["afi"],
+ have_afi["safi"],
+ ),
+ )
+ if "vrf" in want and commands:
+ commands.insert(0, "vrf {0}".format(want["vrf"]))
+
+ return commands
+
+ def _find_vrf(self, item, entries):
+ """This method iterates through the items
+ in `entries` and returns the object that
+ matches `item`.
+
+ :rtype: A dict
+ :returns: the obj in `entries` that matches `item`
+ """
+ obj = {}
+ afi = item.get("vrf")
+
+ if afi:
+ obj = search_obj_in_list(afi, entries, key="vrf") or {}
+ else:
+ for x in entries:
+ if "vrf" not in remove_empties(x):
+ obj = x
+ break
+ return obj
+
+ def find_af_context(self, want_af_context, have_address_families):
+ """This method iterates through the have AFs
+ and returns the one that matches the want AF
+
+ :rtype: A dict
+ :returns: the corresponding AF in have AFs
+ that matches the want AF
+ """
+ for have_af in have_address_families:
+ if (
+ have_af["afi"] == want_af_context["afi"]
+ and have_af["safi"] == want_af_context["safi"]
+ ):
+ return have_af
+
+ def rotate_next_hops(self, next_hops):
+ """This method iterates through the list of
+ next hops for a given destination network
+ and converts it to a dictionary of dictionaries.
+ Each dictionary has a primary key indicated by the
+ tuple of `dest_vrf`, `forward_router_address` and
+ `interface` and the value of this key is a dictionary
+ that contains all the other attributes of the next hop.
+
+ :rtype: A dict
+ :returns: A next_hops list in a dictionary of dictionaries format
+ """
+ next_hops_dict = {}
+
+ for entry in next_hops:
+ entry = entry.copy()
+ key_list = []
+
+ for x in ["dest_vrf", "forward_router_address", "interface"]:
+ if entry.get(x):
+ key_list.append(entry.pop(x))
+
+ key = tuple(key_list)
+ next_hops_dict[key] = entry
+
+ return next_hops_dict
+
+ def _compute_commands(self, dest, next_hop, updates=None):
+ """This method computes a static route entry command
+ from the specified `dest`, `next_hop` and `updates`
+
+ :rtype: A str
+ :returns: A platform specific static routes command
+ """
+ if not updates:
+ updates = {}
+
+ command = dest
+
+ for x in next_hop:
+ if "." in x or ":" in x or "/" in x:
+ command += " {0}".format(x)
+ else:
+ command += " vrf {0}".format(x)
+
+ for key in sorted(updates):
+ if key == "admin_distance":
+ command += " {0}".format(updates[key])
+ else:
+ command += " {0} {1}".format(key, updates[key])
+
+ return command
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acl_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acl_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acl_interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acl_interfaces/acl_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acl_interfaces/acl_interfaces.py
new file mode 100644
index 00000000..85193821
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acl_interfaces/acl_interfaces.py
@@ -0,0 +1,81 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr acl_interfaces fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.acl_interfaces.acl_interfaces import (
+ Acl_interfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.acl_interfaces import (
+ Acl_interfacesTemplate,
+)
+
+
+class Acl_interfacesFacts(object):
+ """The iosxr acl_interfaces fact class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Acl_interfacesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_config(self, connection):
+ return connection.get_config(flags="interface")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for acl_interfaces
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+
+ if not data:
+ data = self.get_config(connection)
+
+ config_parser = Acl_interfacesTemplate(lines=data.splitlines())
+ entry = sorted(
+ list(config_parser.parse().values()),
+ key=lambda k, sk="name": k[sk],
+ )
+ if entry:
+ for item in entry:
+ item["access_groups"] = sorted(
+ list(item["access_groups"].values()),
+ key=lambda k, sk="afi": k[sk],
+ )
+
+ ansible_facts["ansible_network_resources"].pop("acl_interfaces", None)
+ facts = {"acl_interfaces": []}
+ params = utils.validate_config(self.argument_spec, {"config": entry})
+ for cfg in params["config"]:
+ facts["acl_interfaces"].append(utils.remove_empties(cfg))
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acls/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acls/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acls/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acls/acls.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acls/acls.py
new file mode 100644
index 00000000..efb8d93c
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/acls/acls.py
@@ -0,0 +1,471 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr acls fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+import re
+
+from collections import deque
+from copy import deepcopy
+
+from ansible.module_utils._text import to_text
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.acls.acls import (
+ AclsArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ isipaddress,
+)
+
+
+PROTOCOL_OPTIONS = {
+ "tcp": ("ack", "fin", "psh", "rst", "syn", "urg", "established"),
+ "igmp": (
+ "dvmrp",
+ "host_query",
+ "host_report",
+ "mtrace",
+ "mtrace_response",
+ "pim",
+ "trace",
+ "v2_leave",
+ "v2_report",
+ "v3_report",
+ ),
+ "icmp": (
+ "administratively_prohibited",
+ "alternate_address",
+ "conversion_error",
+ "dod_host_prohibited",
+ "dod_net_prohibited",
+ "echo",
+ "echo_reply",
+ "general_parameter_problem",
+ "host_isolated",
+ "host_precedence_unreachable",
+ "host_redirect",
+ "host_tos_redirect",
+ "host_tos_unreachable",
+ "host_unknown",
+ "host_unreachable",
+ "information_reply",
+ "information_request",
+ "mask_reply",
+ "mask_request",
+ "mobile_redirect",
+ "net_redirect",
+ "net_tos_redirect",
+ "net_tos_unreachable",
+ "net_unreachable",
+ "network_unknown",
+ "no_room_for_option",
+ "option_missing",
+ "packet_too_big",
+ "parameter_problem",
+ "port_unreachable",
+ "precedence_unreachable",
+ "protocol_unreachable",
+ "reassembly_timeout",
+ "redirect",
+ "router_advertisement",
+ "router_solicitation",
+ "source_quench",
+ "source_route_failed",
+ "time_exceeded",
+ "timestamp_reply",
+ "timestamp_request",
+ "traceroute",
+ "ttl_exceeded",
+ "unreachable",
+ ),
+ "icmpv6": (
+ "address_unreachable",
+ "administratively_prohibited",
+ "beyond_scope_of_source_address",
+ "destination_unreachable",
+ "echo",
+ "echo_reply",
+ "erroneous_header_field",
+ "group_membership_query",
+ "group_membership_report",
+ "group_membership_termination",
+ "host_unreachable",
+ "nd_na",
+ "nd_ns",
+ "neighbor_redirect",
+ "no_route_to_destination",
+ "node_information_request_is_refused",
+ "node_information_successful_reply",
+ "packet_too_big",
+ "parameter_problem",
+ "port_unreachable",
+ "query_subject_is_IPv4address",
+ "query_subject_is_IPv6address",
+ "query_subject_is_domainname",
+ "reassembly_timeout",
+ "redirect",
+ "router_advertisement",
+ "router_renumbering",
+ "router_solicitation",
+ "rr_command",
+ "rr_result",
+ "rr_seqnum_reset",
+ "time_exceeded",
+ "ttl_exceeded",
+ "unknown_query_type",
+ "unreachable",
+ "unrecognized_next_header",
+ "unrecognized_option",
+ "whoareyou_reply",
+ "whoareyou_request",
+ ),
+}
+
+
+class AclsFacts(object):
+ """The iosxr acls fact class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = AclsArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_device_data(self, connection):
+ return connection.get("show access-lists afi-all")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for acls
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+ if not data:
+ data = self.get_device_data(connection)
+
+ objs = []
+
+ acl_lines = data.splitlines()
+ # We iterate through the data and create a list of ACLs
+ # where each ACL is a dictionary in the following format:
+ # {'afi': 'ipv4', 'name': 'acl_1', 'aces': ['10 permit 172.16.0.0 0.0.255.255', '20 deny 192.168.34.0 0.0.0.255']}
+ if acl_lines:
+ acl, acls = {}, []
+ for line in acl_lines:
+ if "matches" in line:
+ line = re.sub(r"\([^()]*\)", "", line)
+ if line.startswith("ip"):
+ if acl:
+ acls.append(acl)
+ acl = {"aces": []}
+ acl["afi"], acl["name"] = line.split()[0], line.split()[2]
+ else:
+ acl["aces"].append(line.strip())
+ acls.append(acl)
+
+ # Here we group the ACLs based on AFI
+ # {
+ # 'ipv6': [{'aces': ['10 permit ipv6 2000::/12 any'], 'name': 'acl_2'}],
+ # 'ipv4': [{'aces': ['10 permit 172.16.0.0 0.0.255.255', '20 deny 192.168.34.0 0.0.0.255'], 'name': 'acl_1'},
+ # {'aces': ['20 deny 10.0.0.0/8 log'], 'name': 'acl_3'}]
+ # }
+
+ grouped_acls = {"ipv4": [], "ipv6": []}
+ for acl in acls:
+ acl_copy = deepcopy(acl)
+ del acl_copy["afi"]
+ grouped_acls[acl["afi"]].append(acl_copy)
+
+ # Now that we have the ACLs in a fairly structured format,
+ # we pass it on to render_config to convert it to model spec
+ for key, value in iteritems(grouped_acls):
+ obj = self.render_config(self.generated_spec, value)
+ if obj:
+ obj["afi"] = key
+ objs.append(obj)
+
+ ansible_facts["ansible_network_resources"].pop("acls", None)
+ facts = {}
+
+ facts["acls"] = []
+ params = utils.validate_config(self.argument_spec, {"config": objs})
+ for cfg in params["config"]:
+ facts["acls"].append(utils.remove_empties(cfg))
+
+ ansible_facts["ansible_network_resources"].update(facts)
+
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys
+ from spec for null values
+
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+ config["acls"] = []
+
+ for item in conf:
+ acl = {"name": item["name"]}
+ aces = item.get("aces", [])
+ if aces:
+ acl["aces"] = []
+ for ace in aces:
+ acl["aces"].append(self._render_ace(ace))
+ config["acls"].append(acl)
+
+ return utils.remove_empties(config)
+
+ def _render_ace(self, ace):
+ """
+ Parses an Access Control Entry (ACE) and converts it
+ into model spec
+
+ :param ace: An ACE in device specific format
+ :rtype: dictionary
+ :returns: The ACE in structured format
+ """
+
+ def _parse_src_dest(rendered_ace, ace_queue, direction):
+ """
+ Parses the ACE queue and populates address, wildcard_bits,
+ host or any keys in the source/destination dictionary of
+ ace dictionary, i.e., `rendered_ace`.
+
+ :param rendered_ace: The dictionary containing the ACE in structured format
+ :param ace_queue: The ACE queue
+ :param direction: Specifies whether to populate `source` or `destination`
+ dictionary
+ """
+ element = ace_queue.popleft()
+ if element == "host":
+ rendered_ace[direction] = {"host": ace_queue.popleft()}
+ elif element == "net-group":
+ rendered_ace[direction] = {"net_group": ace_queue.popleft()}
+ elif element == "port-group":
+ rendered_ace[direction] = {"port_group": ace_queue.popleft()}
+ elif element == "any":
+ rendered_ace[direction] = {"any": True}
+
+ elif "/" in element:
+ rendered_ace[direction] = {"prefix": element}
+
+ elif isipaddress(to_text(element)):
+ rendered_ace[direction] = {
+ "address": element,
+ "wildcard_bits": ace_queue.popleft(),
+ }
+
+ def _parse_port_protocol(rendered_ace, ace_queue, direction):
+ """
+ Parses the ACE queue and populates `port_protocol` dictionary in the
+ ACE dictionary, i.e., `rendered_ace`.
+
+ :param rendered_ace: The dictionary containing the ACE in structured format
+ :param ace_queue: The ACE queue
+ :param direction: Specifies whether to populate `source` or `destination`
+ dictionary
+ """
+ if len(ace_queue) > 0 and ace_queue[0] in (
+ "eq",
+ "gt",
+ "lt",
+ "neq",
+ "range",
+ ):
+ element = ace_queue.popleft()
+ port_protocol = {}
+
+ if element == "range":
+ port_protocol["range"] = {
+ "start": ace_queue.popleft(),
+ "end": ace_queue.popleft(),
+ }
+ else:
+ port_protocol[element] = ace_queue.popleft()
+
+ if rendered_ace.get(direction):
+ rendered_ace[direction]["port_protocol"] = port_protocol
+ else:
+ rendered_ace[direction] = {"port_protocol": port_protocol}
+
+ def _parse_protocol_options(rendered_ace, ace_queue, protocol):
+ """
+ Parses the ACE queue and populates protocol specific options
+ of the required dictionary and updates the ACE dictionary, i.e.,
+ `rendered_ace`.
+
+ :param rendered_ace: The dictionary containing the ACE in structured format
+ :param ace_queue: The ACE queue
+ :param protocol: Specifies the protocol that will be populated under
+ `protocol_options` dictionary
+ """
+ if len(ace_queue) > 0:
+ protocol_options = {protocol: {}}
+
+ for match_bit in PROTOCOL_OPTIONS.get(protocol, ()):
+ if match_bit.replace("_", "-") in ace_queue:
+ protocol_options[protocol][match_bit] = True
+ ace_queue.remove(match_bit.replace("_", "-"))
+
+ rendered_ace["protocol_options"] = protocol_options
+
+ def _parse_match_options(rendered_ace, ace_queue):
+ """
+ Parses the ACE queue and populates remaining options in the ACE dictionary,
+ i.e., `rendered_ace`
+
+ :param rendered_ace: The dictionary containing the ACE in structured format
+ :param ace_queue: The ACE queue
+ """
+ if len(ace_queue) > 0:
+ # We deepcopy the actual queue and iterate through the
+ # copied queue. However, we pop off the elements from
+ # the actual queue. Then, in every pass we update the copied
+ # queue with the current state of the original queue.
+ # This is done because a queue cannot be mutated during iteration.
+ copy_ace_queue = deepcopy(ace_queue)
+
+ for element in copy_ace_queue:
+ if element == "precedence":
+ ace_queue.popleft()
+ rendered_ace["precedence"] = ace_queue.popleft()
+
+ elif element == "dscp":
+ ace_queue.popleft()
+ dscp = {}
+ operation = ace_queue.popleft()
+
+ if operation in ("eq", "gt", "neq", "lt", "range"):
+ if operation == "range":
+ dscp["range"] = {
+ "start": ace_queue.popleft(),
+ "end": ace_queue.popleft(),
+ }
+ else:
+ dscp[operation] = ace_queue.popleft()
+ else:
+ # `dscp` can be followed by either the dscp value itself or
+ # the same thing can be represented using "dscp eq <dscp_value>".
+ # In both cases, it would show up as {'dscp': {'eq': "dscp_value"}}.
+ dscp["eq"] = operation
+
+ rendered_ace["dscp"] = dscp
+
+ elif element in ("packet-length", "ttl"):
+ ace_queue.popleft()
+ element_dict = {}
+ operation = ace_queue.popleft()
+
+ if operation == "range":
+ element_dict["range"] = {
+ "start": ace_queue.popleft(),
+ "end": ace_queue.popleft(),
+ }
+ else:
+ element_dict[operation] = ace_queue.popleft()
+
+ rendered_ace[element.replace("-", "_")] = element_dict
+
+ elif element in (
+ "log",
+ "log-input",
+ "fragments",
+ "icmp-off",
+ "capture",
+ "destopts",
+ "authen",
+ "routing",
+ "hop-by-hop",
+ ):
+ rendered_ace[element.replace("-", "_")] = True
+ ace_queue.remove(element)
+
+ copy_ace_queue = deepcopy(ace_queue)
+
+ rendered_ace = {}
+ split_ace = ace.split()
+
+ # Create a queue with each word in the ace
+ # We parse each element and pop it off the queue
+ ace_queue = deque(split_ace)
+
+ # An ACE will always have a sequence number, even if
+ # it is not explicitly provided while configuring
+ sequence = int(ace_queue.popleft())
+ rendered_ace["sequence"] = sequence
+ operation = ace_queue.popleft()
+
+ if operation == "remark":
+ rendered_ace["remark"] = " ".join(split_ace[2:])
+
+ else:
+ rendered_ace["grant"] = operation
+
+ # If the entry is a non-remark entry, the third element
+ # will always be the protocol specified. By default, it's
+ # the AFI.
+ rendered_ace["protocol"] = ace_queue.popleft()
+
+ # Populate source dictionary
+ _parse_src_dest(rendered_ace, ace_queue, direction="source")
+ # Populate port_protocol key in source dictionary
+ _parse_port_protocol(rendered_ace, ace_queue, direction="source")
+ # Populate destination dictionary
+ _parse_src_dest(rendered_ace, ace_queue, direction="destination")
+ # Populate port_protocol key in destination dictionary
+ _parse_port_protocol(
+ rendered_ace,
+ ace_queue,
+ direction="destination",
+ )
+ # Populate protocol_options dictionary
+ _parse_protocol_options(
+ rendered_ace,
+ ace_queue,
+ protocol=rendered_ace["protocol"],
+ )
+ # Populate remaining match options' dictionaries
+ _parse_match_options(rendered_ace, ace_queue)
+
+ # At this stage the queue should be empty
+ # If the queue is not empty, it means that
+ # we haven't been able to parse the entire ACE
+ # In this case, we add the whole unprocessed ACE
+ # to a key called `line` and send it back
+ if len(ace_queue) > 0:
+ rendered_ace = {
+ "sequence": sequence,
+ "line": " ".join(split_ace[1:]),
+ }
+
+ return utils.remove_empties(rendered_ace)
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_address_family/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_address_family/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_address_family/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_address_family/bgp_address_family.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_address_family/bgp_address_family.py
new file mode 100644
index 00000000..dfcd66a3
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_address_family/bgp_address_family.py
@@ -0,0 +1,99 @@
+# -*- 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 iosxr bgp_address_family fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.bgp_address_family.bgp_address_family import (
+ Bgp_address_familyArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.bgp_address_family import (
+ Bgp_address_familyTemplate,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ flatten_config,
+)
+
+
+class Bgp_address_familyFacts(object):
+ """The iosxr bgp_address_family facts class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Bgp_address_familyArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_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_address_family 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)
+
+ nb_data = flatten_config(data, "neighbor")
+ data = flatten_config(nb_data, "vrf")
+ # parse native config using the Bgp_global template
+ bgp_global_parser = Bgp_address_familyTemplate(lines=data.splitlines())
+ objs = bgp_global_parser.parse()
+
+ af = objs.get("address_family")
+ if af:
+ self._post_parse(objs)
+ else:
+ objs["address_family"] = []
+
+ ansible_facts["ansible_network_resources"].pop(
+ "bgp_address_family",
+ None,
+ )
+
+ params = utils.remove_empties(
+ utils.validate_config(self.argument_spec, {"config": objs}),
+ )
+
+ facts["bgp_address_family"] = params.get("config", {})
+ ansible_facts["ansible_network_resources"].update(facts)
+
+ return ansible_facts
+
+ def _post_parse(self, obj):
+ """Converts the intermediate data structure
+ to valid format as per argspec.
+ :param obj: dict
+ """
+ af = obj.get("address_family", {})
+ if af:
+ obj["address_family"] = list(af.values())
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_global/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_global/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_global/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_global/bgp_global.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_global/bgp_global.py
new file mode 100644
index 00000000..e2b5e4a2
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_global/bgp_global.py
@@ -0,0 +1,150 @@
+# -*- 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 iosxr bgp_global fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from copy import deepcopy
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.bgp_global.bgp_global import (
+ Bgp_globalArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.bgp_global import (
+ Bgp_globalTemplate,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ flatten_config,
+)
+
+
+class Bgp_globalFacts(object):
+ """The iosxr bgp_global facts class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Bgp_globalArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def 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_global network resource
+
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+
+ :rtype: dictionary
+ :returns: facts
+ """
+ facts = {}
+ objs = []
+ bgp_global_config = []
+ if not data:
+ data = self.get_config(connection)
+ neighbor_data = flatten_config(data, "neighbor")
+ rpki_server_data = flatten_config(neighbor_data, "rpki server")
+ data = flatten_config(rpki_server_data, "bgp confederation peers")
+
+ # remove address_family configs from bgp_global
+
+ start = False
+ for bgp_line in data.splitlines():
+ if "address-family" in bgp_line:
+ start = True
+ if not start:
+ bgp_global_config.append(bgp_line)
+ if start and "!" in bgp_line:
+ start = False
+
+ # parse native config using the Bgp_global template
+ bgp_global_parser = Bgp_globalTemplate(
+ lines=bgp_global_config,
+ module=self._module,
+ )
+ objs = bgp_global_parser.parse()
+
+ conf_peers = objs.get("bgp", {}).get("confederation", {}).get("peers", {})
+ if conf_peers:
+ objs["bgp"]["confederation"]["peers"] = list(conf_peers.values())
+
+ vrfs = objs.get("vrfs", {})
+
+ # move global vals to their correct position in facts tree
+ # this is only needed for keys that are common between both global
+ # and VRF contexts
+ global_vals = vrfs.pop("vrf_", {})
+ for key, value in iteritems(global_vals):
+ if objs.get(key):
+ objs[key].update(value)
+ else:
+ objs[key] = value
+ # transform vrfs into a list
+ if vrfs:
+ objs["vrfs"] = sorted(
+ list(objs["vrfs"].values()),
+ key=lambda k, sk="vrf": k[sk],
+ )
+ for vrf in objs["vrfs"]:
+ self._post_parse(vrf)
+ else:
+ objs["vrfs"] = []
+
+ self._post_parse(objs)
+
+ ansible_facts["ansible_network_resources"].pop("bgp_global", None)
+
+ params = utils.remove_empties(
+ bgp_global_parser.validate_config(
+ self.argument_spec,
+ {"config": objs},
+ redact=True,
+ ),
+ )
+
+ facts["bgp_global"] = params.get("config", {})
+ ansible_facts["ansible_network_resources"].update(facts)
+
+ return ansible_facts
+
+ def _post_parse(self, obj):
+ """Converts the intermediate data structure
+ to valid format as per argspec.
+ :param obj: dict
+ """
+ neighbors = obj.get("neighbors", [])
+ if neighbors:
+ obj["neighbors"] = sorted(
+ list(neighbors.values()),
+ key=lambda k, sk="neighbor_address": k[sk],
+ )
+ rpki_servers = obj.get("rpki", {}).get("servers", [])
+ if rpki_servers:
+ obj["rpki"]["servers"] = sorted(
+ list(rpki_servers.values()),
+ key=lambda k, sk="name": k[sk],
+ )
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_neighbor_address_family/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_neighbor_address_family/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_neighbor_address_family/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_neighbor_address_family/bgp_neighbor_address_family.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_neighbor_address_family/bgp_neighbor_address_family.py
new file mode 100644
index 00000000..7824406e
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/bgp_neighbor_address_family/bgp_neighbor_address_family.py
@@ -0,0 +1,111 @@
+# -*- 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 iosxr bgp_neighbor_address_family fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.bgp_neighbor_address_family.bgp_neighbor_address_family import (
+ Bgp_neighbor_address_familyArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.bgp_neighbor_address_family import (
+ Bgp_neighbor_address_familyTemplate,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ flatten_config,
+)
+
+
+class Bgp_neighbor_address_familyFacts(object):
+ """The iosxr bgp_neighbor_address_family facts class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Bgp_neighbor_address_familyArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_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_address_family 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)
+ nbr_data = flatten_config(data, "neighbor")
+ data = flatten_config(nbr_data, "vrf")
+ # parse native config using the Bgp_global template
+ bgp_global_parser = Bgp_neighbor_address_familyTemplate(
+ lines=data.splitlines(),
+ )
+ objs = bgp_global_parser.parse()
+
+ if objs:
+ top_lvl_nbrs = objs.get("vrfs", {}).pop("vrf_", {})
+ objs["neighbors"] = self._post_parse(top_lvl_nbrs).get(
+ "neighbors",
+ [],
+ )
+
+ if "vrfs" in objs:
+ for vrf in objs["vrfs"].values():
+ vrf["neighbors"] = self._post_parse(vrf)["neighbors"]
+ objs["vrfs"] = list(objs["vrfs"].values())
+
+ ansible_facts["ansible_network_resources"].pop(
+ "bgp_neighbor_address_family",
+ None,
+ )
+
+ params = utils.remove_empties(
+ utils.validate_config(self.argument_spec, {"config": objs}),
+ )
+
+ facts["bgp_neighbor_address_family"] = 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 "neighbors" in data:
+ data["neighbors"] = sorted(
+ list(data["neighbors"].values()),
+ key=lambda k, s="neighbor_address": k[s],
+ )
+ for nbr in data["neighbors"]:
+ nbr["address_family"] = list(nbr["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
new file mode 100644
index 00000000..4d7e7b10
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/facts.py
@@ -0,0 +1,164 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The facts class for iosxr
+this file validates each subset of facts and selectively
+calls the appropriate facts gathering function
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.facts.facts import (
+ FactsBase,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.acl_interfaces.acl_interfaces import (
+ Acl_interfacesFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.acls.acls import (
+ AclsFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.bgp_address_family.bgp_address_family import (
+ Bgp_address_familyFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.bgp_global.bgp_global import (
+ Bgp_globalFacts,
+)
+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.hostname.hostname import (
+ HostnameFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.interfaces.interfaces import (
+ InterfacesFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.l2_interfaces.l2_interfaces import (
+ L2_InterfacesFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.l3_interfaces.l3_interfaces import (
+ L3_InterfacesFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lacp.lacp import (
+ LacpFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lacp_interfaces.lacp_interfaces import (
+ Lacp_interfacesFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lag_interfaces.lag_interfaces import (
+ Lag_interfacesFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.legacy.base import (
+ Config,
+ Default,
+ Hardware,
+ Interfaces,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lldp_global.lldp_global import (
+ Lldp_globalFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.lldp_interfaces.lldp_interfaces import (
+ Lldp_interfacesFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.logging_global.logging_global import (
+ Logging_globalFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.ntp_global.ntp_global import (
+ Ntp_globalFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.ospf_interfaces.ospf_interfaces import (
+ Ospf_interfacesFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.ospfv2.ospfv2 import (
+ Ospfv2Facts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.ospfv3.ospfv3 import (
+ Ospfv3Facts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.prefix_lists.prefix_lists import (
+ Prefix_listsFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.snmp_server.snmp_server import (
+ Snmp_serverFacts,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.static_routes.static_routes import (
+ Static_routesFacts,
+)
+
+
+FACT_LEGACY_SUBSETS = dict(
+ default=Default,
+ hardware=Hardware,
+ interfaces=Interfaces,
+ config=Config,
+)
+FACT_RESOURCE_SUBSETS = dict(
+ lacp=LacpFacts,
+ lacp_interfaces=Lacp_interfacesFacts,
+ lldp_global=Lldp_globalFacts,
+ lldp_interfaces=Lldp_interfacesFacts,
+ interfaces=InterfacesFacts,
+ l2_interfaces=L2_InterfacesFacts,
+ lag_interfaces=Lag_interfacesFacts,
+ l3_interfaces=L3_InterfacesFacts,
+ acl_interfaces=Acl_interfacesFacts,
+ acls=AclsFacts,
+ static_routes=Static_routesFacts,
+ ospfv2=Ospfv2Facts,
+ ospfv3=Ospfv3Facts,
+ ospf_interfaces=Ospf_interfacesFacts,
+ bgp_neighbor_address_family=Bgp_neighbor_address_familyFacts,
+ bgp_address_family=Bgp_address_familyFacts,
+ bgp_global=Bgp_globalFacts,
+ prefix_lists=Prefix_listsFacts,
+ logging_global=Logging_globalFacts,
+ ntp_global=Ntp_globalFacts,
+ snmp_server=Snmp_serverFacts,
+ hostname=HostnameFacts,
+)
+
+
+class Facts(FactsBase):
+ """The fact class for iosxr"""
+
+ VALID_LEGACY_GATHER_SUBSETS = frozenset(FACT_LEGACY_SUBSETS.keys())
+ VALID_RESOURCE_SUBSETS = frozenset(FACT_RESOURCE_SUBSETS.keys())
+
+ def __init__(self, module):
+ super(Facts, self).__init__(module)
+
+ def get_facts(
+ self,
+ legacy_facts_type=None,
+ resource_facts_type=None,
+ data=None,
+ ):
+ """Collect the facts for iosxr
+
+ :param legacy_facts_type: List of legacy facts types
+ :param resource_facts_type: List of resource fact types
+ :param data: previously collected conf
+ :rtype: dict
+ :return: the facts gathered
+ """
+ if self.VALID_RESOURCE_SUBSETS:
+ self.get_network_resources_facts(
+ FACT_RESOURCE_SUBSETS,
+ resource_facts_type,
+ data,
+ )
+
+ if self.VALID_LEGACY_GATHER_SUBSETS:
+ self.get_network_legacy_facts(
+ FACT_LEGACY_SUBSETS,
+ legacy_facts_type,
+ )
+
+ return self.ansible_facts, self._warnings
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/hostname/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/hostname/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/hostname/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/hostname/hostname.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/hostname/hostname.py
new file mode 100644
index 00000000..832c426d
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/hostname/hostname.py
@@ -0,0 +1,75 @@
+# -*- coding: utf-8 -*-
+# Copyright 2022 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 hostname 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.hostname.hostname import (
+ HostnameArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.hostname import (
+ HostnameTemplate,
+)
+
+
+class HostnameFacts(object):
+ """The iosxr hostname facts class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = HostnameArgs.argument_spec
+
+ def get_config(self, connection):
+ return connection.get("show running-config hostname")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for Hostname 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)
+
+ # parse native config using the Hostname template
+ hostname_parser = HostnameTemplate(
+ lines=data.splitlines(),
+ module=self._module,
+ )
+ objs = hostname_parser.parse()
+
+ ansible_facts["ansible_network_resources"].pop("hostname", None)
+
+ params = utils.remove_empties(
+ hostname_parser.validate_config(
+ self.argument_spec,
+ {"config": objs},
+ redact=True,
+ ),
+ )
+
+ facts["hostname"] = params.get("config", {})
+ ansible_facts["ansible_network_resources"].update(facts)
+
+ return ansible_facts
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/__init__.py
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
new file mode 100644
index 00000000..e89dbca2
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/interfaces/interfaces.py
@@ -0,0 +1,115 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat Inc.
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr interfaces fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+import re
+
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.interfaces.interfaces import (
+ InterfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ get_interface_type,
+)
+
+
+class InterfacesFacts(object):
+ """The iosxr interfaces fact class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = InterfacesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_config(self, connection):
+ return connection.get_config(flags="interface")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for interfaces
+ :param module: the module instance
+ :param connection: the device connection
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+ objs = []
+ if not data:
+ data = self.get_config(connection)
+
+ # operate on a collection of resource x
+ config = ("\n" + data).split("\ninterface ")
+ for conf in config:
+ if conf:
+ obj = self.render_config(self.generated_spec, conf)
+ if obj:
+ objs.append(obj)
+
+ facts = {}
+ if objs:
+ facts["interfaces"] = []
+ params = utils.validate_config(
+ self.argument_spec,
+ {"config": objs},
+ )
+ for cfg in params["config"]:
+ facts["interfaces"].append(utils.remove_empties(cfg))
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys from spec for null values
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+
+ config = deepcopy(spec)
+ match = re.search(r"^(\S+)", conf)
+
+ intf = match.group(1)
+ if match.group(1).lower() == "preconfigure":
+ match = re.search(r"^(\S+) (.*)", conf)
+ if match:
+ intf = match.group(2)
+
+ if get_interface_type(intf) == "unknown":
+ return {}
+ # populate the facts from the configuration
+ config["name"] = intf
+ config["description"] = utils.parse_conf_arg(conf, "description")
+ if utils.parse_conf_arg(conf, "speed"):
+ config["speed"] = int(utils.parse_conf_arg(conf, "speed"))
+ if utils.parse_conf_arg(conf, "mtu"):
+ config["mtu"] = int(utils.parse_conf_arg(conf, "mtu"))
+ config["duplex"] = utils.parse_conf_arg(conf, "duplex")
+ enabled = utils.parse_conf_cmd_arg(conf, "shutdown", False)
+ config["enabled"] = enabled if enabled is not None else True
+
+ return utils.remove_empties(config)
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/__init__.py
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
new file mode 100644
index 00000000..cdb1d72c
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l2_interfaces/l2_interfaces.py
@@ -0,0 +1,159 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat Inc.
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr l2_interfaces fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+import re
+
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.l2_interfaces.l2_interfaces import (
+ L2_InterfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import get_os_version
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ Version,
+ get_interface_type,
+)
+
+
+class L2_InterfacesFacts(object):
+ """The iosxr l2_interfaces fact class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = L2_InterfacesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_config(self, connection):
+ return connection.get_config(flags="interface")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for l2_interfaces
+ :param module: the module instance
+ :param connection: the device connection
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+ objs = []
+ if not data:
+ data = self.get_config(connection)
+
+ # operate on a collection of resource x
+ config = ("\n" + data).split("\ninterface ")
+ for conf in config:
+ if conf:
+ obj = self.render_config(self.generated_spec, conf)
+ if obj:
+ objs.append(obj)
+ facts = {}
+ if objs:
+ facts["l2_interfaces"] = []
+ params = utils.validate_config(
+ self.argument_spec,
+ {"config": objs},
+ )
+ for cfg in params["config"]:
+ facts["l2_interfaces"].append(utils.remove_empties(cfg))
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys from spec for null values
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+ match = re.search(r"^(\S+)", conf)
+
+ intf = match.group(1)
+
+ if match.group(1).lower() == "preconfigure":
+ match = re.search(r"^(\S+) (.*)", conf)
+ if match:
+ intf = match.group(2)
+
+ if get_interface_type(intf) == "unknown":
+ return {}
+
+ if intf.lower().startswith("gi"):
+ config["name"] = intf
+
+ # populate the facts from the configuration
+ native_vlan = re.search(r"dot1q native vlan (\d+)", conf)
+ if native_vlan:
+ config["native_vlan"] = int(native_vlan.group(1))
+
+ dot1q = utils.parse_conf_arg(conf, "encapsulation dot1q")
+ os_version = get_os_version(self._module)
+ if os_version and Version(os_version) > Version("7.0.0"):
+ encapsulation = re.search(
+ r"encapsulation dot1q\s(\d+)\s*(second-dot1q\s\d+)?",
+ conf,
+ )
+ if encapsulation:
+ config["encapsulation"]["dot1q"] = int(
+ encapsulation.group(1),
+ )
+ if encapsulation.group(2):
+ config["encapsulation"]["second_dot1q"] = int(
+ encapsulation.group(2).split("second-dot1q ")[1],
+ )
+ else:
+ config["q_vlan"] = []
+ if dot1q:
+ config["q_vlan"].append(int(dot1q.split(" ")[0]))
+ if len(dot1q.split(" ")) > 1:
+ config["q_vlan"].append(int(dot1q.split(" ")[2]))
+
+ if utils.parse_conf_cmd_arg(conf, "l2transport", True):
+ config["l2transport"] = True
+ if utils.parse_conf_arg(conf, "propagate"):
+ config["propagate"] = True
+ config["l2protocol"] = []
+
+ cdp = utils.parse_conf_arg(conf, "l2protocol cdp")
+ pvst = utils.parse_conf_arg(conf, "l2protocol pvst")
+ stp = utils.parse_conf_arg(conf, "l2protocol stp")
+ vtp = utils.parse_conf_arg(conf, "l2protocol vtp")
+ cpsv = utils.parse_conf_arg(conf, "l2protocol cpsv")
+ if cdp:
+ config["l2protocol"].append({"cdp": cdp})
+ if pvst:
+ config["l2protocol"].append({"pvst": pvst})
+ if stp:
+ config["l2protocol"].append({"stp": stp})
+ if vtp:
+ config["l2protocol"].append({"vtp": vtp})
+ if cpsv:
+ config["l2protocol"].append({"cpsv": cpsv})
+
+ return utils.remove_empties(config)
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/__init__.py
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
new file mode 100644
index 00000000..bf5ce5f8
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/l3_interfaces/l3_interfaces.py
@@ -0,0 +1,131 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr_l3_interfaces fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+import re
+
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.l3_interfaces.l3_interfaces import (
+ L3_InterfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ get_interface_type,
+)
+
+
+class L3_InterfacesFacts(object):
+ """The iosxr_l3_interfaces fact class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = L3_InterfacesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_config(self, connection):
+ return connection.get_config(flags="interface")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for interfaces
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+ objs = []
+
+ if not data:
+ data = self.get_config(connection)
+ # operate on a collection of resource x
+ config = ("\n" + data).split("\ninterface ")
+ for conf in config:
+ if conf:
+ obj = self.render_config(self.generated_spec, conf)
+ if obj:
+ objs.append(obj)
+ facts = {}
+
+ if objs:
+ facts["l3_interfaces"] = []
+ params = utils.validate_config(
+ self.argument_spec,
+ {"config": objs},
+ )
+ for cfg in params["config"]:
+ facts["l3_interfaces"].append(utils.remove_empties(cfg))
+ ansible_facts["ansible_network_resources"].update(facts)
+
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys from spec for null values
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+ match = re.search(r"^(\S+)", conf)
+
+ intf = match.group(1)
+ if match.group(1).lower() == "preconfigure":
+ match = re.search(r"^(\S+) (.*)", conf)
+ if match:
+ intf = match.group(2)
+
+ if get_interface_type(intf) == "unknown":
+ return {}
+
+ # populate the facts from the configuration
+ config["name"] = intf
+
+ # Get the configured IPV4 details
+ ipv4 = []
+ ipv4_all = re.findall(r"ipv4 address (\S+.*)", conf)
+ for each in ipv4_all:
+ each_ipv4 = dict()
+ if "secondary" in each:
+ each_ipv4["address"] = each.split(" secondary")[0]
+ each_ipv4["secondary"] = True
+ else:
+ each_ipv4["address"] = each
+ ipv4.append(each_ipv4)
+ config["ipv4"] = ipv4
+
+ # Get the configured IPV6 details
+ ipv6 = []
+ ipv6_all = re.findall(r"ipv6 address (\S+)", conf)
+ for each in ipv6_all:
+ each_ipv6 = dict()
+ each_ipv6["address"] = each
+ ipv6.append(each_ipv6)
+ config["ipv6"] = ipv6
+
+ return utils.remove_empties(config)
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp/lacp.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp/lacp.py
new file mode 100644
index 00000000..5c80d30d
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp/lacp.py
@@ -0,0 +1,90 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr lacp fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lacp.lacp import (
+ LacpArgs,
+)
+
+
+class LacpFacts(object):
+ """The iosxr lacp fact class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = LacpArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_config(self, connection):
+ return connection.get_config(flags="lacp")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for lacp
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+ if not data:
+ data = self.get_config(connection)
+
+ obj = {}
+ if "lacp" in data:
+ lacp_obj = self.render_config(self.generated_spec, data)
+ if lacp_obj:
+ obj = lacp_obj
+
+ ansible_facts["ansible_network_resources"].pop("lacp", None)
+ facts = {}
+
+ params = utils.validate_config(self.argument_spec, {"config": obj})
+ facts["lacp"] = utils.remove_empties(params["config"])
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys
+ from spec for null values
+
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+
+ system_priority = utils.parse_conf_arg(conf, "priority")
+ config["system"]["priority"] = int(system_priority) if system_priority else system_priority
+ config["system"]["mac"]["address"] = utils.parse_conf_arg(conf, "mac")
+
+ return config
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp_interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp_interfaces/lacp_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp_interfaces/lacp_interfaces.py
new file mode 100644
index 00000000..2e69f7a6
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lacp_interfaces/lacp_interfaces.py
@@ -0,0 +1,120 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr lacp_interfaces fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+import re
+
+from copy import deepcopy
+
+from ansible.module_utils.six import iteritems
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lacp_interfaces.lacp_interfaces import (
+ Lacp_interfacesArgs,
+)
+
+
+class Lacp_interfacesFacts(object):
+ """The iosxr lacp_interfaces fact class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Lacp_interfacesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_config(self, connection):
+ return connection.get_config(flags="interface")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for lacp_interfaces
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+
+ if not data:
+ data = self.get_config(connection)
+ interfaces = ("\n" + data).split("\ninterface ")
+
+ objs = []
+ for interface in interfaces:
+ obj = self.render_config(self.generated_spec, interface)
+ if obj:
+ objs.append(obj)
+
+ ansible_facts["ansible_network_resources"].pop("lacp_interfaces", None)
+ facts = {}
+ if objs:
+ facts["lacp_interfaces"] = []
+ params = utils.validate_config(
+ self.argument_spec,
+ {"config": objs},
+ )
+ for cfg in params["config"]:
+ facts["lacp_interfaces"].append(utils.remove_empties(cfg))
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys
+ from spec for null values
+
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+
+ match = re.search(
+ r"(GigabitEthernet|Bundle-Ether|TenGigE|FortyGigE|HundredGigE)(\S+)",
+ conf,
+ re.M,
+ )
+ if match:
+ config["name"] = match.group(1) + match.group(2)
+
+ temp = {
+ "churn_logging": "lacp churn logging",
+ "switchover_suppress_flaps": "lacp switchover suppress-flaps",
+ "collector_max_delay": "lacp collector-max-delay",
+ "period": "lacp period",
+ }
+
+ for key, value in iteritems(temp):
+ config[key] = utils.parse_conf_arg(conf, value)
+
+ for key in config["system"].keys():
+ config["system"][key] = utils.parse_conf_arg(
+ conf,
+ "lacp system {0}".format(key),
+ )
+
+ return utils.remove_empties(config)
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lag_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lag_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lag_interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lag_interfaces/lag_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lag_interfaces/lag_interfaces.py
new file mode 100644
index 00000000..14435c1f
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lag_interfaces/lag_interfaces.py
@@ -0,0 +1,151 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr lag_interfaces fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+import re
+
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lag_interfaces.lag_interfaces import (
+ Lag_interfacesArgs,
+)
+
+
+class Lag_interfacesFacts(object):
+ """The iosxr lag_interfaces fact class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Lag_interfacesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_config(self, connection):
+ return connection.get_config(flags="interface")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for lag_interfaces
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+
+ if not data:
+ data = self.get_config(connection)
+ interfaces = ("\n" + data).split("\ninterface ")
+
+ objs = []
+
+ for interface in interfaces:
+ if interface.startswith("Bundle-Ether"):
+ obj = self.render_config(
+ self.generated_spec,
+ interface,
+ interfaces,
+ )
+ if obj:
+ objs.append(obj)
+
+ ansible_facts["ansible_network_resources"].pop("lag_interfaces", None)
+ facts = {}
+
+ facts["lag_interfaces"] = []
+ params = utils.validate_config(self.argument_spec, {"config": objs})
+ for cfg in params["config"]:
+ facts["lag_interfaces"].append(utils.remove_empties(cfg))
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, spec, conf, data):
+ """
+ Render config as dictionary structure and delete keys
+ from spec for null values
+
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+ match = re.search(r"(Bundle-Ether)(\d+)", conf, re.M)
+ if match:
+ config["name"] = match.group(1) + match.group(2)
+ config["load_balancing_hash"] = utils.parse_conf_arg(
+ conf,
+ "bundle load-balancing hash",
+ )
+ config["mode"] = utils.parse_conf_arg(conf, "lacp mode")
+ config["links"]["max_active"] = utils.parse_conf_arg(
+ conf,
+ "bundle maximum-active links",
+ )
+ config["links"]["min_active"] = utils.parse_conf_arg(
+ conf,
+ "bundle minimum-active links",
+ )
+ config["members"] = self.parse_members(match.group(2), data)
+
+ return utils.remove_empties(config)
+
+ def parse_members(self, bundle_id, interfaces):
+ """
+ Renders a list of member interfaces for every bundle
+ present in running-config.
+
+ :param bundle_id: The Bundle-Ether ID fetched from running-config
+ :param interfaces: Data of all interfaces present in running-config
+ :rtype: list
+ :returns: A list of member interfaces
+ """
+
+ def _parse_interface(name):
+ if name.startswith("preconfigure"):
+ return name.split()[1]
+ else:
+ return name.split()[0]
+
+ members = []
+ for interface in interfaces:
+ if not interface.startswith("Bu"):
+ match = re.search(
+ r"bundle id (\d+) mode (\S+)",
+ interface,
+ re.M,
+ )
+ if match:
+ if bundle_id == match.group(1):
+ members.append(
+ {
+ "member": _parse_interface(interface),
+ "mode": match.group(2),
+ },
+ )
+
+ return members
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/__init__.py
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
new file mode 100644
index 00000000..9e346d36
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/legacy/base.py
@@ -0,0 +1,265 @@
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+"""
+The iosxr legacy fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+import platform
+import re
+
+from ansible.module_utils.six import iteritems
+from ansible.module_utils.six.moves import zip
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ get_capabilities,
+ run_commands,
+)
+
+
+class FactsBase(object):
+
+ COMMANDS = frozenset()
+
+ def __init__(self, module):
+ self.module = module
+ self.facts = dict()
+ self.warnings = list()
+ self.responses = None
+
+ def populate(self):
+ self.responses = run_commands(
+ self.module,
+ list(self.COMMANDS),
+ check_rc=False,
+ )
+
+
+class Default(FactsBase):
+ def populate(self):
+ self.facts.update(self.platform_facts())
+
+ def platform_facts(self):
+ platform_facts = {}
+
+ resp = get_capabilities(self.module)
+ device_info = resp["device_info"]
+
+ platform_facts["system"] = device_info["network_os"]
+
+ for item in ("model", "image", "version", "platform", "hostname"):
+ val = device_info.get("network_os_%s" % item)
+ if val:
+ platform_facts[item] = val
+
+ platform_facts["api"] = resp["network_api"]
+ platform_facts["python_version"] = platform.python_version()
+
+ return platform_facts
+
+
+class Hardware(FactsBase):
+
+ COMMANDS = ["dir /all", "show memory summary"]
+
+ def populate(self):
+ super(Hardware, self).populate()
+ data = self.responses[0]
+ self.facts["filesystems"] = self.parse_filesystems(data)
+
+ data = self.responses[1]
+ match = re.search(r"Physical Memory: (\d+)M total \((\d+)", data)
+ if match:
+ self.facts["memtotal_mb"] = match.group(1)
+ self.facts["memfree_mb"] = match.group(2)
+
+ def parse_filesystems(self, data):
+ return re.findall(r"^Directory of (\S+)", data, re.M)
+
+
+class Config(FactsBase):
+
+ COMMANDS = ["show running-config"]
+
+ def populate(self):
+ super(Config, self).populate()
+ self.facts["config"] = self.responses[0]
+
+
+class Interfaces(FactsBase):
+
+ COMMANDS = [
+ "show interfaces",
+ "show ipv6 interface",
+ "show lldp",
+ "show lldp neighbors detail",
+ ]
+
+ def populate(self):
+ super(Interfaces, self).populate()
+ self.facts["all_ipv4_addresses"] = list()
+ self.facts["all_ipv6_addresses"] = list()
+
+ interfaces = self.parse_interfaces(self.responses[0])
+ self.facts["interfaces"] = self.populate_interfaces(interfaces)
+
+ data = self.responses[1]
+ if len(data) > 0:
+ data = self.parse_interfaces(data)
+ self.populate_ipv6_interfaces(data)
+
+ if "LLDP is not enabled" not in self.responses[2]:
+ neighbors = self.responses[3]
+ self.facts["neighbors"] = self.parse_neighbors(neighbors)
+
+ def populate_interfaces(self, interfaces):
+ facts = dict()
+ for key, value in iteritems(interfaces):
+ intf = dict()
+ intf["description"] = self.parse_description(value)
+ intf["macaddress"] = self.parse_macaddress(value)
+
+ ipv4 = self.parse_ipv4(value)
+ intf["ipv4"] = self.parse_ipv4(value)
+ if ipv4:
+ self.add_ip_address(ipv4["address"], "ipv4")
+
+ intf["mtu"] = self.parse_mtu(value)
+ intf["bandwidth"] = self.parse_bandwidth(value)
+ intf["duplex"] = self.parse_duplex(value)
+ intf["lineprotocol"] = self.parse_lineprotocol(value)
+ intf["operstatus"] = self.parse_operstatus(value)
+ intf["type"] = self.parse_type(value)
+
+ facts[key] = intf
+ return facts
+
+ def populate_ipv6_interfaces(self, data):
+ for key, value in iteritems(data):
+ if key in ["No", "RPF"] or key.startswith("IP"):
+ continue
+ self.facts["interfaces"][key]["ipv6"] = list()
+ addresses = re.findall(r"\s+(.+), subnet", value, re.M)
+ subnets = re.findall(r", subnet is (.+)$", value, re.M)
+ for addr, subnet in zip(addresses, subnets):
+ ipv6 = dict(address=addr.strip(), subnet=subnet.strip())
+ self.add_ip_address(addr.strip(), "ipv6")
+ self.facts["interfaces"][key]["ipv6"].append(ipv6)
+
+ def add_ip_address(self, address, family):
+ if family == "ipv4":
+ self.facts["all_ipv4_addresses"].append(address)
+ else:
+ self.facts["all_ipv6_addresses"].append(address)
+
+ def parse_neighbors(self, neighbors):
+ facts = dict()
+ nbors = neighbors.split(
+ "------------------------------------------------",
+ )
+ for entry in nbors[1:]:
+ if entry == "":
+ continue
+ intf = self.parse_lldp_intf(entry)
+ if intf not in facts:
+ facts[intf] = list()
+ fact = dict()
+ fact["host"] = self.parse_lldp_host(entry)
+ fact["remote_description"] = self.parse_lldp_remote_desc(entry)
+ fact["port"] = self.parse_lldp_port(entry)
+ facts[intf].append(fact)
+ return facts
+
+ def parse_interfaces(self, data):
+ parsed = dict()
+ key = ""
+ for line in data.split("\n"):
+ if len(line) == 0:
+ continue
+ if line[0] == " ":
+ parsed[key] += "\n%s" % line
+ else:
+ match = re.match(r"^(\S+)", line)
+ if match:
+ key = match.group(1)
+ parsed[key] = line
+ return parsed
+
+ def parse_description(self, data):
+ match = re.search(r"Description: (.+)$", data, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_macaddress(self, data):
+ match = re.search(r"address is (\S+)", data)
+ if match:
+ return match.group(1)
+
+ def parse_ipv4(self, data):
+ match = re.search(r"Internet address is (\S+)/(\d+)", data)
+ if match:
+ addr = match.group(1)
+ masklen = int(match.group(2))
+ return dict(address=addr, masklen=masklen)
+
+ def parse_mtu(self, data):
+ match = re.search(r"MTU (\d+)", data)
+ if match:
+ return int(match.group(1))
+
+ def parse_bandwidth(self, data):
+ match = re.search(r"BW (\d+)", data)
+ if match:
+ return int(match.group(1))
+
+ def parse_duplex(self, data):
+ match = re.search(r"(\w+)(?: D|-d)uplex", data, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_type(self, data):
+ match = re.search(r"Hardware is (.+),", data, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_lineprotocol(self, data):
+ match = re.search(r"line protocol is (.+)\s+?$", data, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_operstatus(self, data):
+ match = re.search(r"^(?:.+) is (.+),", data, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_lldp_intf(self, data):
+ match = re.search(r"^Local Interface: (.+)$", data, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_lldp_remote_desc(self, data):
+ match = re.search(r"Port Description: (.+)$", data, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_lldp_host(self, data):
+ match = re.search(r"System Name: (.+)$", data, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_lldp_port(self, data):
+ match = re.search(r"Port id: (.+)$", data, re.M)
+ if match:
+ return match.group(1)
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_global/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_global/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_global/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_global/lldp_global.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_global/lldp_global.py
new file mode 100644
index 00000000..ce17af21
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_global/lldp_global.py
@@ -0,0 +1,106 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr lldp fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lldp_global.lldp_global import (
+ Lldp_globalArgs,
+)
+
+
+class Lldp_globalFacts(object):
+ """The iosxr lldp fact class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Lldp_globalArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_config(self, connection):
+ return connection.get_config(flags="lldp")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for lldp
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+ if not data:
+ data = self.get_config(connection)
+
+ obj = {}
+ if "lldp" in data:
+ lldp_obj = self.render_config(self.generated_spec, data)
+ if lldp_obj:
+ obj = lldp_obj
+
+ ansible_facts["ansible_network_resources"].pop("lldp_global", None)
+ facts = {}
+
+ params = utils.validate_config(self.argument_spec, {"config": obj})
+ facts["lldp_global"] = utils.remove_empties(params["config"])
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys
+ from spec for null values
+
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+
+ for key in spec.keys():
+ if key == "subinterfaces":
+ config[key] = True if "subinterfaces enable" in conf else None
+
+ elif key == "tlv_select":
+ for item in [
+ "system_name",
+ "port_description",
+ "management_address",
+ "system_description",
+ "system_capabilities",
+ ]:
+ config[key][item] = (
+ False if ("{0} disable".format(item.replace("_", "-"))) in conf else None
+ )
+
+ else:
+ value = utils.parse_conf_arg(conf, key)
+ config[key] = int(value) if value else value
+
+ return config
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_interfaces/lldp_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_interfaces/lldp_interfaces.py
new file mode 100644
index 00000000..f5e20c80
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/lldp_interfaces/lldp_interfaces.py
@@ -0,0 +1,111 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr lldp_interfaces fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+import re
+
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lldp_interfaces.lldp_interfaces import (
+ Lldp_interfacesArgs,
+)
+
+
+class Lldp_interfacesFacts(object):
+ """The iosxr lldp_interfaces fact class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Lldp_interfacesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_config(self, connection):
+ return connection.get_config(flags="interface")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for lldp_interfaces
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+
+ if not data:
+ data = self.get_config(connection)
+ interfaces = ("\n" + data).split("\ninterface ")
+
+ objs = []
+ for interface in interfaces:
+ obj = self.render_config(self.generated_spec, interface)
+ if obj:
+ objs.append(obj)
+
+ ansible_facts["ansible_network_resources"].pop("lldp_interfaces", None)
+ facts = {}
+
+ if objs:
+ facts["lldp_interfaces"] = []
+ params = utils.validate_config(
+ self.argument_spec,
+ {"config": objs},
+ )
+ for cfg in params["config"]:
+ facts["lldp_interfaces"].append(utils.remove_empties(cfg))
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys
+ from spec for null values
+
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+
+ match = re.search(
+ r"(GigabitEthernet|Bundle-Ether|TenGigE|FortyGigE|HundredGigE)(\S+)",
+ conf,
+ re.M,
+ )
+ if match:
+ config["name"] = match.group(1) + match.group(2)
+
+ for key in ["receive", "transmit"]:
+ config[key] = False if ("{0} disable".format(key)) in conf else None
+
+ for x in ["ieee-nearest-bridge", "ieee-nearest-non-tmpr-bridge"]:
+ if x in conf:
+ config["destination"]["mac_address"] = x
+
+ return utils.remove_empties(config)
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/logging_global/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/logging_global/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/logging_global/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/logging_global/logging_global.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/logging_global/logging_global.py
new file mode 100644
index 00000000..47c6c439
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/logging_global/logging_global.py
@@ -0,0 +1,102 @@
+# -*- 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 iosxr logging_global 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.logging_global.logging_global import (
+ Logging_globalArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.logging_global import (
+ Logging_globalTemplate,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ flatten_config,
+)
+
+
+class Logging_globalFacts(object):
+ """The iosxr logging_global facts class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Logging_globalArgs.argument_spec
+
+ def get_config(self, connection):
+ return connection.get("show running-config logging")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for Logging_global 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)
+
+ flatten_context_list = [
+ "logging archive",
+ "logging tls-server",
+ "logging correlator rule",
+ "logging correlator ruleset",
+ "logging events filter",
+ "logging buffered discriminator",
+ "logging monitor discriminator",
+ "logging console discriminator",
+ ]
+
+ for x in flatten_context_list:
+ data = flatten_config(data, x)
+ # parse native config using the Logging_global template
+ logging_global_parser = Logging_globalTemplate(
+ lines=data.splitlines(),
+ module=self._module,
+ )
+ objs = logging_global_parser.parse()
+ objs["tls_servers"] = list(objs.get("tls_servers", {}).values())
+ if objs.get("correlator"):
+ objs["correlator"]["rules"] = list(
+ objs.get("correlator", {}).get("rules", {}).values(),
+ )
+ objs["correlator"]["rule_sets"] = list(
+ objs.get("correlator", {}).get("rule_sets", {}).values(),
+ )
+ for i, x in enumerate(objs["correlator"]["rule_sets"]):
+ if None in x["rulename"]:
+ objs["correlator"]["rule_sets"][i]["rulename"].remove(None)
+
+ ansible_facts["ansible_network_resources"].pop("logging_global", None)
+
+ params = utils.remove_empties(
+ logging_global_parser.validate_config(
+ self.argument_spec,
+ {"config": objs},
+ redact=True,
+ ),
+ )
+
+ facts["logging_global"] = params.get("config", {})
+ ansible_facts["ansible_network_resources"].update(facts)
+
+ return ansible_facts
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ntp_global/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ntp_global/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ntp_global/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ntp_global/ntp_global.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ntp_global/ntp_global.py
new file mode 100644
index 00000000..8cf69525
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ntp_global/ntp_global.py
@@ -0,0 +1,110 @@
+# -*- 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 iosxr ntp_global 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.ntp_global.ntp_global import (
+ Ntp_globalArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.ntp_global import (
+ Ntp_globalTemplate,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ flatten_config,
+)
+
+
+class Ntp_globalFacts(object):
+ """The iosxr ntp_global facts class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Ntp_globalArgs.argument_spec
+
+ def get_config(self, connection):
+ return connection.get("show running-config ntp")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for Ntp_global 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)
+
+ flatten_context_list = ["interface", "ntp"]
+
+ for x in flatten_context_list:
+ data = flatten_config(data, x)
+ # parse native config using the Ntp_global template
+ ntp_global_parser = Ntp_globalTemplate(
+ lines=data.splitlines(),
+ module=self._module,
+ )
+ objs = ntp_global_parser.parse()
+ if "access_group" in objs:
+ objs["access_group"]["vrfs"] = list(
+ objs.get("access_group", {}).get("vrfs", {}).values(),
+ )
+ objs["access_group"]["vrfs"] = sorted(
+ objs["access_group"]["vrfs"],
+ key=lambda k: k["name"],
+ )
+ if "interfaces" in objs:
+ objs["interfaces"] = list(objs.get("interfaces", {}).values())
+ if "peers" in objs:
+ objs["peers"] = list(objs.get("peers", {}).values())
+ if "servers" in objs:
+ objs["servers"] = list(objs.get("servers", {}).values())
+ if "source_vrfs" in objs:
+ objs["source_vrfs"] = list(objs.get("source_vrfs", {}).values())
+
+ pkey = {
+ "authentication_keys": "id",
+ "peers": "peer",
+ "servers": "server",
+ "trusted_keys": "key_id",
+ "source_vrfs": "name",
+ "interfaces": "name",
+ }
+
+ for x in pkey.keys():
+ if x in objs:
+ objs[x] = sorted(objs[x], key=lambda k: k[pkey[x]])
+
+ ansible_facts["ansible_network_resources"].pop("ntp_global", None)
+
+ params = utils.remove_empties(
+ ntp_global_parser.validate_config(
+ self.argument_spec,
+ {"config": objs},
+ redact=True,
+ ),
+ )
+
+ facts["ntp_global"] = params.get("config", {})
+ ansible_facts["ansible_network_resources"].update(facts)
+
+ return ansible_facts
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospf_interfaces/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospf_interfaces/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospf_interfaces/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospf_interfaces/ospf_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospf_interfaces/ospf_interfaces.py
new file mode 100644
index 00000000..7296f70a
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospf_interfaces/ospf_interfaces.py
@@ -0,0 +1,143 @@
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+"""
+The iosxr ospf_interfaces fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+import re
+
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.ospf_interfaces.ospf_interfaces import (
+ Ospf_interfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.ospf_interfaces import (
+ Ospf_interfacesTemplate,
+)
+
+
+class Ospf_interfacesFacts(object):
+ """The iosxr ospf_interfaces facts class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Ospf_interfacesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_ospf_interfaces(self, connection, flag):
+ cmd = "show running-config router " + flag
+ return connection.get(cmd)
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for Ospf_interfaces network resource
+
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+
+ :rtype: dictionary
+ :returns: facts
+ """
+ facts = {}
+ objs = []
+ if not data:
+ data = self.get_ospf_interfaces(connection, flag="ospf")
+ data += "\n" + self.get_ospf_interfaces(connection, flag="ospfv3")
+ end_flag, end_mark, count, v_read = 0, 0, 0, False
+ areas, config_commands = [], []
+ area_str, process, curr_process = "", "", ""
+ data = data.splitlines()
+
+ for line in data:
+ if line.startswith("router") and curr_process != "" and curr_process != line:
+ end_mark, count, end_flag, area_str = 0, 0, 0, ""
+ if end_mark == 0 and count == 0 and line.startswith("router ospf"):
+ curr_process = line
+ process = re.sub("\n", "", line)
+ count += 1
+ config_commands.append(process)
+ else:
+ if line.startswith(" area") or line.startswith(" vrf"):
+ area_str = process + re.sub("\n", "", line)
+ config_commands.append(area_str.replace(" ", " "))
+ end_flag += 1
+ elif line.startswith(" interface"):
+ ospf_int = area_str + re.sub("\n", "", line)
+ # default output format has more spaces with default identation
+ # reset the spaces with replace
+ config_commands.append(ospf_int.replace(" ", " "))
+ v_read = True
+ elif v_read:
+ if "!" not in line:
+ command = ospf_int.replace(" ", " ") + re.sub(
+ "\n",
+ "",
+ line,
+ )
+ config_commands.append(command.replace(" ", " "))
+ else:
+ v_read = False
+ elif end_flag > 0 and "!" not in line:
+ command = area_str + re.sub("\n", "", line)
+ config_commands.append(command.replace(" ", " "))
+ elif "!" in line:
+ end_flag = 0
+ end_mark += 1
+ if end_mark == 3:
+ end_mark, count = 0, 0
+ area_str = ""
+ else:
+ command = process + line
+ command.replace(" ", " ")
+ config_commands.append(re.sub("\n", "", command))
+ areas.append(re.sub("\n", "", command))
+ data = config_commands
+
+ ospf_interfaces_parser = Ospf_interfacesTemplate(
+ lines=data,
+ module=self._module,
+ )
+ objs = list(ospf_interfaces_parser.parse().values())
+ if objs:
+ for item in objs:
+ item["address_family"] = list(item["address_family"].values())
+ for af in item["address_family"]:
+ if af.get("processes"):
+ af["processes"] = list(af["processes"].values())
+
+ ansible_facts["ansible_network_resources"].pop("ospf_interfaces", None)
+
+ params = utils.remove_empties(
+ ospf_interfaces_parser.validate_config(
+ self.argument_spec,
+ {"config": objs},
+ redact=True,
+ ),
+ )
+
+ facts["ospf_interfaces"] = params.get("config", [])
+ ansible_facts["ansible_network_resources"].update(facts)
+
+ return ansible_facts
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/__init__.py
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
new file mode 100644
index 00000000..240ecb4d
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv2/ospfv2.py
@@ -0,0 +1,165 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr snmp fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+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 (
+ NetworkTemplate,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.ospfv2.ospfv2 import (
+ Ospfv2Args,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.ospfv2 import (
+ Ospfv2Template,
+)
+
+
+class Ospfv2Facts(object):
+ """The iosxr snmp fact class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Ospfv2Args.argument_spec
+
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_ospfv2_data(self, connection):
+ return connection.get("show running-config router ospf")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for interfaces
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+
+ if not data:
+ data = self.get_ospfv2_data(connection)
+ end_flag, end_mark, count, v_read = 0, 0, 0, False
+ areas, config_commands = [], []
+ area_str, process, curr_process = "", "", ""
+ data = data.splitlines()
+ for line in data:
+ if line.startswith("router ospf") and curr_process != "" and curr_process != line:
+ end_mark, count, end_flag, area_str = 0, 0, 0, ""
+ if end_mark == 0 and count == 0 and line.startswith("router ospf"):
+ curr_process = line
+ process = re.sub("\n", "", line)
+ count += 1
+ config_commands.append(process)
+ else:
+ if line.startswith(" area") or line.startswith(" vrf"):
+ area_str = process + re.sub("\n", "", line)
+ config_commands.append(area_str.replace(" ", " "))
+ end_flag += 1
+ elif line.startswith(" virtual-link"):
+ virtual_str = area_str + re.sub("\n", "", line)
+ config_commands.append(virtual_str.replace(" ", " "))
+ v_read = True
+ elif v_read:
+ if "!" not in line:
+ command = virtual_str.replace(" ", " ") + re.sub(
+ "\n",
+ "",
+ line,
+ )
+ config_commands.append(command.replace(" ", " "))
+ else:
+ v_read = False
+ elif end_flag > 0 and "!" not in line:
+ command = area_str + re.sub("\n", "", line)
+ config_commands.append(command.replace(" ", " "))
+ elif "!" in line:
+ end_flag = 0
+ end_mark += 1
+ if end_mark == 3:
+ end_mark, count = 0, 0
+ area_str = ""
+ else:
+ command = process + line
+ command.replace(" ", " ")
+ config_commands.append(re.sub("\n", "", command))
+ areas.append(re.sub("\n", "", command))
+ data = config_commands
+ ipv4 = {"processes": []}
+ rmmod = NetworkTemplate(
+ lines=data,
+ tmplt=Ospfv2Template(),
+ module=self._module,
+ )
+ current = rmmod.parse()
+
+ # convert some of the dicts to lists
+ for key, sortv in [("processes", "process_id")]:
+ if key in current and current[key]:
+ current[key] = current[key].values()
+ current[key] = sorted(
+ current[key],
+ key=lambda k, sk=sortv: k[sk],
+ )
+
+ for process in current.get("processes", []):
+ if "areas" in process:
+ process["areas"] = list(process["areas"].values())
+ process["areas"] = sorted(
+ process["areas"],
+ key=lambda k, sk="area_id": k[sk],
+ )
+ for area in process["areas"]:
+ if "ranges" in area:
+ area["ranges"] = sorted(
+ area["ranges"],
+ key=lambda k, s="ranges": k[s],
+ )
+ if "virtual_link" in area:
+ area["virtual_link"] = list(
+ area["virtual_link"].values(),
+ )
+ area["virtual_link"] = sorted(
+ area["virtual_link"],
+ key=lambda k, sk="id": k[sk],
+ )
+ ipv4["processes"].append(process)
+
+ ansible_facts["ansible_network_resources"].pop("ospfv2", None)
+ facts = {}
+ if current:
+ params = rmmod.validate_config(
+ self.argument_spec,
+ {"config": ipv4},
+ redact=True,
+ )
+ params = utils.remove_empties(params)
+
+ facts["ospfv2"] = params["config"]
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/__init__.py
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
new file mode 100644
index 00000000..49302ce9
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/ospfv3/ospfv3.py
@@ -0,0 +1,159 @@
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+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 (
+ NetworkTemplate,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.ospfv3.ospfv3 import (
+ Ospfv3Args,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.ospfv3 import (
+ Ospfv3Template,
+)
+
+
+class Ospfv3Facts(object):
+ """The iosxr snmp fact class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Ospfv3Args.argument_spec
+
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_ospfv3_data(self, connection):
+ return connection.get("show running-config router ospfv3")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for interfaces
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+
+ if not data:
+ data = self.get_ospfv3_data(connection)
+ end_flag, end_mark, count, v_read = 0, 0, 0, False
+ areas, config_commands = [], []
+ area_str, process, curr_process = "", "", ""
+ data = data.splitlines()
+ for line in data:
+ if line.startswith("router ospfv3") and curr_process != "" and curr_process != line:
+ end_mark, count, end_flag, area_str = 0, 0, 0, ""
+ if end_mark == 0 and count == 0 and line.startswith("router ospfv3"):
+ curr_process = line
+ process = re.sub("\n", "", line)
+ count += 1
+ config_commands.append(process)
+ else:
+ if line.startswith(" area") or line.startswith(" vrf"):
+ area_str = process + re.sub("\n", "", line)
+ config_commands.append(area_str.replace(" ", " "))
+ end_flag += 1
+ elif line.startswith(" virtual-link"):
+ virtual_str = area_str + re.sub("\n", "", line)
+ config_commands.append(virtual_str.replace(" ", " "))
+ v_read = True
+ elif v_read:
+ if "!" not in line:
+ command = virtual_str.replace(" ", " ") + re.sub(
+ "\n",
+ "",
+ line,
+ )
+ config_commands.append(command.replace(" ", " "))
+ else:
+ v_read = False
+ elif end_flag > 0 and "!" not in line:
+ command = area_str + re.sub("\n", "", line)
+ config_commands.append(command.replace(" ", " "))
+ elif "!" in line:
+ end_flag = 0
+ end_mark += 1
+ if end_mark == 3:
+ end_mark, count = 0, 0
+ area_str = ""
+ else:
+ command = process + line
+ command.replace(" ", " ")
+ config_commands.append(re.sub("\n", "", command))
+ areas.append(re.sub("\n", "", command))
+ data = config_commands
+ ipv4 = {"processes": []}
+ rmmod = NetworkTemplate(
+ lines=data,
+ tmplt=Ospfv3Template(),
+ module=self._module,
+ )
+ current = rmmod.parse()
+
+ # convert some of the dicts to lists
+ for key, sortv in [("processes", "process_id")]:
+ if key in current and current[key]:
+ current[key] = current[key].values()
+ current[key] = sorted(
+ current[key],
+ key=lambda k, sk=sortv: k[sk],
+ )
+
+ for process in current.get("processes", []):
+ if "areas" in process:
+ process["areas"] = list(process["areas"].values())
+ process["areas"] = sorted(
+ process["areas"],
+ key=lambda k, sk="area_id": k[sk],
+ )
+ for area in process["areas"]:
+ if "ranges" in area:
+ area["ranges"] = sorted(
+ area["ranges"],
+ key=lambda k, s="ranges": k[s],
+ )
+ if "virtual_link" in area:
+ area["virtual_link"] = list(
+ area["virtual_link"].values(),
+ )
+ area["virtual_link"] = sorted(
+ area["virtual_link"],
+ key=lambda k, sk="id": k[sk],
+ )
+ ipv4["processes"].append(process)
+
+ ansible_facts["ansible_network_resources"].pop("ospfv3", None)
+ facts = {}
+ if current:
+ params = rmmod.validate_config(
+ self.argument_spec,
+ {"config": ipv4},
+ redact=True,
+ )
+ params = utils.remove_empties(params)
+
+ facts["ospfv3"] = params["config"]
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/prefix_lists/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/prefix_lists/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/prefix_lists/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/prefix_lists/prefix_lists.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/prefix_lists/prefix_lists.py
new file mode 100644
index 00000000..3bf66576
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/prefix_lists/prefix_lists.py
@@ -0,0 +1,78 @@
+# -*- 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 iosxr prefix_lists 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.prefix_lists.prefix_lists import (
+ Prefix_listsArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.prefix_lists import (
+ Prefix_listsTemplate,
+)
+
+
+class Prefix_listsFacts(object):
+ """The iosxr prefix_lists facts class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Prefix_listsArgs.argument_spec
+
+ def get_config(self, connection):
+ return connection.get("show running-config")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for Prefix_lists 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)
+
+ # parse native config using the Prefix_lists template
+ prefix_lists_parser = Prefix_listsTemplate(
+ lines=data.splitlines(),
+ module=self._module,
+ )
+ objs = list(prefix_lists_parser.parse().values())
+
+ if objs:
+ for item in objs:
+ item["prefix_lists"] = list(item["prefix_lists"].values())
+
+ ansible_facts["ansible_network_resources"].pop("prefix_lists", None)
+
+ params = utils.remove_empties(
+ prefix_lists_parser.validate_config(
+ self.argument_spec,
+ {"config": objs},
+ redact=True,
+ ),
+ )
+
+ facts["prefix_lists"] = params.get("config", [])
+ ansible_facts["ansible_network_resources"].update(facts)
+
+ return ansible_facts
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/snmp_server/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/snmp_server/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/snmp_server/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/snmp_server/snmp_server.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/snmp_server/snmp_server.py
new file mode 100644
index 00000000..a631b35c
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/snmp_server/snmp_server.py
@@ -0,0 +1,104 @@
+# -*- 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 iosxr snmp_server 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.snmp_server.snmp_server import (
+ Snmp_serverArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.rm_templates.snmp_server import (
+ Snmp_serverTemplate,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import (
+ flatten_config,
+)
+
+
+class Snmp_serverFacts(object):
+ """The iosxr snmp_server facts class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Snmp_serverArgs.argument_spec
+
+ def get_config(self, connection):
+ return connection.get("show running-config snmp-server")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for Snmp_server 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)
+
+ flatten_context_list = [
+ "snmp-server vrf",
+ "snmp-server mib bulkstat schema",
+ "snmp-server mib bulkstat transfer-id",
+ "snmp-server correlator rule",
+ "snmp-server interface",
+ "snmp-server correlator rule",
+ "snmp-server correlator ruleset",
+ ]
+
+ for x in flatten_context_list:
+ data = flatten_config(data, x)
+ # parse native config using the Snmp_server template
+ snmp_server_parser = Snmp_serverTemplate(
+ lines=data.splitlines(),
+ module=self._module,
+ )
+ objs = snmp_server_parser.parse()
+
+ dict_to_list = [
+ "context",
+ "mib_object_lists",
+ "mib_schema",
+ "mib_bulkstat_transfer_ids",
+ "vrfs",
+ "interfaces",
+ ]
+ for i in dict_to_list:
+ if i in objs:
+ objs[i] = list(objs[i].values())
+ if i == "vrfs":
+ for j in objs[i]:
+ j["hosts"].remove({})
+ j["context"] = list(j["context"].values())
+
+ ansible_facts["ansible_network_resources"].pop("snmp_server", None)
+
+ params = utils.remove_empties(
+ snmp_server_parser.validate_config(
+ self.argument_spec,
+ {"config": objs},
+ redact=True,
+ ),
+ )
+ facts["snmp_server"] = params.get("config", {})
+ ansible_facts["ansible_network_resources"].update(facts)
+
+ return ansible_facts
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/static_routes/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/static_routes/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/static_routes/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/static_routes/static_routes.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/static_routes/static_routes.py
new file mode 100644
index 00000000..e6e37482
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/facts/static_routes/static_routes.py
@@ -0,0 +1,196 @@
+#
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The iosxr static_routes fact class
+It is in this file the configuration is collected from the device
+for a given resource, parsed, and the facts tree is populated
+based on the configuration.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+import re
+
+from copy import deepcopy
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.static_routes.static_routes import (
+ Static_routesArgs,
+)
+
+
+class Static_routesFacts(object):
+ """The iosxr static_routes fact class"""
+
+ def __init__(self, module, subspec="config", options="options"):
+ self._module = module
+ self.argument_spec = Static_routesArgs.argument_spec
+ spec = deepcopy(self.argument_spec)
+ if subspec:
+ if options:
+ facts_argument_spec = spec[subspec][options]
+ else:
+ facts_argument_spec = spec[subspec]
+ else:
+ facts_argument_spec = spec
+
+ self.generated_spec = utils.generate_dict(facts_argument_spec)
+
+ def get_device_data(self, connection):
+ return connection.get_config(flags="router static")
+
+ def populate_facts(self, connection, ansible_facts, data=None):
+ """Populate the facts for static_routes
+ :param connection: the device connection
+ :param ansible_facts: Facts dictionary
+ :param data: previously collected conf
+ :rtype: dictionary
+ :returns: facts
+ """
+ if not data:
+ data = self.get_device_data(connection)
+
+ objs = []
+
+ if "No such configuration" not in data:
+ for entry in re.compile(r"(\s) vrf").split(data):
+ obj = self.render_config(self.generated_spec, entry)
+ if obj:
+ objs.append(obj)
+
+ ansible_facts["ansible_network_resources"].pop("static_routes", None)
+ facts = {}
+
+ facts["static_routes"] = []
+ params = utils.validate_config(self.argument_spec, {"config": objs})
+ for cfg in params["config"]:
+ facts["static_routes"].append(utils.remove_empties(cfg))
+
+ ansible_facts["ansible_network_resources"].update(facts)
+ return ansible_facts
+
+ def render_config(self, spec, conf):
+ """
+ Render config as dictionary structure and delete keys
+ from spec for null values
+
+ :param spec: The facts tree, generated from the argspec
+ :param conf: The configuration
+ :rtype: dictionary
+ :returns: The generated config
+ """
+ config = deepcopy(spec)
+ entry_list = conf.split(" address-family")
+ config["address_families"] = []
+
+ if "router static" not in entry_list[0]:
+ config["vrf"] = entry_list[0].replace("!", "").strip()
+
+ for item in entry_list[1:]:
+ routes = []
+ address_family = {"routes": []}
+ address_family["afi"], address_family["safi"] = self.parse_af(item)
+
+ destinations = re.findall(r"((?:\S+)/(?:\d+)) (?:.*)", item, re.M)
+ for dest in set(destinations):
+ route = {"next_hops": []}
+ route["dest"] = dest
+
+ regex = r"%s .+$" % dest
+ cfg = re.findall(regex, item, re.M)
+
+ for route_entry in cfg:
+ exit_point = {}
+ exit_point["forward_router_address"] = self.parse_faddr(
+ route_entry,
+ )
+ exit_point["interface"] = self.parse_intf(route_entry)
+ exit_point["admin_distance"] = self.parse_admin_distance(
+ route_entry,
+ )
+
+ for x in [
+ "tag",
+ "tunnel-id",
+ "metric",
+ "description",
+ "track",
+ "vrflabel",
+ "dest_vrf",
+ ]:
+ exit_point[x.replace("-", "_")] = self.parse_attrib(
+ route_entry,
+ x.replace("dest_vrf", "vrf"),
+ )
+
+ route["next_hops"].append(exit_point)
+
+ routes.append(route)
+ address_family["routes"] = sorted(
+ routes,
+ key=lambda i: i["dest"],
+ )
+ config["address_families"].append(address_family)
+
+ return utils.remove_empties(config)
+
+ def parse_af(self, item):
+ match = re.search(r"(?:\s*)(\w+)(?:\s*)(\w+)", item, re.M)
+ if match:
+ return match.group(1), match.group(2)
+
+ def parse_faddr(self, item):
+ for x in item.split(" "):
+ if (":" in x or "." in x) and "/" not in x:
+ return x
+
+ def parse_intf(self, item):
+ inf_search_strs = [
+ r" ((\w+)((?:\d)/(?:\d)/(?:\d)/(?:\d+)))",
+ r" (([a-zA-Z]+)(?:\d+))",
+ ]
+ for i in inf_search_strs:
+ match = re.search(i, item, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_attrib(self, item, attrib):
+ match = re.search(r" %s (\S+)" % attrib, item)
+ if match:
+ val = match.group(1).strip("'")
+ if attrib in ["tunnel-id", "vrflabel", "tag", "metric"]:
+ val = int(val)
+ return val
+
+ def parse_admin_distance(self, item):
+ split_item = item.split(" ")
+ for item in [
+ "vrf",
+ "metric",
+ "tunnel-id",
+ "vrflabel",
+ "track",
+ "tag",
+ "description",
+ ]:
+ try:
+ del split_item[split_item.index(item) + 1]
+ del split_item[split_item.index(item)]
+ except ValueError:
+ continue
+ try:
+ return [
+ i
+ for i in split_item
+ if "." not in i and ":" not in i and ord(i[0]) > 48 and ord(i[0]) < 57
+ ][0]
+ except IndexError:
+ return None
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/iosxr.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/iosxr.py
new file mode 100644
index 00000000..ea15fdfc
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/iosxr.py
@@ -0,0 +1,588 @@
+# This code is part of Ansible, but is an independent component.
+# This particular file snippet, and this file snippet only, is BSD licensed.
+# Modules you write using this snippet, which is embedded dynamically by Ansible
+# still belong to the author of the module, and may assign their own license
+# to the complete work.
+#
+# Copyright (c) 2015 Peter Sprygada, <psprygada@ansible.com>
+# Copyright (c) 2017 Red Hat Inc.
+#
+# Redistribution and use in source and binary forms, with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+import json
+import re
+
+from difflib import Differ
+
+from ansible.module_utils._text import to_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,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_list
+
+
+try:
+ from ncclient.xml_ import to_xml
+
+ HAS_NCCLIENT = True
+except ImportError:
+ HAS_NCCLIENT = False
+
+try:
+ from lxml import etree
+
+ HAS_XML = True
+except ImportError:
+ HAS_XML = False
+
+_EDIT_OPS = frozenset(["merge", "create", "replace", "delete"])
+
+BASE_1_0 = "{urn:ietf:params:xml:ns:netconf:base:1.0}"
+
+NS_DICT = {
+ "BASE_NSMAP": {"xc": "urn:ietf:params:xml:ns:netconf:base:1.0"},
+ "BANNERS_NSMAP": {None: "http://cisco.com/ns/yang/Cisco-IOS-XR-infra-infra-cfg"},
+ "INTERFACES_NSMAP": {None: "http://openconfig.net/yang/interfaces"},
+ "INSTALL_NSMAP": {None: "http://cisco.com/ns/yang/Cisco-IOS-XR-spirit-install-instmgr-oper"},
+ "INSTALL_OLD_NSMAP": {None: "http://cisco.com/ns/yang/Cisco-IOS-XR-installmgr-admin-oper"},
+ "HOST-NAMES_NSMAP": {None: "http://cisco.com/ns/yang/Cisco-IOS-XR-shellutil-cfg"},
+ "M:TYPE_NSMAP": {"idx": "urn:ietf:params:xml:ns:yang:iana-if-type"},
+ "ETHERNET_NSMAP": {None: "http://openconfig.net/yang/interfaces/ethernet"},
+ "CETHERNET_NSMAP": {None: "http://cisco.com/ns/yang/Cisco-IOS-XR-drivers-media-eth-cfg"},
+ "INTERFACE-CONFIGURATIONS_NSMAP": {None: "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-cfg"},
+ "INFRA-STATISTICS_NSMAP": {None: "http://cisco.com/ns/yang/Cisco-IOS-XR-infra-statsd-oper"},
+ "INTERFACE-PROPERTIES_NSMAP": {None: "http://cisco.com/ns/yang/Cisco-IOS-XR-ifmgr-oper"},
+ "IP-DOMAIN_NSMAP": {None: "http://cisco.com/ns/yang/Cisco-IOS-XR-ip-domain-cfg"},
+ "SYSLOG_NSMAP": {None: "http://cisco.com/ns/yang/Cisco-IOS-XR-infra-syslog-cfg"},
+ "AAA_NSMAP": {None: "http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-lib-cfg"},
+ "AAA_LOCALD_NSMAP": {None: "http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-locald-cfg"},
+}
+
+
+command_spec = {"command": dict(), "prompt": dict(default=None), "answer": dict(default=None)}
+
+CONFIG_MISPLACED_CHILDREN = [re.compile(r"^end-\s*(.+)$")]
+
+# Objects defined in Route-policy Language guide of IOS_XR.
+# Reconfiguring these objects replace existing configurations.
+# Hence these objects should be played direcly from candidate
+# configurations
+CONFIG_BLOCKS_FORCED_IN_DIFF = [
+ {"start": re.compile(r"^route-policy"), "end": re.compile(r"end-policy$")},
+ {"start": re.compile(r"^prefix-set"), "end": re.compile(r"end-set$")},
+ {"start": re.compile(r"^as-path-set"), "end": re.compile(r"end-set$")},
+ {"start": re.compile(r"^community-set"), "end": re.compile(r"end-set$")},
+ {"start": re.compile(r"^rd-set"), "end": re.compile(r"end-set$")},
+ {"start": re.compile(r"^extcommunity-set"), "end": re.compile(r"end-set$")},
+]
+
+
+def get_connection(module):
+ if hasattr(module, "connection"):
+ return module.connection
+
+ capabilities = get_capabilities(module)
+ network_api = capabilities.get("network_api")
+ if network_api in ["cliconf", "ansible.netcommon.grpc"]:
+ module.connection = Connection(module._socket_path)
+ elif network_api == "netconf":
+ module.connection = NetconfConnection(module._socket_path)
+ else:
+ module.fail_json(msg="Invalid connection type {0!s}".format(network_api))
+
+ return module.connection
+
+
+def get_capabilities(module):
+ if hasattr(module, "capabilities"):
+ return module.capabilities
+ try:
+ capabilities = Connection(module._socket_path).get_capabilities()
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+ module.capabilities = json.loads(capabilities)
+
+ return module.capabilities
+
+
+def build_xml_subtree(container_ele, xmap, param=None, opcode=None):
+ sub_root = container_ele
+ meta_subtree = list()
+
+ for key, meta in xmap.items():
+ candidates = meta.get("xpath", "").split("/")
+ if container_ele.tag == candidates[-2]:
+ parent = container_ele
+ elif sub_root.tag == candidates[-2]:
+ parent = sub_root
+ else:
+ parent = sub_root.find(
+ ".//" + meta.get("xpath", "").split(sub_root.tag + "/", 1)[1].rsplit("/", 1)[0],
+ )
+
+ if (
+ opcode in ("delete", "merge") and meta.get("operation", "unknown") == "edit"
+ ) or meta.get("operation", None) is None:
+
+ if meta.get("tag", False) is True:
+ if parent.tag == container_ele.tag:
+ if meta.get("ns", False) is True:
+ child = etree.Element(candidates[-1], nsmap=NS_DICT[key.upper() + "_NSMAP"])
+ else:
+ child = etree.Element(candidates[-1])
+ meta_subtree.append(child)
+ sub_root = child
+ else:
+ if meta.get("ns", False) is True:
+ child = etree.SubElement(
+ parent,
+ candidates[-1],
+ nsmap=NS_DICT[key.upper() + "_NSMAP"],
+ )
+ else:
+ child = etree.SubElement(parent, candidates[-1])
+
+ if meta.get("attrib", None) is not None and opcode in ("delete", "merge"):
+ child.set(BASE_1_0 + meta.get("attrib"), opcode)
+
+ continue
+
+ text = None
+ param_key = key.split(":")
+ if param_key[0] == "a":
+ if param is not None and param.get(param_key[1], None) is not None:
+ text = param.get(param_key[1])
+ elif param_key[0] == "m":
+ if meta.get("value", None) is not None:
+ text = meta.get("value")
+
+ if text:
+ if meta.get("ns", False) is True:
+ child = etree.SubElement(
+ parent,
+ candidates[-1],
+ nsmap=NS_DICT[key.upper() + "_NSMAP"],
+ )
+ else:
+ child = etree.SubElement(parent, candidates[-1])
+ child.text = text
+
+ if meta.get("attrib", None) is not None and opcode in ("delete", "merge"):
+ child.set(BASE_1_0 + meta.get("attrib"), opcode)
+
+ if len(meta_subtree) > 1:
+ for item in meta_subtree:
+ container_ele.append(item)
+
+ if sub_root == container_ele:
+ return None
+ else:
+ return sub_root
+
+
+def build_xml(container, xmap=None, params=None, opcode=None, namespace=None):
+ """
+ Builds netconf xml rpc document from meta-data
+
+ Args:
+ container: the YANG container within the namespace
+ xmap: meta-data map to build xml tree
+ params: Input params that feed xml tree values
+ opcode: operation to be performed (merge, delete etc.)
+
+ Example:
+ Module inputs:
+ banner_params = [{'banner':'motd', 'text':'Ansible banner example', 'state':'present'}]
+
+ Meta-data definition:
+ bannermap = collections.OrderedDict()
+ bannermap.update([
+ ('banner', {'xpath' : 'banners/banner', 'tag' : True, 'attrib' : "operation"}),
+ ('a:banner', {'xpath' : 'banner/banner-name'}),
+ ('a:text', {'xpath' : 'banner/banner-text', 'operation' : 'edit'})
+ ])
+
+ Fields:
+ key: exact match to the key in arg_spec for a parameter
+ (prefixes --> a: value fetched from arg_spec, m: value fetched from meta-data)
+ xpath: xpath of the element (based on YANG model)
+ tag: True if no text on the element
+ attrib: attribute to be embedded in the element (e.g. xc:operation="merge")
+ operation: if edit --> includes the element in edit_config() query else ignores for get() queries
+ value: if key is prefixed with "m:", value is required in meta-data
+
+ Output:
+ <config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <banners xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-infra-infra-cfg">
+ <banner xc:operation="merge">
+ <banner-name>motd</banner-name>
+ <banner-text>Ansible banner example</banner-text>
+ </banner>
+ </banners>
+ </config>
+ :returns: xml rpc document as a string
+ """
+ if not namespace:
+ namespace = container
+ if opcode == "filter":
+ root = etree.Element("filter", type="subtree")
+ elif opcode in ("delete", "merge"):
+ root = etree.Element("config", nsmap=NS_DICT["BASE_NSMAP"])
+
+ container_ele = etree.SubElement(root, container, nsmap=NS_DICT[namespace.upper() + "_NSMAP"])
+
+ if xmap is not None:
+ if params is None:
+ build_xml_subtree(container_ele, xmap, opcode=opcode)
+ else:
+ subtree_list = list()
+ for param in to_list(params):
+ subtree_ele = build_xml_subtree(container_ele, xmap, param=param, opcode=opcode)
+ if subtree_ele is not None:
+ subtree_list.append(subtree_ele)
+
+ for item in subtree_list:
+ container_ele.append(item)
+
+ return etree.tostring(root, encoding="unicode")
+
+
+def etree_find(root, node):
+ try:
+ root = etree.fromstring(to_bytes(root))
+ except (ValueError, etree.XMLSyntaxError):
+ pass
+
+ return root.find(".//%s" % node.strip())
+
+
+def etree_findall(root, node):
+ try:
+ root = etree.fromstring(to_bytes(root))
+ except (ValueError, etree.XMLSyntaxError):
+ pass
+
+ return root.findall(".//%s" % node.strip())
+
+
+def is_cliconf(module):
+ capabilities = get_capabilities(module)
+ return capabilities.get("network_api") == "cliconf"
+
+
+def is_netconf(module):
+ capabilities = get_capabilities(module)
+ network_api = capabilities.get("network_api")
+ if network_api == "netconf":
+ if not HAS_NCCLIENT:
+ module.fail_json(msg="ncclient is not installed")
+ if not HAS_XML:
+ module.fail_json(msg="lxml is not installed")
+ return True
+
+ return False
+
+
+def get_config_diff(module, running=None, candidate=None):
+ conn = get_connection(module)
+
+ if is_cliconf(module):
+ try:
+ response = conn.get("show commit changes diff")
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+ return response
+ elif is_netconf(module):
+ if running and candidate:
+ # ignore rpc-reply root node and diff from data element onwards
+ running_data_ele = etree.fromstring(to_bytes(running.strip())).getchildren()[0]
+ candidate_data_ele = etree.fromstring(to_bytes(candidate.strip())).getchildren()[0]
+
+ running_data = to_text(etree.tostring(running_data_ele)).strip()
+ candidate_data = to_text(etree.tostring(candidate_data_ele)).strip()
+ if running_data != candidate_data:
+ d = Differ()
+ diff = list(d.compare(running_data.splitlines(), candidate_data.splitlines()))
+ return "\n".join(diff).strip()
+
+ return None
+
+
+def discard_config(module):
+ conn = get_connection(module)
+ try:
+ if is_netconf(module):
+ conn.discard_changes(remove_ns=True)
+ else:
+ conn.discard_changes()
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+
+
+def commit_config(
+ module,
+ comment=None,
+ confirmed=False,
+ confirm_timeout=None,
+ persist=False,
+ check=False,
+ label=None,
+):
+ conn = get_connection(module)
+ reply = None
+ try:
+ if is_netconf(module):
+ if check:
+ reply = conn.validate(remove_ns=True)
+ else:
+ reply = conn.commit(
+ confirmed=confirmed,
+ timeout=confirm_timeout,
+ persist=persist,
+ remove_ns=True,
+ )
+ elif is_cliconf(module):
+ if check:
+ module.fail_json(
+ msg="Validate configuration is not supported with network_cli connection type",
+ )
+ else:
+ reply = conn.commit(comment=comment, label=label)
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+
+ return reply
+
+
+def get_oper(module, filter=None):
+ conn = get_connection(module)
+
+ if filter is not None:
+ try:
+ if is_netconf(module):
+ response = conn.get(filter=filter, remove_ns=True)
+ else:
+ response = conn.get(filter)
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+ else:
+ return None
+
+ return to_bytes(etree.tostring(response), errors="surrogate_then_replace").strip()
+
+
+def get_config(module, config_filter=None, source="running"):
+ conn = get_connection(module)
+
+ # Note: Does not cache config in favour of latest config on every get operation.
+ try:
+ if is_netconf(module):
+ out = to_xml(conn.get_config(source=source, filter=config_filter, remove_ns=True))
+ elif is_cliconf(module):
+ out = conn.get_config(source=source, flags=config_filter)
+ cfg = out.strip()
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+ return cfg
+
+
+def check_existing_commit_labels(conn, label):
+ out = conn.get(command="show configuration history detail | include %s" % label)
+ label_exist = re.search(label, out, re.M)
+ if label_exist:
+ return True
+ else:
+ return False
+
+
+def load_config(
+ module,
+ command_filter,
+ commit=False,
+ replace=False,
+ comment=None,
+ admin=False,
+ exclusive=False,
+ running=None,
+ nc_get_filter=None,
+ label=None,
+):
+
+ conn = get_connection(module)
+
+ diff = None
+ if is_netconf(module):
+ # FIXME: check for platform behaviour and restore this
+ # conn.lock(target = 'candidate')
+ # conn.discard_changes()
+
+ try:
+ for filter in to_list(command_filter):
+ conn.edit_config(config=filter, remove_ns=True)
+
+ candidate = get_config(module, source="candidate", config_filter=nc_get_filter)
+ diff = get_config_diff(module, running, candidate)
+
+ if commit and diff:
+ commit_config(module)
+ else:
+ discard_config(module)
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+ finally:
+ # conn.unlock(target = 'candidate')
+ pass
+
+ elif is_cliconf(module):
+ try:
+ if label:
+ old_label = check_existing_commit_labels(conn, label)
+ if old_label:
+ module.fail_json(
+ msg="commit label {%s} is already used for"
+ " an earlier commit, please choose a different label"
+ " and rerun task" % label,
+ )
+
+ response = conn.edit_config(
+ candidate=command_filter,
+ commit=commit,
+ admin=admin,
+ exclusive=exclusive,
+ replace=replace,
+ comment=comment,
+ label=label,
+ )
+ if module._diff:
+ diff = response.get("diff")
+
+ # Overwrite the default diff by the IOS XR commit diff.
+ # See plugins/cliconf/iosxr.py for this key set: show_commit_config_diff
+ diff = response.get("show_commit_config_diff")
+
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+
+ return diff
+
+
+def run_commands(module, commands, check_rc=True):
+ connection = get_connection(module)
+ try:
+ return connection.run_commands(commands=commands, check_rc=check_rc)
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc))
+
+
+def copy_file(module, src, dst, proto="scp"):
+ conn = get_connection(module)
+ try:
+ conn.copy_file(source=src, destination=dst, proto=proto)
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+
+
+def get_file(module, src, dst, proto="scp"):
+ conn = get_connection(module)
+ try:
+ conn.get_file(source=src, destination=dst, proto=proto)
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+
+
+# A list of commands like {end-set, end-policy, ...} are part of configuration
+# block like { prefix-set, as-path-set , ... } but they are not indented properly
+# to be included with their parent. sanitize_config will add indentation to
+# end-* commands so they are included with their parents
+def sanitize_config(config, force_diff_prefix=None):
+ conf_lines = config.split("\n")
+ for regex in CONFIG_MISPLACED_CHILDREN:
+ for index, line in enumerate(conf_lines):
+ m = regex.search(line)
+ if m and m.group(0):
+ if force_diff_prefix:
+ conf_lines[index] = " " + m.group(0) + force_diff_prefix
+ else:
+ conf_lines[index] = " " + m.group(0)
+ conf = ("\n").join(conf_lines)
+ return conf
+
+
+def mask_config_blocks_from_diff(config, candidate, force_diff_prefix):
+ conf_lines = config.split("\n")
+ candidate_lines = candidate.split("\n")
+
+ for regex in CONFIG_BLOCKS_FORCED_IN_DIFF:
+ block_index_start_end = []
+ start_index = None
+ for index, line in enumerate(candidate_lines):
+ startre = regex["start"].search(line)
+ if startre and startre.group(0):
+ start_index = index
+ else:
+ endre = regex["end"].search(line)
+ if endre and endre.group(0) and start_index:
+ end_index = index
+ new_block = True
+ for prev_start, prev_end in block_index_start_end:
+ if start_index == prev_start:
+ # This might be end-set of another regex
+ # otherwise we would be having new start
+ new_block = False
+ break
+ if new_block and end_index:
+ block_index_start_end.append((start_index, end_index))
+
+ for start, end in block_index_start_end:
+ diff = False
+ if candidate_lines[start] in conf_lines:
+ run_conf_start_index = conf_lines.index(candidate_lines[start])
+ else:
+ diff = False
+ continue
+ for i in range(start, end + 1):
+ if conf_lines[run_conf_start_index] == candidate_lines[i]:
+ run_conf_start_index = run_conf_start_index + 1
+ else:
+ diff = True
+ break
+ if diff:
+ run_conf_start_index = conf_lines.index(candidate_lines[start])
+ for i in range(start, end + 1):
+ conf_lines[run_conf_start_index] = (
+ conf_lines[run_conf_start_index] + force_diff_prefix
+ )
+ run_conf_start_index = run_conf_start_index + 1
+
+ conf = ("\n").join(conf_lines)
+ return conf
+
+
+def get_os_version(module):
+ connection = get_connection(module)
+ if connection.get_device_info():
+ os_version = connection.get_device_info()["network_os_version"]
+ return os_version
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/__init__.py
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/providers/cli/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/__init__.py
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/providers/cli/config/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/__init__.py
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/providers/cli/config/bgp/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/__init__.py
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
new file mode 100644
index 00000000..0d539340
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/address_family.py
@@ -0,0 +1,133 @@
+#
+# (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
new file mode 100644
index 00000000..29e4a1d2
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/neighbors.py
@@ -0,0 +1,136 @@
+#
+# (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
new file mode 100644
index 00000000..bd2c08ae
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/cli/config/bgp/process.py
@@ -0,0 +1,121 @@
+#
+# (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
new file mode 100644
index 00000000..afb9b9e7
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/module.py
@@ -0,0 +1,71 @@
+#
+# (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
new file mode 100644
index 00000000..94220ffa
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/providers/providers.py
@@ -0,0 +1,127 @@
+#
+# (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/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/acl_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/acl_interfaces.py
new file mode 100644
index 00000000..c2cf4f90
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/acl_interfaces.py
@@ -0,0 +1,64 @@
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+import re
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.network_template import (
+ NetworkTemplate,
+)
+
+
+class Acl_interfacesTemplate(NetworkTemplate):
+ def __init__(self, lines=None):
+ super(Acl_interfacesTemplate, self).__init__(lines=lines, tmplt=self)
+
+ # fmt: off
+ PARSERS = [
+ {
+ 'name': 'interface',
+ 'getval': re.compile(
+ r'''
+ ^interface
+ \s(preconfigure)*\s*
+ (?P<name>\S+)$''', re.VERBOSE,
+ ),
+ 'setval': 'interface {{ name }}',
+ 'result': {
+ '{{ name }}': {
+ 'name': '{{ name }}',
+ 'access_groups': {},
+ },
+ },
+ 'shared': True,
+ },
+ {
+ "name": "access_groups",
+ "getval": re.compile(
+ r"""
+ \s+(?P<afi>ipv4|ipv6)
+ \saccess-group\s(?P<acl_name>\S+)
+ \s(?P<direction>\S+)$
+ """,
+ re.VERBOSE,
+ ),
+ "setval": "{{ afi }} access-group {{ name }} {{ 'egress' if direction == 'out' else 'ingress' }}",
+ "result": {
+ "{{ name }}": {
+ "access_groups": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "acls": [
+ {
+ "name": "{{ acl_name }}",
+ "direction": "{{ 'in' if direction == 'ingress' else 'out' }}",
+ },
+ ],
+ },
+ },
+ },
+ },
+ },
+ ]
+ # fmt: on
diff --git a/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
new file mode 100644
index 00000000..a1d9bfda
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_address_family.py
@@ -0,0 +1,1182 @@
+# -*- 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_aggregate_address(aggaddr):
+ cmd = "aggregate-address {value}"
+
+ if aggaddr.get("as_set"):
+ cmd += " as-set"
+ if aggaddr.get("as_confed_set"):
+ cmd += " as-confed-set"
+ if aggaddr.get("summary_only"):
+ cmd += " summary-only"
+ if aggaddr.get("route_policy"):
+ cmd += " route-policy {route_policy}"
+
+ return cmd.format(**aggaddr)
+
+
+def _tmpl_allocate_label(config_data):
+ if "allocate_label" in config_data:
+ command = "allocate-label"
+ if "all" in config_data["allocate_label"]:
+ command += " all"
+
+ if "route_policy" in config_data["allocate_label"]:
+ command += " route-policy {route_policy}".format(**config_data["route_policy"])
+
+ return command
+
+
+def _tmpl_bgp_origin_as_validation(config_data):
+ origin_as_conf = config_data.get("bgp", {}).get("origin_as", {}).get("validation")
+ if origin_as_conf:
+ command = []
+ if "disable" in origin_as_conf:
+ command.append("bgp origin-as validation disable")
+ if "ibgp" in origin_as_conf.get("signal", {}):
+ command.append("bgp origin-as validation signal ibgp")
+
+ return command
+
+
+def _tmpl_bgp_dampening(config_data):
+ dampening_conf = config_data.get("bgp", {}).get("dampening", {})
+ if dampening_conf:
+ command = "bgp dampening"
+ if "value" in dampening_conf:
+ command += " " + str(dampening_conf["value"])
+ if "route_policy" in dampening_conf:
+ command += " route-policy " + dampening_conf["route_policy"]
+
+ return command
+
+
+def _tmpl_maximum_paths_ibgp(config_data):
+
+ ibgp_conf = config_data.get("maximum_paths", {}).get("ibgp", {})
+ if ibgp_conf:
+ command = "maximum-paths ibgp"
+ if "max_path_value" in ibgp_conf:
+ command += " " + str(ibgp_conf["max_path_value"])
+ if "order_igp_metric" in ibgp_conf:
+ command += " order igp-metric"
+ elif "selective_order_igp_metric" in ibgp_conf:
+ command += " selective order igp-metric"
+ elif "set" in ibgp_conf.get("unequal_cost", {}):
+ command += " unequal-cost"
+ if "order_igp_metric" in ibgp_conf.get("unequal_cost", {}):
+ command += " order igp-metric"
+ elif "selective_order_igp_metric" in ibgp_conf.get(
+ "unequal_cost",
+ {},
+ ):
+ command += " selective order igp-metric"
+ return command
+
+
+def _tmpl_maximum_paths_ebgp(config_data):
+
+ ebgp_conf = config_data.get("maximum_paths", {}).get("ebgp", {})
+ if ebgp_conf:
+ command = "maximum-paths ebgp"
+ if "max_path_value" in ebgp_conf:
+ command += " " + str(ebgp_conf["max_path_value"])
+ if "order_igp_metric" in ebgp_conf:
+ command += " order igp-metric"
+ elif "selective_order_igp_metric" in ebgp_conf:
+ command += " selective order igp-metric"
+ return command
+
+
+def _tmpl_maximum_paths_eibgp(config_data):
+
+ eibgp_conf = config_data.get("maximum_paths", {}).get("eibgp", {})
+ if eibgp_conf:
+ command = "maximum-paths ebgp"
+ if "max_path_value" in eibgp_conf:
+ command += " " + str(eibgp_conf["max_path_value"])
+ if "order_igp_metric" in eibgp_conf:
+ command += " order igp-metric"
+ elif "selective_order_igp_metric" in eibgp_conf:
+ command += " selective order igp-metric"
+ return command
+
+
+def _tmpl_network(config_data):
+ cmd = "network {network}"
+ if config_data.get("backdoor_route_policy"):
+ cmd += " backdoor-route-policy {backdoor-route-policy}"
+ if config_data.get("route_policy"):
+ cmd += " route-policy {route_policy}"
+ return cmd.format(**config_data)
+
+
+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"],
+ )
+ commands.append(command)
+ if "trigger_delay_critical" in nexthop_conf:
+ command = "nexthop trigger-delay critical " + str(
+ nexthop_conf["trigger_delay_non_critical"],
+ )
+ commands.append(command)
+ if "trigger_delay_non_critical" in nexthop_conf:
+ command = "nexthop trigger-delay non-critical " + str(
+ nexthop_conf["trigger_delay_non_critical"],
+ )
+ commands.append(command)
+ if "route_policy" in nexthop_conf:
+ command += " route-policy " + nexthop_conf["route_policy"]
+
+ return commands
+
+
+def _tmpl_optimal_route(config_data):
+ orr_conf = config_data.get("optimal_route_reflection", {})
+ if orr_conf:
+ command = "optimal-route-reflection"
+ if "group_name" in orr_conf:
+ command += " " + str(orr_conf["value"])
+ if "primary_address" in orr_conf:
+ command += " " + orr_conf["primary_address"]
+ if "secondary_address" in orr_conf:
+ command += " " + orr_conf["secondary_address"]
+ return command
+
+
+def _tmpl_update(config_data):
+ update_conf = config_data.get("update", {})
+ update_wait = config_data.get("update", {}).get("wait_install")
+ update_limit = config_data.get("update", {}).get("limit", {})
+ commands = []
+ if update_conf:
+ if update_wait:
+ command = "update wait-install"
+ commands.append(command)
+ if "address_family" in update_limit:
+ command = "update limit address-family " + str(
+ update_limit["address_family"],
+ )
+ commands.append(command)
+ if "sub_group" in update_limit:
+ if "ibgp" in update_limit["sub_group"]:
+ command = "update limit sub-group ibgp " + str(
+ update_limit["sub_group"]["ibgp"],
+ )
+ commands.append(command)
+ if "ebgp" in update_limit["sub_group"]:
+ command = "update limit sub-group ebgp " + str(
+ update_limit["sub_group"]["ebgp"],
+ )
+ commands.append(command)
+ return commands
+
+
+def _tmplt_redistribute(redis):
+ command = "redistribute {protocol}".format(**redis)
+ if redis.get("id"):
+ command += " {id}".format(**redis)
+ if redis.get("metric"):
+ command += " metric {metric}".format(**redis)
+ if redis.get("level"):
+ command += " level {level}".format(**redis)
+ if redis.get("internal"):
+ command += " internal"
+ if redis.get("external"):
+ command += " external"
+ if redis.get("nssa_external"):
+ command += " nssa-external"
+ if redis.get("external_ospf"):
+ command += " external {external_ospf}".format(**redis)
+ if redis.get("route_policy"):
+ command += " route-policy {route_policy}".format(**redis)
+ return command
+
+
+def _tmpl_vrf_all(config_data):
+ conf = config_data.get("vrf_all", {})
+ commands = []
+ if conf:
+ if "source_rt_import_policy" in conf:
+ commands.append("vrf all source rt import-policy")
+ if "label_mode" in conf:
+ command = "vrf all label mode"
+ if "per_ce" in conf.get("label_mode"):
+ command += " per-ce"
+ elif "per_vrf" in conf.get("label_mode"):
+ command += " per-vrf"
+ elif "route_policy" in conf.get("label_mode"):
+ command += " route-policy " + conf["route_policy"]
+ if "table_policy" in conf:
+ command = "vrf all table-policy " + conf["table_policy"]
+ commands.append(command)
+ return command
+
+
+def _tmpl_wt(config_data):
+ conf = config_data.get("weight", "")
+ if conf:
+ command = "weight"
+ if "reset_on_import" in conf:
+ command += " reset-on-import"
+ elif "reset_on_import_disable" in conf:
+ command += " reset-on-import disable"
+ return command
+
+
+def _tmpl_label_mode(conf):
+ if "label_mode" in conf:
+ command = "vrf all label mode"
+ if "per_ce" in conf.get("label_mode"):
+ command += " per-ce"
+ elif "per_vrf" in conf.get("label_mode"):
+ command += " per-vrf"
+ elif "per_prefix" in conf.get("label_mode"):
+ command += " per-prefix"
+ elif "route_policy" in conf.get("label_mode"):
+ command += " route-policy " + conf["route_policy"]
+ return command
+
+
+class Bgp_address_familyTemplate(NetworkTemplate):
+ def __init__(self, lines=None):
+ super(Bgp_address_familyTemplate, self).__init__(
+ lines=lines,
+ tmplt=self,
+ )
+
+ # fmt: off
+ PARSERS = [
+ {
+ "name": "router",
+ "getval": re.compile(
+ r"""
+ ^router\s
+ bgp
+ \s(?P<as_num>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "router bgp {{ as_number }}",
+ "result": {"as_number": "{{ as_num }}"},
+ "shared": True,
+ },
+ {
+ "name": "vrf",
+ "getval": re.compile(
+ r"""
+ \s+vrf
+ \s(?P<vrf>\b(?!all\b)\S+)$""",
+ re.VERBOSE,
+ ),
+ "setval": "vrf {{ vrf }}",
+ "result": {
+ },
+ "shared": True,
+ },
+ {
+ "name": "address_family",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\b(?!all\b)\S+))?
+ (?P<address_family>\s+address-family\s(?P<afi>\S+)\s(?P<safi>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "address-family {{ afi}} {{safi}}",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "afi": "{{ afi}}",
+ "safi": "{{safi}}",
+ "vrf": "{{ vrf }}",
+ },
+ },
+ },
+ "shared": True,
+ },
+ {
+ "name": "advertise_best_external",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+advertise\s(?P<abe>best-external)
+ $""", re.VERBOSE,
+ ),
+ "setval": "advertise best-external",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "advertise_best_external": "{{True if abe is defined}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "allocate_label",
+ "getval": re.compile(
+ r"""
+ \s+allocate-label\s(?P<all>all)
+ (\sroute-policy\s(?P<route_policy>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_allocate_label,
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "allocate_label": {
+ "all": "{{True if all is defined}}",
+ "route_policy": "{{route_policy}}",
+ },
+ },
+ },
+ },
+ },
+
+ {
+ "name": "aggregate_address",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+aggregate-address\s(?P<value>\S+)
+ (\sas-set(?P<as_set>))?
+ (\sas-confed-set(?P<as_confed_set>))?
+ (\ssummary-only(?P<summery_only>))?
+ (\sroute-policy\s(?P<route_policy>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmplt_aggregate_address,
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "aggregate_address": [
+ {
+ "as_set": "{{True if as_set is defined}}",
+ "as_confed_set": "{{True if as_confed_set is defined}}",
+ "summary_only": "{{True if summery_only is defined}}",
+ "value": "{{value}}",
+ "route_policy": "{{route_policy}}",
+ },
+ ],
+ },
+ },
+ },
+
+ },
+ {
+ "name": "additional_paths",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+additional-paths\s(?P<value>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "additional-paths {{additional_paths}}",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "additional_paths": "{{value}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "as_path_loopcheck_out_disable",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+as-path-loopcheck\sout(?P<value>\sdisable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "as-path-loopcheck out disable",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "as_path_loopcheck_out_disable": "{{True if value is defined }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_attribute_download",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+bgp\s(?P<value>attribute-download)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp attribute-download",
+ "compval": "bgp.attribute_download",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d()}}': {
+ "bgp": {
+ "attribute_download": "{{True if value is defined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_bestpath_origin_as_use",
+ "getval": re.compile(
+ r"""
+ \s+bgp\sbestpath\s(?P<origin_as>origin-as\suse\svalidity)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp bestpath origin-as use validity",
+ "compval": "bgp.bestpath.origin_as.use",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "bgp": {
+ "bestpath": {"origin_as": {"use": {"validity": "{{True if origin_as is defined }}"}}},
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_bestpath_origin_as_allow",
+ "getval": re.compile(
+ r"""
+ \s+bgp\sbestpath\s(?P<origin_as>origin-as\sallow\sinvalid)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp bestpath origin-as allow invalid",
+ "compval": "bgp.bestpath.origin_as.allow",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "bgp": {
+ "bestpath": {
+ "origin_as": {"allow": {"invalid": "{{True if origin_as is defined }}"}},
+ },
+ },
+ },
+ },
+ },
+
+ },
+ {
+ "name": "bgp_reflection_disable",
+ "getval": re.compile(
+ r"""
+ \s+bgp\sclient-to-client
+ \sreflection
+ \sdisable(?P<disable>)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp client-to-client reflection disable",
+ "compval": "bgp.client_to_client.reflection.disable",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "bgp": {
+ "client_to_client": {
+ "reflection": {
+ "disable": "{{True if disable is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_client_to_client_reflection_cluster_id",
+ "getval": re.compile(
+ r"""
+ \s+bgp\sclient-to-client
+ (\sreflection\scluster-id(?P<cs_id>\s\d+))?
+ (\sdisable(?P<disable>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp client-to-clinet reflection cluster-id "
+ "{{ bgp.client_to_client.reflection.cluster_id }} disable",
+ "compval": "bgp.client_to_client.reflection.cluster_id",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "bgp": {
+ "client_to_client": {
+ "reflection": {
+ "cluster_id_disable": {
+ "cluster_id": "{{cs_id}}",
+ "disable": "{{True if disable is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_dampening",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+bgp\sdampening(?P<set>)
+ (\s(?P<value>\d+))?
+ (\sroute-policy\s(?P<route_policy>)\S+)?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_bgp_dampening,
+ "compval": "bgp.dampening",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "bgp": {
+ "dampening": {
+ "set": "{{True if set is defined}}",
+ "value": "{{value}}",
+ "route_policy": "{{route_policy}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_label_delay",
+ "getval": re.compile(
+ r"""
+ \s+bgp\slabel-delay(?P<set>)
+ (\s(?P<first>\S+))
+ (\s(?P<second>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp label-delay {{ bgp.label_delay.delay_second_parts}} {{ bgp.label_delay.delay_ms_parts}}",
+ "compval": "bgp.label_delay",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "bgp": {
+ "label_delay": {
+ "delay_second_parts": "{{first}}",
+ "delay_ms_parts": "{{second}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_import_delay",
+ "getval": re.compile(
+ r"""
+ \s+bgp\simport-delay(?P<set>)
+ (\s(?P<first>\S+))
+ (\s(?P<second>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp import-delay {{ bgp.import_delay.delay_second_parts}} {{ bgp.import_delay.delay_ms_parts}}",
+ "compval": "bgp.import_delay",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "bgp": {
+ "import_delay": {
+ "delay_second_parts": "{{first}}",
+ "delay_ms_parts": "{{second}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_origin_as_validation",
+ "getval": re.compile(
+ r"""
+ \s+bgp\sorigin-as\svalidation
+ (\s(?P<disable>disable))?
+ (\ssignal\s(?P<signal>ibgp))?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_bgp_origin_as_validation,
+ "compval": "bgp.origin_as.validation",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "bgp": {
+ "origin_as": {
+ "validation": {
+ "disable": "{{True if disable is defined}}",
+ "signal": {
+ "ibgp": "{{True if signal is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_scan_time",
+ "getval": re.compile(
+ r"""
+ \s+bgp\sscan-time\s(?P<scan_time>\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp scan-time {{bgp.scan_time}}",
+ "compval": "bgp.scan_time",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "bgp": {
+ "scan_time": "{{scan_time}}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "default_martian_check_disable",
+ "getval": re.compile(
+ r"""
+ \s+default-martian-check(?P<disable>\sdisable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "default-martian-check disable",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "default_martian_check_disable": "{{ True if disable is defined}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "distance",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+distance\sbgp
+ (\s(?P<external>\d+))?
+ (\s(?P<internal>\d+))?
+ (\s(?P<local>\d+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "distnace bgp {{distnace.bgp.routes_external_to_as}} "
+ "{{distnace.bgp.routes_internal_to_as}} {{distnace.bgp.local_routes}}",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "distance": {
+ "routes_external_to_as": "{{external}}",
+ "routes_internal_to_as": "{{internal}}",
+ "local_routes": "{{local}}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "dynamic_med",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+dynamic-med\sinterval\s(?P<dynamic_med>\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "dynamic-med interval {{dynamic_med}}",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "dynamic_med": "{{ dynamic_med}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "maximum_paths_ibgp",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+maximum-paths\sibgp\s((?P<max_path_value>\S+))?
+ (\sorder\sigp-metric(?P<order_igp_metric>))?
+ (\sselective\sorder\sigp-metric(?P<selective_order_igp_metric>))?
+ (\sunequal-cost(?P<unequal_cost>))?
+ (\sorder\sigp-metric(?P<order_igp_metric1>))?
+ (\sselective\sorder\sigp-metric(?P<selective_order_igp_metric1>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_maximum_paths_ibgp,
+ "compval": "maximum_paths.ibgp",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "maximum_paths": {
+ "ibgp": {
+ "max_path_value": "{{ max_path_value }}",
+ "order_igp_metric": "{{ True if order_igp_metric is defined}}",
+ "selective_order_igp_metric":
+ "{{ True if selective_order_igp_metric is defined}}",
+ "unequal_cost": {
+ "set": "{{ True if unequal_cost is defined}}",
+ "order_igp_metric": "{{ True if order_igp_metric1 is defined}}",
+ "selective_order_igp_metric": "{{ True if selective_order_igp_metric1 is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "maximum_paths_ebgp",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+maximum-paths\sebgp\s((?P<max_path_value>\S+))?
+ (\sorder\sigp-metric(?P<order_igp_metric>))?
+ (\sselective\sorder\sigp-metric(?P<selective_order_igp_metric>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_maximum_paths_ebgp,
+ "compval": "maximum_paths.ebgp",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "maximum_paths": {
+ "ebgp": {
+ "max_path_value": "{{ max_path_value }}",
+ "order_igp_metric": "{{ True if order_igp_metric is defined}}",
+ "selective_order_igp_metric":
+ "{{ True if selective_order_igp_metric is defined}}",
+
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "maximum_paths_eibgp",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+maximum-paths\seibgp\s((?P<max_path_value>\S+))?
+ (\sorder\sigp-metric(?P<order_igp_metric>))?
+ (\sselective\sorder\sigp-metric(?P<selective_order_igp_metric>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_maximum_paths_eibgp,
+ "compval": "maximum_paths.eibgp",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "maximum_paths": {
+ "eibgp": {
+ "max_path_value": "{{ max_path_value }}",
+ "order_igp_metric": "{{ True if order_igp_metric is defined}}",
+ "selective_order_igp_metric":
+ "{{ True if selective_order_igp_metric is defined}}",
+
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "networks",
+ "getval": re.compile(
+ r"""
+ \s+network\s(?P<value>\S+)
+ (\sbackdoor-route-policy\s(?P<backdoor_route_policy>)\S+)?
+ (\sroute-policy\s(?P<route_policy>)\S+)?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_network,
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "networks": [
+ {
+ "backdoor_route_policy": "{{backdoor_route_policy}}",
+ "network": "{{value}}",
+ "route_policy": "{{route_policy}}",
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ "name": "nexthop",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+nexthop
+ (\sresolution\sprefix-length\sminimum\s(?P<value>\d+))?
+ (\strigger-delay\scritical\s(?P<trigger_delay_critical>\d+))?
+ (\strigger-delay\snon-critical\s(?P<trigger_delay_non_critical>\d+))?
+ (\sroute-policy\s(?P<route_policy>)\S+)?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_nexthop,
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "nexthop": {
+ "trigger_delay_critical": "{{trigger_delay_critical}}",
+ "trigger_delay_non_critical": "{{trigger_delay_non_critical}}",
+ "resolution_prefix_length_minimum": "{{value}}",
+ "route_policy": "{{route_policy}}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "optimal_route_reflection",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+optimal-route-reflection
+ (\s(?P<value>\S+))?
+ (\s(?P<primary>\S+))?
+ (\s(?P<secondary>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_optimal_route,
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "optimal_route_reflection": {
+ "group_name": "{{value}}",
+ "primary_address": "{{primary}}",
+ "secondary_address": "{{secondary}}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "permanent_network_route_policy",
+ "getval": re.compile(
+ r"""
+ \s+permanent-network\s(?P<value>route_policy\S+)?
+ $""", re.VERBOSE,
+ ),
+ "setval": "permanent-network route-policy {{permanent_network_route_policy}}",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "permanent_network_route_policy": "{{route_policy}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "retain_local_label",
+ "getval": re.compile(
+ r"""
+ \s+retain\slocal-label\s(?P<value>\d+)?
+ $""", re.VERBOSE,
+ ),
+ "setval": "retain local-label {{retain_local_label}}",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "retain_local_label": "{{value}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "update",
+ "getval": re.compile(
+ r"""
+ \s+update
+ (\slimit)?
+ (\ssub-group)?
+ (\sibgp\s(?P<ibgp>\d+))?
+ (\sebgp\s(?P<ebgp>\d+))?
+ (\saddress-family\s(?P<af>\d+))?
+ (\swait-install(?P<wait>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_update,
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "update": {
+ "wait_install": "{{True if wait is defined}}",
+ "limit": {
+ "sub_group": {
+ "ibgp": "{{ibgp}}",
+ "ebgp": "{{ebgp}}",
+ },
+ "address_family": "{{af}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "redistribute",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+redistribute
+ \s(?P<protocol>\S+)
+ (\s(?P<id>\S+))?
+ (\smetric\s(?P<metric>\d+))?
+ (\slevel\s(?P<level>\S+))?
+ (\sinternal(?P<internal>))?
+ (\sexternal(?P<external>)(\s(?P<ospf_external>\S+))?)?
+ (\snssa-external(?P<nssa_external>))?
+ (\sroute-policy\s(?P<route_policy>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmplt_redistribute,
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "redistribute": [
+ {
+ "protocol": "{{protocol}}",
+ "id": "{{id}}",
+ "route_policy": "{{route_policy}}",
+ "metric": "{{metric}}",
+ "internal": "{{True if internal is defined}}",
+ "external": "{{True if external is defined}}",
+ "level": "{{level}}",
+ "ospf_external": "{{ospf_external}}",
+ "nssa_external": "{{True if nssa_external is defined}}",
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ "name": "inter_as_install",
+ "getval": re.compile(
+ r"""
+ \s+inter-as\s(?P<inter_as>install)
+ $""", re.VERBOSE,
+ ),
+ "setval": "inter-as install",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "inter_as_install": "{{True if inter_as is defined}}",
+ },
+ },
+ },
+
+ },
+ {
+ "name": "segmented_multicast",
+ "getval": re.compile(
+ r"""
+ \s+(?P<segmented_multicast>segmented-multicast)
+ $""", re.VERBOSE,
+ ),
+ "setval": "segmented-multicast",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "segmented_multicast": "{{True if segmented_multicast is defined}}",
+ },
+ },
+ },
+
+ },
+ {
+ "name": "global_table_multicast",
+ "getval": re.compile(
+ r"""
+ \s+(?P<global_table_multicast>global-table-multicast)
+ $""", re.VERBOSE,
+ ),
+ "setval": "global-table-multicast",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "global_table_multicast": "{{True if global_table_multicast is defined}}",
+ },
+ },
+ },
+
+ },
+ {
+ "name": "table_policy",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ (\s+table-policy\s(?P<table_policy>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "table-policy {{table_policy}}",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "table_policy": "{{table_policy}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "vrf_all_conf",
+ "getval": re.compile(
+ r"""
+ \s+vrf\sall
+ (\s+source\srt(?P<source_rt_import_policy>\simport-policy))?
+ (\s+table-policy\s(?P<table_policy>\S+))?
+ (\s+label\smode)?
+ (\s+(?P<per_ce>per-ce))?
+ (\s+(?P<per_vrf>per-vrf))?
+ (\s+route_policy\s(?P<route_policy>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_vrf_all,
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "vrf_all_conf": {
+ "source_rt_import_policy": "{{ True if source_rt_import_policy is defined}}",
+ "table_policy": "{{table_policy}}",
+ "label_mode": {
+ "per_ce": "{{ True if per_ce is defined}}",
+ "per_vrf": "{{True if per_vrf is defined}}",
+ "route_policy": "{{route_policy}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "weight",
+ "getval": re.compile(
+ r"""
+ \s+weight
+ (\sreset-on-import\sdisable(?P<reset_on_import_disable>))?
+ (\sreset-on-import(?P<reset_on_import>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_wt,
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "weight": {
+ "reset_on_import_disable": "{{ True if reset_on_import_disable is defined}}",
+ "reset_on_import": "{{ True if reset_on_import is defined}}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "route_target_download",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+route-target\s(?P<value>download)
+ $""", re.VERBOSE,
+ ),
+ "setval": "route-target download",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "route_target_download": "{{True if value is defined }}",
+
+ },
+ },
+ },
+ },
+ {
+ "name": "mvpn_single_forwarder_selection_all",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+mvpn\ssingle-forwarder-selection\s(?P<value>all)
+ $""", re.VERBOSE,
+ ),
+ "setval": "mvpn single-forwarder-selection all",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "mvpn_single_forwarder_selection_all": "{{True if value is defined }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "mvpn_single_forwarder_selection_highest_ip_address",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+mvpn\ssingle-forwarder-selection\s(?P<value>highest-ip-address)
+ $""", re.VERBOSE,
+ ),
+ "setval": "mvpn single-forwarder-selection highest-ip-address",
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "mvpn_single_forwarder_selection_highest_ip_address": "{{True if value is defined }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "label_mode",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+label\smode\s(?P<per_ce>per-ce)?(?P<per_prefix>per-prefix)?
+ (?P<per_vrf>per-vrf)?
+ (?P<rr>route-policy\s\S+)?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_label_mode,
+ "result": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi + "_vrf_" + vrf|d() }}': {
+ "label_mode": {
+ "per_ce": "{{ True if per_ce is defined}}",
+ "per_prefix": "{{ True if per_prefix is defined}}",
+ "per_vrf": "{{ True if per_vrf is defined}}",
+ "route_policy": "{{ route_policy}}",
+ },
+ },
+ },
+ },
+ },
+ ]
+ # fmt: on
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
new file mode 100644
index 00000000..f584d13f
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_global.py
@@ -0,0 +1,3133 @@
+# -*- 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_global 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_confederation_peers(config_data):
+ cmds = []
+ base_cmd = "bgp confederation peers "
+ peers = config_data.get("bgp", {}).get("confederation", {}).get("peers")
+ if peers:
+ for peer in peers:
+ cmds.append(base_cmd + str(peer))
+ return cmds
+
+
+class Bgp_globalTemplate(NetworkTemplate):
+ def __init__(self, lines=None, module=None):
+ super(Bgp_globalTemplate, 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": "vrf",
+ "getval": re.compile(
+ r"""
+ \s+vrf
+ \s(?P<vrf>\S+)$""",
+ re.VERBOSE,
+ ),
+ "setval": "vrf {{ vrf }}",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "vrf": "{{ vrf }}",
+ },
+ },
+ },
+ "shared": True,
+ },
+
+ {
+ "name": "bfd_minimum_interval",
+ "getval": re.compile(
+ r"""
+ \s+bfd\s(?P<min_interval>minimum-interval\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "compval": "bfd.minimum_interval",
+ "setval": "bfd minimum-interval {{bfd.minimum_interval}}",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bfd": {"minimum_interval": "{{ min_interval.split(" ")[1] }}"},
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd_multiplier",
+ "getval": re.compile(
+ r"""
+ \s+bfd\s(?P<multiplier>multiplier\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bfd multiplier {{bfd.multiplier}}",
+ "compval": "bfd.multiplier",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bfd": {"multiplier": "{{multiplier.split(" ")[1]}}"},
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_as_path_loopcheck",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<loopcheck>as-path-loopcheck)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp as-path-loopcheck",
+ "compval": "bgp.as_path_loopcheck",
+ "result": {
+ "bgp": {
+ "as_path_loopcheck": "{{ True if loopcheck is defined }}",
+ },
+ },
+ },
+ {
+ "name": "bgp_auto_policy_soft_reset",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<auto_policy_soft_reset_disable>auto-policy-soft-reset\sdisable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp auto-policy-soft-reset disable",
+ "compval": "bgp.auto_policy_soft_reset",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "auto_policy_soft_reset": {
+ "disable": "{{True if auto_policy_soft_reset_disable is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_cluster_id",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<cluster_id>cluster-id\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp cluster-id {{bgp.cluster_id}}",
+ "compval": "bgp.cluster_id",
+ "result": {
+ "bgp": {
+ "cluster_id": "{{cluster_id.split(" ")[1]}}",
+ },
+ },
+ },
+ {
+ "name": "bgp_default_local_preference",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<default_local_pref>default\slocal-preference\s\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp default local-preference {{bgp.default.local_preference}}",
+ "compval": "bgp.default.local-preference",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "default": {
+ "local_preference": "{{default_local_pref.split(" ")[2] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_enforce_first_as_disable",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<enforce_first_as_disable>enforce-first-as\sdisable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp enforce-first-as disable",
+ "compval": "bgp.enforce_first_as.disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "enforce_first_as": {
+ "disable": "{{ True if enforce_first_as_disable is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_fast_external_fallover_disable",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<fast_external_fallover_disable>fast-external-fallover\sdisable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp fast-external-fallover disable",
+ "compval": "bgp.fast_external_fallover.disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "fast_external_fallover": {
+ "disable": "{{True if fast_external_fallover_disable is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_install_diversion",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<install_diversion>install\sdiversion)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp install diversion",
+ "compval": "bgp.install.diversion",
+ "result": {
+ "bgp": {
+ "install": {
+ "diversion": "{{True if install_diversion is defined}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_max_neighbors",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<max_neighbors>maximum\sneighbor\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp maximum neighbor {{bgp.maximum.neighbor}}",
+ "compval": "bgp.maximum.neighbor",
+ "result": {
+ "bgp": {
+ "maximum":
+ {
+ "neighbor": "{{max_neighbors.split(" ")[2] }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_redistribute_internal",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<redistribute_internal>redistribute-internal)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp redistribute-internal",
+ "compval": "bgp.redistribute_internal",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "redistribute_internal": "{{ True if redistribute_internal is defined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_router_id",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<router_id>router-id\s\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp router-id {{ bgp.router_id }}",
+ "compval": "bgp.router_id",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "router_id": "{{router_id.split(" ")[1]}}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_scan_time",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<scan_time>scan-time\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp scan-time {{ bgp.scan_time }}",
+ "compval": "bgp.scan_time",
+ "result": {
+ "bgp": {
+ "scan_time": "{{scan_time.split(" ")[1]}}",
+ },
+ },
+ },
+ {
+ "name": "bgp_unsafe_ebgp_policy",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<unsafe_ebgp_policy>unsafe-ebgp-policy)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp unsafe-ebgp-policy",
+ "compval": "bgp.unsafe_ebgp_policy",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "unsafe_ebgp_policy": "{{ True if unsafe_ebgp_policy is defined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_update_delay",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<update_delay>update-delay\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp update-delay {{ bgp.update_delay }}",
+ "compval": "bgp.update_delay",
+ "result": {
+ "bgp": {
+ "update_delay": "{{update_delay.split(" ")[1]}}",
+
+ },
+ },
+ },
+ {
+ "name": "bgp_bestpath_aigp",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<bestpath_aigp_ignore>bestpath\saigp\signore)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp bestpath aigp ignore",
+ "compval": "bgp.bestpath.aigp.ignore",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "bestpath": {
+ "aigp": {
+ "ignore": "{{ True if bestpath_aigp_ignore is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_bestpath_as_path_ignore",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<as_path_ignore>bestpath\sas-path\signore)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp bestpath as-path ignore",
+ "compval": "bgp.bestpath.as_path.ignore",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "bestpath": {
+ "as_path": {
+ "ignore": "{{ True if as_path_ignore is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_bestpath_as_path_multipath_relax",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<as_path_multipath_relax>bestpath\sas-path\smultipath-relax)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp bestpath as-path multipath-relax",
+ "compval": "bgp.bestpath.as_path.multipath_relax",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "bestpath": {
+ "as_path": {
+ "multipath_relax": "{{ True if as_path_multipath_relax is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_bestpath_med_always",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<always>bestpath\smed\salways)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp bestpath med always",
+ "compval": "bgp.bestpath.med.always",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "bestpath": {
+ "med": {
+ "always": "{{ True if always is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_bestpath_med_confed",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<confed>bestpath\smed\sconfed)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp bestpath med confed",
+ "compval": "bgp.bestpath.med.confed",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "bestpath": {
+ "med": {
+ "confed": "{{ True if confed is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_bestpath_med_missing_as_worst",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<missing_as_worst>bestpath\smed\smissing-as-worst)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp bestpath med missing-as-worst)",
+ "compval": "bgp.bestpath.med.missing_as_worst",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "bestpath": {
+ "med": {
+ "missing_as_worst": "{{ True if missing_as_worst is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_bestpath_compare_routerid",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<compare_routerid>bestpath\scompare-routerid)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp bestpath compare-routerid",
+ "compval": "bgp.bestpath.compare_routerid",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "bestpath": {
+ "compare_routerid": "{{ True if compare_routerid is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_bestpath_cost_community_ignore",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<cost_community_ignore>bestpath\scost-community\signore)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp bestpath cost-community ignore",
+ "compval": "bgp.bestpath.cost_community.ignore",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "bestpath": {
+ "cost_community": {
+ "ignore": "{{ True if cost_community_ignore is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_bestpath_origin_as_use",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<origin_as_use>bestpath\sorigin-as\suse\svalidity)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp bestpath origin-as use validity",
+ "compval": "bgp.bestpath.origin_as.use.validity",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "bestpath": {
+ "origin_as": {
+ "use": {"validity": "{{ True if origin_as_use is defined }}"},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_bestpath_origin_as_allow",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<origin_as_allow>bestpath\sorigin-as\sallow\sinvalid)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp bestpath origin-as allow invalid",
+ "compval": "bgp.bestpath.origin_as.allow.invalid",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "bestpath": {
+ "origin_as":
+ {
+ "allow": {"invalid": "{{ True if origin_as_allow is defined }}"},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_confederation_identifier",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<confederation_identifier>confederation\sidentifier\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp confederation identifier {{ bgp.confederation.identifier}}",
+ "compval": "bgp.confederation.identifier",
+ "result": {
+ "bgp": {
+ "confederation": {
+ "identifier": "{{confederation_identifier.split(" ")[2]}}",
+ },
+
+ },
+ },
+ },
+ {
+ "name": "bgp_confederation_peers",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<confederation_peers>confederation\speers\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmplt_confederation_peers,
+ "compval": "bgp.confederation.peers",
+ "result": {
+ "bgp": {
+ "confederation": {
+ "peers": {
+ "peer" + "{{confederation_peers.split(" ")[2]}}": "{{confederation_peers.split(" ")[2]}}",
+ },
+ },
+
+ },
+ },
+ },
+ {
+ "name": "bgp_graceful_restart_set",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<graceful_restart_set>graceful-restart)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp graceful-restart",
+ "compval": "bgp.graceful_restart.set",
+ "result": {
+ "bgp": {
+ "graceful_restart": {
+ "set": "{{ True if graceful_restart_set is defined }}",
+ },
+
+ },
+ },
+ },
+ {
+ "name": "bgp_graceful_restart_graceful_reset",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<graceful_restart_graceful_reset>graceful-restart\sgraceful-reset)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp graceful-restart graceful-reset",
+ "compval": "bgp.graceful_restart.graceful_reset",
+ "result": {
+ "bgp": {
+ "graceful_restart": {
+ "graceful_reset": "{{ True if graceful_restart_graceful_reset is defined}}",
+ },
+
+ },
+ },
+ },
+ {
+ "name": "bgp_graceful_restart_restart_time",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<graceful_restart_restart_time>graceful-restart\srestart-time\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp graceful-restart restart-time {{ bgp.graceful_restart.restart_time}}",
+ "compval": "bgp.graceful_restart.restart_time",
+ "result": {
+ "bgp": {
+ "graceful_restart": {
+ "restart_time": "{{ graceful_restart_restart_time.split(" ")[2] }}",
+ },
+
+ },
+ },
+ },
+ {
+ "name": "bgp_graceful_restart_purge_time",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<graceful_restart_purge_time>graceful-restart\spurge-time\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp graceful-restart purge-time {{ bgp.graceful_restart.purge_time}}",
+ "compval": "bgp.graceful_restart.purge_time",
+ "result": {
+ "bgp": {
+ "graceful_restart": {
+ "purge_time": "{{ graceful_restart_purge_time.split(" ")[2] }}",
+ },
+
+ },
+ },
+ },
+ {
+ "name": "bgp_graceful_restart_stalepath_time",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<graceful_restart_stalepath_time>graceful-restart\sstalepath-time\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp graceful-restart stalepath-time {{ bgp.graceful_restart.stalepath_time}}",
+ "compval": "bgp.graceful_restart.stalepath_time",
+ "result": {
+ "bgp": {
+ "graceful_restart": {
+ "stalepath_time": "{{ graceful_restart_stalepath_time.split(" ")[2] }}",
+ },
+
+ },
+ },
+ },
+ {
+ "name": "bgp_log_message",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<log_message>log\smessage\sdisable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp log message disable",
+ "compval": "bgp.log_message.message.disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "log": {
+ "log_message": {"disable": "{{ True if log_message is defined }}"},
+ },
+ },
+ },
+
+ },
+ },
+ },
+ {
+ "name": "bgp_log_neighbor_changes_detail",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<log_neighbor_changes_detail>log\sneighbor\schanges\sdetail)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp log neighbor changes detail",
+ "compval": "bgp.log.neighbor.changes.detail",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "log": {
+ "neighbor": {
+ "changes": {
+ "detail": "{{True if log_neighbor_changes_detail is defined }}",
+ },
+ },
+ },
+ },
+ },
+
+ },
+ },
+ },
+ {
+ "name": "bgp_log_neighbor_changes_disable",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<log_neighbor_changes_disable>log\sneighbor\schanges\sdisable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp log neighbor changes disable",
+ "compval": "bgp.log.neighbor.changes.disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "log": {
+ "neighbor": {
+ "changes": {
+ "disable":
+ "{{ True if log_neighbor_changes_disable is defined }}",
+ },
+ },
+ },
+ },
+ },
+
+ },
+ },
+ },
+ {
+ "name": "bgp_multipath_as_path_ignore_onwards",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<multipath>multipath\sas-path\signore\sonwards)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp multipath as-path ignore onwards",
+ "compval": "bgp.multipath.as_path.ignore.onwards",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "bgp": {
+ "multipath": {
+ "as_path": {"ignore": {"onwards": "{{ not not multipath}}"}},
+ },
+ },
+ },
+
+ },
+ },
+ },
+ {
+ "name": "bgp_origin_as_validation_disable",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<origin_as_validation_disable>origin-as\svalidation\sdisable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp origin-as validation disable",
+ "compval": "bgp.origin_as.validation.disable",
+ "result": {
+ "bgp": {
+ "origin_as": {
+ "validation": {"disable": "{{ not not origin_as_validation_disable}}"},
+ },
+
+ },
+ },
+ },
+ {
+ "name": "bgp_origin_as_validation_signal_ibgp",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<origin_as_validation_signal_ibgp>origin-as\svalidation\ssignal\sibgp)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp origin-as validation signal ibgp",
+ "compval": "bgp.origin_as.validation.signal.ibgp",
+ "result": {
+ "bgp": {
+ "origin_as": {
+ "validation": {"signal": {"ibgp": "{{ not not origin_as_validation_signal_ibgp }}"}},
+ },
+
+ },
+ },
+ },
+ {
+ "name": "bgp_origin_as_validation_time_off",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<validation_time_off>origin-as\svalidation\stime\soff)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp origin-as validation time off",
+ "compval": "bgp.origin_as.validation.time.off",
+ "result": {
+ "bgp": {
+ "origin_as": {
+ "validation": {"time": {"time_off": "{{ not not validation_time_off }}"}},
+ },
+
+ },
+ },
+ },
+ {
+ "name": "bgp_origin_as_validation_time",
+ "getval": re.compile(
+ r"""
+ \s+bgp\s(?P<validation_time>origin-as\svalidation\stime\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bgp origin-as validation time {{ bgp.origin_as.validation.time.time_in_second }}",
+ "compval": "bgp.origin_as.validation.time.time_in_second",
+ "result": {
+ "bgp": {
+ "origin_as": {
+ "validation": {"time": {"time_in_second": "{{ validation_time.split(" ")[3] }}"}},
+ },
+
+ },
+ },
+ },
+
+ {
+ "name": "bgp_default_information_originate",
+ "getval": re.compile(
+ r"""
+ \s+default-information\s(?P<default_information_originate>originate)
+ $""", re.VERBOSE,
+ ),
+ "setval": "default-information originate",
+ "compval": "default_information.originate",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "default_information": {
+ "originate": "{{ not not default_information_originate }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_default_metric",
+ "getval": re.compile(
+ r"""
+ \s+default-metric\s(?P<default_metric>\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "default-metric {{default_metric}}",
+ "compval": "default_metric",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "default_metric": "{{ default_metric }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "bgp_graceful_maintenance",
+ "getval": re.compile(
+ r"""
+ \s+graceful-maintenance\sactivate\s(?P<graceful_maintenance>\S*)
+ $""", re.VERBOSE,
+ ),
+ "setval": "graceful_maintenance {{graceful_maintenance.activate}}",
+ "compval": "graceful_maintenance.activate",
+ "result": {
+ "graceful_maintenance": {"activate": "{{ graceful_maintenance }}"},
+ },
+ },
+ {
+ "name": "ibgp_policy_out_enforce_modifications",
+ "getval": re.compile(
+ r"""
+ \s+ibgp\spolicy\sout\s(?P<ibgp_policy_out>enforce-modifications)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ibgp policy out enforce-modifications",
+ "compval": "ibgp.policy.out.enforce_modifications",
+ "result": {
+ "ibgp": {"policy": {"out": {"enforce_modifications": "{{ not not ibgp_policy_out }}"}}},
+ },
+ },
+ {
+ "name": "mpls_activate_interface",
+ "getval": re.compile(
+ r"""
+ \s+mpls\sactivate\sinterface(?P<mpls_interface>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "mpls activate interface {{mpls.activate.interface}}",
+ "compval": "mpls.activate.interface",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "mpls": {"activate": {"interface": "{{ mpls_interface }}"}},
+ },
+ },
+ },
+ },
+ {
+ "name": "mvpn",
+ "getval": re.compile(
+ r"""
+ \s(?P<mvpn>mvpn)
+ $""", re.VERBOSE,
+ ),
+ "setval": "mvpn",
+ "compval": "mvpn",
+ "result": {
+ "mvpn": "{{ not not mvpn }}",
+ },
+ },
+ {
+ "name": "nsr_set",
+ "getval": re.compile(
+ r"""
+ \s(?P<nsr>nsr\s*)
+ $""", re.VERBOSE,
+ ),
+ "setval": "nsr",
+ "compval": "nsr.set",
+ "result": {
+ "nsr": {"set": "{{ not not nsr }}"},
+ },
+ },
+ {
+ "name": "nsr_disable",
+ "getval": re.compile(
+ r"""
+ \snsr\s(?P<nsr_disable>disable\s*)
+ $""", re.VERBOSE,
+ ),
+ "setval": "nsr disable",
+ "compval": "nsr.disable",
+ "result": {
+ "nsr": {"disable": "{{ not not nsr_disable }}"},
+ },
+ },
+ {
+ "name": "socket_receive_buffer_size",
+ "getval": re.compile(
+ r"""
+ \s+socket\s(?P<socket_rcv_buffer_size>receive-buffer-size\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "socket receive-buffer-size {{ socket.receive_buffer_size}}",
+ "compval": "socket.receive_buffer_size",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "socket": {"receive_buffer_size": "{{ socket_rcv_buffer_size.split(" ")[1] }}"},
+ },
+ },
+ },
+ },
+ {
+ "name": "socket_send_buffer_size",
+ "getval": re.compile(
+ r"""
+ \s+socket\s(?P<socket_send_buffer_size>send-buffer-size\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "socket send-buffer-size {{ socket.send_buffer_size}}",
+ "compval": "socket.send_buffer_size",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "socket": {"send_buffer_size": "{{ socket_send_buffer_size.split(" ")[1] }}"},
+ },
+ },
+ },
+ },
+ {
+ "name": "update_in_error_handling_basic_ebgp_disable",
+ "getval": re.compile(
+ r"""
+ \s+update\sin\serror-handling\sbasic\sebgp\s(?P<disable>disable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "update in error-handling basic ebgp disable",
+ "compval": "update.in.error_handling.basic.ebgp.disable",
+ "result": {
+ "update": {"in": {"error_handling": {"basic": {"ebgp": {"disable": "{{ not not disable }}"}}}}},
+ },
+ },
+ {
+ "name": "update_in_error_handling_basic_ibgp_disable",
+ "getval": re.compile(
+ r"""
+ \s+update\sin\serror-handling\sbasic\sibgp\s(?P<disable>disable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "update in error-handling basic ibgp disable",
+ "compval": "update.in.error_handling.basic.ibgp.disable",
+ "result": {
+ "update": {"in": {"error_handling": {"basic": {"ibgp": {"disable": "{{ not not disable }}"}}}}},
+ },
+ },
+ {
+ "name": "update_in_error_handling_extended_ebgp",
+ "getval": re.compile(
+ r"""
+ \s+update\sin\serror-handling\sextended\s(?P<extended_ebgp>ebgp)
+ $""", re.VERBOSE,
+ ),
+ "setval": "update in error-handling extended ebgp",
+ "compval": "update.in.error_handling.extended.ebgp",
+ "result": {
+ "update": {"in": {"error_handling": {"extended": {"ebgp": "{{ not not extended_ebgp}}"}}}},
+ },
+ },
+ {
+ "name": "update_in_error_handling_extended_ibgp",
+ "getval": re.compile(
+ r"""
+ \s+update\sin\serror-handling\sextended\s(?P<extended_ibgp>ibgp)
+ $""", re.VERBOSE,
+ ),
+ "setval": "update in error-handling extended ibgp",
+ "compval": "update.in.error_handling.extended.ibgp",
+ "result": {
+ "update": {"in": {"error_handling": {"extended": {"ibgp": "{{ not not extended_ibgp}}"}}}},
+ },
+ },
+ {
+ "name": "update_out_logging",
+ "getval": re.compile(
+ r"""
+ \s+update\sout\s(?P<update_out_logging>logging)
+ $""", re.VERBOSE,
+ ),
+ "setval": "update out logging",
+ "compval": "update.out.logging",
+ "result": {
+ "update": {"out": {"logging": "{{ not not update_out_logging}}"}},
+ },
+ },
+ {
+ "name": "update_limit",
+ "getval": re.compile(
+ r"""
+ \s+update\slimit\s(?P<update_limit>\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "update limit {{ update.limit }}",
+ "compval": "update.limit",
+ "result": {
+ "update": {"limit": "{{ update_limit}}"},
+ },
+ },
+ {
+ "name": "rpki_route_value",
+ "getval": re.compile(
+ r"""
+ \srpki
+ \sroute
+ \s(?P<value>\S+)
+ \smax
+ \s(?P<max>\d+)
+ \sorigin
+ \s(?P<origin>\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "rpki route {{ rpki.route.value }} max {{rpki.route.max }} "
+ "origin {{rpki.route.origin }}",
+ "compval": "rpki.route",
+ "result": {
+ "rpki": {
+ "route": {
+ "value": "{{value}}",
+ "origin": "{{origin}}",
+ "max": "{{max}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "rpki_server_name",
+ "getval": re.compile(
+ r"""
+ \srpki
+ \s(?P<value>server\s\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "rpki server {{ name }}",
+ "compval": "rpki.server.name",
+ "result": {
+ "rpki":
+ {
+ "servers": {"{{value.split(" ")[1]}}": {"name": "{{ value.split(" ")[1] }}"}},
+ },
+ },
+ },
+ {
+ "name": "rpki_server_purge_time",
+ "getval": re.compile(
+ r"""
+ \srpki
+ \s(?P<rpki_server>server\s\S+)
+ \s(?P<purge_time>purge-time\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "purge-time {{ purge_time }}",
+ "compval": "purge_time",
+ "result": {
+ "rpki":
+ {
+ "servers": {"{{rpki_server.split(" ")[1]}}": {"purge_time": "{{ purge_time.split(" ")[1] }}"}},
+ },
+ },
+ },
+ {
+ "name": "rpki_server_refresh_time",
+ "getval": re.compile(
+ r"""
+ \srpki
+ \s(?P<rpki_server>server\s\S+)
+ \s(?P<refresh_time>refresh-time\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "refresh-time {{ refresh_time.value }}",
+ "compval": "refresh_time.value",
+ "result": {
+ "rpki": {
+ "servers": {
+ "{{rpki_server.split(" ")[1]}}": {
+ "refresh_time": {
+ "value": "{{ refresh_time.split(" ")[1] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "rpki_server_refresh_time_off",
+ "getval": re.compile(
+ r"""
+ \srpki
+ \s(?P<rpki_server>server\s\S+)
+ \srefresh-time
+ \s(?P<refresh_time>off)
+ $""", re.VERBOSE,
+ ),
+ "setval": "refresh-time off",
+ "compval": "refresh_time.time_off",
+ "result": {
+ "rpki": {
+ "servers": {
+ "{{rpki_server.split(" ")[1] }}": {
+ "refresh_time": {
+ "time_off": "{{ True if refresh_time is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "rpki_server_response_time_off",
+ "getval": re.compile(
+ r"""
+ \srpki
+ \s(?P<rpki_server>server\s\S+)
+ \sresponse-time
+ \s(?P<response_time>off)
+ $""", re.VERBOSE,
+ ),
+ "setval": "response-time off",
+ "compval": "response_time.time_off",
+ "result": {
+ "rpki": {
+ "servers": {
+ "{{rpki_server.split(" ")[1]}}": {
+ "response_time": {
+ "time_off": "{{ True if response_time is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "rpki_server_response_time",
+ "getval": re.compile(
+ r"""
+ \srpki
+ \s(?P<rpki_server>\sserver\S+)
+ \s(?P<response_time>response-time\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "response-time {{ response_time.value }}",
+ "compval": "response_time.value",
+ "result": {
+ "rpki": {
+ "servers": {
+ "{{rpki_server.split(" ")[1]}}": {
+ "response_time": {
+ "value": "{{ response_time.split(" ")[1] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "rpki_server_shutdown",
+ "getval": re.compile(
+ r"""
+ \srpki
+ \s(?P<rpki_server>server\s\S+)
+ \s(?P<shutdown>shutdown)
+ $""", re.VERBOSE,
+ ),
+ "setval": "shutdown",
+ "compval": "shutdown",
+ "result": {
+ "rpki": {
+ "servers": {"{{rpki_server.split(" ")[1]}}": {"shutdown": "{{ True if shutdown is defined}}"}},
+ },
+ },
+ },
+ {
+ "name": "rpki_server_transport_ssh",
+ "getval": re.compile(
+ r"""
+ \srpki
+ \s(?P<rpki_server>server\s\S+)
+ \stransport
+ \sssh
+ \s(?P<ssh_port>port\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "transport ssh port {{ transport.ssh.port }}",
+ "compval": "transport.ssh.port",
+ "result": {
+ "rpki": {
+ "servers": {
+ "{{rpki_server.split(" ")[1]}}": {
+ "transport": {
+ "ssh": {
+ "port": "{{ ssh_port.split(" ")[1] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "rpki_server_transport_tcp",
+ "getval": re.compile(
+ r"""
+ \srpki
+ \s(?P<rpki_server>server\s\S+)
+ \stransport
+ \stcp
+ \s(?P<tcp_port>port\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "transport tcp port {{ transport.tcp.port }}",
+ "compval": "transport.tcp.port",
+ "result": {
+ "rpki": {
+ "servers": {
+ "{{rpki_server.split(" ")[1]}}": {
+ "transport": {
+ "tcp": {
+ "port": "{{ tcp_port.split(" ")[1] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_address",
+ "getval": re.compile(
+ r"""
+ \s+neighbor\s(?P<value>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "neighbor {{ neighbor_address }}",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{value}}":
+ {
+ "neighbor_address": "{{value}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "advertisement_interval",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<advertise_in>advertisement-interval\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "advertisement-interval {{ advertisement_interval }}",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "advertisement_interval": "{{ advertise_in.split(" ")[1] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd_fast_detect_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \sbfd
+ \sfast-detect
+ \s(?P<disable>disable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bfd fast-detect disable",
+ "compval": "bfd.fast_detect.disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "bfd": {
+ "fast_detect": {"disable": "{{ True if disable is defined }}"},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd_fast_detect_set",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \sbfd
+ \s(?P<fast_detect>fast-detect)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bfd fast-detect",
+ "compval": "bfd.fast_detect.set",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "bfd": {
+ "fast_detect": {"set": "{{ True if fast_detect is defined }}"},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd_fast_detect_strict_mode",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "bfd": {
+ "fast_detect": {"strict_mode": "{{ True if strict_mode is defined }}"},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd_nbr_multiplier",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \sbfd
+ \s(?P<multiplier>multiplier\s\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bfd multiplier {{ bfd.multiplier}}",
+ "compval": "bfd.multiplier",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}":
+ {
+ "bfd":
+ {
+ "multiplier": "{{multiplier.split(" ")[1]}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd_nbr_minimum_interval",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \sbfd
+ \s(?P<min_interval>minimum-interval\s\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bfd minimum-interval {{ bfd.minimum_interval}}",
+ "compval": "bfd.minimum_interval",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}":
+ {
+ "bfd":
+ {
+ "minimum_interval": "{{min_interval.split(" ")[1]}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bmp_activate",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \sbmp-activate
+ \s(?P<bmp_activate>server\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bmp-activate server {{bmp_activate.server}}",
+ "compval": "bmp_activate.serevr",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "bmp_activate": {"server": "{{ bmp_activate.split(" ")[1] }}"},
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_cluster_id",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<cluster_id>cluster-id\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "cluster-id {{ cluster_id }}",
+ "compval": "cluster_id",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {"cluster_id": "{{ cluster_id.split(" ")[1] }}"},
+ },
+ },
+ },
+
+ },
+ },
+ {
+ "name": "neighbor_description",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \sdescription\s(?P<description>.+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "description {{ description }}",
+ "compval": "description",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {"description": "{{ description }}"},
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "dmz_link_bandwidth",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<dmz_link_bandwidth>dmz-link-bandwidth)
+ $""", re.VERBOSE,
+ ),
+ "setval": "dmz-link-bandwidth",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}":
+ {
+ "dmz_link_bandwidth":
+ {
+ "set": "{{ True if dmz_link_bandwidth is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "dmz_link_bandwidth_inheritance_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "dmz_link_bandwidth":
+ {
+ "inheritance_disable": "{{ True if dmz_link_bandwidth is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "ebgp_multihop_value",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<ebgp_multihop>ebgp-multihop\s\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ebgp-multihop {{ ebgp_multihop.value}}",
+ "compval": "ebgp_multihop.value",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "ebgp_multihop": {
+ "value": "{{ ebgp_multihop.split(" ")[1] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "ebgp_multihop_mpls",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<ebgp_multihop>ebgp-multihop\s\S*\smpls)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ebgp-multihop mpls",
+ "compval": "ebgp_multihop.mpls",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "ebgp_multihop": {"mpls": "{{ True if ebgp_multihop is defined }}"},
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "ebgp_recv_extcommunity_dmz",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "ebgp_recv_extcommunity_dmz": {
+ "inheritance_disable": "{{ True if ebgp_recv_extcommunity_dmz is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "ebgp_recv_extcommunity_dmz_set",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "ebgp_recv_extcommunity_dmz": {
+ "set": "{{ True if ebgp_recv_extcommunity_dmz is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "ebgp_send_extcommunity_dmz",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "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+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "ebgp_send_extcommunity_dmz": {
+ "set": "{{ True if ebgp_send_extcommunity_dmz is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "ebgp_send_extcommunity_dmz_cumulatie",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "ebgp_send_extcommunity_dmz": {
+ "cumulatie": "{{ True if ebgp_send_extcommunity_dmz is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "egress_engineering",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<egress_engineering>egress-engineering\sinheritance-disable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "egress-engineering inheritance-disable ",
+ "compval": "egress_engineering.inheritance_disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "egress_engineering": {
+ "inheritance_disable": "{{ True if egress_engineering is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "egress_engineering_set",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<egress_engineering>egress-engineering)
+ $""", re.VERBOSE,
+ ),
+ "setval": "egress-engineering",
+ "compval": "egress_engineering.set",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "egress_engineering": {
+ "set": "{{ True if egress_engineering is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_enforce_first_as_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<enforce_first_as_disable>enforce-first-as\sdisable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "enforce-first-as disable",
+ "compval": "enforce_first_as.disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "enforce_first_as": {
+ "disable": "{{ True if enforce_first_as_disable is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_graceful_restart_restart_time",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "graceful_restart": {
+ "restart_time": "{{ graceful_restart_restart_time.split(" ")[2] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_graceful_restart_stalepath_time",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "graceful_restart": {
+ "stalepath_time": "{{ graceful_restart_stalepath_time.split(" ")[2] }}",
+ },
+ },
+ },
+ },
+
+ },
+ },
+ },
+ {
+ "name": "ignore_connected_check_set",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<ignore_connected_check>ignore-connected-check)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ignore-connected-check",
+ "compval": "ignore_connected_check.set",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "ignore_connected_check": {
+ "set": "{{ True if ignore_connected_check is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "ignore_connected_check",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "ignore_connected_check": {
+ "inheritance_disable": "{{ True if ignore_connected_check is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "keychain",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<keychain>keychain\sinheritance-disable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "keychain inheritance-disable ",
+ "compval": "keychain.inheritance_disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "keychain": {
+ "inheritance_disable": "{{ True if keychain is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "keychain_name",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<keychain>keychain\s\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "keychain {{ name }}",
+ "compval": "keychain.name",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "keychain": {
+ "name": "{{ keychain.split(" ")[1] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "remote_as",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<remote_as>remote-as\s\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "remote-as {{ remote_as }}",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "remote_as": "{{ remote_as.split(" ")[1] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "local_as_inheritance_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<local_as>local-as\sinheritance-disable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "local-as inheritance-disable",
+ "compval": "local_as.inheritance_disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "local_as": {
+ "inheritance_disable": "{{ True if local_as is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "local_as",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<local_as>local-as\s\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "local-as {{ local_as.value }}",
+ "compval": "local_as.value",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "local_as": {
+ "value": "{{ local_as.split(" ")[1] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "local_address",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \slocal
+ \s(?P<local>address\sinheritance-disable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "local address inheritance-disable",
+ "compval": "local.address.inheritance_disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "local": {
+ "address": {
+ "inheritance_disable": "{{ True if local is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "local",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \slocal
+ \s(?P<local>address\s\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "local address {{ local.address.ipv4_address }}",
+ "compval": "local.address.ipv4_address",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "local": {
+ "address": {
+ "ipv4_address": "{{ local.split(" ")[1] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "origin_as",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \sorigin-as
+ \s(?P<origin_as>validation\sdisable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "origin-as validation disable",
+ "compval": "origin-as.validation.disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "origin_as": {
+ "validation": {
+ "disable": "{{ True if origin_as is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "receive_buffer_size",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<receive_buffer_size>receive-buffer-size\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "receive-buffer-size {{ receive_buffer_size }}",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "receive_buffer_size": "{{ receive_buffer_size.split(" ")[1] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "send_buffer_size",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<send_buffer_size>send-buffer-size\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "send-buffer-size {{ send_buffer_size }}",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "send_buffer_size": "{{ send_buffer_size.split(" ")[1] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "session_open_mode",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "session_open_mode": "{{ session_open_mode.split(" ")[1] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_shutdown",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<shutdown>shutdown)
+ $""", re.VERBOSE,
+ ),
+ "setval": "shutdown",
+ "compval": "shutdown",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "shutdown": {
+ "set": "{{ True if shutdown is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_shutdown_inheritance_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<shutdown>shutdown\sinheritance_disable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "shutdown inheritance-disable",
+ "compval": "shutdown.inheritance_disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "shutdown": {"inheritance_disable": "{{ True if shutdown is defined }}"},
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "dscp",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<dscp>dscp\s\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "dscp {{ dscp }}",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "dscp": "{{ dscp.split(" ")[1] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_tcp_mss_inheritance_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<tcp_mss_disable>tcp\smss\sinheritance-disable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "tcp mss inheritance-disable",
+ "compval": "tcp.mss.inheritance_disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "tcp": {
+ "mss": {
+ "inheritance_disable": "{{ True if tcp_mss_disable is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_tcp_mss",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<tcp_mss>tcp\smss\s\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "tcp mss {{ tcp.mss.value }}",
+ "compval": "tcp.mss.value",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "tcp": {
+ "mss": {
+ "value": "{{ tcp_mss.split(" ")[2] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_timers_keepalive",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "timers": {
+ "keepalive_time": "{{ timers_keepalive_time.split(" ")[1] }}",
+ "holdtime": "{{ timers_holdtime.split(" ")[0] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "update_source",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \supdate-source
+ \s(?P<update_source>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "update-source {{ update_source}}",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "update_source": "{{ update_source}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_ttl_security_inheritance_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<ttl_security>ttl-security\sinheritance-disable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ttl-security inheritance-disable",
+ "compval": "ttl_security.inheritance_disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "ttl_security": {
+ "inheritance_disable": "{{ True if ttl_security is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_ttl_security",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<ttl_security>ttl-security)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ttl-security",
+ "compval": "ttl_security.set",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "ttl_security": {
+ "set": "{{ True if ttl_security is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_graceful_maintenance_set",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<graceful_maintenance>graceful-maintenance)
+ $""", re.VERBOSE,
+ ),
+ "setval": "graceful-maintenance",
+ "compval": "graceful_maintenance.set",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "graceful_maintenance": {
+ "set": "{{ True if graceful_maintenance is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_graceful_maintenance_activate",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<graceful_maintenance>graceful-maintenance\sactivate)
+ $""", re.VERBOSE,
+ ),
+ "setval": "graceful-maintenance activate",
+ "compval": "graceful_maintenance.activate.set",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "graceful_maintenance": {
+ "activate": {"set": "{{ True if graceful_maintenance is defined }}"},
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+
+ {
+ "name": "neighbor_graceful_maintenance_activate_inheritance_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<graceful_maintenance>activate\sinheritance-disable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "graceful-maintenance activate inheritance-disable",
+ "compval": "graceful_maintenance.activate.inheritance_disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "graceful_maintenance": {
+ "activate": {
+ "inheritance_disable": "{{ True if graceful_maintenance is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_graceful_maintenance_as_prepends",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "graceful_maintenance": {
+ "as_prepends": {
+ "inheritance_disable": "{{ True if as_prepends is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_graceful_maintenance_local_preference_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "graceful_maintenance": {
+ "local_preference": {
+ "inheritance_disable": "{{ True if local_preference is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_graceful_maintenance_local_preference",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "graceful_maintenance": {
+ "local_preference": {
+ "value": "{{ local_preference.split(" ")[1]}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_graceful_maintenance_as_prepends_value",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "graceful_maintenance": {
+ "as_prepends": {
+ "value": "{{ as_prepends.split(" ")[1]}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_capability_additional_paths_send",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \scapability
+ \sadditional-paths
+ \s(?P<additional_paths_send>send)
+ $""", re.VERBOSE,
+ ),
+ "setval": "capability additional-paths send",
+ "compval": "capability.additional_paths.send.set",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "capability": {
+ "additional_paths": {
+ "send": {
+ "set": "{{ True if additional_paths_send is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_capability_additional_paths_send_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "capability": {
+ "additional_paths": {
+ "send": {
+ "disable": "{{ True if additional_paths_send is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_capability_additional_paths_rcv",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \scapability
+ \sadditional-paths
+ \s(?P<additional_paths_receive>receive)
+ $""", re.VERBOSE,
+ ),
+ "setval": "capability additional-paths receive",
+ "compval": "capability.additional_paths.receive.set",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "capability": {
+ "additional_paths": {
+ "receive": {
+ "set": "{{ True if additional_paths_receive is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_capability_additional_paths_rcv_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "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+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "capability": {
+ "suppress": {
+ "four_byte_AS": {
+ "set": "{{ True if suppress_4_byte_as is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_capability_suppress_all",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \scapability
+ \ssuppress
+ \s(?P<all>all)
+ $""", re.VERBOSE,
+ ),
+ "setval": "capability suppress all",
+ "compval": "capability.suppress.all.set",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "capability": {
+ "suppress": {
+ "all": {
+ "set": "{{ True if all is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_capability_suppress_all_inheritance_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \scapability
+ \ssuppress
+ \s(?P<all>all\sinheritance-disable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "capability suppress all inheritance-disable",
+ "compval": "capability.suppress.all.inheritance_disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "capability": {
+ "suppress": {
+ "all": {
+ "inheritance_disable": "{{ True if all is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+
+ {
+ "name": "neighbor_log_message_in_value",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "log": {
+ "log_message": {
+ "in": {
+ "value": "{{ value.split(" ")[1] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_log_message_in_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \slog
+ \smessage
+ \s(?P<disable>in\sdisable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "log message in disable",
+ "compval": "log.log_message.in.disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "log": {
+ "log_message": {
+ "in": {
+ "disable": "{{ True if disable is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_log_message_in_inheritance_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "log": {
+ "log_message": {
+ "in": {
+ "inheritance_disable": "{{ True if disable is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_log_message_out_value",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "log": {
+ "log_message": {
+ "out": {
+ "value": "{{ value.split(" ")[1] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_log_message_out_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \slog
+ \smessage
+ \s(?P<disable>out\sdisable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "log message out disable",
+ "compval": "log.log_message.out.disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "log": {
+ "log_message": {
+ "out": {
+ "disable": "{{ True if disable is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_log_message_out_inheritance_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "log": {
+ "log_message": {
+ "out": {
+ "inheritance_disable": "{{ True if disable is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_update_in_filtering_attribute_filter_group",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "update": {
+ "in": {
+ "filtering": {
+ "attribute_filter": {
+ "group": "{{ attribute_filter_group.split(" ")[2] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_update_in_filtering_logging_disable",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \s(?P<logging_disable>logging\sdisable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "update in filtering logging disable",
+ "compval": "update.in.filtering.logging.disable",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "update": {
+ "in": {
+ "filtering": {
+ "logging": {
+ "disable": "{{True if logging_disable is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "neighbor_update_in_filtering_message_buffers",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "update": {
+ "in": {
+ "filtering": {
+ "update_message": {
+ "buffers": "{{ message_buffers.split(" ")[2] }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "rd_auto",
+ "getval": re.compile(
+ r"""
+ \s+rd(?P<rd_auto>\sauto)
+ $""", re.VERBOSE,
+ ),
+ "setval": "rd auto",
+ "compval": "rd.auto",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "rd": {
+ "auto": "{{True if rd_auto is defined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "timers_keepalive",
+ "getval": re.compile(
+ r"""
+ \s+timers\sbgp\s(?P<timers_keepalive_time>\d+)\s(?P<hold_time>\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "timers bgp {{ timers.keepalive_time}} {{ timers.holdtime}}",
+ "compval": "timers",
+ "result": {
+ "vrfs": {
+ '{{ "vrf_" + vrf|d() }}': {
+ "timers": {
+ "keepalive_time": "{{ timers_keepalive_time }}",
+ "holdtime": "{{ hold_time}}",
+ },
+ },
+ },
+ },
+ },
+
+ ]
+ # fmt: on
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_neighbor_address_family.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_neighbor_address_family.py
new file mode 100644
index 00000000..3d12e882
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/bgp_neighbor_address_family.py
@@ -0,0 +1,1038 @@
+# -*- 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_neighbor_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 _tmpl_aigp(config_data):
+ conf = config_data.get("aigp", {})
+ commands = []
+ if conf:
+ if "set" in conf:
+ commands.append("aigp")
+ if "disable" in conf:
+ commands.append("aigp disable")
+ if "send_cost_community_disable" in conf:
+ commands.append("aigp send cost-community disable")
+ if "send_med" in conf and "set" in conf.get("send_med", {}):
+ commands.append("aigp send med")
+ if "send_med" in conf and "disable" in conf.get("send_med", {}):
+ commands.append("aigp send med disable")
+ return commands
+
+
+def _tmpl_validation(config_data):
+ conf = config_data.get("validation", {})
+ command = ""
+ if conf:
+ if "set" in conf:
+ command = "validation"
+ if "disable" in conf:
+ command = "validation disbale"
+ if "redirect" in conf:
+ command = "validation redirect"
+ return command
+
+
+def _tmpl_next_hop_unchanged(config_data):
+ conf = config_data.get("next_hop_unchanged", {})
+ command = ""
+ if conf:
+ if "set" in conf:
+ command = "next-hop-unchanged"
+ if "inheritance_disable" in conf:
+ command += "next-hop-unchanged inheritance-disable"
+ if "multipath" in conf:
+ command = "next-hop-unchanged multipath"
+ return command
+
+
+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 = " "
+ if "set" in conf:
+ command = "remove-private-AS"
+ if "inbound" in conf:
+ command += " inbound"
+ if "entire_aspath" in conf:
+ command += " entire-aspath"
+ elif "inheritance_disable" in conf:
+ command = "remove-private-AS inheritance-disable"
+ return command
+
+
+def _tmpl_default_originate(config_data):
+ conf = config_data.get("default_originate", {})
+ command = ""
+ if conf:
+ if "set" in conf:
+ command = "default-originate"
+ if "inheritance_disable" in conf:
+ command = "default-originate inheritance-disable"
+ if "route_policy" in conf:
+ command = "default-originate route_policy " + conf["route_policy"]
+ return command
+
+
+class Bgp_neighbor_address_familyTemplate(NetworkTemplate):
+ def __init__(self, lines=None):
+ super(Bgp_neighbor_address_familyTemplate, self).__init__(
+ lines=lines,
+ tmplt=self,
+ )
+
+ # 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+vrf\s(?P<vrf>\S+))?
+ (\s+(?P<nbr_address>neighbor\s\S+))
+ (?P<address_family>\s+address-family\s(?P<afi>\S+)\s(?P<safi>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "address-family {{ afi}} {{safi}}",
+ "result": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "neighbor_address": "{{nbr_address.split(" ")[1]}}",
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi }}': {
+ "afi": "{{ afi}}",
+ "safi": "{{safi}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "shared": True,
+ },
+ {
+ "name": "aigp",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \saigp(?P<aigp>)
+ (\sdisable(?P<disable>))?
+ (\ssend\smed(?P<send_med>))?
+ (\ssend\smed\sdisable(?P<send_disable>))?
+ (\ssend\scost-community\sdisable(?P<cc_disable>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_aigp,
+ "result": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi }}': {
+ "aigp": {
+ "set": "{{ True if aigp is defined }}",
+ "disable": "{{ True if disable is defined}}",
+ "send_med": {
+ "set": "{{ True if send_med is defined }}",
+ "disable": "{{ True if send_disable is defined}}",
+ },
+ "send_cost_community_disable": "{{True if cc_disable is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "allowas_in",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "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+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "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+(?P<nbr_address>neighbor\s\S+)
+ \sbestpath\sorigin-as\sallow\sinvalid(?P<invalid>)
+ $""", re.VERBOSE,
+ ),
+ "setval": "bestpath origin-as allow invalid",
+ "result": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "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+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \scapability\sorf\sprefix\s(?P<capability_orf_prefix>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "capability orf prefix {{capability_orf_prefix }}",
+ "result": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi }}': {
+ "capability_orf_prefix": "{{capability_orf_prefix}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "default_originate",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \sdefault-originate(?P<default_originate>)
+ (\sroute-policy\s(?P<route_policy>\S+))?
+ (\sinheritance-disable(?P<inheritance_disable>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_default_originate,
+ "result": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi}}': {
+ "default_originate": {
+ "set": "{{True if default_originate is defined}}",
+ "route_policy": "{{route_policy}}",
+ "inheritance_disable": "{{True if inheritance_disable is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "long_lived_graceful_restart_capable",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "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+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "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+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "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+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \smultipath(?P<multipath>)
+ $""", re.VERBOSE,
+ ),
+ "setval": "multipath",
+ "result": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi }}': {
+ "multipath": "{{True if multipath is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "next_hop_self",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "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",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \snext-hop-unchanged(?P<next_hop_unchanged>)
+ (\sinheritance-disable(?P<inheritance_disable>))?
+ (\smultipath(?P<multipath>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_next_hop_unchanged,
+ "result": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi}}': {
+ "next_hop_unchanged": {
+ "set": "{{True if next_hop_self is defined }}",
+ "inheritance_disable": "{{True if inheritance_disable is defined}}",
+ "multipath": "{{True if multipath is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "optimal_route_reflection_group_name",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \soptimal-route-reflection\s(?P<group_name>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "optimal-route-reflection {{optimal_route_reflection_group_name}}",
+ "result": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi }}': {
+ "optimal_route_reflection_group_name": "{{ group_name}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "orf_route_policy",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \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": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi }}': {
+ "orf_route_policy": "{{orf_rr}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "origin_as",
+ "getval": re.compile(
+ r"""
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \sorigin-as\svalidation\sdisable(?P<origin_as>)
+ $""", re.VERBOSE,
+ ),
+ "setval": "origin-as validation disable",
+ "result": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi }}': {
+ "origin_as": {
+ "validation": {
+ "disable": "{{True if origin_as is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "route_policy.inbound",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \sroute-policy\s(?P<route_policy>\S+)
+ \sin
+ $""", re.VERBOSE,
+ ),
+ "setval": "route-policy {{route_policy.inbound}} in",
+ "result": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi }}': {
+ "route_policy": {
+ "inbound": "{{route_policy}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "route_policy.outbound",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \sroute-policy\s(?P<route_policy>\S+)
+ \sout
+ $""", re.VERBOSE,
+ ),
+ "setval": "route-policy {{route_policy.outbound}} out",
+ "result": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi }}': {
+ "route_policy": {
+ "outbound": "{{route_policy}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "remove_private_AS",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi }}': {
+ "remove_private_AS": {
+ "set": "{{True if remove_private_AS is defined}}",
+ "inbound": "{{True if inbound is defined}}",
+ "entire_aspath": "{{True if entire_aspath is defined}}",
+ "inheritance_disable": "{{True if inheritance_disable is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "route_reflector_client",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "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+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "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+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "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+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "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+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\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": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "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+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \ssoft-reconfiguration
+ \sinbound(?P<inbound>)
+ (\salways(?P<always>))?
+ (\sinheritance-disable(?P<inheritance_disable>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_soft_reconfiguration,
+ "result": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "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+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \sweight\s(?P<weight>\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "weight {{weight}}",
+ "result": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi }}': {
+ "weight": "{{weight}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "validation",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \svalidation(?P<validation>)
+ (\sredirect(?P<redirect>))?
+ (\sdisable(?P<disable>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": _tmpl_validation,
+ "result": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi }}': {
+ "validation": {
+ "set": "{{True if validation is defined}}",
+ "redirect": "{{True if redirect is defined }}",
+ "disable": "{{ True if disable is defined}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "site_of_origin",
+ "getval": re.compile(
+ r"""
+ (\s+vrf\s(?P<vrf>\S+))?
+ \s+(?P<nbr_address>neighbor\s\S+)
+ \ssite-of-origin\s(?P<site_of_origin>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "site-of-origin {{site_of_origin}}",
+ "result": {
+ "vrfs": {
+ "{{ 'vrf_' + vrf|d() }}": {
+ "vrf": "{{ vrf }}",
+ "neighbors": {
+ "{{nbr_address.split(" ")[1]}}": {
+ "address_family": {
+ '{{"address_family_" + afi + "_" + safi }}': {
+ "site_of_origin": "{{site_of_origin}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ ]
+ # fmt: on
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/hostname.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/hostname.py
new file mode 100644
index 00000000..1be361fe
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/hostname.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+# Copyright 2022 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 Hostname 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,
+)
+
+
+class HostnameTemplate(NetworkTemplate):
+ def __init__(self, lines=None, module=None):
+ super(HostnameTemplate, self).__init__(
+ lines=lines,
+ tmplt=self,
+ module=module,
+ )
+
+ # fmt: off
+ PARSERS = [
+ {
+ "name": "hostname",
+ "getval": re.compile(
+ r"""
+ ^hostname\s(?P<hostname>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "hostname {{ hostname }}",
+ "result": {
+ "hostname": "{{ hostname }}",
+ },
+ },
+ ]
+ # fmt: on
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/logging_global.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/logging_global.py
new file mode 100644
index 00000000..90d78d77
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/logging_global.py
@@ -0,0 +1,866 @@
+# -*- 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 Logging_global 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_host(config_data):
+ command = "logging"
+ if config_data.get("host"):
+ command += " {host}".format(host=config_data["host"])
+ if config_data.get("vrf"):
+ command += " vrf {vrf}".format(vrf=config_data["vrf"])
+ if config_data.get("severity"):
+ command += " severity {severity}".format(
+ severity=config_data["severity"],
+ )
+ if config_data.get("port"):
+ command += " port {port}".format(port=config_data["port"])
+ return command
+
+
+def tmplt_correlator_rule(config_data):
+ commands = []
+ rule_name = config_data.get("rule_name")
+ rule_type = config_data.get("rule_type")
+ base_command = "logging correlator rule {rule_name} type {rule_type}".format(
+ rule_type=rule_type,
+ rule_name=rule_name,
+ )
+ if config_data.get("timeout"):
+ commands.append(
+ "{base_command} timeout {timeout}".format(
+ timeout=config_data["timeout"],
+ base_command=base_command,
+ ),
+ )
+ if config_data.get("timeout_rootcause"):
+ commands.append(
+ "{base_command} timeout-rootcause {timeout}".format(
+ timeout=config_data["timeout_rootcause"],
+ base_command=base_command,
+ ),
+ )
+ if config_data.get("reissue_nonbistate"):
+ commands.append(
+ "{base_command} reissue-nonbistate".format(
+ base_command=base_command,
+ ),
+ )
+ if config_data.get("reparent"):
+ commands.append(
+ "{base_command} reparent".format(base_command=base_command),
+ )
+ if config_data.get("context_correlation"):
+ commands.append(
+ "{base_command} context-correlation".format(
+ base_command=base_command,
+ ),
+ )
+ return commands
+
+
+def tmplt_correlator_ruleset(config_data):
+ command = "logging correlator ruleset"
+ if config_data.get("name"):
+ command += " {name}".format(name=config_data["name"])
+ if config_data.get("rulename"):
+ command += " rulename {rulename}".format(
+ rulename=config_data["rulename"],
+ )
+ return command
+
+
+def tmplt_files(config_data):
+ command = "logging"
+ if config_data.get("name"):
+ command += " file {name}".format(name=config_data["name"])
+ if config_data.get("path"):
+ command += " path {path}".format(path=config_data["path"])
+ if config_data.get("maxfilesize"):
+ command += " maxfilesize {maxfilesize}".format(
+ maxfilesize=config_data["maxfilesize"],
+ )
+ if config_data.get("severity"):
+ command += " severity {severity}".format(
+ severity=config_data["severity"],
+ )
+ return command
+
+
+def tmplt_source_interface(config_data):
+ command = "logging source-interface"
+ if config_data.get("interface"):
+ command += " {interface}".format(interface=config_data["interface"])
+ if config_data.get("vrf"):
+ command += " vrf {vrf}".format(vrf=config_data["vrf"])
+ return command
+
+
+def tmplt_tls_servers(config_data):
+ commands = []
+ name = config_data.get("name")
+ base_command = "logging tls-server {name}".format(name=name)
+ if config_data.get("tls_hostname"):
+ commands.append(
+ "{base_command} tls-hostname {tls}".format(
+ tls=config_data["tls_hostname"],
+ base_command=base_command,
+ ),
+ )
+ if config_data.get("trustpoint"):
+ commands.append(
+ "{base_command} trustpoint {trustpoint}".format(
+ trustpoint=config_data["trustpoint"],
+ base_command=base_command,
+ ),
+ )
+ if config_data.get("vrf"):
+ commands.append(
+ "{base_command} vrf {vrf}".format(
+ vrf=config_data["vrf"],
+ base_command=base_command,
+ ),
+ )
+ if config_data.get("severity"):
+ commands.append(
+ "{base_command} severity {severity}".format(
+ severity=config_data["severity"],
+ base_command=base_command,
+ ),
+ )
+ if len(commands) == 0:
+ commands.append(base_command)
+ return commands
+
+
+def rem_tmplt_tls_servers(config_data):
+ command = "logging tls-server"
+ if config_data.get("name"):
+ command += " {name}".format(name=config_data["name"])
+ return command
+
+
+class Logging_globalTemplate(NetworkTemplate):
+ def __init__(self, lines=None, module=None):
+ super(Logging_globalTemplate, self).__init__(
+ lines=lines,
+ tmplt=self,
+ module=module,
+ )
+
+ # fmt: off
+ PARSERS = [
+ {
+ "name": "archive.device",
+ "getval": re.compile(
+ r"""
+ ^logging\sarchive
+ (\s+device\s(?P<device>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging archive device {{archive.device}}",
+ "result": {
+ "archive": {
+ "device": "{{ device }}",
+ },
+ },
+ },
+ {
+ "name": "archive.severity",
+ "getval": re.compile(
+ r"""
+ ^logging\sarchive
+ (\s+severity\s(?P<severity>alerts|critical|debugging|emergencies|errors|informational|notifications|warnings))
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging archive severity {{archive.severity}}",
+ "result": {
+ "archive": {
+ "severity": "{{severity}}",
+ },
+ },
+ },
+ {
+ "name": "archive.file_size",
+ "getval": re.compile(
+ r"""
+ ^logging\sarchive
+ (\s+file-size\s(?P<file_size>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging archive file-size {{archive.file_size}}",
+ "result": {
+ "archive": {
+ "file_size": "{{ file_size }}",
+ },
+ },
+ },
+ {
+ "name": "archive.frequency",
+ "getval": re.compile(
+ r"""
+ ^logging\sarchive
+ (\s+frequency\s(?P<frequency>daily|weekly))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging archive frequency {{archive.frequency}}",
+ "result": {
+ "archive": {
+ "frequency": "{{ frequency }}",
+ },
+ },
+ },
+ {
+ "name": "archive.archive_size",
+ "getval": re.compile(
+ r"""
+ ^logging\sarchive
+ (\s+archive-size\s(?P<archive_size>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging archive archive-size {{archive.archive_size}}",
+ "result": {
+ "archive": {
+ "archive_size": "{{ archive_size }}",
+ },
+ },
+ },
+ {
+ "name": "archive.archive_length",
+ "getval": re.compile(
+ r"""
+ ^logging\sarchive
+ (\s+archive-length\s(?P<archive_length>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging archive archive-length {{archive.archive_length}}",
+ "result": {
+ "archive": {
+ "archive_length": "{{ archive_length}}",
+ },
+ },
+ },
+ {
+ "name": "hosts",
+ "getval": re.compile(
+ r"""
+ ^logging
+ (\s(?P<host>\S+))?
+ (\svrf\s(?P<vrf>\w+))?
+ (\sseverity\s(?P<severity>alerts|critical|debugging|emergencies|error|informational|notifications|warnings))?
+ (\sport\s(?P<port>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": tmplt_host,
+ "result": {
+ "hosts": [{
+ "host": "{{ host }}",
+ "port": "{{ port }}",
+ "vrf": "{{ vrf }}",
+ "severity": "{{severity}}",
+ }],
+ },
+
+ },
+ {
+ "name": "buffered.size",
+ "getval": re.compile(
+ r"""
+ ^logging\sbuffered
+ (\s(?P<size>[1-9][0-9]*))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging buffered {{buffered.size}}",
+ "result": {
+ "buffered": {
+ "size": "{{ size }}",
+ },
+
+ },
+ },
+ {
+ "name": "buffered.severity",
+ "getval": re.compile(
+ r"""
+ ^logging\sbuffered
+ (\s(?P<severity>alerts|critical|debugging|emergencies|errors|informational|notifications|warnings))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging buffered {{buffered.severity}}",
+ "result": {
+
+ "buffered": {
+ "severity": "{{ severity }}",
+ },
+ },
+
+ },
+ {
+ "name": "buffered.discriminator",
+ "getval": re.compile(
+ r"""
+ ^logging\sbuffered\sdiscriminator
+ \s+(?P<match_nomatch>\S+)\s(?P<name>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging buffered discriminator {{match_params}} {{name}}",
+ "result": {
+ "buffered": {
+ "discriminator": [
+ {
+ "match_params": "{{ match_nomatch }}",
+ "name": "{{name}}",
+ },
+ ],
+ },
+
+ },
+ },
+ {
+ "name": "console.severity",
+ "getval": re.compile(
+ r"""
+ ^logging\sconsole
+ (\s(?P<severity>alerts|critical|debugging|emergencies|errors|informational|notifications|warning$))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging console {{console.severity}}",
+ "result": {
+ "console": {
+ "severity": "{{ severity }}",
+ },
+ },
+ },
+ {
+ "name": "console.state",
+ "getval": re.compile(
+ r"""
+ ^logging\sconsole
+ \s(?P<disable>disable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "{{ 'logging console disable' if console.state =='disabled' else 'no logging console disable' }}",
+ "result": {
+ "console": {
+ "state": "{{ 'disabled' if disable is defined }}",
+ },
+ },
+ },
+ {
+ "name": "console.discriminator",
+ "getval": re.compile(
+ r"""
+ ^logging\sconsole\sdiscriminator
+ \s+(?P<match_nomatch>\S+)\s(?P<name>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging console discriminator {{match_params}} {{name}}",
+ "result": {
+ "console": {
+ "discriminator": [
+ {
+ "match_params": "{{ match_nomatch }}",
+ "name": "{{name}}",
+ },
+ ],
+ },
+ },
+ },
+ {
+ "name": "correlator.buffer_size",
+ "getval": re.compile(
+ r"""
+ ^logging\scorrelator
+ (\sbuffer-size\s(?P<buffer_size>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging correlator buffer-size {{correlator.buffer_size }}",
+ "result": {
+ "correlator": {
+ "buffer_size": "{{ buffer_size }}",
+ },
+ },
+ },
+ {
+ "name": "correlator.rules",
+ "getval": re.compile(
+ r"""
+ ^logging\scorrelator
+ (\srule\s(?P<name>\S+))?
+ (\stype\s(?P<rule_type>\S+))?
+ (\s+reissue-nonbistate(?P<reissue_nonbistate>))?
+ (\s+timeout\s(?P<timeout>\S+))?
+ (\s+reparent(?P<reparent>))?
+ (\s+context-correlation(?P<context_correlation>))?
+ (\s+timeout-rootcause\s(?P<timeout_rootcause>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": tmplt_correlator_rule,
+ "result": {
+ "correlator": {
+ "rules": {
+ "{{name}}": {
+ "rule_name": "{{ name }}",
+ "rule_type": "{{ rule_type }}",
+ "reissue_nonbistate": "{{ True if reissue_nonbistate is defined }}",
+ "timeout": "{{ timeout }}",
+ "reparent": "{{ True if reparent is defined }}",
+ "context_correlation": "{{ True if context_correlation is defined }}",
+ "timeout_rootcause": "{{ timeout_rootcause }}",
+
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "correlator.rule_sets",
+ "getval": re.compile(
+ r"""
+ ^logging\scorrelator\sruleset\s(?P<name>\S+)
+ (\srulename\s(?P<rulename>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": tmplt_correlator_ruleset,
+ "result": {
+ "correlator": {
+ "rule_sets": {
+ "{{name}}": {
+ "name": "{{ name }}",
+ "rulename": ["{{ rulename }}"],
+
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "events.threshold",
+ "getval": re.compile(
+ r"""
+ ^logging\sevents
+ (\sthreshold\s(?P<threshold>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging events threshold {{events.threshold}}",
+ "result": {
+ "events":
+ {"threshold": "{{ threshold }}"},
+ },
+
+ },
+ {
+ "name": "events.buffer_size",
+ "getval": re.compile(
+ r"""
+ ^logging\sevents
+ (\sbuffer-size\s(?P<buffer_size>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging events buffer-size {{events.buffer_size}}",
+ "result": {
+ "events": {"buffer_size": "{{ buffer_size }}"},
+ },
+
+ },
+ {
+ "name": "events.display_location",
+ "getval": re.compile(
+ r"""
+ ^logging\sevents
+ (\sdisplay-location(?P<display_location>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging events display-location",
+ "result": {
+ "events":
+ {
+ "display_location": "{{ True if display_location is defined }}",
+
+ },
+
+ },
+ },
+ {
+ "name": "events.filter_match",
+ "getval": re.compile(
+ r"""
+ ^logging\sevents\sfilter
+ (\s+match\s(?P<match>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging events filter match {{match}}",
+ "result": {
+ "events": {
+ "filter_match": [
+ "{{ match }}",
+ ],
+ },
+ },
+ },
+ {
+ "name": "events.severity",
+ "getval": re.compile(
+ r"""
+ ^logging\sevents
+ (\slevel\s(?P<severity>alerts|critical|debugging|emergencies|errors|informational|notifications|warnings))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging events level {{events.severity}}",
+ "result": {
+ "events":
+ {
+ "severity": "{{ severity }}",
+
+ },
+ },
+ },
+ {
+ "name": "files",
+ "getval": re.compile(
+ r"""
+ ^logging
+ (\sfile\s(?P<file>\S+))?
+ (\spath\s(?P<path>\S+))?
+ (\smaxfilesize\s(?P<maxfilesize>\S+))?
+ (\sseverity\s(?P<severity>alerts|critical|debugging|emergencies|errors|info|notifications|warning))?
+ $""", re.VERBOSE,
+ ),
+ "setval": tmplt_files,
+ "result": {
+ "files": [
+ {
+ "name": "{{file}}",
+ "path": "{{path}}",
+ "maxfilesize": "{{maxfilesize}}",
+ "severity": "{{ severity }}",
+
+ },
+ ],
+ },
+ },
+ {
+ "name": "facility",
+ "getval": re.compile(
+ r"""
+ ^logging\sfacility
+ \s(?P<facility>auth|cron|daemon|kern|local0|local1|local2|local3|local4|local5|local6|local7|lpr|mail|news|sys10|sys11|sys12|sys13|sys14|sys9|syslog|user|uucp)
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging facility {{ facility }}",
+ "result": {
+ "facility": "{{ facility }}",
+ },
+ },
+ {
+ "name": "format",
+ "getval": re.compile(
+ r"""
+ ^logging\sformat
+ (\srfc5424(?P<format>))
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging format rfc5424",
+ "result": {
+ "format": "{{True if format is defined}}",
+ },
+ },
+ {
+ "name": "hostnameprefix",
+ "getval": re.compile(
+ r"""
+ ^logging
+ (\shostnameprefix\s(?P<hostnameprefix>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging hostnameprefix {{hostnameprefix}}",
+ "result": {
+ "hostnameprefix": "{{hostnameprefix}}",
+ },
+ },
+ {
+ "name": "ipv4.dscp",
+ "getval": re.compile(
+ r"""
+ ^logging
+ \sipv4\sdscp\s(?P<dscp>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging ipv4 dscp {{ipv4.dscp}}",
+ "result": {
+ "ipv4": {
+ "dscp": "{{dscp}}",
+ },
+ },
+ },
+ {
+ "name": "ipv6.dscp",
+ "getval": re.compile(
+ r"""
+ ^logging
+ (\sipv6\sdscp\s(?P<dscp>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging ipv6 dscp {{ipv6.dscp}}",
+ "result": {
+ "ipv6": {
+ "dscp": "{{dscp}}",
+ },
+ },
+ },
+ {
+ "name": "ipv4.precedence",
+ "getval": re.compile(
+ r"""
+ ^logging
+ (\sipv4\sprecedence\s(?P<precedence>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging ipv4 precedence {{ipv4.precedence}}",
+ "result": {
+ "ipv4": {"precedence": "{{precedence}}"},
+ },
+ },
+ {
+ "name": "ipv6.precedence",
+ "getval": re.compile(
+ r"""
+ ^logging
+ (\sipv6\sprecedence\s(?P<precedence>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging ipv6 precedence {{ipv6.precedence}}",
+ "result": {
+ "ipv6": {"precedence": "{{precedence}}"},
+ },
+ },
+ {
+ "name": "localfilesize",
+ "getval": re.compile(
+ r"""
+ ^logging
+ (\slocalfilesize\s(?P<localfilesize>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging localfilesize {{localfilesize}}",
+ "result": {
+ "localfilesize": "{{localfilesize}}",
+ },
+ },
+ {
+ "name": "suppress.duplicates",
+ "getval": re.compile(
+ r"""
+ ^logging
+ (\ssuppress\sduplicates(?P<suppress_duplicates>))
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging suppress duplicates",
+ "result": {
+ "suppress":
+ {"duplicates": "{{True if suppress_duplicates is defined}}"},
+ },
+ },
+ {
+ "name": "suppress.apply_rule",
+ "getval": re.compile(
+ r"""
+ ^logging\ssuppress\sapply\srule\s(?P<apply_rules>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging suppress apply rule {{suppress.apply_rule}}",
+ "result": {
+ "suppress": {"apply_rule": "{{apply_rules}}"},
+ },
+ },
+ {
+ "name": "history.size",
+ "getval": re.compile(
+ r"""
+ ^logging\shistory
+ (\ssize\s(?P<size>\d+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging history size {{history.size}}",
+ "result": {
+ "history": {
+ "severity": "{{ severity }}",
+ "size": "{{ size }}",
+ },
+ },
+ },
+ {
+ "name": "history.severity",
+ "getval": re.compile(
+ r"""
+ ^logging\shistory
+ (\s(?P<severity>alerts|critical|debugging|emergencies|errors|informational|notifications|warning))
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging history {{history.severity}}",
+ "result": {
+ "history": {
+ "severity": "{{ severity }}",
+ },
+ },
+ },
+ {
+ "name": "history.state",
+ "getval": re.compile(
+ r"""
+ ^logging\shistory
+ \s(?P<disable>disable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "{{ 'logging history disable' if history.state =='disabled' else 'no logging history disable' }}",
+ "result": {
+ "history": {
+ "state": "{{ 'disabled' if disable is defined }}",
+ },
+ },
+ },
+ {
+ "name": "monitor.severity",
+ "getval": re.compile(
+ r"""
+ ^logging\smonitor
+ (\s(?P<severity>alerts|critical|debugging|emergencies|errors|informational|notifications|warning))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging monitor {{monitor.severity}}",
+ "result": {
+ "monitor": {
+ "severity": "{{ severity }}",
+ },
+ },
+ },
+ {
+ "name": "monitor.state",
+ "getval": re.compile(
+ r"""
+ ^logging\smonitor\s(?P<disable>disable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "{{ 'logging monitor disable' if monitor.state =='disabled' else 'no logging monitor disable' }}",
+ "result": {
+ "monitor": {
+ "state": "{{ 'disabled' if disable is defined }}",
+ },
+ },
+ },
+ {
+ "name": "monitor.discriminator",
+ "getval": re.compile(
+ r"""
+ ^logging\smonitor\sdiscriminator
+ \s+(?P<match_nomatch>\S+)\s(?P<name>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging monitor discriminator {{match_params}} {{name}}",
+ "result": {
+ "monitor": {
+ "discriminator": [
+ {
+ "match_params": "{{ match_nomatch }}",
+ "name": "{{name}}",
+ },
+ ],
+ },
+
+ },
+ },
+ {
+ "name": "source_interfaces",
+ "getval": re.compile(
+ r"""
+ ^logging\ssource-interface
+ (\s(?P<interface>\S+))?
+ (\svrf\s(?P<vrf>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": tmplt_source_interface,
+ "result": {
+ "source_interfaces": [
+ {
+ "interface": "{{ interface }}",
+ "vrf": "{{ vrf }}",
+ },
+ ],
+ },
+ },
+ {
+ "name": "trap.severity",
+ "getval": re.compile(
+ r"""
+ ^logging\strap
+ \s(?P<severity>alerts|critical|debugging|emergencies|errors|informational|notifications|warning)
+ $""", re.VERBOSE,
+ ),
+ "setval": "logging trap {{ trap.severity }}",
+ "result": {
+ "trap": {
+ "severity": "{{ severity }}",
+ },
+ },
+ },
+ {
+ "name": "trap.state",
+ "getval": re.compile(
+ r"""
+ ^logging\strap
+ \s(?P<disable>disable)
+ $""", re.VERBOSE,
+ ),
+ "setval": "{{ 'logging trap disable' if trap.state =='disabled' else 'no logging trap disable' }}",
+ "result": {
+ "trap": {
+ "state": "{{ 'disabled' if disable is defined }}",
+ },
+ },
+ },
+ {
+ "name": "tls_servers",
+ "getval": re.compile(
+ r"""
+ ^logging\stls-server\s(?P<name>\S+)
+ (\s+vrf\s(?P<vrf>\S+))?
+ (\s+trustpoint\s(?P<trustpoint>\S+))?
+ (\s+tls-hostname\s(?P<tls_hostname>\S+))?
+ (\s(?P<severity>alerts|critical|debugging|emergencies|errors|informational|notifications|warnings))?
+ $""", re.VERBOSE,
+ ),
+ "setval": tmplt_tls_servers,
+ "remval": rem_tmplt_tls_servers,
+ "result": {
+ "tls_servers": {
+ "{{name}}": {
+ "name": "{{ name }}",
+ "trustpoint": "{{trustpoint}}",
+ "vrf": "{{vrf}}",
+ "severity": "{{severity}}",
+ "tls_hostname": "{{tls_hostname}}",
+ },
+ },
+ },
+ },
+ ]
+ # fmt: on
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ntp_global.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ntp_global.py
new file mode 100644
index 00000000..497f9c2b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ntp_global.py
@@ -0,0 +1,680 @@
+# -*- 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 Ntp_global 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_interfaces(config_data):
+ commands = []
+ name = config_data.get("name")
+ vrf = config_data.get("vrf", "")
+ if vrf:
+ base_command = "ntp interface {name} vrf {vrf}".format(
+ name=name,
+ vrf=vrf,
+ )
+ else:
+ base_command = "ntp interface {name}".format(name=name)
+ if config_data.get("broadcast_client"):
+ commands.append(
+ "{base_command} broadcast client".format(
+ base_command=base_command,
+ ),
+ )
+ if config_data.get("broadcast_key"):
+ commands.append(
+ "{base_command} broadcast key {broadcast_key}".format(
+ broadcast_key=config_data.get("broadcast_key"),
+ base_command=base_command,
+ ),
+ )
+ if config_data.get("broadcast_destination"):
+ commands.append(
+ "{base_command} broadcast destination {broadcast_destination}".format(
+ broadcast_destination=config_data.get("broadcast_destination"),
+ base_command=base_command,
+ ),
+ )
+ if config_data.get("broadcast_version"):
+ commands.append(
+ "{base_command} broadcast version {broadcast_version}".format(
+ broadcast_version=config_data.get("broadcast_version"),
+ base_command=base_command,
+ ),
+ )
+ if config_data.get("multicast_destination"):
+ commands.append(
+ "{base_command} multicast destination {multicast_destination}".format(
+ multicast_destination=config_data.get("multicast_destination"),
+ base_command=base_command,
+ ),
+ )
+ if config_data.get("multicast_client"):
+ commands.append(
+ "{base_command} multicast client {multicast_client}".format(
+ multicast_client=config_data.get("multicast_client"),
+ base_command=base_command,
+ ),
+ )
+ if config_data.get("multicast_key"):
+ commands.append(
+ "{base_command} multicast key {multicast_key}".format(
+ multicast_key=config_data.get("multicast_key"),
+ base_command=base_command,
+ ),
+ )
+ elif config_data.get("multicast_version"):
+ commands.append(
+ "{base_command} multicast version {multicast_version}".format(
+ multicast_version=config_data.get("multicast_version"),
+ base_command=base_command,
+ ),
+ )
+ elif config_data.get("multicast_ttl"):
+ commands.append(
+ "{base_command} multicast ttl {multicast_ttl}".format(
+ multicast_ttl=config_data.get("multicast_ttl"),
+ base_command=base_command,
+ ),
+ )
+ return commands
+
+
+def tmplt_access_group_vrfs(config_data):
+ commands = []
+ vrf_name = config_data.get("name")
+ base_command = "ntp access-group vrf {name}".format(name=vrf_name)
+ for ip in ["ipv4", "ipv6"]:
+ if config_data.get(ip, {}).get("serve"):
+ commands.append(
+ "{base_command} {ip} serve {serve}".format(
+ base_command=base_command,
+ serve=config_data.get(ip, {}).get("serve"),
+ ip=ip,
+ ),
+ )
+ if config_data.get(ip, {}).get("serve_only"):
+ commands.append(
+ "{base_command} {ip} serve-only {serve_only}".format(
+ base_command=base_command,
+ serve_only=config_data.get(ip, {}).get("serve_only"),
+ ip=ip,
+ ),
+ )
+ if config_data.get(ip, {}).get("query_only"):
+ commands.append(
+ "{base_command} {ip} query-only {query_only}".format(
+ base_command=base_command,
+ query_only=config_data.get(ip, {}).get("query_only"),
+ ip=ip,
+ ),
+ )
+ if config_data.get(ip, {}).get("peer"):
+ commands.append(
+ "{base_command} {ip} peer {peer}".format(
+ base_command=base_command,
+ peer=config_data.get(ip, {}).get("peer"),
+ ip=ip,
+ ),
+ )
+
+ return commands
+
+
+class Ntp_globalTemplate(NetworkTemplate):
+ def __init__(self, lines=None, module=None):
+ super(Ntp_globalTemplate, self).__init__(
+ lines=lines,
+ tmplt=self,
+ module=module,
+ )
+
+ # fmt: off
+ PARSERS = [
+ {
+ "name": "access_group.ipv4.peer",
+ "getval": re.compile(
+ r"""
+ ^ntp\saccess-group\sipv4\speer\s(?P<peer>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp access-group ipv4 peer {{access_group.ipv4.peer}}",
+ "result": {
+ "access_group": {
+ "ipv4": {
+ "peer": "{{ peer }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "access_group.ipv4.serve",
+ "getval": re.compile(
+ r"""
+ ^ntp\saccess-group\sipv4\sserve\s(?P<serve>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp access-group ipv4 serve {{access_group.ipv4.serve}}",
+ "result": {
+ "access_group": {
+ "ipv4": {
+ "serve": "{{ serve }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "access_group.ipv4.serve_only",
+ "getval": re.compile(
+ r"""
+ ^ntp\saccess-group\sipv4\sserve-only\s(?P<serve>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp access-group ipv4 serve-only {{access_group.ipv4.serve_only}}",
+ "result": {
+ "access_group": {
+ "ipv4": {
+ "serve_only": "{{ serve }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "access_group.ipv4.query_only",
+ "getval": re.compile(
+ r"""
+ ^ntp\saccess-group\sipv4\squery-only\s(?P<query_only>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp access-group ipv4 query-only {{access_group.ipv4.query_only}}",
+ "result": {
+ "access_group": {
+ "ipv4": {
+ "query_only": "{{ query_only }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "access_group.ipv6.peer",
+ "getval": re.compile(
+ r"""
+ ^ntp\saccess-group\sipv6\speer\s(?P<peer>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp access-group ipv6 peer {{access_group.ipv6.peer}}",
+ "result": {
+ "access_group": {
+ "ipv6": {
+ "peer": "{{ peer }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "access_group.ipv6.serve",
+ "getval": re.compile(
+ r"""
+ ^ntp\saccess-group\sipv6\sserve\s(?P<serve>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp access-group ipv6 serve {{access_group.ipv6.serve}}",
+ "result": {
+ "access_group": {
+ "ipv6": {
+ "serve": "{{ serve }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "access_group.ipv6.serve_only",
+ "getval": re.compile(
+ r"""
+ ^ntp\saccess-group\sipv6\sserve-only\s(?P<serve>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp access-group ipv6 serve-only {{access_group.ipv6.serve_only}}",
+ "result": {
+ "access_group": {
+ "ipv6": {
+ "serve_only": "{{ serve }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "access_group.ipv6.query_only",
+ "getval": re.compile(
+ r"""
+ ^ntp\saccess-group\sipv6\squery-only\s(?P<query_only>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp access-group ipv6 query-only {{access_group.ipv6.query_only}}",
+ "result": {
+ "access_group": {
+ "ipv6": {
+ "query_only": "{{ query_only }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "vrfs",
+ "getval": re.compile(
+ r"""
+ ^ntp\saccess-group
+ (\svrf\s(?P<vrf>\S+))
+ (\s(?P<ipv6>ipv6))?
+ (\s(?P<ipv4>ipv4))?
+ (\speer\s(?P<peer>\S+))?
+ (\sserve\s(?P<serve>\S+))?
+ (\sserve-only\s(?P<serve_only>\S+))?
+ (\squery-only\s(?P<query_only>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": tmplt_access_group_vrfs,
+ "result": {
+ "access_group": {
+ "vrfs": {
+ "{{vrf}}": {
+ "name": "{{vrf}}",
+ "ipv6": {
+ "query_only": "{{ query_only if ipv6 is defined else ''}}",
+ "serve_only": "{{ serve_only if ipv6 is defined else ''}}",
+ "serve": "{{ serve if ipv6 is defined else ''}}",
+ "peer": "{{ peer if ipv6 is defined else ''}}",
+ },
+ "ipv4": {
+ "query_only": "{{ query_only if ipv4 is defined else ''}}",
+ "serve_only": "{{ serve_only if ipv4 is defined else ''}}",
+ "serve": "{{ serve if ipv4 is defined else ''}}",
+ "peer": "{{ peer if ipv4 is defined else '' }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "authenticate",
+ "getval": re.compile(
+ r"""
+ ^ntp\s(?P<authenticate>authenticate)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp authenticate",
+ "result": {
+ "authenticate": "{{ not not authenticate }}",
+ },
+ },
+ {
+ "name": "authentication_keys",
+ "getval": re.compile(
+ r"""
+ ^ntp\sauthentication-key\s(?P<id>\d+)\smd5\s(?P<encryption>encrypted)\s(?P<key>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp authentication-key {{ id }} md5 "
+ "{{ ('encrypted ') if encryption else 'clear ' }}"
+ "{{ key }}",
+ "result": {
+ "authentication_keys": [
+ {
+ "id": "{{ id }}",
+ "key": "{{ key }}",
+ "encryption": "{{ not not encryption }}",
+ },
+ ],
+ },
+ },
+ {
+ "name": "log_internal_sync",
+ "getval": re.compile(
+ r"""
+ ^ntp\s(?P<log_internal_sync>log-internal-sync)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp log-internal-sync",
+ "result": {
+ "log_internal_sync": "{{ not not log_internal_sync }}",
+ },
+ },
+ {
+ "name": "broadcastdelay",
+ "getval": re.compile(
+ r"""
+ ^ntp\sbroadcastdelay\s(?P<broadcastdelay>\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp broadcastdelay {{ broadcastdelay }}",
+ "result": {
+ "broadcastdelay": "{{ broadcastdelay }}",
+ },
+ },
+ {
+ "name": "drift.aging_time",
+ "getval": re.compile(
+ r"""
+ ^ntp\sdrift\saging\stime\s(?P<aging_time>\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp drift aging time {{ drift.aging_time }}",
+ "result": {
+ "drift": {
+ "aging_time": "{{ aging_time }}",
+ },
+ },
+ },
+ {
+ "name": "drift.file",
+ "getval": re.compile(
+ r"""
+ ^ntp\sdrift\sfile\s(?P<file>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp drift file {{ drift.file }}",
+ "result": {
+ "drift": {
+ "file": "{{ file }}",
+ },
+ },
+ },
+ {
+ "name": "ipv4.dscp",
+ "getval": re.compile(
+ r"""
+ ^ntp
+ \sipv4\sdscp\s(?P<dscp>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp ipv4 dscp {{ipv4.dscp}}",
+ "result": {
+ "ipv4": {
+ "dscp": "{{dscp}}",
+ },
+ },
+ },
+ {
+ "name": "ipv4.precedence",
+ "getval": re.compile(
+ r"""
+ ^ntp
+ (\sipv4\sprecedence\s(?P<precedence>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp ipv4 precedence {{ipv4.precedence}}",
+ "result": {
+ "ipv4": {"precedence": "{{precedence}}"},
+ },
+ },
+ {
+ "name": "ipv6.dscp",
+ "getval": re.compile(
+ r"""
+ ^ntp
+ \sipv6\sdscp\s(?P<dscp>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp ipv6 dscp {{ipv6.dscp}}",
+ "result": {
+ "ipv6": {
+ "dscp": "{{dscp}}",
+ },
+ },
+ },
+ {
+ "name": "ipv6.precedence",
+ "getval": re.compile(
+ r"""
+ ^ntp
+ (\sipv6\sprecedence\s(?P<precedence>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp ipv6 precedence {{ipv6.precedence}}",
+ "result": {
+ "ipv6": {"precedence": "{{precedence}}"},
+ },
+ },
+ {
+ "name": "max_associations",
+ "getval": re.compile(
+ r"""
+ ^ntp\smax-associations\s(?P<max_associations>\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp max-associations {{ max_associations }}",
+ "result": {
+ "max_associations": "{{ max_associations }}",
+ },
+ },
+ {
+ "name": "master.stratum",
+ "getval": re.compile(
+ r"""
+ ^ntp\smaster\s(?P<master>\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp master {{ master.stratum }}",
+ "result": {
+ "master": {
+ "stratum": "{{ master }}",
+ },
+ },
+ },
+ {
+ "name": "passive",
+ "getval": re.compile(
+ r"""
+ ^ntp\s(?P<passive>passive)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp passive",
+ "result": {
+ "passive": "{{ not not passive }}",
+ },
+ },
+ {
+ "name": "update_calendar",
+ "getval": re.compile(
+ r"""
+ ^ntp\s(?P<update_calendar>update-calendar)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp update-calendar",
+ "result": {
+ "update_calendar": "{{ not not update_calendar }}",
+ },
+ },
+ {
+ "name": "source_interface",
+ "getval": re.compile(
+ r"""
+ ^ntp\ssource\s(?P<source>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp source {{ source_interface }}",
+ "result": {
+ "source_interface": "{{ source }}",
+ },
+ },
+ {
+ "name": "source_vrfs",
+ "getval": re.compile(
+ r"""
+ ^ntp\ssource\svrf\s(?P<vrf>\S+)\s(?P<source>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp vrf {{vrf}} source {{name}}",
+ "result": {
+ "source_vrfs": {
+ "{{vrf}}": {
+ "name": "{{ source }}",
+ "vrf": "{{vrf}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "trusted_keys",
+ "getval": re.compile(
+ r"""
+ ^ntp\strusted-key\s(?P<key>\d+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp trusted-key {{ key_id }}",
+ "result": {
+ "trusted_keys": [
+ {
+ "key_id": "{{ key }}",
+ },
+ ],
+ },
+ },
+ {
+ "name": "peers",
+ "getval": re.compile(
+ r"""
+ ^ntp\speer
+ (\svrf\s(?P<vrf>\S+))?
+ \s(?P<peer>\S+)
+ (\sversion\s(?P<version>\d+))?
+ (\skey\s(?P<key>\d+))?
+ (\sminpoll\s(?P<minpoll>\d+))?
+ (\smaxpoll\s(?P<maxpoll>\d+))?
+ (\s(?P<prefer>prefer))?
+ (\s(?P<burst>burst))?
+ (\s(?P<iburst>iburst))?
+ (\ssource\s(?P<source>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp peer"
+ "{{ (' vrf ' + vrf) if vrf is defined else '' }}"
+ "{{ ( ' ' + peer ) if peer is defined else '' }}"
+ "{{ ' burst' if burst is defined else ''}}"
+ "{{ ' iburst' if iburst is defined else ''}}"
+ "{{ (' key ' + key_id|string) if key_id is defined else '' }}"
+ "{{ (' minpoll ' + minpoll|string) if minpoll is defined else '' }}"
+ "{{ (' maxpoll ' + maxpoll|string) if maxpoll is defined else '' }}"
+ "{{ ' prefer' if prefer is defined else ''}}"
+ "{{ (' version ' + version|string) if version is defined else '' }}"
+ "{{ (' source ' + source|string) if source is defined else '' }}",
+ "result": {
+ "peers": {
+ "{{peer}}_{{vrf|d()}}": {
+ "peer": "{{ peer }}",
+ "vrf": "{{ vrf }}",
+ "burst": "{{ not not burst }}",
+ "iburst": "{{ not not iburst }}",
+ "key_id": "{{ key }}",
+ "minpoll": "{{ minpoll }}",
+ "maxpoll": "{{ maxpoll }}",
+ "prefer": "{{ not not prefer }}",
+ "version": "{{ version }}",
+ "source": "{{source}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "servers",
+ "getval": re.compile(
+ r"""
+ ^ntp\sserver
+ (\svrf\s(?P<vrf>\S+))?
+ \s(?P<server>\S+)
+ (\sversion\s(?P<version>\d+))?
+ (\skey\s(?P<key>\d+))?
+ (\sminpoll\s(?P<minpoll>\d+))?
+ (\smaxpoll\s(?P<maxpoll>\d+))?
+ (\s(?P<prefer>prefer))?
+ (\s(?P<burst>burst))?
+ (\s(?P<iburst>iburst))?
+ (\ssource\s(?P<source>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "ntp server"
+ "{{ (' vrf ' + vrf) if vrf is defined else '' }}"
+ "{{ ( ' ' + server ) if server is defined else '' }}"
+ "{{ ' burst' if burst is defined else ''}}"
+ "{{ ' iburst' if iburst is defined else ''}}"
+ "{{ (' key ' + key_id|string) if key_id is defined else '' }}"
+ "{{ (' minpoll ' + minpoll|string) if minpoll is defined else '' }}"
+ "{{ (' maxpoll ' + maxpoll|string) if maxpoll is defined else '' }}"
+ "{{ ' prefer' if prefer is defined else ''}}"
+ "{{ (' version ' + version|string) if version is defined else '' }}"
+ "{{ (' source ' + source|string) if source is defined else '' }}",
+ "result": {
+ "servers": {
+ "{{server}}_{{vrf|d()}}": {
+ "server": "{{ server }}",
+ "vrf": "{{ vrf }}",
+ "burst": "{{ not not burst }}",
+ "iburst": "{{ not not iburst }}",
+ "key_id": "{{ key }}",
+ "minpoll": "{{ minpoll }}",
+ "maxpoll": "{{ maxpoll }}",
+ "prefer": "{{ not not prefer }}",
+ "version": "{{ version }}",
+ "source": "{{source}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "interfaces",
+ "getval": re.compile(
+ r"""
+ ^ntp\sinterface\s(?P<name>\S+)
+ (\svrf\s(?P<vrf>\S+))?
+ (\smulticast\sclient\s(?P<m_client>\S+))?
+ (\smulticast\skey\s(?P<m_key>\S+))?
+ (\smulticast\sdestination\s(?P<m_dest>\S+))?
+ (\smulticast\sversion\s(?P<m_version>\S+))?
+ (\smulticast\sttl\s(?P<m_ttl>\S+))?
+ (\sbroadcast\sclient(?P<b_client>))?
+ (\sbroadcast\skey\s(?P<b_key>\S+))?
+ (\sbroadcast\sdestination\s(?P<b_dest>\S+))?
+ (\sbroadcast\sversion\s(?P<ntp_version>\d+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": tmplt_interfaces,
+ "result": {
+ "interfaces": {
+ "{{name}}_{{vrf|d()}}": {
+ "vrf": "{{vrf}}",
+ "name": "{{name}}",
+ "broadcast_client": "{{True if b_client is defined}}",
+ "multicast_key": "{{m_key}}",
+ "multicast_destination": "{{m_dest}}",
+ "multicast_client": "{{m_client}}",
+ "multicast_version": "{{m_version}}",
+ "multicast_ttl": "{{m_ttl}}",
+ "broadcast_key": "{{b_key}}",
+ "broadcast_destination": "{{b_dest}}",
+ "broadcast_version": "{{ntp_version}}",
+ },
+ },
+ },
+ },
+
+ ]
+ # fmt: on
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospf_interfaces.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospf_interfaces.py
new file mode 100644
index 00000000..a6181edd
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospf_interfaces.py
@@ -0,0 +1,1416 @@
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+import re
+
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.network_template import (
+ NetworkTemplate,
+)
+
+
+def get_ospf_type(afi):
+ return "ospf" if afi == "ipv4" else "ospfv3"
+
+
+def get_interface_type(name):
+ return "GigabitEthernet" if name.startswith("GigabitEthernet") else "Loopback"
+
+
+def _compute_command(cfg):
+ ospf_type = get_ospf_type(cfg["address_family"]["afi"])
+ type = get_interface_type(cfg["name"])
+ area = cfg["address_family"]["processes"]["area"]
+ pid = cfg["address_family"]["processes"]["process_id"]
+ cmd = "router {0} {1} area {2} interface {3} {4}".format(
+ ospf_type,
+ pid,
+ area["area_id"],
+ type,
+ cfg["name"].split(type)[1],
+ )
+ return cmd
+
+
+def _tmplt_ospf_int_delete(config_data):
+ ospf_type = get_ospf_type(config_data["afi"])
+ type = get_interface_type(config_data["name"])
+ area = config_data["area"]
+ command = "router {0} {1} area {2} interface {3} {4}".format(
+ ospf_type,
+ config_data["process"],
+ area["area_id"],
+ type,
+ config_data["name"].split(type)[1],
+ )
+ return command
+
+
+def _tmplt_ospf_config(config_data):
+ command = _compute_command(config_data)
+ return command
+
+
+def _tmplt_ospf_authentication_md_config(config_data):
+ command = _compute_command(config_data)
+ auth = config_data["address_family"]["authentication"]
+ if auth["message_digest"].get("keychain"):
+ command += " authentication message-digest keychain " + auth["message_digest"]["keychain"]
+ return command
+
+
+def _tmplt_ospf_authentication_md_set(config_data):
+ command = _compute_command(config_data)
+ auth = config_data["address_family"]["authentication"]
+ if auth.get("message_digest") and auth["message_digest"].get("keychain"):
+ command += " authentication message-digest"
+ elif auth.get("null_auth"):
+ command += " authentication null"
+ return command
+
+
+def _tmplt_ospf_authentication_key(config_data):
+ command = _compute_command(config_data)
+ auth = config_data["address_family"]["authentication_key"]
+ if auth.get("password"):
+ command += " authentication-key " + auth["password"]
+ elif auth.get("encrypted"):
+ command += " authentication-key encrypted " + auth["encrypted"]
+ elif auth.get("clear"):
+ command += " authentication-key clear " + auth["clear"]
+ return command
+
+
+def _tmplt_ospf_int_bfd_min_int(config_data):
+ command = _compute_command(config_data)
+ bfd = config_data["address_family"]["bfd"]
+ if bfd.get("minimum_interval"):
+ command += " bfd minimum-interval " + str(bfd["minimum_interval"])
+ return command
+
+
+def _tmplt_ospf_int_bfd_mult(config_data):
+ command = _compute_command(config_data)
+ bfd = config_data["address_family"]["bfd"]
+ if bfd.get("multiplier"):
+ command += " bfd multiplier " + str(bfd["multiplier"])
+ return command
+
+
+def _tmplt_ospf_int_bfd_fd(config_data):
+ command = _compute_command(config_data)
+ bfd = config_data["address_family"]["bfd"]
+ if bfd.get("fast_detect") and bfd["fast_detect"].get("set"):
+ command += " bfd fast-detect"
+ elif bfd.get("fast_detect") and bfd["fast_detect"].get("disable"):
+ command += " bfd fast-detect disable"
+ elif bfd.get("fast_detect") and bfd["fast_detect"].get("strict_mode"):
+ command += " bfd fast-detect strict-mode"
+ return command
+
+
+def _tmplt_ospf_cost_config(config_data):
+ command = _compute_command(config_data)
+ command += " cost " + str(config_data["address_family"]["cost"])
+ return command
+
+
+def _tmplt_ospf_cost_fallback_config(config_data):
+ command = _compute_command(config_data)
+ fallback = config_data["address_family"]["cost_fallback"]
+ command += (
+ " cost-fallback " + str(fallback["cost"]) + " threshold " + str(fallback["threshold"])
+ )
+ return command
+
+
+def _tmplt_ospf_dead_int_config(config_data):
+ command = _compute_command(config_data)
+ command += " dead-interval " + str(
+ config_data["address_family"]["dead_interval"],
+ )
+ return command
+
+
+def _tmplt_ospf_demand_config(config_data):
+ command = _compute_command(config_data)
+ if config_data["address_family"]["demand_circuit"]:
+ command += " demand-circuit enable"
+ else:
+ command += " demand-circuit disable"
+ return command
+
+
+class Ospf_interfacesTemplate(NetworkTemplate):
+ def __init__(self, lines=None, module=None):
+ super(Ospf_interfacesTemplate, self).__init__(
+ lines=lines,
+ tmplt=self,
+ module=module,
+ )
+
+ # fmt: off
+ PARSERS = [
+ {
+ "name": "name",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ $''',
+ re.VERBOSE,
+ ),
+ "remval": _tmplt_ospf_int_delete,
+ "setval": _tmplt_ospf_config,
+ "compval": "name",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ },
+ },
+ },
+ "shared": True,
+ },
+ {
+ "name": "authentication.message_digest",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sauthentication(?P<authentication>)
+ \s(?P<opt>message-digest)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_authentication_md_set,
+ "compval": "address_family.authentication.message_digest",
+ "result": {
+ "{{ name }}": {
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "authentication": {
+ "set": "{{ True if authentication is defined and opt is undefined }}",
+ "message_digest": {
+ "set": "{{ True if opt == 'message-digest' else None }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "authentication.message_digest.keychain",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sauthentication(?P<authentication>)
+ \s(?P<message_digest>message-digest)
+ \skeychain\s(?P<keychain>\S+)$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_authentication_md_config,
+ "compval": "address_family.authentication.message_digest.keychain",
+ "result": {
+ "{{ name }}": {
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "authentication": {
+ "message_digest": {
+ "keychain": "{{ keychain }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "authentication.null_auth",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sauthentication(?P<authentication>)
+ \s(?P<opt>null)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_authentication_md_set,
+ "compval": "address_family.authentication.null_auth",
+ "result": {
+ "{{ name }}": {
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "authentication": {
+ "set": "{{ True if authentication is defined and opt is undefined }}",
+ "null_auth": "{{ True if opt == 'null' else None }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "authentication_key",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sauthentication-key
+ (\sencrypted\s(?P<encrypted>\S+))?
+ (\s(?P<key>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_authentication_key,
+ "compval": "address_family.authentication_key",
+ "result": {
+ "{{ name }}": {
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "authentication_key": {
+ "encrypted": "{{ encrypted }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd.minimum_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sbfd(?P<bfd>)
+ \sminimum-interval\s(?P<minimum_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_int_bfd_min_int,
+ "compval": "address_family.bfd.minimum_interval",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+
+ },
+ },
+ "bfd": {
+ "minimum_interval": "{{ minimum_interval|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd.multiplier",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sbfd(?P<bfd>)
+ \smultiplier\s(?P<multiplier>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_int_bfd_mult,
+ "compval": "address_family.bfd.multiplier",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+
+ },
+ },
+ "bfd": {
+ "multiplier": "{{ multiplier|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd.fast_detect.set",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sbfd(?P<bfd>)
+ \sfast-detect(?P<fast_detect>)
+ (\s(?P<opt>(disable|strict-mode)))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_int_bfd_fd,
+ "compval": "address_family.bfd.fast_detect.set",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+
+ },
+ },
+ "bfd": {
+ "fast_detect": {
+ "set": "{{ True if opt != 'disable' and opt != 'strict-mode' and fast_detect is defined else None }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd.fast_detect.disable",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sbfd(?P<bfd>)
+ \sfast-detect(?P<fast_detect>)
+ (\s(?P<opt>(disable|strict-mode)))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_int_bfd_fd,
+ "compval": "address_family.bfd.fast_detect.disable",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+
+ },
+ },
+ "bfd": {
+ "fast_detect": {
+ "disable": "{{ True if opt == 'disable' else None }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd.fast_detect.strict_mode",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sbfd(?P<bfd>)
+ \sfast-detect(?P<fast_detect>)
+ \s(?P<opt>strict-mode)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_int_bfd_fd,
+ "compval": "address_family.bfd.fast_detect.strict_mode",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "bfd": {
+ "fast_detect": {
+ "strict_mode": "{{ True if opt == 'strict-mode' else None }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \scost\s(?P<cost>\S+)$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_cost_config,
+ "compval": "address_family.cost",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "cost": "{{ cost }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "cost_fallback",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \scost-fallback\s(?P<cost>\S+)
+ \sthreshold\s(?P<threshold>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_cost_fallback_config,
+ "compval": "address_family.cost_fallback",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "cost_fallback": {
+ "cost": "{{ cost }}",
+ "threshold": "{{ threshold }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "dead_interval",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sdead-interval\s(?P<dead_interval>\S+)
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_dead_int_config,
+ "compval": "address_family.dead_interval",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "dead_interval": "{{ dead_interval }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "demand_circuit",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sdemand-circuit\s(?P<demand_circuit>\S+)
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_demand_config,
+ "compval": "address_family.demand_circuit",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "demand_circuit": "{{ True if demand_circuit == 'enable' else False if demand_circuit == 'disable' else None }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "flood_reduction",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sflood-reduction\s(?P<flood_reduction>\S+)
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "flood-reduction {{ 'enable' if flood_reduction == True else 'disable' }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "flood_reduction": "{{ True if flood_reduction == 'enable' else False if flood_reduction == 'disable' else None }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "hello_interval",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \shello-interval\s(?P<dead_interval>\S+)
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "hello-interval {{ hello_interval }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "hello_interval": "{{ hello_interval }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "link_down.set",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \s(?P<link_down>link-down)
+ (\s(?P<disable>disable))?
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "link-down",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "link_down": {
+ "set": "{{ True if link_down is defined and disable is undefined else None}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "link_down.disable",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \s(?P<link_down>link-down)
+ \s(?P<disable>disable)
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "link-down disable",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "link_down": {
+ "disable": "{{ True if disable is defined else None }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "message_digest_key",
+ "getval": re.compile(
+ r"""
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \smessage-digest-key
+ \s(?P<id>\d+)
+ \smd5
+ \s(?P<encryption>\d)
+ \s(?P<key>\S+)$""",
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface "
+ "{{ type }} {{ name }} #message-digest-key {{ message_digest_key.id }} "
+ "md5 encrypted {{ message_digest_key.encrypted}}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "message_digest_key": {
+ "id": "{{ id }}",
+ "encrypted": "{{ encryption }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "mpls.set_ldp",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \s(?P<mpls>mpls)
+ \s(?P<ldp>set_ldp)
+ (\s(?P<sync>sync))?
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "mpls ldp",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "mpls": {
+ "set_ldp": "{{ True if set_ldp is defined and sync is undefined else None}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "mpls.ldp_sync",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \s(?P<mpls>mpls)
+ \s(?P<ldp>ldp)
+ \s(?P<sync>sync)
+ (\s(?P<disable>disable))?
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "mpls ldp sync",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "mpls": {
+ "ldp_sync": "{{ True if sync is defined and disable is undefined else None}}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "mpls.ldp_sync_disable",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \s(?P<mpls>mpls)
+ \s(?P<ldp>ldp)
+ \s(?P<sync>sync)
+ \s(?P<disable>disable)
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "mpls ldp sync disable",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "mpls": {
+ "ldp_sync": "{{ False if disable is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "mtu_ignore",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \smtu-ignore\s(?P<mtu_ignore>\S+)
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "mtu_ignore {{ 'enable' if mtu_ignore == 'True' else 'disable' if mtu_ignore == 'False' }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "mtu_ignore": "{{ True if mtu_ignore == 'enable' else False if mtu_ignore == 'disable' else None }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "network",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \snetwork\s(?P<network>\S+)
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "network {{ network }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "network": "{{ network }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "packet_size",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \spacket-size\s(?P<packet_size>\S+)
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "packet-size {{ packet_size }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "packet_size": "{{ packet_size }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "passive",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \spassive\s(?P<passive>\S+)
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "passive {{ 'enable' if passive == 'True' else 'disable' if passive == 'False' }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "passive": "{{ True if passive == 'enable' else False if passive == 'disable' else None }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "prefix_suppression.disable",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sprefix-suppression\s(?P<prefix_suppression>\S+)
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "prefix-suppression {{ prefix_suppression }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "prefix_suppression": {
+ "disable": "{{ True if prefix_suppression == 'disable' else None }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "prefix_suppression.secondary_address",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \s(?P<prefix_suppression>prefix-suppression)
+ \s(?P<secondary_address>secondary-address)
+ (\s(?P<disable>disable))?
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "prefix-suppression secondary-address {{ disable if secondary_address is False }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "prefix_suppression": {
+ "secondary_address": "{{ True if secondary_address is defined and "
+ "disable is undefined else False if disable is defined else None }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "priority",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \spriority\s(?P<priority>\d+)
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "priority {{ priority }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "priority": "{{ priority|int }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "retransmit_interval",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \sretransmit-interval\s(?P<retransmit_interval>\d+)
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "retransmit-interval {{ retransmit_interval }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "retransmit_interval": "{{ retransmit_interval|int }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "security.ttl_hops",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \s(?P<security>security)
+ \s(?P<ttl>ttl)
+ \shops\s(?P<hops>\d+)
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "security ttl hops {{ hops }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "security_ttl": {
+ "hops": "{{ hops|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "security.ttl",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \s(?P<security>security)
+ \s(?P<ttl>ttl)
+ (\s(?P<hops>hops))?
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "security ttl",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "security_ttl": {
+ "set": "{{ True if ttl is defined and hops is undefined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "transmit_delay",
+ "getval": re.compile(
+ r'''
+ ^router
+ \s(?P<ospf_type>ospf|ospfv3)
+ \s(?P<process_id>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sinterface\s(?P<name>\S+)
+ \stransmit-delay\s(?P<transmit_delay>\d+)
+ $''',
+ re.VERBOSE,
+ ),
+ "setval": "router {{ ospf_type }} {{ process_id }} area {{ area_id }} interface {{ type }} {{ name }} "
+ "transmit-delay {{ transmit_delay }}",
+ "result": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ "type": "{{ 'gigabitethernet' if 'GigabitEthernet' in name else 'loopback' if 'Loopback' in name }}",
+ "address_family": {
+ "{{ ospf_type }}": {
+ "afi": "{{ 'ipv4' if ospf_type == 'ospf' else 'ipv6' }}",
+ "processes": {
+ "{{ process_id }}": {
+ "process_id": "{{ process_id }}",
+ "area": {
+ "area_id": "{{ area_id }}",
+ },
+ },
+ },
+ "transmit_delay": "{{ transmit_delay|int }}",
+ },
+ },
+ },
+ },
+ },
+ ]
+ # fmt: on
diff --git a/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
new file mode 100644
index 00000000..e5a54a64
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv2.py
@@ -0,0 +1,2856 @@
+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.rm_base.network_template import (
+ NetworkTemplate,
+)
+
+
+def _tmplt_ospf_default_information(config_data):
+ if "default_information_originate" in config_data:
+ command = "default-information originate"
+ if "always" in config_data["default_information_originate"]:
+ command += " always"
+ if "metric" in config_data["default_information_originate"]:
+ command += " metric {metric}".format(**config_data["default_information_originate"])
+ if "metric_type" in config_data["default_information_originate"]:
+ command += " metric-type {metric_type}".format(
+ **config_data["default_information_originate"]
+ )
+ if "route_policy" in config_data["default_information_originate"]:
+ command += " route-policy {route_policy}".format(
+ **config_data["default_information_originate"]
+ )
+ return command
+
+
+def _tmplt_ospf_auto_cost(config_data):
+ if "auto_cost" in config_data:
+ command = "auto-cost"
+ if "disable" in config_data["auto_cost"]:
+ command += " disable"
+ if "reference_bandwidth" in config_data["auto_cost"]:
+ command += " reference-bandwidth {reference_bandwidth}".format(
+ **config_data["auto_cost"]
+ )
+ return command
+
+
+def _tmplt_ospf_bfd(config_data):
+ if "bfd" in config_data:
+ command = "bfd"
+ if "minimum_interval" in config_data["bfd"]:
+ command += " minimum-interval {minimum_interval}".format(**config_data["bfd"])
+
+ if "multiplier" in config_data["bfd"]:
+ command += " multiplier {multiplier}".format(**config_data["bfd"])
+
+ return command
+
+
+def _tmplt_ospf_security(config_data):
+ if "security_ttl" in config_data:
+ command = "security_ttl"
+ if "set" in config_data["security_ttl"]:
+ command += " ttl"
+ elif config_data["security_ttl"].get("hops"):
+ command += " ttl hops {0}".format(
+ config_data["security_ttl"].get("hops"),
+ )
+ return command
+
+
+def _tmplt_ospf_log_adjacency(config_data):
+ if "log_adjacency_changes" in config_data:
+ command = "log adjacency"
+ if "set" in config_data["log_adjacency_changes"]:
+ command += " changes"
+ elif config_data["log_adjacency_changes"].get("disable"):
+ command += " disable"
+ elif config_data["log_adjacency_changes"].get("details"):
+ command += " details"
+ return command
+
+
+def _tmplt_ospf_log_max_lsa(config_data):
+ if "max_lsa" in config_data:
+ command = "max-lsa"
+ if "threshold" in config_data["max_lsa"]:
+ command += " {0}".format(config_data["max_lsa"].get("threshold"))
+ if "warning_only" in config_data["max_lsa"]:
+ command += " warning-only {0}".format(
+ config_data["max_lsa"].get("warning_only"),
+ )
+ if "ignore_time" in config_data["max_lsa"]:
+ command += " ignore-time {0}".format(
+ config_data["max_lsa"].get("ignore_time"),
+ )
+ if "ignore_count" in config_data["max_lsa"]:
+ command += " ignore-count {0}".format(
+ config_data["max_lsa"].get("ignore_count"),
+ )
+ if "reset_time" in config_data["max_lsa"]:
+ command += " reset-time {0}".format(
+ config_data["max_lsa"].get("reset_time"),
+ )
+ return command
+
+
+def _tmplt_ospf_max_metric(config_data):
+ if "max_metric" in config_data:
+ command = "max-metric"
+ if "router_lsa" in config_data["max_metric"]:
+ command += " router-lsa"
+ if "external_lsa" in config_data["max_metric"]:
+ command += " external-lsa {external_lsa}".format(**config_data["max_metric"])
+ if "include_stub" in config_data["max_metric"]:
+ command += " include-stub"
+ if "on_startup" in config_data["max_metric"]:
+ if "time" in config_data["max_metric"]["on_startup"]:
+ command += " on-startup {time}".format(**config_data["max_metric"]["on_startup"])
+ elif "wait_for_bgp" in config_data["max_metric"]["on_startup"]:
+ command += " on-startup wait-for-bgp"
+ if "summary_lsa" in config_data["max_metric"]:
+ command += " summary-lsa {summary_lsa}".format(**config_data["max_metric"])
+ return command
+
+
+def _tmplt_ospf_distance_admin(config_data):
+ if "admin_distance" in config_data:
+ command = "distance"
+ if config_data["admin_distance"].get("value"):
+ command += " {0}".format(
+ config_data["admin_distance"].get("value"),
+ )
+ if config_data["admin_distance"].get("source"):
+ command += " {0}".format(
+ config_data["admin_distance"].get("source"),
+ )
+ if config_data["admin_distance"].get("wildcard"):
+ command += " {0}".format(
+ config_data["admin_distance"].get("wildcard"),
+ )
+ if config_data["admin_distance"].get("access_list"):
+ command += " {0}".format(
+ config_data["admin_distance"].get("access_list"),
+ )
+ return command
+
+
+def _tmplt_ospf_distance_ospf(config_data):
+ if "ospf_distance" in config_data:
+ command = "distance ospf"
+ if config_data["ospf_distance"].get("external"):
+ command += " external {0}".format(
+ config_data["ospf_distance"].get("external"),
+ )
+ if config_data["ospf_distance"].get("inter_area"):
+ command += " inter-area {0}".format(
+ config_data["ospf_distance"].get("inter_area"),
+ )
+ if config_data["ospf_distance"].get("intra_area"):
+ command += " intra-area {0}".format(
+ config_data["ospf_distance"].get("intra_area"),
+ )
+ return command
+
+
+def _tmplt_ospf_nsr(config_data):
+ if "nsr" in config_data:
+ command = "nsr"
+ if "set" in config_data["nsr"]:
+ command += " nsr"
+ elif config_data["nsr"].get("disable"):
+ command += " nsr {0}".format("disable")
+ return command
+
+
+def _tmplt_ospf_protocol(config_data):
+ if "protocol_shutdown" in config_data:
+ command = "protocol"
+ if "set" in config_data["protocol_shutdown"]:
+ command += " shutdown"
+ elif config_data["shutdown"].get("host_mode"):
+ command += " shutdown host-mode"
+ elif config_data["shutdown"].get("on_reload"):
+ command += " shutdown on-reload"
+ return command
+
+
+def _tmplt_microloop_avoidance(config_data):
+ if "microloop_avoidance" in config_data:
+ command = "microloop avoidance"
+ if "protected" in config_data["microloop_avoidance"]:
+ command += " protected"
+ if "segment_routing" in config_data["microloop_avoidance"]:
+ command += " segment_routing"
+ if "rib_update_delay" in config_data["microloop_avoidance"]:
+ command += " rin-update-delay {0}".config_data["microloop_avoidance"].get(
+ "rib_update_delay",
+ )
+ return command
+
+
+def _tmplt_ospf_bfd_fast_detect(config_data):
+ if "bfd" in config_data:
+ command = "bfd"
+ if "fast_detect" in config_data["bfd"]:
+ fast_detect = config_data["bfd"].get("fast_detect")
+ command += " fast-detect"
+ if "strict_mode" in fast_detect:
+ command += " strict-mode"
+ return command
+
+
+def _tmplt_ospf_mpls_traffic_eng(config_data):
+ if "traffic_eng" in config_data:
+ command = "mpls traffic-eng"
+ if "igp_intact" in config_data["traffic_eng"]:
+ command += " igp-intact"
+ if "ldp_sync_update" in config_data["traffic_eng"]:
+ command += " ldp_sync_update"
+ if "multicast_intact" in config_data["traffic_eng"]:
+ command += " multicast_intact"
+ if "auto_route_exclude" in config_data["traffic_eng"]:
+ policy = config_data["traffic_eng"].get("autoroute_exclude")
+ command += " autoroute-exlude route-policy {0}".format(
+ policy.get("route_policy"),
+ )
+ return command
+
+
+def _tmplt_ospf_authentication_md(config_data):
+ command = []
+ if "authentication" in config_data:
+ if config_data["authentication"].get("message_digest"):
+ command = "authentication message-digest"
+ md = config_data["authentication"].get("message_digest")
+ if md.get("keychain"):
+ command += " keychain " + md.get("keychain")
+ return command
+
+
+def _tmplt_ospf_authentication(config_data):
+ command = []
+ if "authentication" in config_data:
+ if config_data["authentication"].get("keychain"):
+ command = "authentication keychain " + config_data["authentication"].get("keychain")
+ elif config_data["authentication"].get("no_auth"):
+ command = "authentication null"
+ return command
+
+
+def _tmplt_ospf_adjacency_stagger(config_data):
+ if "adjacency_stagger" in config_data:
+ command = "adjacency stagger".format(**config_data)
+ if config_data["adjacency_stagger"].get("min_adjacency") and config_data[
+ "adjacency_stagger"
+ ].get("min_adjacency"):
+ command += " {0} {1}".format(
+ config_data["adjacency_stagger"].get("min_adjacency"),
+ config_data["adjacency_stagger"].get("max_adjacency"),
+ )
+ elif config_data["adjacency_stagger"].get("disable"):
+ command += " disable"
+ return command
+
+
+def _tmplt_ospf_adjacency_distribute_bgp_state(config_data):
+ if "distribute_link_list" in config_data:
+ command = "distribute link-state"
+ if config_data["distribute_link_list"].get("instance_id"):
+ command += " instance-id {0}".format(
+ config_data["distribute_link_list"].get("instance_id"),
+ )
+ elif config_data["distribute_link_list"].get("throttle"):
+ command += " throttle {0}".format(
+ config_data["distribute_link_list"].get("throttle"),
+ )
+ return command
+ elif "distribute_bgp_ls" in config_data:
+ command = "distribute bgp-ls"
+ if config_data["distribute_bgp_ls"].get("instance_id"):
+ command += " instance-id {0}".format(
+ config_data["distribute_bgp_ls"].get("instance_id"),
+ )
+ elif config_data["distribute_bgp_ls"].get("throttle"):
+ command += " throttle {0}".format(
+ config_data["distribute_bgp_ls"].get("throttle"),
+ )
+ return command
+
+
+def _tmplt_ospf_capability_opaque(config_data):
+ if "capability" in config_data:
+ if "opaque" in config_data["capability"]:
+ command = "capability opaque"
+ opaque = config_data["capability"].get("opaque")
+ if "disable" in opaque:
+ command += "capability opaque disable"
+ return command
+
+
+def _tmplt_ospf_authentication_key(config_data):
+ if "authentication_key" in config_data:
+ command = "authentication-key".format(**config_data)
+ if config_data["authentication_key"].get("password"):
+ command += " {0}".format(
+ config_data["authentication_key"].get("password"),
+ )
+ return command
+
+
+def _tmplt_ospf_area_authentication(config_data):
+ if "authentication" in config_data:
+ command = "area {area_id} authentication".format(**config_data)
+ if config_data["authentication"].get("keychain"):
+ command += " keychain " + config_data["authentication"].get(
+ "keychain",
+ )
+ elif config_data["authentication"].get("no_auth"):
+ command += " null"
+ return command
+
+
+def _tmplt_ospf_area_authentication_md(config_data):
+ if "authentication" in config_data:
+ command = "area {area_id} authentication".format(**config_data)
+ if "message_digest" in config_data["authentication"]:
+ command = "authentication message-digest"
+ md = config_data["authentication"].get("message_digest")
+ if md.get("keychain"):
+ command += " keychain " + md.get("keychain")
+ return command
+
+
+def _tmplt_ospf_area_authentication_key(config_data):
+ if "authentication_key" in config_data:
+ command = "area {area_id} authentication-key".format(**config_data)
+ if config_data["authentication_key"].get("password"):
+ command += " {0}".format(
+ config_data["authentication_key"].get("password"),
+ )
+ return command
+
+
+def _tmplt_ospf_area_mpls_ldp(config_data):
+ commands = []
+ if "mpls" in config_data:
+ command = "area {area_id} mpls".format(**config_data)
+ if config_data["mpls"].get("ldp"):
+ ldp = config_data["mpls"].get("ldp")
+ if "auto_config" in ldp:
+ command += " auto-config"
+ commands.append(command)
+ if "sync" in ldp:
+ command += " sync"
+ commands.append(command)
+ if "sync_igp_shortcuts" in ldp:
+ command += " sync-igp-shortcuts"
+ commands.append(command)
+ return commands
+
+
+def _tmplt_ospf_area_bfd(config_data):
+ if "bfd" in config_data:
+ command = "area {area_id} bfd".format(**config_data)
+ if "minimum_interval" in config_data["bfd"]:
+ command += " minimum-interval {minimum_interval}".format(**config_data["bfd"])
+
+ if "multiplier" in config_data["bfd"]:
+ command += " multiplier {multiplier}".format(**config_data["bfd"])
+
+ return command
+
+
+def _tmplt_ospf_area_bfd_fast_detect(config_data):
+ if "bfd" in config_data:
+ command = "area {area_id} bfd".format(**config_data)
+ if "fast_detect" in config_data["bfd"]:
+ fast_detect = config_data["bfd"].get("fast_detect")
+ command += " fast-detect"
+ if "strict_mode" in fast_detect:
+ command += " strict-mode"
+ return command
+
+
+def _tmplt_ospf_mpls_ldp(config_data):
+ commands = []
+ if "mpls" in config_data:
+ command = "mpls".format(**config_data)
+ if config_data["mpls"].get("ldp"):
+ ldp = config_data["mpls"].get("ldp")
+ if "auto_config" in ldp:
+ command += " auto-config"
+ commands.append(command)
+ if "sync" in ldp:
+ command += " sync"
+ commands.append(command)
+ if "sync_igp_shortcuts" in ldp:
+ command += " sync-igp-shortcuts"
+ commands.append(command)
+ return commands
+
+
+def _tmplt_ospf_area_nssa(config_data):
+ if "nssa" in config_data:
+ command = "area {area_id} nssa".format(**config_data)
+ if config_data["nssa"].get("no_redistribution"):
+ command += " no-redistribution"
+ if config_data["nssa"].get("no_summary"):
+ command += " no-summary"
+ return command
+
+
+def _tmplt_ospf_area_nssa_def_info_origin(config_data):
+ if "nssa" in config_data:
+ command = "area {area_id} nssa".format(**config_data)
+ if "default_information_originate" in config_data["nssa"]:
+ command += " default-information-originate"
+ def_info_origin = config_data["nssa"].get(
+ "default_information_originate",
+ )
+ if "metric" in def_info_origin:
+ command += " metric {metric}".format(
+ **config_data["nssa"]["default_information_originate"]
+ )
+ if "metric_type" in def_info_origin:
+ command += " metric-type {metric_type}".format(
+ **config_data["nssa"]["default_information_originate"]
+ )
+ return command
+
+
+def _tmplt_ospf_area_nssa_translate(config_data):
+ if "nssa" in config_data:
+ command = "area {area_id} nssa".format(**config_data)
+ if config_data["nssa"].get("translate"):
+ command += " translate"
+ translate = config_data["nssa"].get("translate")
+ if "type7" in translate:
+ command += " type7"
+ if translate["type7"].get("always"):
+ command += " always"
+ return command
+
+
+def _tmplt_ospf_area_vlink_authentication(config_data):
+ if "authentication" in config_data:
+ command = "area {area_id} virtual-link {id} authentication".format(**config_data)
+ if config_data["authentication"].get("keychain"):
+ command += " keychain " + config_data["authentication"].get(
+ "keychain",
+ )
+ elif config_data["authentication"].get("no_auth"):
+ command += " null"
+ return command
+
+
+def _tmplt_ospf_area_vlink_authentication_md(config_data):
+ if "authentication" in config_data:
+ command = "area {area_id} virtual-link {id} authentication".format(**config_data)
+ if config_data["authentication"].get("message_digest"):
+ command = "authentication message-digest"
+ md = config_data["authentication"].get("message_digest")
+ if md.get("keychain"):
+ command += " keychain " + md.get("keychain")
+ return command
+
+
+def _tmplt_ospf_area_vlink_authentication_key(config_data):
+ if "authentication_key" in config_data:
+ command = "area {area_id} virtual-link {id} authentication-key".format(**config_data)
+ if config_data["authentication_key"].get("password"):
+ command += " {0}".format(
+ config_data["authentication_key"].get("password"),
+ )
+ return command
+
+
+def _tmplt_ospf_area_stub(config_data):
+ if "stub" in config_data:
+ command = "area {area_id} stub".format(**config_data)
+ if config_data["stub"].get("no_summary"):
+ command += " no-summary"
+ return command
+
+
+def _tmplt_ospf_area_ranges(config_data):
+ if "ranges" in config_data:
+ commands = []
+ for k, v in iteritems(config_data["ranges"]):
+ cmd = "area {area_id} range".format(**config_data)
+ temp_cmd = " {address}".format(**v)
+ if "advertise" in v:
+ temp_cmd += " advertise"
+ elif "not_advertise" in v:
+ temp_cmd += " not-advertise"
+ cmd += temp_cmd
+ commands.append(cmd)
+ return commands
+
+
+def _tmplt_prefix_suppression(config_data):
+ if "prefix_suppression" in config_data:
+ if "set" in config_data["prefix_suppression"]:
+ command = "prefix-suppression"
+ if "secondary_address" in config_data["prefix_suppression"]:
+ command = "prefix-suppression secondary-address"
+ return command
+
+
+def _tmplt_protocol_shutdown(config_data):
+ if "protocol_shutdown" in config_data:
+ if "set" in config_data["protocol_shutdown"]:
+ command = "protocol-shutdown"
+ if "host_mode" in config_data["protocol_shutdown"]:
+ command = "protocol-shutdown host-mode"
+ if "on_reload" in config_data["protocol_shutdown"]:
+ command = "protocol-shutdown on-reload"
+ return command
+
+
+def _tmplt_timers_lsa(config_data):
+ if "timers" in config_data:
+ command = "timers lsa"
+ if "group_pacing" in config_data["timers"]["lsa"]:
+ command += " group-pacing {group_pacing}".format(**config_data["timers"]["lsa"])
+ if "min_arrival" in config_data["timers"]["lsa"]:
+ command += " min-arrival {min_arrival}".format(**config_data["timers"]["lsa"])
+ if "refresh" in config_data["timers"]["lsa"]:
+ command += " refresh {refresh}".format(**config_data["timers"]["lsa"])
+ return command
+
+
+def _tmplt_timers_graceful_shutdown(config_data):
+ if "timers" in config_data:
+ command = "timers graceful-shutdown"
+ if "initial_delay" in config_data["timers"]["graceful-shutdown"]:
+ command += " initial delay {initial_delay}".format(
+ **config_data["timers"]["graceful-shutdown"]
+ )
+ if "retain_routes" in config_data["timers"]["graceful-shutdown"]:
+ command += " retain routes {retain_routes}".format(
+ **config_data["timers"]["graceful-shutdown"]
+ )
+ return command
+
+
+class Ospfv2Template(NetworkTemplate):
+ def __init__(self, lines=None, module=None):
+ super(Ospfv2Template, self).__init__(
+ lines=lines,
+ tmplt=self,
+ module=module,
+ )
+
+ # fmt: off
+ PARSERS = [
+ {
+ "name": "pid",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "router ospf {{ process_id }}",
+ "result": {
+ "processes": {"{{ pid }}": {"process_id": "{{ pid }}"}},
+ },
+ "shared": True,
+ },
+ {
+ "name": "cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \scost(?P<cost>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "cost {{ cost }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "cost": "{{ cost|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "default_metric",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdefault-metric(?P<default_metric>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "default-metric {{ default_metric }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "default_metric": "{{ default_metric|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "packet_size",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \spacket-size(?P<packet_size>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "packet-size {{ packet_size }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "packet_size": "{{ packet_size|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "dead_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdead-interval(?P<dead_interval>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "dead-interval {{ dead_interval }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "dead_interval": "{{ dead_interval|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "hello_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \shello-interval(?P<hello_interval>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "hello-interval {{ hello_interval }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "hello_interval": "{{ hello_interval|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "priority",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \spriority(?P<priority>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "priority {{ priority }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "priority": "{{ priority|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "weight",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sweight(?P<weight>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "weight {{ weight }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "weight": "{{ weight|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "retransmit_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sretransmit-interval(?P<retransmit_interval>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "retransmit-interval {{ retransmit_interval }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "retransmit_interval": "{{ retransmit_interval|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "transmit_delay",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \stransmit-delay(?P<transmit_delay>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "transmit-delay {{ transmit_delay }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "transmit_delay": "{{ transmit_delay|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "passive",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \spassive\s(?P<passive>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "passive {{ passive }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "passive": "{{ passive }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "process.database_filter",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdatabase-filter
+ \sall
+ \sout\s(?P<database_filter>\s\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "process.database_filter",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "database_filter": "{{ database_filter }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "demand_circuit",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdemand-circuit\s(?P<demand_circuit>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "demand-circuit {{ demand_circuit }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "demand_circuit": "{{ demand_circuit }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "external_out",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sexternal-out\s(?P<external_out>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "external-out {{ external_out }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "external_out": "{{ external_out }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "router_id",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \srouter-id\s(?P<router_id>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "router-id {{ router_id }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "router_id": "{{ router_id }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "summary_in",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \ssummary-in\s(?P<summary_in>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "summary-in {{ summary_in }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "summary_in": "{{ summary_in }}",
+ },
+ },
+ },
+ },
+
+ {
+ "name": "mtu_ignore",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \smtu-ignore\s(?P<mtu_ignore>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "mtu-ignore {{ mtu_ignore }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "mtu_ignore": "{{ mtu_ignore }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "flood_reduction",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sflood-reduction\s(?P<flood_reduction>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "flood-reduction {{ flood_reduction }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "flood_reduction": "{{ flood_reduction }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "loopback_stub_network",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sloopback(?P<loopback>)
+ \sstub-network\s(?P<stub_network>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "loopback stub-network {{ stub_network }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "loopback_stub_network": "{{ loopback_stub_network }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "address_family_unicast",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \saddress-family(?P<address_family>)
+ \sipv4(?P<ipv4>)
+ \sunicast(?P<unicast>)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "address_family_unicast",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "address_family_unicast": "{{ True if unicast is defined }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "default_weight",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sapply-weight(?P<apply_weight>)
+ \sdefault-weight(?P<default_weight>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "apply-weight default-weight {{ default_weight }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "apply_weight": {
+ "default_weight": "{{ default_weight|int }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bandwidth",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sapply-weight(?P<apply_weight>)
+ \sbandwidth(?P<bandwidth>\s\d+)?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "apply-weight bandwidth {{ bandwidth }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "apply_weight": {
+ "bandwidth": "{{ bandwidth|int }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "adjacency_stagger",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sadjacency(?P<adjacency>)
+ \sstagger(?P<stagger>)
+ (\s(?P<min_adjacency>\d+))?
+ (\s(?P<max_adjacency>\d+))?
+ (\sdisable(?P<disable>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_adjacency_stagger,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "adjacency_stagger": {
+ "min_adjacency": "{{ min_adjacency|int }}",
+ "max_adjacency": "{{ max_adjacency }}",
+ "disable": "{{ True if disable is defined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "authentication",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sauthentication(?P<auth>)
+ (\skeychain\s(?P<keychain>\S+)*)?
+ (\snull(?P<no_auth>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_authentication,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "authentication": {
+ "no_auth": "{{ True if no_auth is defined }}",
+ "keychain": "{{ keychain }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "authentication.message_digest",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sauthentication(?P<auth>)
+ \smessage-digest(?P<md>)
+ \skeychain\s(?P<md_key>\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_authentication_md,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "authentication": {
+ "message_digest": {
+ "keychain": "{{ md_key }}",
+ "set": "{{ True if md is defined and md_key is undefined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "default_information_originate",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdefault-information(?P<default_information>)
+ (\soriginate(?P<originate>))?
+ (\salways(?P<always>))?
+ (\smetric\s(?P<metric>\d+))?
+ (\smetric-type\s(?P<metric_type>\d+))?
+ (\sroute_policy\s(?P<route_policy>)\S+)?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_default_information,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "default_information_originate": {
+ "always": "{{ True if always is defined }}",
+ "metric": "{{ metric|int }}",
+ "metric_type": "{{ metric_type|int }}",
+ "route_policy": "{{ route_policy }}",
+ "set": "{{ True if default_information is defined and always is undefined and metric "
+ "is undefined and metric_type is undefined and route_policy is undefined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "auto_cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sauto-cost(?P<auto_cost>)
+ (\sreference-bandwidth\s(?P<reference_bandwidth>\d+))?
+ (\sdisable(?P<disable>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_auto_cost,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "auto_cost": {
+ "disable": "{{ True if disable is defined }}",
+ "reference_bandwidth": "{{ reference_bandwidth|int }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sbfd(?P<bfd>)
+ (\sminimum-interval\s(?P<minimum_interval>\d+))?
+ (\smultiplier\s(?P<multiplier>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_bfd,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "bfd": {
+ "minimum_interval": "{{ minimum_interval|int }}",
+ "multiplier": "{{ multiplier|int }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd.fast_detect",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sbfd(?P<bfd>)
+ \sfast-detect(?P<fast_detect>)
+ (\s(?P<disable>disable))?
+ (\s(?P<strict_mode>strict-mode))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_bfd_fast_detect,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "bfd": {
+ "fast_detect": {
+ "set": "{{ True if disable is undefined and strict_mode is undefined }}",
+ "strict_mode": "{{ True if strict_mode is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "security",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \ssecurity(?P<security>)
+ \sttl(?P<ttl>)?
+ (\shops\s(?P<hops>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_security,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "security_ttl": {
+ "set": "{{ True if ttl is defined and hops is undefined }}",
+ "hops": "{{ hops }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "nsr",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \snsr(?P<nsr>)
+ \sdisable(?P<disable>)?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_nsr,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "nsr": {
+ "set": "{{ True if nsr is defined and disable is undefined }}",
+ "disable": "{{ True if disable is defined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "protocol",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sprotocol(?P<protocol>)
+ \s(shutdown(?P<shutdown>))
+ (\shost-mode(?P<host_mode>))?
+ (\son-reload\s(?P<on_reload>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_protocol,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "protocol_shutdown": {
+ "set": "{{ True if shutdown is defined and host-mode is undefined and on_reload is undefined }}",
+ "host_mode": "{{ True if host_mode is defined }}",
+ "on_reload": "{{ True if on_reload is defined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "capability",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \scapability(?P<capability>)
+ (\stype7\s(?P<type7>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "capability type7 {{ type7 }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "capability": {
+ "type7": "{{ type7 }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "capability.opaque",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \scapability(?P<capability>)?
+ \sopaque(?P<opaque>)
+ (\sdisable(?P<disable>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_capability_opaque,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "capability": {
+ "opaque": {
+ "disable": "{{ True if disable is defined }}",
+ "set": "{{ True if opaque is defined and disable is undefined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "admin_distance",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdistance\s(?P<value>d+)
+ \s(?P<source>\S+)
+ \s(?P<wildcard>\S+)
+ (\s(?P<access_list>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_distance_admin,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "distance": {
+ "admin_distance": {
+ "value": "{{ value|int }}",
+ "source": "{{ source }}",
+ "wildcard": "{{ wildcard }}",
+ "access_list": "{{ access_list }}",
+ },
+ },
+ },
+ },
+ },
+ },
+
+ {
+ "name": "ospf_distance",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdistance(?P<value>)
+ \sospf(?P<ospf>)
+ (\sexternal\s(?P<external>\d+))?
+ (\sinter-area\s(?P<inter_area>\d+))?
+ (\sintra-area\s(?P<intra_area>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_distance_ospf,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "distance": {
+ "ospf_distance": {
+ "external": "{{ external|int }}",
+ "inter_area": "{{ inter_area|int }}",
+ "intra_area": "{{ intra_area|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "authentication_key",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sauthentication-key(?P<auth_key>)
+ (\s(?P<password>\S+))?
+ (\sclear\s(?P<clear>)\S+)?
+ (\sencrypted(?P<encrypted>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_authentication_key,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "authentication_key": {
+ "clear": "{{ clear }}",
+ "encrypted": "{{ encrypted}}",
+ "password": "{{ password if clear is undefined and encrypted is undefined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.default_cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sdefault-cost\s(?P<default_cost>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} default-cost {{ default_cost }}",
+ "compval": "default_cost",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "default_cost": "{{ default_cost|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.dead_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sdead-interval\s(?P<dead_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} dead-interval {{ dead_interval }}",
+ "compval": "dead_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "dead_interval": "{{ dead_interval|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.hello_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \shello-interval\s(?P<hello_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} hello-interval {{ hello_interval }}",
+ "compval": "hello_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "hello_interval": "{{ hello_interval|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.transmit_delay",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \stransmit-delay\s(?P<transmit_delay>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} transmit-delay {{ transmit_delay }}",
+ "compval": "transmit_delay",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "transmit_delay": "{{ transmit_delay|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \scost\s(?P<cost>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} cost {{ cost }}",
+ "compval": "cost",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "cost": "{{ cost|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.priority",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \spriority\s(?P<priority>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} priority {{ priority }}",
+ "compval": "priority",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "priority": "{{ priority|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.weight",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sweight\s(?P<weight>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} weight {{ weight }}",
+ "compval": "weight",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "weight": "{{ weight|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.packet_size",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \spacket-size\s(?P<packet_size>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} packet-size {{ packet_size }}",
+ "compval": "packet_size",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "packet_size": "{{ packet_size|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.summary_in",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \ssummary-in\s(?P<summary_in>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} summary-in {{ summary_in }}",
+ "compval": "summary_in",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "summary_in": "{{ summary_in }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.demand_circuit",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sdemand-circuit\s(?P<demand_circuit>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} demand-circuit {{ demand_circuit }}",
+ "compval": "demand_circuit",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "demand_circuit": "{{ demand_circuit }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.passive",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \spassive\s(?P<passive>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} passive {{ passive }}",
+ "compval": "passive",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "passive": "{{ passive }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.external_out",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sexternal-out\s(?P<external_out>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} external-out {{ external_out }}",
+ "compval": "passive",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "external_out": "{{ external_out }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.mtu_ignore",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \smtu-ignore\s(?P<mtu_ignore>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} mtu-ignore {{ mtu_ignore }}",
+ "compval": "mtu_ignore",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "mtu_ignore": "{{ mtu_ignore }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.authentication",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sauthentication(?P<auth>)
+ (\skeychain\s(?P<keychain>\S+))?
+ (\snull(?P<no_auth>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_authentication,
+ "compval": "authentication",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "authentication": {
+ "no_auth": "{{ True if no_auth is defined }}",
+ "keychain": "{{ keychain }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.authentication_key",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sauthentication-key(?P<auth_key>)
+ (\s(?P<password>\S+))?
+ (\sclear\s(?P<clear>)\S+)?
+ (\sencrypted(?P<encrypted>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_authentication_key,
+ "compval": "authentication_key",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "authentication_key": {
+ "clear": "{{ clear }}",
+ "encrypted": "{{ encrypted}}",
+ "password": "{{ password if clear is undefined and encrypted is undefined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.authentication.message_digest",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sauthentication(?P<auth>)
+ \smessage-digest(?P<md>)
+ \skeychain(?P<md_key>\s\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_authentication_md,
+ "compval": "authentication.message_digest",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "authentication": {
+ "message_digest": {
+ "keychain": "{{ md_key }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.mpls_traffic_eng",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \smpls(?P<mpls>)
+ \straffic-end(?P<traffic_eng>)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} mpls traffic-eng",
+ "compval": "mpls_traffic_eng",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "mpls": {
+ "traffic_eng": "{{ True if traffic_eng is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.mpls_ldp",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \smpls(?P<mpls>)
+ (\sauto-config(?P<auto_config>))?
+ (\ssync(?P<sync>))?
+ (\ssync-igp-shortcuts(?P<syn_igp_shortcuts>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_mpls_ldp,
+ "compval": "mpls_ldp",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "mpls": {
+ "ldp": {
+ "auto_config": "{{ True if auto_config is defined }}",
+ "sync": "{{ True if sync is defined }}",
+ "sync_igp_shortcuts": "{{ True if sync_igp_shortcuts is defined }}",
+
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.bfd",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sbfd(?P<bfd>)
+ (\sminimum-interval\s(?P<minimum_interval>\d+))?
+ (\smultiplier\s(?P<multiplier>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_bfd,
+ "compval": "bfd",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "bfd": {
+ "minimum_interval": "{{ minimum_interval|int }}",
+ "multiplier": "{{ multiplier|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.bfd.fast_detect",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sbfd(?P<bfd>)
+ \sarea(?P<area_id>)
+ \sfast-detect(?P<fast_detect>)
+ (\s(?P<disable>disable))?
+ (\s(?P<strict_mode>strict-mode))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_bfd_fast_detect,
+ "compval": "bfd.fast_detect",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "bfd": {
+ "fast_detect": {
+ "set": "{{ True if disable is undefined and strict_mode is undefined }}",
+ "strict_mode": "{{ True if strict_mode is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.stub",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sstub(?P<nssa>)
+ (\sno-summary(?P<no_sum>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_stub,
+ "compval": "stub",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "area_id": "{{ area_id }}",
+ "stub": {
+ "set": "{{ True if stub is defined and no_summary is undefined }}",
+ "no_summary": "{{ True if no_summary is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.nssa",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \snssa(?P<nssa>)
+ (\sno-redistribution(?P<no_redis>))?
+ (\sno-summary(?P<no_sum>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_nssa,
+ "compval": "nssa",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "area_id": "{{ area_id }}",
+ "nssa": {
+ "set": "{{ True if nssa is defined and no_summary is undefined and no_redis is undefined }}",
+ "no_summary": "{{ True if no_summary is defined }}",
+ "no_redistribution": "{{ True if no_redis is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.nssa.default_information_originate",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \snssa(?P<nssa>)
+ (\sno-redistribution(?P<no_redis>))?
+ (\sdefault-information-originate(?P<def_info_origin>))?
+ (\smetric\s(?P<metric>\d+))?
+ (\smetric-type\s(?P<metric_type>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_nssa_def_info_origin,
+ "compval": "nssa.default_information_originate",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "nssa": {
+ "default_information_originate": {
+ "metric": "{{ metric|int }}",
+ "metric_type": "{{ metric_type|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.ranges",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \srange(?P<range>)
+ \s(?P<address>\S+)
+ (\sadvertise(?P<advertise>))
+ (\snot-advertise(?P<not_advertise>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_ranges,
+ "compval": "ranges",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "ranges": [
+ {
+ "address": "{{ address }}",
+ "advertise": "{{ True if advertise is defined }}",
+ "not_advertise": "{{ True if not_advertise is defined }}",
+ },
+ ],
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.nssa.translate",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \snssa(?P<nssa>)
+ \stranslate(?P<translate>)
+ \stype7(?P<type7>)
+ \salways\s(?P<always>)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_nssa_translate,
+ "compval": "nssa.translate",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "area_id": "{{ area_id }}",
+ "nssa": {
+ "translate": {
+ "type7": {
+ "always": "{{ True if always is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "virtual_link.hello_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \shello-interval\s(?P<hello_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} virtual-link {{ id }} hello-interval {{ hello_interval }}",
+ "compval": "hello_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}":
+ {
+ "id": "{{ id }}",
+ "hello_interval": "{{ hello_interval|int }}",
+ },
+
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "virtual_link.dead_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \sdead-interval\s(?P<dead_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} virtual-link {{ id }} dead-interval {{ dead_interval }}",
+ "compval": "dead_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}": {
+ "id": "{{ id }}",
+ "dead_interval": "{{ dead_interval|int }}",
+ },
+
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "virtual_link.retransmit_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \sretransmit-interval\s(?P<retransmit_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} virtual-link {{ id }} retransmit-interval {{ retransmit_interval }}",
+ "compval": "retransmit_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}": {
+ "id": "{{ id }}",
+ "retransmit_interval": "{{ retransmit_interval|int }}",
+ },
+ },
+
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "virtual_link.authentication",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \savirtual-link\s(?P<id>\S+)
+ \sauthentication(?P<auth>)
+ (\skeychain\s(?P<keychain>\S+))?
+ (\snull(?P<no_auth>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_vlink_authentication,
+ "compval": "authentication",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "authentication": {
+ "no_auth": "{{ True if no_auth is defined }}",
+ "keychain": "{{ keychain }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "virtual_link.authentication_key",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \sauthentication-key(?P<auth_key>)
+ (\s(?P<password>\S+))?
+ (\sclear\s(?P<clear>)\S+)?
+ (\sencrypted(?P<encrypted>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_vlink_authentication_key,
+ "compval": "authentication_key",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}": {
+ "authentication_key": {
+ "clear": "{{ clear }}",
+ "encrypted": "{{ encrypted}}",
+ "password": "{{ password if clear is undefined and encrypted is undefined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "virtual_link.authentication.message_digest",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \sauthentication(?P<auth>)
+ \smessage-digest(?P<md>)
+ \skeychain(?P<md_key>\s\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_vlink_authentication_md,
+ "compval": "authentication.message_digest",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}": {
+ "authentication": {
+ "message_digest": {
+ "keychain": "{{ md_key }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "link_down_fast_detect",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \slink-down
+ \sfast-detect(?P<fast_detect>)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "link-down fast-detect",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "link_down_fast_detect": "{{ True if fast_detect is defined }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "nsr",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \snsr
+ \sdisable(?P<disable>)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "nsr disable",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "disable": "{{ True if disable is defined }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "database_filter",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdatabase-filter
+ \sall
+ \sout\s(?P<outing>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "database-filter all out {{ outing }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "outing": "{{ outing }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "distribute_link_state",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdistribute(?P<distribute>)
+ \slink-state(?P<link_state>)
+ (\sinstance-id(?P<inst_id>\d+))?
+ (\sthrottle(?P<throttle>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_adjacency_distribute_bgp_state,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "distribute_link_list": {
+ "instance_id": "{{ inst_id|int }}",
+ "throttle": "{{ throttle }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "distribute_bgp_ls",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sdistribute(?P<distribute>)
+ \sbgp-ls(?P<bgp_ls>)
+ (\sinstance-id(?P<inst_id>\d+))?
+ (\sthrottle(?P<throttle>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_adjacency_distribute_bgp_state,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "distribute_bgp_ls": {
+ "instance_id": "{{ inst_id|int }}",
+ "throttle": "{{ throttle }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "log_adjacency_changes",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \slog(?P<security>)
+ \sadjacency(?P<adjacency>)?
+ (\schanges(?P<changes>))?
+ (\sdisable(?P<disable>))?
+ (\sdetails(?P<details>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_log_adjacency,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "log_adjacency_changes": {
+ "set": "{{ True if changes is defined }}",
+ "disable": "{{ True if disable is defined }}",
+ "details": "{{ True if details is defined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "max_lsa",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ (\smax-lsa\s(?P<threshold>\d+))?
+ (\swarning-only\s(?P<warning_only>\d+)?
+ (\signore-time\s(?P<ignore_time>\d+))?
+ (\signore-count\s(?P<ignore_count>\d+))?
+ (\sreset-time\s(?P<reset_time>)\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_log_max_lsa,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "max_lsa": {
+ "threshold": "{{ threshold|int }}",
+ "warning_only": "{{ warning_only|int }}",
+ "ignore_time": "{{ ignore_time|int }}",
+ "ignore_count": "{{ ignore_count|int }}",
+ "reset_time": "{{ reset_time|int }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "max_metric",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \smax-metric
+ \s*(?P<router_lsa>)
+ (\s*external-lsa(?P<external_lsa>))?
+ (\s(?P<max_metric_value>\d+))?
+ \s*(?P<include_stub>include-stub)*
+ \s*(?P<on_startup>on-startup)*
+ \s*(?P<wait_period>\d+)*
+ \s*(wait-for\sbgp)*
+ \s*(?P<bgp_asn>\d+)*
+ \s*(?P<summary_lsa>summary-lsa)*
+ \s*(?P<sum_lsa_max_metric_value>\d+)*
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_max_metric,
+ "remval": "max-metric router-lsa",
+ "result": {
+ "processes": {
+ '{{ "pid" }}': {
+ "max_metric": {
+ "router_lsa": {
+ "set": "{{ True if router_lsa is defined and external_lsa is undefined else None }}",
+ "external_lsa": {
+ "set": "{{ True if external_lsa is defined and max_metric_value is undefined else None }}",
+ "max_metric_value": "{{ max_metric_value }}",
+ },
+ "include_stub": "{{ not not include_stub }}",
+ "on_startup": {
+ "set": "{{ True if on_startup is defined and (wait_period and bgp_asn) is undefined else None }}",
+ "wait_period": "{{ wait_period }}",
+ "wait_for_bgp_asn": "{{ bgp_asn }}",
+ },
+ "summary_lsa": {
+ "set": "{{ True if summary_lsa is defined and sum_lsa_max_metric_value is undefined else None }}",
+ "max_metric_value": "{{ sum_lsa_max_metric_value }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "mpls_ldp",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \smpls(?P<mpls>)
+ (\sauto-config(?P<auto_config>))?
+ (\ssync(?P<sync>))?
+ (\ssync-igp-shortcuts(?P<syn_igp_shortcuts>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_mpls_ldp,
+ "compval": "mpls_ldp",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "mpls": {
+ "ldp": {
+ "auto_config": "{{ True if auto_config is defined }}",
+ "sync": "{{ True if sync is defined }}",
+ "sync_igp_shortcuts": "{{ True if sync_igp_shortcuts is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "microloop_avoidance",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \smicroloop(?P<microloop>)
+ \savoidance(?P<avoidance>)
+ (\s(?P<protected>protected))?
+ (\s(?P<segment_routing>segment-routing))?
+ (\srib-update-delay\s(?P<rib_update_delay>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_microloop_avoidance,
+ "compval": "microloop_avoidance",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "microloop_avoidance": {
+ "protected": "{{ True if protected is defined }}",
+ "segment_routing": "{{ True if segment_routing is defined }}",
+ "rib_update_delay": "{{ rib_update_delay }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "mpls_traffic_eng",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \smpls(?P<mpls>)
+ \straffic-end(?P<traffic_eng>)
+ (\sautoroute-exclude(?P<autoroute>))?
+ (\sroute-policy(?P<route_policy>\S+))?
+ (\s(?P<igp_intact>igp_intact))?
+ (\s(?P<ldp_sync_update>ldp-sync-update))?
+ (\s(?P<multicast_intact>multicast-intact))?
+ (\srouter-id\s(?P<router_id>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_mpls_traffic_eng,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "mpls": {
+ "autoroute_exclude": {
+ "route_policy": "{{ route_policy }}",
+ },
+ "igp_intact": "{{ True if igp_intact is defined }}",
+ "ldp_sync_update": "{{ True if ldp_sync_update is defined }}",
+ "multicast_intact": "{{ True if multicast_intact is defined }}",
+ "router_id": "{{ router_id }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "prefix_suppression",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sprefix-suppression(?P<prefix_suppression>)
+ (\s(?P<secondary_address>secondary-address))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_prefix_suppression,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "prefix_suppression": {
+ "set": "{{ True if prefix_suppression is defined and secondary_address is undefined }}",
+ "secondary_address": "{{ True if secondary_address is defined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "protocol_shutdown",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \sprotocol-shutdown(?P<protocol_shutdown>)
+ (\s(?P<host_mode>host-mode))?
+ (\s(?P<on_reload>on-reload))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_protocol_shutdown,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "protocol_shutdown": {
+ "set": "{{ True if protocol_shutdown is defined and host_mode is undefined and on_reload is undefined }}",
+ "host_mode": "{{ True if host_mode is defined }}",
+ "on_reload": "{{ True if on_reload is defined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "timers.lsa",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \stimers
+ \slsa
+ (\sgroup-pacing\s(?P<group_pacing>\d+))?
+ (\smin-arrival\s(?P<min_arrival>\d+))?
+ (\srefresh\s(?P<refresh>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_timers_lsa,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "lsa": {
+ "group_pacing": "{{ group_pacing|int }}",
+ "min_arrival": "{{ min_arrival|int }}",
+ "refresh": "{{ refresh|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "timers.graceful_shutdown",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \stimers
+ \sgraceful_shutdown
+ (\sinitial delay\s(?P<initial_delay>\d+))?
+ (\sretain routes\s(?P<retain_routes>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_timers_graceful_shutdown,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "graceful_shutdown": {
+ "initial_delay": "{{ initial_delay|int }}",
+ "retain_routes": "{{ retain_routes|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "throttle.spf",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \stimers
+ \sthrottle
+ \sspf
+ (\s(?P<change_delay>\d+))
+ (\s(?P<second_delay>\d+))
+ (\s(?P<max_wait>\d+))
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "timers throttle spf {{ throttle.spf.change_delay }} {{ throttle.spf.second_delay }} {{ throttle.spf.max_wait }}",
+ "compval": "throttle.lsa_all",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "throttle": {
+ "lsa_all": {
+ "initial_delay": "{{ initial_delay }}",
+ "min_delay": "{{ min_delay }}",
+ "max_delay": "{{ max_delay }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "throttle.lsa_all",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \stimers
+ \sthrottle
+ \slsa
+ \sall
+ (\s(?P<initial_delay>\d+))
+ (\s(?P<min_delay>\d+))
+ (\s(?P<max_delay>\d+))
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "timers throttle lsa all {{ throttle.lsa_all.initial_delay }} {{ throttle.lsa_all.min_delay }} {{ throttle.lsa_all.max_delay }}",
+ "compval": "throttle.lsa_all",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "throttle": {
+ "lsa_all": {
+ "initial_delay": "{{ initial_delay }}",
+ "min_delay": "{{ min_delay }}",
+ "max_delay": "{{ max_delay }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "throttle.fast_reroute",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \stimers
+ \sthrottle
+ \sfast-reroute\s(?P<fast_reroute>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "timers throttle fast-reroute {{ fast_reroute }}",
+ "compval": "throttle.fast_reroute",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "throttle": {
+ "fast_reroute": "{{ fast_reroute }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "timers.pacing_flood",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospf\s(?P<pid>\S+)
+ \stimers
+ \spacing
+ \sflood\s(?P<pacing_flood>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "timers pacing flood {{ pacing_flood }}",
+ "compval": "timers.pacing_flood",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "pacing_flood": "{{ pacing_flood }}",
+
+ },
+ },
+ },
+ },
+ },
+ ]
+ # fmt: on
diff --git a/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
new file mode 100644
index 00000000..14e3720b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ospfv3.py
@@ -0,0 +1,2779 @@
+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.rm_base.network_template import (
+ NetworkTemplate,
+)
+
+
+def _tmplt_ospf_default_information(config_data):
+ if "default_information_originate" in config_data:
+ command = "default-information originate"
+ if "always" in config_data["default_information_originate"]:
+ command += " always"
+ if "metric" in config_data["default_information_originate"]:
+ command += " metric {metric}".format(**config_data["default_information_originate"])
+ if "metric_type" in config_data["default_information_originate"]:
+ command += " metric-type {metric_type}".format(
+ **config_data["default_information_originate"]
+ )
+ if "route_policy" in config_data["default_information_originate"]:
+ command += " route-policy {route_policy}".format(
+ **config_data["default_information_originate"]
+ )
+ return command
+
+
+def _tmplt_ospf_auto_cost(config_data):
+ if "auto_cost" in config_data:
+ command = "auto-cost"
+ if "disable" in config_data["auto_cost"]:
+ command += " disable"
+ if "reference_bandwidth" in config_data["auto_cost"]:
+ command += " reference-bandwidth {reference_bandwidth}".format(
+ **config_data["auto_cost"]
+ )
+ return command
+
+
+def _tmplt_ospfv3_bfd_minimum_interval(config_data):
+ if "bfd" in config_data:
+ if "minimum_interval" in config_data["bfd"]:
+ command = "bfd minimum-interval {minimum_interval}".format(**config_data["bfd"])
+ return command
+
+
+def _tmplt_ospfv3_bfd_multiplier(config_data):
+ if "bfd" in config_data:
+ if "multiplier" in config_data["bfd"]:
+ command = "bfd multiplier {multiplier}".format(**config_data["bfd"])
+ return command
+
+
+def _tmplt_ospf_security(config_data):
+ if "security_ttl" in config_data:
+ command = "security_ttl"
+ if "set" in config_data["security_ttl"]:
+ command += " ttl"
+ elif config_data["security_ttl"].get("hops"):
+ command += " ttl hops {0}".format(
+ config_data["security_ttl"].get("hops"),
+ )
+ return command
+
+
+def _tmplt_ospf_log_adjacency(config_data):
+ if "log_adjacency_changes" in config_data:
+ command = "log adjacency"
+ if "set" in config_data["log_adjacency_changes"]:
+ command += " changes"
+ elif config_data["log_adjacency_changes"].get("disable"):
+ command += " disable"
+ elif config_data["log_adjacency_changes"].get("details"):
+ command += " details"
+ return command
+
+
+def _tmplt_ospf_log_max_lsa(config_data):
+ if "max_lsa" in config_data:
+ command = "max-lsa"
+ if "threshold" in config_data["max_lsa"]:
+ command += " {0}".format(config_data["max_lsa"].get("threshold"))
+ if "warning_only" in config_data["max_lsa"]:
+ command += " warning-only {0}".format(
+ config_data["max_lsa"].get("warning_only"),
+ )
+ if "ignore_time" in config_data["max_lsa"]:
+ command += " ignore-time {0}".format(
+ config_data["max_lsa"].get("ignore_time"),
+ )
+ if "ignore_count" in config_data["max_lsa"]:
+ command += " ignore-count {0}".format(
+ config_data["max_lsa"].get("ignore_count"),
+ )
+ if "reset_time" in config_data["max_lsa"]:
+ command += " reset-time {0}".format(
+ config_data["max_lsa"].get("reset_time"),
+ )
+ return command
+
+
+def _tmplt_ospf_max_metric(config_data):
+ if "max_metric" in config_data:
+ command = "max-metric"
+ if "router_lsa" in config_data["max_metric"]:
+ command += " router-lsa"
+ if "external_lsa" in config_data["max_metric"]:
+ command += " external-lsa {external_lsa}".format(**config_data["max_metric"])
+ if "include_stub" in config_data["max_metric"]:
+ command += " include-stub"
+ if "on_startup" in config_data["max_metric"]:
+ if "time" in config_data["max_metric"]["on_startup"]:
+ command += " on-startup {time}".format(**config_data["max_metric"]["on_startup"])
+ elif "wait_for_bgp" in config_data["max_metric"]["on_startup"]:
+ command += " on-startup wait-for-bgp"
+ if "summary_lsa" in config_data["max_metric"]:
+ command += " summary-lsa {summary_lsa}".format(**config_data["max_metric"])
+ return command
+
+
+def _tmplt_ospf_distance_admin(config_data):
+ if "admin_distance" in config_data:
+ command = "distance"
+ if config_data["admin_distance"].get("value"):
+ command += " {0}".format(
+ config_data["admin_distance"].get("value"),
+ )
+ if config_data["admin_distance"].get("source"):
+ command += " {0}".format(
+ config_data["admin_distance"].get("source"),
+ )
+ if config_data["admin_distance"].get("wildcard"):
+ command += " {0}".format(
+ config_data["admin_distance"].get("wildcard"),
+ )
+ if config_data["admin_distance"].get("access_list"):
+ command += " {0}".format(
+ config_data["admin_distance"].get("access_list"),
+ )
+ return command
+
+
+def _tmplt_ospf_distance_ospf(config_data):
+ if "ospf_distance" in config_data:
+ command = "distance ospf"
+ if config_data["ospf_distance"].get("external"):
+ command += " external {0}".format(
+ config_data["ospf_distance"].get("external"),
+ )
+ if config_data["ospf_distance"].get("inter_area"):
+ command += " inter-area {0}".format(
+ config_data["ospf_distance"].get("inter_area"),
+ )
+ if config_data["ospf_distance"].get("intra_area"):
+ command += " intra-area {0}".format(
+ config_data["ospf_distance"].get("intra_area"),
+ )
+ return command
+
+
+def _tmplt_ospf_nsr(config_data):
+ if "nsr" in config_data:
+ command = "nsr"
+ if "set" in config_data["nsr"]:
+ command += " nsr"
+ elif config_data["nsr"].get("disable"):
+ command += " nsr {0}".format("disable")
+ return command
+
+
+def _tmplt_ospf_protocol(config_data):
+ if "protocol_shutdown" in config_data:
+ command = "protocol"
+ if "set" in config_data["protocol_shutdown"]:
+ command += " shutdown"
+ elif config_data["shutdown"].get("host_mode"):
+ command += " shutdown host-mode"
+ elif config_data["shutdown"].get("on_reload"):
+ command += " shutdown on-reload"
+ return command
+
+
+def _tmplt_microloop_avoidance(config_data):
+ if "microloop_avoidance" in config_data:
+ command = "microloop avoidance"
+ if "protected" in config_data["microloop_avoidance"]:
+ command += " protected"
+ if "segment_routing" in config_data["microloop_avoidance"]:
+ command += " segment_routing"
+ if "rib_update_delay" in config_data["microloop_avoidance"]:
+ command += " rin-update-delay {0}".config_data["microloop_avoidance"].get(
+ "rib_update_delay",
+ )
+ return command
+
+
+def _tmplt_ospf_bfd_fast_detect(config_data):
+ if "bfd" in config_data:
+ if "fast_detect" in config_data["bfd"]:
+ command = "bfd"
+ fast_detect = config_data["bfd"].get("fast_detect")
+ command += " fast-detect"
+ if "strict_mode" in fast_detect:
+ command += " strict-mode"
+ return command
+
+
+def _tmplt_ospf_mpls_traffic_eng(config_data):
+ if "traffic_eng" in config_data:
+ command = "mpls traffic-eng"
+ if "igp_intact" in config_data["traffic_eng"]:
+ command += " igp-intact"
+ if "ldp_sync_update" in config_data["traffic_eng"]:
+ command += " ldp_sync_update"
+ if "multicast_intact" in config_data["traffic_eng"]:
+ command += " multicast_intact"
+ if "auto_route_exclude" in config_data["traffic_eng"]:
+ policy = config_data["traffic_eng"].get("autoroute_exclude")
+ command += " autoroute-exlude route-policy {0}".format(
+ policy.get("route_policy"),
+ )
+ return command
+
+
+def _tmplt_ospf_authentication_ipsec(config_data):
+ if "authentication" in config_data:
+ if config_data["authentication"].get("ipsec"):
+ command = "authentication ipsec"
+ md = config_data["authentication"].get("ipsec")
+ if md.get("spi"):
+ command += " spi " + str(md.get("spi"))
+ if md.get("algorithim_type"):
+ command += " " + md.get("algorithim_type")
+ if md.get("clear_key"):
+ command += " clear " + md.get("clear_key")
+ elif md.get("password_key"):
+ command += " password " + md.get("password_key")
+ elif md.get("key"):
+ command += " " + md.get("key")
+ return command
+
+
+def _tmplt_ospfv3_demand_circuit(config_data):
+ if "demand_circuit" in config_data:
+ command = "demand-circuit"
+ return command
+
+
+def _tmplt_ospfv3_passive(config_data):
+ if "passive" in config_data:
+ command = "passive"
+ return command
+
+
+def _tmplt_ospfv3_demand_mtu_ignore(config_data):
+ if "mtu_ignore" in config_data:
+ command = "mtu-ignore"
+ return command
+
+
+def _tmplt_ospfv3_authentication(config_data):
+ if "authentication" in config_data:
+ if config_data["authentication"].get("disable"):
+ command = "authentication disable"
+ return command
+
+
+def _tmplt_ospf_adjacency_distribute_bgp_state(config_data):
+ if "distribute_link_list" in config_data:
+ command = "distribute link-state"
+ if config_data["distribute_link_list"].get("instance_id"):
+ command += " instance-id {0}".format(
+ config_data["distribute_link_list"].get("instance_id"),
+ )
+ elif config_data["distribute_link_list"].get("throttle"):
+ command += " throttle {0}".format(
+ config_data["distribute_link_list"].get("throttle"),
+ )
+ return command
+ elif "distribute_bgp_ls" in config_data:
+ command = "distribute bgp-ls"
+ if config_data["distribute_bgp_ls"].get("instance_id"):
+ command += " instance-id {0}".format(
+ config_data["distribute_bgp_ls"].get("instance_id"),
+ )
+ elif config_data["distribute_bgp_ls"].get("throttle"):
+ command += " throttle {0}".format(
+ config_data["distribute_bgp_ls"].get("throttle"),
+ )
+ return command
+
+
+def _tmplt_ospf_capability_opaque(config_data):
+ if "capability" in config_data:
+ if "opaque" in config_data["capability"]:
+ command = "capability opaque"
+ opaque = config_data["capability"].get("opaque")
+ if "disable" in opaque:
+ command += "capability opaque disable"
+ return command
+
+
+def _tmplt_ospfv3_area_authentication(config_data):
+ if "authentication" in config_data:
+ if config_data["authentication"].get("disable"):
+ command = "area {area_id} ".format(**config_data)
+ command += "authentication disable"
+ return command
+
+
+def _tmplt_ospfv3_area_authentication_ipsec(config_data):
+ if "authentication" in config_data:
+ command = "area {area_id} ".format(**config_data)
+ if config_data["authentication"].get("ipsec"):
+ command += "authentication ipsec"
+ md = config_data["authentication"].get("ipsec")
+ if md.get("spi"):
+ command += " spi " + str(md.get("spi"))
+ if md.get("algorithim_type"):
+ command += " " + md.get("algorithim_type")
+ if md.get("clear_key"):
+ command += " clear " + md.get("clear_key")
+ elif md.get("password_key"):
+ command += " password " + md.get("password_key")
+ elif md.get("key"):
+ command += " " + md.get("key")
+ return command
+
+
+def _tmplt_ospf_area_mpls_ldp(config_data):
+ commands = []
+ if "mpls" in config_data:
+ command = "area {area_id} mpls".format(**config_data)
+ if config_data["mpls"].get("ldp"):
+ ldp = config_data["mpls"].get("ldp")
+ if "auto_config" in ldp:
+ command += " auto-config"
+ commands.append(command)
+ if "sync" in ldp:
+ command += " sync"
+ commands.append(command)
+ if "sync_igp_shortcuts" in ldp:
+ command += " sync-igp-shortcuts"
+ commands.append(command)
+ return commands
+
+
+def _tmplt_ospfv3_area_bfd_minimum_interval(config_data):
+ if "bfd" in config_data:
+ if "minimum_interval" in config_data["bfd"]:
+ command = "area {area_id} ".format(**config_data)
+ command += " bfd minimum-interval {minimum_interval}".format(**config_data["bfd"])
+ return command
+
+
+def _tmplt_ospfv3_area_bfd_multiplier(config_data):
+ if "bfd" in config_data:
+ if "multiplier" in config_data["bfd"]:
+ command = "area {area_id} ".format(**config_data)
+ command += "bfd multiplier {multiplier}".format(**config_data["bfd"])
+ return command
+
+
+def _tmplt_ospfv3_area_bfd_fast_detect(config_data):
+ if "bfd" in config_data:
+ if "fast_detect" in config_data["bfd"]:
+ command = "area {area_id} ".format(**config_data)
+ fast_detect = config_data["bfd"].get("fast_detect")
+ command += "bfd fast-detect"
+ if "strict_mode" in fast_detect:
+ command += " strict-mode"
+ return command
+
+
+def _tmplt_ospf_mpls_ldp(config_data):
+ commands = []
+ if "mpls" in config_data:
+ command = "mpls".format(**config_data)
+ if config_data["mpls"].get("ldp"):
+ ldp = config_data["mpls"].get("ldp")
+ if "auto_config" in ldp:
+ command += " auto-config"
+ commands.append(command)
+ if "sync" in ldp:
+ command += " sync"
+ commands.append(command)
+ if "sync_igp_shortcuts" in ldp:
+ command += " sync-igp-shortcuts"
+ commands.append(command)
+ return commands
+
+
+def _tmplt_ospf_area_nssa(config_data):
+ if "nssa" in config_data:
+ command = "area {area_id} nssa".format(**config_data)
+ if config_data["nssa"].get("no_redistribution"):
+ command += " no-redistribution"
+ if config_data["nssa"].get("no_summary"):
+ command += " no-summary"
+ return command
+
+
+def _tmplt_ospf_area_nssa_def_info_origin(config_data):
+ if "nssa" in config_data:
+ command = "area {area_id} nssa".format(**config_data)
+ if "default_information_originate" in config_data["nssa"]:
+ command += " default-information-originate"
+ def_info_origin = config_data["nssa"].get(
+ "default_information_originate",
+ )
+ if "metric" in def_info_origin:
+ command += " metric {metric}".format(
+ **config_data["nssa"]["default_information_originate"]
+ )
+ if "metric_type" in def_info_origin:
+ command += " metric-type {metric_type}".format(
+ **config_data["nssa"]["default_information_originate"]
+ )
+ return command
+
+
+def _tmplt_ospf_area_nssa_translate(config_data):
+ if "nssa" in config_data:
+ command = "area {area_id} nssa".format(**config_data)
+ if config_data["nssa"].get("translate"):
+ command += " translate"
+ translate = config_data["nssa"].get("translate")
+ if "type7" in translate:
+ command += " type7"
+ if translate["type7"].get("always"):
+ command += " always"
+ return command
+
+
+def _tmplt_ospf_area_vlink_authentication(config_data):
+ if "authentication" in config_data:
+ command = "area {area_id} virtual-link {id} authentication".format(**config_data)
+ if config_data["authentication"].get("keychain"):
+ command += " keychain " + config_data["authentication"].get(
+ "keychain",
+ )
+ elif config_data["authentication"].get("no_auth"):
+ command += " null"
+ return command
+
+
+def _tmplt_ospf_area_vlink_authentication_md(config_data):
+ if "authentication" in config_data:
+ command = "area {area_id} virtual-link {id} authentication".format(**config_data)
+ if config_data["authentication"].get("message_digest"):
+ command = "authentication message-digest"
+ md = config_data["authentication"].get("message_digest")
+ if md.get("keychain"):
+ command += " keychain " + md.get("keychain")
+ return command
+
+
+def _tmplt_ospf_area_vlink_authentication_key(config_data):
+ if "authentication_key" in config_data:
+ command = "area {area_id} virtual-link {id} authentication-key".format(**config_data)
+ if config_data["authentication_key"].get("password"):
+ command += " {0}".format(
+ config_data["authentication_key"].get("password"),
+ )
+ return command
+
+
+def _tmplt_ospf_area_stub(config_data):
+ if "stub" in config_data:
+ command = "area {area_id} stub".format(**config_data)
+ if config_data["stub"].get("no_summary"):
+ command += " no-summary"
+ return command
+
+
+def _tmplt_ospf_area_ranges(config_data):
+ if "ranges" in config_data:
+ commands = []
+ for k, v in iteritems(config_data["ranges"]):
+ cmd = "area {area_id} range".format(**config_data)
+ temp_cmd = " {address}".format(**v)
+ if "advertise" in v:
+ temp_cmd += " advertise"
+ elif "not_advertise" in v:
+ temp_cmd += " not-advertise"
+ cmd += temp_cmd
+ commands.append(cmd)
+ return commands
+
+
+def _tmplt_prefix_suppression(config_data):
+ if "prefix_suppression" in config_data:
+ if "set" in config_data["prefix_suppression"]:
+ command = "prefix-suppression"
+ if "secondary_address" in config_data["prefix_suppression"]:
+ command = "prefix-suppression secondary-address"
+ return command
+
+
+def _tmplt_protocol_shutdown(config_data):
+ if "protocol_shutdown" in config_data:
+ if "set" in config_data["protocol_shutdown"]:
+ command = "protocol-shutdown"
+ if "host_mode" in config_data["protocol_shutdown"]:
+ command = "protocol-shutdown host-mode"
+ if "on_reload" in config_data["protocol_shutdown"]:
+ command = "protocol-shutdown on-reload"
+ return command
+
+
+def _tmplt_timers_lsa(config_data):
+ if "timers" in config_data:
+ command = "timers lsa"
+ if "group_pacing" in config_data["timers"]["lsa"]:
+ command += " group-pacing {group_pacing}".format(**config_data["timers"]["lsa"])
+ if "min_arrival" in config_data["timers"]["lsa"]:
+ command += " min-arrival {min_arrival}".format(**config_data["timers"]["lsa"])
+ if "refresh" in config_data["timers"]["lsa"]:
+ command += " refresh {refresh}".format(**config_data["timers"]["lsa"])
+ return command
+
+
+def _tmplt_timers_graceful_shutdown(config_data):
+ if "timers" in config_data:
+ command = "timers graceful-shutdown"
+ if "initial_delay" in config_data["timers"]["graceful-shutdown"]:
+ command += " initial delay {initial_delay}".format(
+ **config_data["timers"]["graceful-shutdown"]
+ )
+ if "retain_routes" in config_data["timers"]["graceful-shutdown"]:
+ command += " retain routes {retain_routes}".format(
+ **config_data["timers"]["graceful-shutdown"]
+ )
+ return command
+
+
+class Ospfv3Template(NetworkTemplate):
+ def __init__(self, lines=None, module=None):
+ super(Ospfv3Template, self).__init__(
+ lines=lines,
+ tmplt=self,
+ module=module,
+ )
+
+ # fmt: off
+ PARSERS = [
+ {
+ "name": "pid",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "router ospfv3 {{ process_id }}",
+ "result": {
+ "processes": {"{{ pid }}": {"process_id": "{{ pid }}"}},
+ },
+ "shared": True,
+ },
+ {
+ "name": "cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \scost(?P<cost>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "cost {{ cost }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "cost": "{{ cost|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "default_metric",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdefault-metric(?P<default_metric>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "default-metric {{ default_metric }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "default_metric": "{{ default_metric|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "packet_size",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \spacket-size(?P<packet_size>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "packet-size {{ packet_size }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "packet_size": "{{ packet_size|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "dead_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdead-interval(?P<dead_interval>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "dead-interval {{ dead_interval }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "dead_interval": "{{ dead_interval|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "hello_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \shello-interval(?P<hello_interval>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "hello-interval {{ hello_interval }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "hello_interval": "{{ hello_interval|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "priority",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \spriority(?P<priority>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "priority {{ priority }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "priority": "{{ priority|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "weight",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sweight(?P<weight>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "weight {{ weight }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "weight": "{{ weight|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "retransmit_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sretransmit-interval(?P<retransmit_interval>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "retransmit-interval {{ retransmit_interval }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "retransmit_interval": "{{ retransmit_interval|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "transmit_delay",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \stransmit-delay(?P<transmit_delay>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "transmit-delay {{ transmit_delay }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "transmit_delay": "{{ transmit_delay|int }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "passive",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ (\spassive(?P<passive>))?
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": _tmplt_ospfv3_passive,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "passive": "{{ True if passive is defined }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "process.database_filter",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdatabase-filter
+ \sall
+ \sout\s(?P<database_filter>\s\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "process.database_filter",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "database_filter": "{{ database_filter }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "demand_circuit",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ (\sdemand-circuit(?P<demand_circuit>))?
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": _tmplt_ospfv3_demand_circuit,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "demand_circuit": "{{ True if demand_circuit is defined }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "router_id",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \srouter-id\s(?P<router_id>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "router-id {{ router_id }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "router_id": "{{ router_id }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "mtu_ignore",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ (\smtu-ignore(?P<mtu_ignore>))?
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": _tmplt_ospfv3_demand_mtu_ignore,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "mtu_ignore": "{{ True if mtu_ignore is defined }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "flood_reduction",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sflood-reduction\s(?P<flood_reduction>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "flood-reduction {{ True if flood_reduction is defined }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "flood_reduction": "{{ flood_reduction }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "loopback_stub_network",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sloopback(?P<loopback>)
+ \sstub-network\s(?P<stub_network>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "loopback stub-network {{ stub_network }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "loopback_stub_network": "{{ loopback_stub_network }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "address_family_unicast",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \saddress-family(?P<address_family>)
+ \sipv4(?P<ipv4>)
+ \sunicast(?P<unicast>)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "address_family_unicast",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "address_family_unicast": "{{ True if unicast is defined }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "default_weight",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sapply-weight(?P<apply_weight>)
+ \sdefault-weight(?P<default_weight>\s\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "apply-weight default-weight {{ default_weight }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "apply_weight": {
+ "default_weight": "{{ default_weight|int }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bandwidth",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sapply-weight(?P<apply_weight>)
+ \sbandwidth(?P<bandwidth>\s\d+)?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "apply-weight bandwidth {{ bandwidth }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "apply_weight": {
+ "bandwidth": "{{ bandwidth|int }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "authentication",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sauthentication(?P<auth>)
+ (\sdisable(?P<disable>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospfv3_authentication,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "authentication": {
+ "disable": "{{ True if disable is defined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "authentication.ipsec",
+ "getval": re.compile(
+ r"""^router
+ \sospfv3\s(?P<pid>\S+)
+ \sauthentication(?P<auth>)
+ \sipsec(?P<ipsec>)
+ \sspi\s(?P<spi>\d+)
+ (\s(?P<algo_type>\S+))?
+ (\spassword\s(?P<password_key>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_authentication_ipsec,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "authentication": {
+ "ipsec": {
+ "spi": "{{ spi }}",
+ "algorithim_type": "{{ algo_type }}",
+ "clear_key": "{{ clear_key }}",
+ "password_key": "{{ password_key }}",
+ "key": "{{ key }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "default_information_originate",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdefault-information(?P<default_information>)
+ (\soriginate(?P<originate>))?
+ (\salways(?P<always>))?
+ (\smetric\s(?P<metric>\d+))?
+ (\smetric-type\s(?P<metric_type>\d+))?
+ (\sroute_policy\s(?P<route_policy>)\S+)?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_default_information,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "default_information_originate": {
+ "always": "{{ True if always is defined }}",
+ "metric": "{{ metric|int }}",
+ "metric_type": "{{ metric_type|int }}",
+ "route_policy": "{{ route_policy }}",
+ "set": "{{ True if default_information is defined and always is undefined and metric "
+ "is undefined and metric_type is undefined and route_policy is undefined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "auto_cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sauto-cost(?P<auto_cost>)
+ (\sreference-bandwidth\s(?P<reference_bandwidth>\d+))?
+ (\sdisable(?P<disable>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_auto_cost,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "auto_cost": {
+ "disable": "{{ True if disable is defined }}",
+ "reference_bandwidth": "{{ reference_bandwidth|int }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd.minimum_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sbfd(?P<bfd>)
+ \sminimum-interval\s(?P<minimum_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospfv3_bfd_minimum_interval,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "bfd": {
+ "minimum_interval": "{{ minimum_interval|int }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd.multiplier",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sbfd(?P<bfd>)
+ \smultiplier\s(?P<multiplier>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospfv3_bfd_multiplier,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "bfd": {
+ "multiplier": "{{ multiplier|int }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "bfd.fast_detect",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sbfd(?P<bfd>)
+ \sfast-detect(?P<fast_detect>)
+ (\s(?P<disable>disable))?
+ (\s(?P<strict_mode>strict-mode))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_bfd_fast_detect,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "bfd": {
+ "fast_detect": {
+ "set": "{{ True if disable is undefined and strict_mode is undefined }}",
+ "strict_mode": "{{ True if strict_mode is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "security",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \ssecurity(?P<security>)
+ \sttl(?P<ttl>)?
+ (\shops\s(?P<hops>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_security,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "security_ttl": {
+ "set": "{{ True if ttl is defined and hops is undefined }}",
+ "hops": "{{ hops }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "nsr",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \snsr(?P<nsr>)
+ \sdisable(?P<disable>)?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_nsr,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "nsr": {
+ "set": "{{ True if nsr is defined and disable is undefined }}",
+ "disable": "{{ True if disable is defined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "protocol",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sprotocol(?P<protocol>)
+ \s(shutdown(?P<shutdown>))
+ (\shost-mode(?P<host_mode>))?
+ (\son-reload\s(?P<on_reload>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_protocol,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "protocol_shutdown": {
+ "set": "{{ True if shutdown is defined and host-mode is undefined and on_reload is undefined }}",
+ "host_mode": "{{ True if host_mode is defined }}",
+ "on_reload": "{{ True if on_reload is defined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "capability",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \scapability(?P<capability>)
+ (\stype7\s(?P<type7>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "capability type7 {{ type7 }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "capability": {
+ "type7": "{{ type7 }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "capability.opaque",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \scapability(?P<capability>)?
+ \sopaque(?P<opaque>)
+ (\sdisable(?P<disable>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_capability_opaque,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "capability": {
+ "opaque": {
+ "disable": "{{ True if disable is defined }}",
+ "set": "{{ True if opaque is defined and disable is undefined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "admin_distance",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdistance\s(?P<value>d+)
+ \s(?P<source>\S+)
+ \s(?P<wildcard>\S+)
+ (\s(?P<access_list>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_distance_admin,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "distance": {
+ "admin_distance": {
+ "value": "{{ value|int }}",
+ "source": "{{ source }}",
+ "wildcard": "{{ wildcard }}",
+ "access_list": "{{ access_list }}",
+ },
+ },
+ },
+ },
+ },
+ },
+
+ {
+ "name": "ospf_distance",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdistance(?P<value>)
+ \sospfv3(?P<ospf>)
+ (\sexternal\s(?P<external>\d+))?
+ (\sinter-area\s(?P<inter_area>\d+))?
+ (\sintra-area\s(?P<intra_area>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_distance_ospf,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "distance": {
+ "ospf_distance": {
+ "external": "{{ external|int }}",
+ "inter_area": "{{ inter_area|int }}",
+ "intra_area": "{{ intra_area|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.default_cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sdefault-cost\s(?P<default_cost>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} default-cost {{ default_cost }}",
+ "compval": "default_cost",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "default_cost": "{{ default_cost|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.dead_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sdead-interval\s(?P<dead_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} dead-interval {{ dead_interval }}",
+ "compval": "dead_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "dead_interval": "{{ dead_interval|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.hello_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \shello-interval\s(?P<hello_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} hello-interval {{ hello_interval }}",
+ "compval": "hello_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "hello_interval": "{{ hello_interval|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.transmit_delay",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \stransmit-delay\s(?P<transmit_delay>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} transmit-delay {{ transmit_delay }}",
+ "compval": "transmit_delay",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "transmit_delay": "{{ transmit_delay|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.cost",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \scost\s(?P<cost>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} cost {{ cost }}",
+ "compval": "cost",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "cost": "{{ cost|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.priority",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \spriority\s(?P<priority>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} priority {{ priority }}",
+ "compval": "priority",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "priority": "{{ priority|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.weight",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sweight\s(?P<weight>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} weight {{ weight }}",
+ "compval": "weight",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "weight": "{{ weight|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.packet_size",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \spacket-size\s(?P<packet_size>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} packet-size {{ packet_size }}",
+ "compval": "packet_size",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "packet_size": "{{ packet_size|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.summary_in",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \ssummary-in\s(?P<summary_in>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} summary-in {{ summary_in }}",
+ "compval": "summary_in",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "summary_in": "{{ summary_in }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.demand_circuit",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sdemand-circuit\s(?P<demand_circuit>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} demand-circuit {{ demand_circuit }}",
+ "compval": "demand_circuit",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "demand_circuit": "{{ demand_circuit }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.passive",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \spassive\s(?P<passive>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} passive {{ passive }}",
+ "compval": "passive",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "passive": "{{ passive }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.external_out",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sexternal-out\s(?P<external_out>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} external-out {{ external_out }}",
+ "compval": "passive",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "external_out": "{{ external_out }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.mtu_ignore",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \smtu-ignore\s(?P<mtu_ignore>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "area {{ area_id }} mtu-ignore {{ mtu_ignore }}",
+ "compval": "mtu_ignore",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "mtu_ignore": "{{ mtu_ignore }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.authentication",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sauthentication(?P<auth>)
+ (\sdisable(?P<disable>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospfv3_area_authentication,
+ "compval": "authentication",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "authentication": {
+ "disable": "{{ True if disable is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.authentication.ipsec",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sauthentication(?P<auth_key>)
+ \sipsec(?P<ipsec>)
+ \sspi\s(?P<spi>\d+)
+ (\s(?P<algo_type>\S+))?
+ (\spassword\s(?P<password_key>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospfv3_area_authentication_ipsec,
+ "compval": "authentication.ipsec",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "authentication": {
+ "ipsec": {
+ "spi": "{{ spi }}",
+ "algorithim_type": "{{ algo_type }}",
+ "clear_key": "{{ clear_key }}",
+ "password_key": "{{ password_key }}",
+ "key": "{{ key }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.mpls_traffic_eng",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \smpls(?P<mpls>)
+ \straffic-end(?P<traffic_eng>)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} mpls traffic-eng",
+ "compval": "mpls_traffic_eng",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "mpls": {
+ "traffic_eng": "{{ True if traffic_eng is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.mpls_ldp",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \smpls(?P<mpls>)
+ (\sauto-config(?P<auto_config>))?
+ (\ssync(?P<sync>))?
+ (\ssync-igp-shortcuts(?P<syn_igp_shortcuts>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_mpls_ldp,
+ "compval": "mpls_ldp",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "mpls": {
+ "ldp": {
+ "auto_config": "{{ True if auto_config is defined }}",
+ "sync": "{{ True if sync is defined }}",
+ "sync_igp_shortcuts": "{{ True if sync_igp_shortcuts is defined }}",
+
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.bfd.minimum_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sbfd(?P<bfd>)
+ \sminimum-interval\s(?P<minimum_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospfv3_area_bfd_minimum_interval,
+ "compval": "bfd.minimum_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "bfd": {
+ "minimum_interval": "{{ minimum_interval|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.bfd.multiplier",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sbfd(?P<bfd>)
+ \smultiplier\s(?P<multiplier>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospfv3_area_bfd_multiplier,
+ "compval": "bfd.multiplier",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "bfd": {
+ "multiplier": "{{ multiplier|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.bfd.fast_detect",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sbfd(?P<bfd>)
+ \sarea(?P<area_id>)
+ \sfast-detect(?P<fast_detect>)
+ (\s(?P<disable>disable))?
+ (\s(?P<strict_mode>strict-mode))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospfv3_area_bfd_fast_detect,
+ "compval": "bfd.fast_detect",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "bfd": {
+ "fast_detect": {
+ "set": "{{ True if disable is undefined and strict_mode is undefined }}",
+ "strict_mode": "{{ True if strict_mode is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.stub",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \sstub(?P<nssa>)
+ (\sno-summary(?P<no_sum>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_stub,
+ "compval": "stub",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "area_id": "{{ area_id }}",
+ "stub": {
+ "set": "{{ True if stub is defined and no_summary is undefined }}",
+ "no_summary": "{{ True if no_summary is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.nssa",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \snssa(?P<nssa>)
+ (\sno-redistribution(?P<no_redis>))?
+ (\sno-summary(?P<no_sum>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_nssa,
+ "compval": "nssa",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "area_id": "{{ area_id }}",
+ "nssa": {
+ "set": "{{ True if nssa is defined and no_summary is undefined and no_redis is undefined }}",
+ "no_summary": "{{ True if no_summary is defined }}",
+ "no_redistribution": "{{ True if no_redis is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.nssa.default_information_originate",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \snssa(?P<nssa>)
+ (\sno-redistribution(?P<no_redis>))?
+ (\sdefault-information-originate(?P<def_info_origin>))?
+ (\smetric\s(?P<metric>\d+))?
+ (\smetric-type\s(?P<metric_type>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_nssa_def_info_origin,
+ "compval": "nssa.default_information_originate",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "nssa": {
+ "default_information_originate": {
+ "metric": "{{ metric|int }}",
+ "metric_type": "{{ metric_type|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.ranges",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \srange(?P<range>)
+ \s(?P<address>\S+)
+ (\sadvertise(?P<advertise>))
+ (\snot-advertise(?P<not_advertise>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_ranges,
+ "compval": "ranges",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "ranges": [
+ {
+ "address": "{{ address }}",
+ "advertise": "{{ True if advertise is defined }}",
+ "not_advertise": "{{ True if not_advertise is defined }}",
+ },
+ ],
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "area.nssa.translate",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \snssa(?P<nssa>)
+ \stranslate(?P<translate>)
+ \stype7(?P<type7>)
+ \salways\s(?P<always>)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_nssa_translate,
+ "compval": "nssa.translate",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "area_id": "{{ area_id }}",
+ "nssa": {
+ "translate": {
+ "type7": {
+ "always": "{{ True if always is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "virtual_link.hello_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \shello-interval\s(?P<hello_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} virtual-link {{ id }} hello-interval {{ hello_interval }}",
+ "compval": "hello_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}":
+ {
+ "id": "{{ id }}",
+ "hello_interval": "{{ hello_interval|int }}",
+ },
+
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "virtual_link.dead_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \sdead-interval\s(?P<dead_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} virtual-link {{ id }} dead-interval {{ dead_interval }}",
+ "compval": "dead_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}": {
+ "id": "{{ id }}",
+ "dead_interval": "{{ dead_interval|int }}",
+ },
+
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "virtual_link.retransmit_interval",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \sretransmit-interval\s(?P<retransmit_interval>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "area {{ area_id }} virtual-link {{ id }} retransmit-interval {{ retransmit_interval }}",
+ "compval": "retransmit_interval",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}": {
+ "id": "{{ id }}",
+ "retransmit_interval": "{{ retransmit_interval|int }}",
+ },
+ },
+
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "virtual_link.authentication",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \savirtual-link\s(?P<id>\S+)
+ \sauthentication(?P<auth>)
+ (\skeychain\s(?P<keychain>\S+))?
+ (\snull(?P<no_auth>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_vlink_authentication,
+ "compval": "authentication",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "authentication": {
+ "no_auth": "{{ True if no_auth is defined }}",
+ "keychain": "{{ keychain }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "virtual_link.authentication_key",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \sauthentication-key(?P<auth_key>)
+ (\s(?P<password>\S+))?
+ (\sclear\s(?P<clear>)\S+)?
+ (\sencrypted(?P<encrypted>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_vlink_authentication_key,
+ "compval": "authentication_key",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}": {
+ "authentication_key": {
+ "clear": "{{ clear }}",
+ "encrypted": "{{ encrypted}}",
+ "password": "{{ password if clear is undefined and encrypted is undefined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "virtual_link.authentication.message_digest",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sarea\s(?P<area_id>\S+)
+ \svirtual-link\s(?P<id>\S+)
+ \sauthentication(?P<auth>)
+ \smessage-digest(?P<md>)
+ \skeychain(?P<md_key>\s\S+)
+ *$""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_area_vlink_authentication_md,
+ "compval": "authentication.message_digest",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "areas": {
+ "{{ area_id }}": {
+ "area_id": "{{ area_id }}",
+ "virtual_link": {
+ "{{ id }}": {
+ "authentication": {
+ "message_digest": {
+ "keychain": "{{ md_key }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "link_down_fast_detect",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \slink-down
+ \sfast-detect(?P<fast_detect>)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "link-down fast-detect",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "link_down_fast_detect": "{{ True if fast_detect is defined }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "nsr",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \snsr
+ \sdisable(?P<disable>)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "nsr disable",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "disable": "{{ True if disable is defined }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "database_filter",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdatabase-filter
+ \sall
+ \sout\s(?P<outing>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+
+ "setval": "database-filter all out {{ outing }}",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "outing": "{{ outing }}",
+ },
+ },
+ },
+ },
+ {
+ "name": "distribute_link_state",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdistribute(?P<distribute>)
+ \slink-state(?P<link_state>)
+ (\sinstance-id(?P<inst_id>\d+))?
+ (\sthrottle(?P<throttle>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_adjacency_distribute_bgp_state,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "distribute_link_list": {
+ "instance_id": "{{ inst_id|int }}",
+ "throttle": "{{ throttle }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "distribute_bgp_ls",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sdistribute(?P<distribute>)
+ \sbgp-ls(?P<bgp_ls>)
+ (\sinstance-id(?P<inst_id>\d+))?
+ (\sthrottle(?P<throttle>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_adjacency_distribute_bgp_state,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "distribute_bgp_ls": {
+ "instance_id": "{{ inst_id|int }}",
+ "throttle": "{{ throttle }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "log_adjacency",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \slog(?P<security>)
+ \sadjacency(?P<adjacency>)?
+ (\schanges(?P<changes>))?
+ (\sdisable(?P<disable>))?
+ (\sdetails(?P<details>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_log_adjacency,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "log_adjacency_changes": {
+ "set": "{{ True changes id defined and disable is undefined and detail is undefined }}",
+ "disable": "{{ True if disable is defined }}",
+ "details": "{{ True if details is defined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "max_lsa",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ (\smax-lsa\s(?P<threshold>\d+))?
+ (\swarning-only\s(?P<warning_only>\d+)?
+ (\signore-time\s(?P<ignore_time>\d+))?
+ (\signore-count\s(?P<ignore_count>\d+))?
+ (\sreset-time\s(?P<reset_time>)\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_log_max_lsa,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "max_lsa": {
+ "threshold": "{{ threshold|int }}",
+ "warning_only": "{{ warning_only|int }}",
+ "ignore_time": "{{ ignore_time|int }}",
+ "ignore_count": "{{ ignore_count|int }}",
+ "reset_time": "{{ reset_time|int }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "max_metric",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \smax-metric
+ \s*(?P<router_lsa>)
+ (\s*external-lsa(?P<external_lsa>))?
+ (\s(?P<max_metric_value>\d+))?
+ \s*(?P<include_stub>include-stub)*
+ \s*(?P<on_startup>on-startup)*
+ \s*(?P<wait_period>\d+)*
+ \s*(wait-for\sbgp)*
+ \s*(?P<bgp_asn>\d+)*
+ \s*(?P<summary_lsa>summary-lsa)*
+ \s*(?P<sum_lsa_max_metric_value>\d+)*
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_max_metric,
+ "remval": "max-metric router-lsa",
+ "result": {
+ "processes": {
+ '{{ "pid" }}': {
+ "max_metric": {
+ "router_lsa": {
+ "set": "{{ True if router_lsa is defined and external_lsa is undefined else None }}",
+ "external_lsa": {
+ "set": "{{ True if external_lsa is defined and max_metric_value is undefined else None }}",
+ "max_metric_value": "{{ max_metric_value }}",
+ },
+ "include_stub": "{{ not not include_stub }}",
+ "on_startup": {
+ "set": "{{ True if on_startup is defined and (wait_period and bgp_asn) is undefined else None }}",
+ "wait_period": "{{ wait_period }}",
+ "wait_for_bgp_asn": "{{ bgp_asn }}",
+ },
+ "summary_lsa": {
+ "set": "{{ True if summary_lsa is defined and sum_lsa_max_metric_value is undefined else None }}",
+ "max_metric_value": "{{ sum_lsa_max_metric_value }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "mpls_ldp",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \smpls(?P<mpls>)
+ (\sauto-config(?P<auto_config>))?
+ (\ssync(?P<sync>))?
+ (\ssync-igp-shortcuts(?P<syn_igp_shortcuts>))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_mpls_ldp,
+ "compval": "mpls_ldp",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "mpls": {
+ "ldp": {
+ "auto_config": "{{ True if auto_config is defined }}",
+ "sync": "{{ True if sync is defined }}",
+ "sync_igp_shortcuts": "{{ True if sync_igp_shortcuts is defined }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "microloop_avoidance",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \smicroloop(?P<microloop>)
+ \savoidance(?P<avoidance>)
+ (\s(?P<protected>protected))?
+ (\s(?P<segment_routing>segment-routing))?
+ (\srib-update-delay\s(?P<rib_update_delay>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_microloop_avoidance,
+ "compval": "microloop_avoidance",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "microloop_avoidance": {
+ "protected": "{{ True if protected is defined }}",
+ "segment_routing": "{{ True if segment_routing is defined }}",
+ "rib_update_delay": "{{ rib_update_delay }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "mpls_traffic_eng",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \smpls(?P<mpls>)
+ \straffic-end(?P<traffic_eng>)
+ (\sautoroute-exclude(?P<autoroute>))?
+ (\sroute-policy(?P<route_policy>\S+))?
+ (\s(?P<igp_intact>igp_intact))?
+ (\s(?P<ldp_sync_update>ldp-sync-update))?
+ (\s(?P<multicast_intact>multicast-intact))?
+ (\srouter-id\s(?P<router_id>\S+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_ospf_mpls_traffic_eng,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "mpls": {
+ "autoroute_exclude": {
+ "route_policy": "{{ route_policy }}",
+ },
+ "igp_intact": "{{ True if igp_intact is defined }}",
+ "ldp_sync_update": "{{ True if ldp_sync_update is defined }}",
+ "multicast_intact": "{{ True if multicast_intact is defined }}",
+ "router_id": "{{ router_id }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "prefix_suppression",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sprefix-suppression(?P<prefix_suppression>)
+ (\s(?P<secondary_address>secondary-address))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_prefix_suppression,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "prefix_suppression": {
+ "set": "{{ True if prefix_suppression is defined and secondary_address is undefined }}",
+ "secondary_address": "{{ True if secondary_address is defined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "protocol_shutdown",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \sprotocol-shutdown(?P<protocol_shutdown>)
+ (\s(?P<host_mode>host-mode))?
+ (\s(?P<on_reload>on-reload))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_protocol_shutdown,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "protocol_shutdown": {
+ "set": "{{ True if protocol_shutdown is defined and host_mode is undefined and on_reload is undefined }}",
+ "host_mode": "{{ True if host_mode is defined }}",
+ "on_reload": "{{ True if on_reload is defined }}",
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "timers.lsa",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \stimers
+ \slsa
+ (\sgroup-pacing\s(?P<group_pacing>\d+))?
+ (\smin-arrival\s(?P<min_arrival>\d+))?
+ (\srefresh\s(?P<refresh>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_timers_lsa,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "lsa": {
+ "group_pacing": "{{ group_pacing|int }}",
+ "min_arrival": "{{ min_arrival|int }}",
+ "refresh": "{{ refresh|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "timers.graceful_shutdown",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \stimers
+ \sgraceful_shutdown
+ (\sinitial delay\s(?P<initial_delay>\d+))?
+ (\sretain routes\s(?P<retain_routes>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": _tmplt_timers_graceful_shutdown,
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "graceful_shutdown": {
+ "initial_delay": "{{ initial_delay|int }}",
+ "retain_routes": "{{ retain_routes|int }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "throttle.spf",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \stimers
+ \sthrottle
+ \sspf
+ (\s(?P<change_delay>\d+))
+ (\s(?P<second_delay>\d+))
+ (\s(?P<max_wait>\d+))
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "timers throttle spf {{ throttle.spf.change_delay }} {{ throttle.spf.second_delay }} {{ throttle.spf.max_wait }}",
+ "compval": "throttle.lsa_all",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "throttle": {
+ "lsa_all": {
+ "initial_delay": "{{ initial_delay }}",
+ "min_delay": "{{ min_delay }}",
+ "max_delay": "{{ max_delay }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "throttle.lsa_all",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \stimers
+ \sthrottle
+ \slsa
+ \sall
+ (\s(?P<initial_delay>\d+))
+ (\s(?P<min_delay>\d+))
+ (\s(?P<max_delay>\d+))
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "timers throttle lsa all {{ throttle.lsa_all.initial_delay }} {{ throttle.lsa_all.min_delay }} {{ throttle.lsa_all.max_delay }}",
+ "compval": "throttle.lsa_all",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "throttle": {
+ "lsa_all": {
+ "initial_delay": "{{ initial_delay }}",
+ "min_delay": "{{ min_delay }}",
+ "max_delay": "{{ max_delay }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "throttle.fast_reroute",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \stimers
+ \sthrottle
+ \sfast-reroute\s(?P<fast_reroute>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "timers throttle fast-reroute {{ fast_reroute }}",
+ "compval": "throttle.fast_reroute",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "throttle": {
+ "fast_reroute": "{{ fast_reroute }}",
+ },
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "timers.pacing_flood",
+ "getval": re.compile(
+ r"""
+ ^router
+ \sospfv3\s(?P<pid>\S+)
+ \stimers
+ \spacing
+ \sflood\s(?P<pacing_flood>\d+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "timers pacing flood {{ pacing_flood }}",
+ "compval": "timers.pacing_flood",
+ "result": {
+ "processes": {
+ "{{ pid }}": {
+ "timers": {
+ "pacing_flood": "{{ pacing_flood }}",
+
+ },
+ },
+ },
+ },
+ },
+ ]
+ # fmt: on
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ping.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ping.py
new file mode 100644
index 00000000..74703fbe
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/ping.py
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+# Copyright 2022 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 Ping 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,
+)
+
+
+class PingTemplate(NetworkTemplate):
+ def __init__(self, lines=None):
+ super(PingTemplate, self).__init__(lines=lines, tmplt=self)
+
+ # fmt: off
+ PARSERS = [
+ {
+ 'name': 'rate',
+ 'getval': re.compile(
+ r'''
+ ^Success\srate\sis
+ (\s(?P<pct>\d+))?
+ (\spercent\s\((?P<rx>\d+)/(?P<tx>\d+)\))?
+ (,\s+round-trip\smin/avg/max\s=)?
+ (\s(?P<min>\d+)/(?P<avg>\d+)/(?P<max>\d+))?
+ (\s+\w+\s*$|.*\s*$)?
+ ''', re.VERBOSE,
+ ),
+ "setval": "ping"
+ "{{ (' vrf ' + vrf) if vrf is defined else '' }}"
+ "{{ (' ' + afi|string ) if afi is defined else '' }}"
+ "{{ (' ' + dest ) if dest is defined else '' }}"
+ "{{ (' count ' + count|string ) if count is defined else '' }}"
+ "{{ (' df-bit' ) if df_bit|d(False) else '' }}"
+ "{{ (' sweep' ) if sweep|d(False) else '' }}"
+ "{{ (' validate' ) if validate|d(False) else '' }}"
+ "{{ (' size ' + size|string ) if size is defined else '' }}"
+ "{{ (' source ' + source) if source is defined else '' }}",
+ 'result': {
+ "ping": {
+ 'loss_percentage': '{{ 100 - pct|int }}%',
+ 'loss': '{{ 100 - pct|int }}',
+ 'rx': '{{ rx|int }}',
+ 'tx': '{{ tx|int }}',
+ 'rtt': {
+ 'min': '{{ min }}',
+ 'avg': '{{ avg }}',
+ 'max': '{{ max }}',
+ },
+ },
+ },
+ },
+ ]
+ # fmt: on
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/prefix_lists.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/prefix_lists.py
new file mode 100644
index 00000000..8dc6ceee
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/prefix_lists.py
@@ -0,0 +1,127 @@
+# -*- 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 Prefix_lists 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,
+)
+
+
+class Prefix_listsTemplate(NetworkTemplate):
+ def __init__(self, lines=None, module=None):
+ super(Prefix_listsTemplate, self).__init__(
+ lines=lines,
+ tmplt=self,
+ module=module,
+ )
+
+ # fmt: off
+ PARSERS = [
+ {
+ "name": "prefix_list",
+ "getval": re.compile(
+ r"""
+ (?P<afi>^(ipv4|ipv6))
+ \sprefix-list\s(?P<name>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "{{afi}} prefix-list {{name}}",
+ "result": {
+ "{{ afi }}": {
+ "afi": "{{ afi }}",
+ "prefix_lists": {
+ "{{ name }}": {
+ "name": "{{ name }}",
+ },
+ },
+ },
+
+ },
+ "shared": True,
+ },
+ {
+ "name": "prefix",
+ "getval": re.compile(
+ r"""
+ \s(?P<sequence>\d+)
+ \s(?P<action>deny|permit)
+ \s(?P<prefix>\S+)
+ (\seq\s(?P<eq>\d+))?
+ (\sge\s(?P<ge>\d+))?
+ (\sle\s(?P<le>\d+))?
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "{{afi}} prefix-list {{name}} {{sequence}} {{action}} {{prefix}}"
+ "{{ (' eq ' + eq|string) if eq|d('') else '' }}"
+ "{{ (' ge ' + ge|string) if ge|d('') else '' }}"
+ "{{ (' le ' + le|string) if le|d('') else '' }}",
+ "result": {
+ "{{ afi |d()}}": {
+ "afi": "{{ afi|d() }}",
+ "prefix_lists": {
+ "{{ name|d() }}": {
+ "name": "{{ name|d()}}",
+ "entries": [
+ {
+ "sequence": "{{ sequence|d(None) }}",
+ "action": "{{ action }}",
+ "prefix": "{{ prefix }}",
+ "eq": "{{ eq }}",
+ "ge": "{{ ge }}",
+ "le": "{{ le }}",
+ },
+ ],
+ },
+ },
+ },
+ },
+ },
+ {
+ "name": "description",
+ "getval": re.compile(
+ r"""
+ \s(?P<sequence>\d+)
+ \s(?P<action>remark)
+ \s(?P<desc>\S+)
+ $""",
+ re.VERBOSE,
+ ),
+ "setval": "{{afi}} prefix-list {{name}} {{sequence}} {{action}} {{description}}",
+ "result": {
+ "{{ afi|d() }}": {
+ "afi": "{{ afi|d() }}",
+ "prefix_lists": {
+ "{{ name|d() }}": {
+ "name": "{{ name|d() }}",
+ "entries": [
+ {
+ "sequence": "{{ sequence|d(None) }}",
+ "action": "{{ action }}",
+ "description": "{{ desc }}",
+ },
+ ],
+ },
+ },
+ },
+ },
+ },
+
+ ]
+ # fmt: on
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/snmp_server.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/snmp_server.py
new file mode 100644
index 00000000..77fe0606
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/rm_templates/snmp_server.py
@@ -0,0 +1,3223 @@
+# -*- 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 Snmp_server 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 communities_tmplt(config_data):
+ name = config_data.get("name", "")
+ command = "snmp-server community {name}".format(name=name)
+ if config_data.get("rw"):
+ command += " RW"
+ elif config_data.get("ro"):
+ command += " RO"
+ if config_data.get("sdrowner"):
+ command += " SDROwner"
+ elif config_data.get("systemowner"):
+ command += " SystemOwner"
+ if config_data.get("acl_v4"):
+ command += " IPv4 {IPv4}".format(IPv4=config_data["acl_v4"])
+ if config_data.get("acl_v6"):
+ command += " IPv6 {IPv6}".format(IPv6=config_data["acl_v6"])
+ if config_data.get("v4_acl"):
+ command += " {v4_acl}".format(v4_acl=config_data["v4_acl"])
+ return command
+
+
+def community_maps_tmplt(config_data):
+ name = config_data.get("name", "")
+ command = "snmp-server community-map {name}".format(name=name)
+ if config_data.get("context"):
+ command += " context {context}".format(context=config_data["context"])
+ if config_data.get("security_name"):
+ command += " security-name {security_name}".format(
+ security_name=config_data["security_name"],
+ )
+ if config_data.get("target_list"):
+ command += " target-list {target_list}".format(
+ target_list=config_data["target_list"],
+ )
+ return command
+
+
+def tmplt_correlator_rule(config_data):
+ rule_name = config_data.get("rule_name")
+ command = "snmp-server correlator rule {rule_name}".format(
+ rule_name=rule_name,
+ )
+ if config_data.get("timeout"):
+ command += " timeout {timeout}".format(timeout=config_data["timeout"])
+ return command
+
+
+def group_tmplt(config_data):
+ group = config_data.get("group", "")
+ command = "snmp-server group {group}".format(group=group)
+ if config_data.get("version"):
+ command += " {version}".format(version=config_data["version"])
+ if config_data.get("notify"):
+ command += " notify {notify}".format(notify=config_data["notify"])
+ if config_data.get("read"):
+ command += " read {read}".format(read=config_data["read"])
+ if config_data.get("write"):
+ command += " write {write}".format(write=config_data["write"])
+ if config_data.get("context"):
+ command += " context {context}".format(context=config_data["context"])
+ if config_data.get("acl_v4"):
+ command += " IPv4 {acl_v4}".format(acl_v4=config_data["acl_v4"])
+ if config_data.get("acl_v6"):
+ command += " IPv6 {acl_v6}".format(acl_v6=config_data["acl_v6"])
+ if config_data.get("v4_acl"):
+ command += " {v4_acl}".format(v4_acl=config_data["v4_acl"])
+ return command
+
+
+def host_tmplt(config_data):
+ host = config_data.get("host", "")
+ command = "snmp-server host {host}".format(host=host)
+ if config_data.get("informs"):
+ command += " informs"
+ if config_data.get("traps"):
+ command += " traps"
+ if config_data.get("version"):
+ command += " version {version}".format(version=config_data["version"])
+ if config_data.get("community"):
+ command += " {community}".format(community=config_data["community"])
+ if config_data.get("udp_port"):
+ command += " udp-port {udp_port}".format(
+ udp_port=config_data["udp_port"],
+ )
+ if config_data.get("write"):
+ command += " write {write}".format(write=config_data["write"])
+ return command
+
+
+def interfaces_tmplt(config_data):
+ interface = config_data.get("name", "")
+ notification_linkupdown_disable = config_data.get(
+ "notification_linkupdown_disable",
+ "",
+ )
+ index_persistent = config_data.get("index_persistent", "")
+
+ cmds = []
+ if notification_linkupdown_disable:
+ command = "snmp-server interface {interface} notification linkupdown disable".format(
+ interface=interface,
+ )
+ cmds.append(command)
+ if config_data.get("index_persistent"):
+ command = "snmp-server snmp-server interface {interface} index persistence".format(
+ interface=interface,
+ )
+ cmds.append(command)
+ if not notification_linkupdown_disable and not index_persistent and interface:
+ command = "snmp-server interface {interface}".format(
+ interface=interface,
+ )
+ cmds.append(command)
+ return cmds
+
+
+def mib_schema_tmplt(config_data):
+ name = config_data.get("name", "")
+ object_list = config_data.get("object_list", "")
+ poll_interval = config_data.get("poll_interval", "")
+
+ cmds = []
+ if object_list:
+ command = "snmp-server mib bulkstat schema {name} object-list {object_list}".format(
+ name=name,
+ object_list=object_list,
+ )
+ cmds.append(command)
+ if poll_interval:
+ command = "snmp-server mib bulkstat schema {name} poll-interval {poll_interval}".format(
+ name=name,
+ poll_interval=poll_interval,
+ )
+ cmds.append(command)
+ if not object_list and not poll_interval and name:
+ command = "snmp-server mib bulkstat schema {name}".format(name=name)
+ cmds.append(command)
+ return cmds
+
+
+def mib_bulkstat_transfer_ids_tmplt(config_data):
+ name = config_data.get("name", "")
+ buffer_size = config_data.get("buffer_size", "")
+ enable = config_data.get("enable", "")
+ format_schemaASCI = config_data.get("format_schemaASCI", "")
+ retain = config_data.get("retain", "")
+ retry = config_data.get("retry", "")
+ schema = config_data.get("schema", "")
+ transfer_interval = config_data.get("transfer_interval", "")
+
+ cmds = []
+ if buffer_size:
+ command = "snmp-server mib bulkstat transfer-id {name} buffer-size {buffer_size}".format(
+ name=name,
+ buffer_size=buffer_size,
+ )
+ cmds.append(command)
+ if enable:
+ command = "snmp-server mib bulkstat transfer-id {name} enable".format(
+ name=name,
+ )
+ cmds.append(command)
+ if format_schemaASCI:
+ command = "snmp-server mib bulkstat transfer-id {name} format schemaASCII".format(
+ name=name,
+ )
+ cmds.append(command)
+ if retain:
+ command = "snmp-server mib bulkstat transfer-id {name} retain {retain}".format(
+ name=name,
+ retain=retain,
+ )
+ cmds.append(command)
+ if retry:
+ command = "snmp-server mib bulkstat transfer-id {name} retry {retry}".format(
+ name=name,
+ retry=retry,
+ )
+ cmds.append(command)
+ if schema:
+ command = "snmp-server mib bulkstat transfer-id {name} schema {schema}".format(
+ name=name,
+ schema=schema,
+ )
+ cmds.append(command)
+ if transfer_interval:
+ command = "snmp-server mib bulkstat transfer-id {name} transfer_interval {transfer_interval}".format(
+ name=name,
+ transfer_interval=transfer_interval,
+ )
+ cmds.append(command)
+ if (
+ not any(
+ [
+ buffer_size,
+ enable,
+ format_schemaASCI,
+ retry,
+ retain,
+ schema,
+ transfer_interval,
+ ],
+ )
+ and name
+ ):
+ command = "snmp-server mib bulkstat transfer-id {name}".format(
+ name=name,
+ )
+ cmds.append(command)
+ return cmds
+
+
+def overload_control_tmplt(config_data):
+ config_data = config_data.get("overload_control", {})
+ command = "snmp-server overload-control"
+ if config_data.get("overload_drop_time"):
+ command += " {overload_drop_time}".format(
+ overload_drop_time=config_data["overload_drop_time"],
+ )
+ if config_data.get("overload_throttle_rate"):
+ command += " {overload_throttle_rate}".format(
+ overload_throttle_rate=config_data["overload_throttle_rate"],
+ )
+ return command
+
+
+def targets_tmplt(config_data):
+ name = config_data.get("name", "")
+ command = ""
+ if name:
+ command = "snmp-server target list {name}".format(name=name)
+ if config_data.get("host"):
+ command += " host {host}".format(host=config_data["host"])
+ if config_data.get("vrf"):
+ command += " vrf {vrf}".format(vrf=config_data["vrf"])
+ return command
+
+
+def tmplt_traps_isis(config_data):
+ isis = config_data.get("traps", {}).get("isis", {})
+ command = "snmp-server traps isis"
+ if isis.get("all"):
+ command += " all"
+ else:
+ if isis.get("adjacency_change"):
+ command += " adjacency-change"
+ if isis.get("area_mismatch"):
+ command += " area-mismatch"
+ if isis.get("attempt_to_exceed_max_sequence"):
+ command += " attempt-to-exceed-max-sequence"
+ if isis.get("authentication_failure"):
+ command += " authentication-failure"
+ if isis.get("authentication_type_failure"):
+ command += " authentication-type-failure"
+ if isis.get("corrupted_lsp_detected"):
+ command += " corrupted-lsp-detected"
+ if isis.get("database_overload"):
+ command += " database-overload"
+ if isis.get("id_len_mismatch"):
+ command += " id-len-mismatch"
+ if isis.get("lsp_error_detected"):
+ command += " lsp-error-detected"
+ if isis.get("lsp_too_large_to_propagate"):
+ command += " lsp-too-large-to-propagate"
+ if isis.get("manual_address_drops"):
+ command += " manual-address-drops"
+ if isis.get("max_area_addresses_mismatch"):
+ command += " max-area-addresses-mismatch"
+ if isis.get("orig_lsp_buff_size_mismatch"):
+ command += " orig-lsp-buff-size-mismatch"
+ if isis.get("version_skew"):
+ command += " version-skew"
+ if isis.get("own_lsp_purge"):
+ command += " own-lsp-purge"
+ if isis.get("rejected_adjacency"):
+ command += " rejected-adjacency"
+ if isis.get("protocols_supported_mismatch"):
+ command += " protocols-supported-mismatch"
+ if isis.get("sequence_number_skip"):
+ command += " sequence-number-skip"
+ return command
+
+
+def user_tmplt(config_data):
+ user = config_data.get("user", "")
+ group = config_data.get("group", "")
+ version = config_data.get("version", "")
+ command = "snmp-server user {user} {group} {version}".format(
+ user=user,
+ group=group,
+ version=version,
+ )
+ if config_data.get("acl_v4"):
+ command += " IPv4 {acl_v4}".format(acl_v4=config_data["acl_v4"])
+ if config_data.get("acl_v6"):
+ command += " IPv6 {acl_v6}".format(acl_v6=config_data["acl_v6"])
+ if config_data.get("v4_acl"):
+ command += " {v4_acl}".format(v4_acl=config_data["v4_acl"])
+ if config_data.get("SDROwner"):
+ command += " SDROwner"
+ elif config_data.get("SystemOwner"):
+ command += " SystemOwner"
+ return command
+
+
+class Snmp_serverTemplate(NetworkTemplate):
+ def __init__(self, lines=None, module=None):
+ super(Snmp_serverTemplate, self).__init__(
+ lines=lines,
+ tmplt=self,
+ module=module,
+ )
+
+ # fmt: off
+ PARSERS = [
+ {
+ "name": "chassis_id",
+ "getval": re.compile(
+ r"""
+ ^snmp-server
+ (\s+chassis-id\s(?P<chassis_id>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server chassis-id {{chassis_id}}",
+ "result": {
+ "chassis_id": "{{chassis_id}}",
+ },
+ },
+ {
+ "name": "communities",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\scommunity
+ (\s(?P<name>\S+))?
+ (\sRW(?P<rw>))?
+ (\sRO(?P<ro>))?
+ (\sSDROwner(?P<sdrowner>))?
+ (\sSystemOwner(?P<systemowner>))?
+ (\sIPv4\s(?P<ipv4>\S+))?
+ (\sIPv6\s(?P<ipv6>\S+))?
+ (\s(?P<v4acl>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": communities_tmplt,
+ "result": {
+ "communities": [
+ {
+ "name": "{{ name }}",
+ "rw": "{{ True if rw is defined }}",
+ "ro": "{{ True if ro is defined }}",
+ "acl_v4": "{{ipv4}}",
+ "acl_v6": "{{ipv6}}",
+ "sdrowner": "{{True if sdrowner is defined}}",
+ "systemowner": "{{True if systemowner is defined }}",
+ "v4_acl": "{{v4acl}}",
+ },
+ ],
+ },
+ },
+ {
+ "name": "community_maps",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\scommunity-map
+ (\s(?P<name>\S+))?
+ (\scontext\s(?P<context>\S+))?
+ (\ssecurity-name\s(?P<security_name>\S+))?
+ (\starget-list\s(?P<target_list>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": community_maps_tmplt,
+ "result": {
+ "community_maps": [
+ {
+ "name": "{{ name }}",
+ "context": "{{context}}",
+ "security_name": "{{security_name}}",
+ "target_list": "{{target_list}}",
+ },
+ ],
+ },
+ },
+ {
+ "name": "correlator.buffer_size",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\scorrelator
+ (\sbuffer-size\s(?P<buffer_size>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server correlator buffer-size {{correlator.buffer_size }}",
+ "result": {
+ "correlator": {
+ "buffer_size": "{{ buffer_size }}",
+ },
+ },
+ },
+ {
+ "name": "correlator.rules",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\scorrelator
+ (\srule\s(?P<name>\S+))?
+ (\s+timeout\s(?P<timeout>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": tmplt_correlator_rule,
+ "result": {
+ "correlator": {
+ "rules": [
+ {
+ "rule_name": "{{ name }}",
+ "timeout": "{{ timeout }}",
+
+ },
+ ],
+ },
+ },
+ },
+ {
+ "name": "correlator.rule_sets",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\scorrelator\sruleset\s(?P<name>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server correlator ruleset {{name}}",
+ "result": {
+ "correlator": {
+ "rule_sets":
+ [
+ {"name": "{{ name }}"},
+ ],
+ },
+ },
+ },
+ {
+ "name": "contact",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\scontact\s(?P<name>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server contact {{contact}}",
+ "result": {
+ "contact": "{{name}}",
+ },
+ },
+ {
+ "name": "context",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\scontext\s(?P<name>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server context {{name}}",
+ "result": {
+ "context": {
+ "{{name}}": "{{name}}",
+ },
+ },
+ },
+ {
+ "name": "drop.report_IPv4",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\sdrop
+ (\sreport\sacl\sIPv4\s(?P<report_IPv4>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server drop report acl IPv4 {{drop.report_IPv4}}",
+ "result": {
+ "drop": {
+ "report_IPv4": "{{report_IPv4}}",
+ },
+ },
+ },
+ {
+ "name": "drop.report_IPv6",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\sdrop
+ (\sreport\sacl\sIPv6\s(?P<report_IPv6>\S+))
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server drop report acl IPv6 {{drop.report_IPv6}}",
+ "result": {
+ "drop": {
+ "report_IPv6": "{{report_IPv6}}",
+ },
+ },
+ },
+ {
+ "name": "drop.unknown_user",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\sdrop
+ (\sunknown-user(?P<unknown_user>))
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server drop unknown-user",
+ "result": {
+ "drop": {
+ "unknown_user": "{{True if unknown_user is defined}}",
+ },
+ },
+ },
+ {
+ "name": "groups",
+ "getval": re.compile(
+ r"""
+ ^snmp-server
+ (\sgroup\s(?P<group>\S+))
+ (\s(?P<version>v1|v2c|v3))
+ (\snotify\s(?P<notify>\S+))?
+ (\sread\s(?P<read>\S+))?
+ (\swrite\s(?P<write>\S+))?
+ (\scontext\s(?P<context>\S+))?
+ (\sIPv4\s(?P<IPv4>\S+))?
+ (\sIPv6\s(?P<IPv6>\S+))?
+ (\s(?P<v4acl>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": group_tmplt,
+ "result": {
+ "groups": [
+ {
+ "group": "{{ group }}",
+ "acl_v4": "{{IPv4}}",
+ "acl_v6": "{{IPv6}}",
+ "context": "{{context}}",
+ "notify": "{{notify}}",
+ "read": "{{read}}",
+ "write": "{{write}}",
+ "v4_acl": "{{v4acl}}",
+ "version": "{{version}}",
+ },
+ ],
+ },
+ },
+ {
+ "name": "hosts",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\shost\s(?P<host>\S+))
+ (\s(?P<traps>traps))?
+ (\s(?P<informs>informs))?
+ (\sversion\s(?P<version>1|2c|3))?
+ (\s(?P<community>\S+))?
+ (\sudp-port\s(?P<port>\d+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": host_tmplt,
+ "result": {
+ "hosts": [
+ {
+ "host": "{{ host }}",
+ "traps": "{{True if traps is defined}}",
+ "informs": "{{True if informs is defined}}",
+ "community": "{{community}}",
+ "udp_port": "{{port}}",
+ "version": "{{version}}",
+ },
+ ],
+ },
+ },
+ {
+ "name": "ifindex",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\sifindex\spersist(?P<ifindex>))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server ifindex persist",
+ "result": {
+ "ifindex": "{{True if ifindex is defined}}",
+ },
+ },
+ {
+ "name": "ifmib.internal_cache_max_duration",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\sifmib
+ (\sinternal\scache\smax-duration\s(?P<cache>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server ifmib internal cache max-duration {{ifmib.internal_cache_max_duration}}",
+ "result": {
+ "ifmib": {
+ "internal_cache_max_duration": "{{cache}}",
+ },
+ },
+ },
+ {
+ "name": "ifmib.ipsubscriber",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\sifmib
+ (\sipsubscriber(?P<ipsub>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server ifmib ipsubscriber",
+ "result": {
+ "ifmib": {
+ "internal_cache_max_duration": "{{cache}}",
+ "ipsubscriber": "{{True if ipsub is defined}}",
+ "stats": "{{True if s_cache is defined}}",
+ "ifalias_long": "{{True if long is defined}}",
+ },
+ },
+ },
+ {
+ "name": "ifmib.stats",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\sifmib
+ (\sstats\scache(?P<s_cache>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server ifmib stats cache",
+ "result": {
+ "ifmib": {
+ "stats": "{{True if s_cache is defined}}",
+ },
+ },
+ },
+ {
+ "name": "ifmib.ifalias_long",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\sifmib
+ (\sifalias\slong(?P<long>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server ifmib ifalias long",
+ "result": {
+ "ifmib": {
+ "ifalias_long": "{{True if long is defined}}",
+ },
+ },
+ },
+ {
+ "name": "inform.pending",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\sinform
+ (\spending\s(?P<pending>\d+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server inform pending {{inform.pending}}",
+ "result": {
+ "inform": {
+ "pending": "{{pending}}",
+
+ },
+ },
+ },
+ {
+ "name": "inform.retries",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\sinform
+ (\sretries\s(?P<retries>\d+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server inform retries {{inform.retries}}",
+ "result": {
+ "inform": {
+ "retries": "{{retries}}",
+ },
+ },
+ },
+ {
+ "name": "inform.timeout",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\sinform
+ (\stimeout\s(?P<timeout>\d+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server inform pending {{inform.timeout}}",
+ "result": {
+ "inform": {
+ "timeout": "{{timeout}}",
+
+ },
+ },
+ },
+ {
+ "name": "interfaces",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\sinterface\s(?P<interface>\S+))
+ (\snotification\slinkupdown\sdisable(?P<notification_linkupdown_disable>))?
+ (\sndex\spersistence(?P<index_persistent>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": interfaces_tmplt,
+ "result": {
+ "interfaces": {
+ "{{interface}}": {
+ "name": "{{ interface }}",
+ "notification_linkupdown_disable": "{{True if notification_linkupdown_disable is defined}}",
+ "index_persistent": "{{True if index_persistent is defined}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "ipv4.dscp",
+ "getval": re.compile(
+ r"""
+ ^snmp-server
+ \sipv4\sdscp\s(?P<dscp>\S+)
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server ipv4 dscp {{ipv4.dscp}}",
+ "result": {
+ "ipv4": {
+ "dscp": "{{dscp}}",
+ },
+ },
+ },
+ {
+ "name": "ipv6.dscp",
+ "getval": re.compile(
+ r"""
+ ^snmp-server
+ (\sipv6\sdscp\s(?P<dscp>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server ipv6 dscp {{ipv6.dscp}}",
+ "result": {
+ "ipv6": {
+ "dscp": "{{dscp}}",
+ },
+ },
+ },
+ {
+ "name": "ipv4.precedence",
+ "getval": re.compile(
+ r"""
+ ^snmp-server
+ (\sipv4\sprecedence\s(?P<precedence>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server ipv4 precedence {{ipv4.precedence}}",
+ "result": {
+ "ipv4": {"precedence": "{{precedence}}"},
+ },
+ },
+ {
+ "name": "ipv6.precedence",
+ "getval": re.compile(
+ r"""
+ ^snmp-server
+ (\sipv6\sprecedence\s(?P<precedence>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server ipv6 precedence {{ipv6.precedence}}",
+ "result": {
+ "ipv6": {"precedence": "{{precedence}}"},
+ },
+ },
+ {
+ "name": "location",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\slocation\s(?P<loc>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server location {{location}}",
+ "result": {
+ "location": "{{ loc }}",
+ },
+ },
+ {
+ "name": "logging_threshold_oid_processing",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\slogging\sthreshold\soid-processing\s(?P<loc>\d+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server logging threshold oid-processing {{logging_threshold_oid_processing}}",
+ "result": {
+ "logging_threshold_oid_processing": "{{ loc }}",
+ },
+ },
+ {
+ "name": "logging_threshold_pdu_processing",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\slogging\sthreshold\spdu-processing\s(?P<loc>\d+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server logging threshold pdu-processing {{logging_threshold_pdu_processing}}",
+ "result": {
+ "logging_threshold_pdu_processing": "{{ loc }}",
+ },
+ },
+ {
+ "name": "mib_bulkstat_max_procmem_size",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\smib\sbulkstat\smax-procmem-size\s(?P<loc>\d+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server mib bulkstat max-procmem-size {{mib_bulkstat_max_procmem_size}}",
+ "result": {
+ "mib_bulkstat_max_procmem_size": "{{ loc }}",
+ },
+ },
+ {
+ "name": "mib_object_lists",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\smib\sbulkstat\sobject-list\s(?P<o_list>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server mib bulkstat object-list {{mib_object}}",
+ "result": {
+ "mib_object_lists": {
+ "{{o_list}}": "{{o_list}}",
+ },
+ },
+ },
+ {
+ "name": "mib_schema",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\smib\sbulkstat\sschema\s(?P<mib>\S+))
+ (\sobject-list\s(?P<o_list>\S+))?
+ (\spoll-interval\s(?P<p_interval>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": mib_schema_tmplt,
+ "result": {
+ "mib_schema": {
+ "{{mib}}": {
+ "name": "{{ mib }}",
+ "poll_interval": "{{p_interval}}",
+ "object_list": "{{o_list}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "mib_bulkstat_transfer_ids",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\smib\sbulkstat\stransfer-id\s(?P<mib1>\S+))
+ (\sretry\s(?P<retry>\S+))?
+ (\sbuffer-size\s(?P<buffer_size>\S+))?
+ (\senable(?P<enable>))?
+ (\sformat\sschemaASCII(?P<format>))?
+ (\sretain\s(?P<retain>\S+))?
+ (\sschema\s(?P<schema>\S+))?
+ (\stransfer-interval\s(?P<ti>\S+))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": mib_bulkstat_transfer_ids_tmplt,
+ "result": {
+ "mib_bulkstat_transfer_ids": {
+ "{{mib1}}": {
+ "name": "{{ mib1 }}",
+ "buffer_size": "{{buffer_size}}",
+ "enable": "{{True if enable is defined}}",
+ "format_schemaASCI": "{{True if format is defined}}",
+ "retain": "{{retain}}",
+ "schema": "{{schema}}",
+ "retry": "{{retry}}",
+ "transfer_interval": "{{ti}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "mroutemib_send_all_vrf",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\smroutemib\ssend-all-vrf(?P<send>))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server mroutemib send-all-vrf",
+ "result": {
+ "mroutemib_send_all_vrf": "{{ True if send is defined }}",
+ },
+ },
+ {
+ "name": "notification_log_mib.size",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\snotification-log-mib
+ (\ssize\s(?P<size>\d+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server notification-log-mib size {{notification_log_mib.size}}",
+ "result": {
+ "notification_log_mib": {
+ "size": "{{size}}",
+ },
+ },
+ },
+ {
+ "name": "notification_log_mib.default",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\snotification-log-mib
+ (\sdefault(?P<default>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server notification-log-mib default",
+ "result": {
+ "notification_log_mib": {
+ "default": "{{True if default is defined}}",
+ },
+ },
+ },
+ {
+ "name": "notification_log_mib.disable",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\snotification-log-mib
+ (\sdisable(?P<disable>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server notification-log-mib disable",
+ "result": {
+ "notification_log_mib": {
+ "disable": "{{True if disable is defined}}",
+ },
+ },
+ },
+ {
+ "name": "notification_log_mib.GlobalSize",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\snotification-log-mib
+ (\sGlobalSize\s(?P<gsize>\d+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server notification-log-mib GlobalSize {{notification_log_mib.GlobalSize}}",
+ "result": {
+ "notification_log_mib": {
+ "GlobalSize": "{{gsize}}",
+
+ },
+ },
+ },
+ {
+ "name": "oid_poll_stats",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\soid-poll-stats(?P<oid_stats>))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server oid-poll-stats",
+ "result": {
+ "oid_poll_stats": "{{ True if oid_stats is defined }}",
+ },
+ },
+ {
+ "name": "overload_control",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\soverload-control
+ (\s(?P<overload_drop_time>\d+))?
+ (\s(?P<overload_throttle_rate>\d+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": overload_control_tmplt,
+ "result": {
+ "overload_control": {
+ "overload_drop_time": "{{overload_drop_time}}",
+ "overload_throttle_rate": "{{overload_throttle_rate}}",
+ },
+ },
+ },
+ {
+ "name": "packetsize",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\spacketsize\s(?P<packetsize>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server packetsize {{packetsize}}",
+ "result": {
+ "packetsize": "{{ packetsize }}",
+ },
+ },
+ {
+ "name": "queue_length",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\squeue-length\s(?P<queue_length>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server queue-length {{queue_length}}",
+ "result": {
+ "queue_length": "{{ queue_length }}",
+ },
+ },
+ {
+ "name": "targets",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\starget\slist\s(?P<targets>\S+))
+ (\shost\s(?P<host>\S+))?
+ (\svrf\s(?P<vrf>\S+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": targets_tmplt,
+ "result": {
+ "targets": [
+ {
+ "name": "{{ targets }}",
+ "host": "{{host}}",
+ "vrf": "{{vrf}}",
+ },
+ ],
+ },
+ },
+ {
+ "name": "throttle_time",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\sthrottle-time\s(?P<throttle_time>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server throttle-time {{throttle_time}}",
+ "result": {
+ "throttle_time": "{{ throttle_time }}",
+ },
+ },
+ {
+ "name": "timeouts.duplicate",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\stimeouts
+ (\sduplicate\s(?P<duplicate>\d+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server timeouts duplicate {{timeouts.duplicate}}",
+ "result": {
+ "timeouts": {
+ "duplicate": "{{duplicate}}",
+ },
+ },
+ },
+ {
+ "name": "timeouts.inQdrop",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\stimeouts
+ (\sinQdrop\s(?P<inQdrop>\d+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server timeouts inQdrop {{timeouts.inQdrop}}",
+ "result": {
+ "timeouts": {
+ "inQdrop": "{{inQdrop}}",
+ },
+ },
+ },
+ {
+ "name": "timeouts.subagent",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\stimeouts
+ (\ssubagent\s(?P<subagent>\d+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server timeouts subagent {{timeouts.subagent}}",
+ "result": {
+ "timeouts": {
+ "subagent": "{{subagent}}",
+
+ },
+ },
+ },
+ {
+ "name": "timeouts.pdu_stats",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\stimeouts
+ (\spdu\sstats\s(?P<pdu>\d+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server timeouts pdu stats {{timeouts.pdu_stats}}",
+ "result": {
+ "timeouts": {
+ "pdu_stats": "{{pdu}}",
+
+ },
+ },
+ },
+ {
+ "name": "timeouts.threshold",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\stimeouts
+ (\sthreshold\s(?P<threshold>\d+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server timeouts threshold {{timeouts.threshold}}",
+ "result": {
+ "timeouts": {
+ "threshold": "{{threshold}}",
+ },
+ },
+ },
+ {
+ "name": "trap.throttle_time",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\strap
+ (\sthrottle-time\s(?P<throttle_time>\d+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server trap throttle-time {{trap.throttle_time}}",
+ "result": {
+ "trap": {
+ "throttle_time": "{{throttle_time}}",
+
+ },
+ },
+ },
+ {
+ "name": "trap.authentication_vrf_disable",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\strap
+ (\sauthentication\svrf\sdisable(?P<authentication_vrf_disable>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server trap authentication vrf disable",
+ "result": {
+ "trap": {
+ "authentication_vrf_disable": "{{True if authentication_vrf_disable is defined}}",
+ },
+ },
+ },
+ {
+ "name": "trap.link_ietf",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\strap
+ (\slink\sietf(?P<link_ietf>))?
+ (\sthrottle-time\s(?P<throttle_time>\d+))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server trap link ietf",
+ "result": {
+ "trap": {
+ "link_ietf": "{{True if link_ietf is defined}}",
+ },
+ },
+ },
+ {
+ "name": "trap_source",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\strap-source\s(?P<trap_source>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server trap-source {{trap_source}}",
+ "result": {
+ "trap_source": "{{ trap_source }}",
+ },
+ },
+ {
+ "name": "trap_timeout",
+ "getval": re.compile(
+ r"""
+ ^snmp-server(\strap-timeout\s(?P<trap_timeout>\S+))
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server trap-timeout {{trap_timeout}}",
+ "result": {
+ "trap_timeout": "{{ trap_timeout }}",
+ },
+ },
+ {
+ "name": "traps.addrpool.low",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\saddrpool\slow(?P<addrpool_low>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps addrpool low",
+ "result": {
+ "traps": {
+ "addrpool": {
+ "low": "{{True if addrpool_low is defined}}",
+ },
+ },
+
+ },
+ },
+ {
+ "name": "traps.addrpool.high",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\saddrpool\shigh(?P<addrpool_high>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps addrpool high",
+ "result": {
+ "traps": {
+ "addrpool": {
+ "high": "{{True if addrpool_high is defined}}",
+ },
+ },
+
+ },
+ },
+ {
+ "name": "traps.bfd",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sbfd(?P<bfd>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps bfd",
+ "result": {
+ "traps": {
+ "bfd": "{{True if bfd is defined}}",
+ },
+ },
+ },
+ {
+ "name": "traps.bgp.cbgp2",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sbgp\scbgp2(?P<bgp_cgp2>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps bgp cbgp2",
+ "result": {
+ "traps": {
+
+ "bgp": {
+ "cbgp2": "{{True if bgp_cgp2 is defined}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "traps.bgp.updown",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sbgp\supdown(?P<bgp_updown>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps bgp updown",
+ "result": {
+ "traps": {
+ "bgp": {
+ "updown": "{{True if updown is defined}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "traps.bulkstat_collection",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+
+ (\sbulkstat\scollection(?P<bulkstat_collection>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps bulkstat collection",
+ "result": {
+ "traps": {
+
+ "bulkstat_collection": "{{True if bulkstat_collection is defined}}",
+
+ },
+ },
+ },
+ {
+ "name": "traps.bulkstat_transfer",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sbulkstat\stransfer(?P<bulkstat_t>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps bulkstat transfer",
+ "result": {
+ "traps": {
+
+ "bulkstat_transfer": "{{True if bulkstat_t is defined}}",
+
+ },
+ },
+ },
+ {
+ "name": "traps.bridgemib",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sbridgemib(?P<bridgemib>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps bridgemib",
+ "result": {
+ "traps": {
+
+ "bridgemib": "{{True if bridgemib is defined}}",
+
+ },
+ },
+ },
+ {
+ "name": "traps.copy_complete",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\scopy-complete(?P<copy_complete>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps copy-complete",
+ "result": {
+ "traps": {
+
+ "copy_complete": "{{True if copy_complete is defined}}",
+
+ },
+ },
+ },
+ {
+ "name": "traps.cisco_entity_ext",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\scisco-entity-ext(?P<cee>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps cisco-entity-ext",
+ "result": {
+ "traps": {
+
+ "cisco_entity_ext": "{{True if cee is defined}}",
+
+ },
+ },
+ },
+ {
+ "name": "traps.config",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sconfig(?P<config>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps config",
+ "result": {
+ "traps": {
+
+ "config": "{{True if config is defined}}",
+
+ },
+ },
+ },
+ {
+ "name": "traps.diameter.peerdown",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sdiameter\speerdown(?P<peerdown>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps diameter peerdown",
+ "result": {
+ "traps": {
+ "diameter": {
+ "peerdown": "{{True if peerdown is defined}}",
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.diameter.peerup",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sdiameter\speerup(?P<peerup>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps diameter peerup",
+ "result": {
+ "traps": {
+ "diameter": {
+ "peerup": "{{True if peerup is defined}}",
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.diameter.protocolerror",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sdiameter\sprotocolerror(?P<protocolerror>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps diameter protocolerror",
+ "result": {
+ "traps": {
+ "diameter": {
+ "protocolerror": "{{True if protocolerror is defined}}",
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.diameter.permanentfail",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sdiameter\spermanentfail(?P<permanentfail>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps diameter permanentfail",
+ "result": {
+ "traps": {
+ "diameter": {
+ "permanentfail": "{{True if permanentfail is defined}}",
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.diameter.transientfail",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sdiameter\stransientfail(?P<transientfail>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps diameter transientfail",
+ "result": {
+ "traps": {
+ "diameter": {
+ "transientfail": "{{True if transientfail is defined}}",
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.entity",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sentity(?P<entity>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps entity",
+ "result": {
+ "traps": {
+ "entity": "{{True if entity is defined}}",
+ },
+ },
+ },
+ {
+ "name": "traps.entity_redundancy.all",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sentity-redundancy\sall(?P<all>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps entity-redundancy all",
+ "result": {
+ "traps": {
+ "entity_redundancy": {
+ "all": "{{True if all is defined }}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.entity_redundancy.status",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sentity-redundancy\sstatus(?P<status>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps entity-redundancy status",
+ "result": {
+ "traps": {
+ "entity_redundancy": {
+ "status": "{{True if status is defined }}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.entity_redundancy.switchover",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sentity-redundancy\sswitchover(?P<switchover>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps entity-redundancy switchover",
+ "result": {
+ "traps": {
+ "entity_redundancy": {
+ "switchover": "{{True if switchover is defined }}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.entity_state.operstatus",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sentity-state\soperstatus(?P<operstatus>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps entity-state operstatus",
+ "result": {
+ "traps": {
+ "entity_state": {
+ "operstatus": "{{True if operstatus is defined }}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.entity_state.switchover",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sentity-state\sswitchover(?P<switchover>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps entity-state switchover",
+ "result": {
+ "traps": {
+ "entity_state": {
+ "switchover": "{{True if switchover is defined }}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.flash.insertion",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sflash\sinsertion(?P<f_insertion>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps flash insertion",
+ "result": {
+ "traps": {
+ "flash": {
+ "insertion": "{{True if f_insertion is defined }}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.flash.removal",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sflash\sremoval(?P<f_removal>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps flash removal",
+ "result": {
+ "traps": {
+ "flash": {
+ "removal": "{{True if f_removal is defined }}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.fru_ctrl",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sfru-ctrl(?P<fru_ctrl>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps fru-ctrl",
+ "result": {
+ "traps": {
+ "fru_ctrl": "{{True if fru_ctrl is defined }}",
+ },
+ },
+ },
+ {
+ "name": "traps.hsrp",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\shsrp(?P<hsrp>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps hsrp",
+ "result": {
+ "traps": {
+ "hsrp": "{{True if hsrp is defined }}",
+ },
+ },
+ },
+ {
+ "name": "traps.ipsla",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sipsla(?P<ipsla>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ipsla",
+ "result": {
+ "traps": {
+ "ipsla": "{{True if ipsla is defined }}",
+ },
+ },
+ },
+ {
+ "name": "traps.ipsec.start",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sipsec\stunnel\sstart(?P<ipsec_start>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ipsec tunnel start",
+ "result": {
+ "traps": {
+ "ipsec": {
+ "start": "{{True if ipsec_start is defined}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "traps.ipsec.stop",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sipsec\stunnel\sstop(?P<ipsec_stop>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ipsec tunnel stop",
+ "result": {
+ "traps": {
+ "ipsec": {
+ "stop": "{{True if ipsec_stop is defined}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "traps.isakmp.start",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sisakmp\stunnel\sstart(?P<isakmp_start>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps isakmp tunnel start",
+ "result": {
+ "traps": {
+ "isakmp": {
+ "start": "{{True if isakmp_start is defined}}",
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.isakmp.stop",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sisakmp\stunnel\sstop(?P<isakmp_stop>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps isakmp tunnel stop",
+ "result": {
+ "traps": {
+ "isakmp": {
+ "stop": "{{True if isakmp_stop is defined}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "traps.isis",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sisis\sall(?P<isis_all>))?
+ (\sisis(\sdatabase-overload(?P<database_overload>))?(\smanual-address-drops(?P<manual_address_drops>))?
+ (\scorrupted-lsp-detected(?P<corrupted_lsp_detected>))?
+ (\sattempt-to-exceed-max-sequence(?P<attempt_to_exceed_max_sequence>))?
+ (\sid-len-mismatch(?P<id_len_mismatch>))?
+ (\smax-area-addresses-mismatch(?P<max_area_addresses_mismatch>))?
+ (\sown-lsp-purge(?P<own_lsp_purge>))?
+ (\ssequence-number-skip(?P<sequence_number_skip>))?
+ (\sauthentication-type-failure(?P<authentication_type_failure>))?
+ (\sauthentication-failure(?P<authentication_failure>))?
+ (\sversion-skew(?P<version_skew>))?
+ (\sarea-mismatch(?P<area_mismatch>))?
+ (\srejected-adjacency(?P<rejected_adjacency>))?
+ (\slsp-too-large-to-propagate(?P<lsp_too_large_to_propagate>))?
+ (\sorig-lsp-buff-size-mismatch(?P<orig_lsp_buff_size_mismatch>))?
+ (\sprotocols-supported-mismatch(?P<protocols_supported_mismatch>))?
+ (\sadjacency-change(?P<adjacency_change>))?
+ (\slsp-error-detected(?P<lsp_error_detected>))?)?
+ $""", re.VERBOSE,
+ ),
+ "setval": tmplt_traps_isis,
+ "result": {
+ "traps": {
+
+ "isis": {
+ "all": "{{True if isis_all is defined}}",
+ "id_len_mismatch": "{{True if id_len_mismatch is defined}}",
+ "database_overload": "{{True if database_overload is defined}}",
+ "manual_address_drops": "{{True if manual_address_drops is defined}}",
+ "corrupted_lsp_detected": "{{True if corrupted_lsp_detected is defined}}",
+ "attempt_to_exceed_max_sequence": "{{True if attempt_to_exceed_max_sequence is defined}}",
+ "max_area_addresses_mismatch": "{{True if max_area_addresses_mismatch is defined}}",
+ "own_lsp_purge": "{{True if own_lsp_purge is defined}}",
+ "sequence_number_skip": "{{True if sequence_number_skip is defined}}",
+ "authentication_type_failure": "{{True if authentication_type_failure is defined}}",
+ "authentication_failure": "{{True if authentication_failure is defined}}",
+ "version_skew": "{{True if version_skew is defined}}",
+ "area_mismatch": "{{True if area_mismatch is defined}}",
+ "rejected_adjacency": "{{True if rejected_adjacency is defined}}",
+ "lsp_too_large_to_propagate": "{{True if lsp_too_large_to_propagate is defined}}",
+ "orig_lsp_buff_size_mismatch": "{{True if orig_lsp_buff_size_mismatch is defined}}",
+ "protocols_supported_mismatch": "{{True if protocols_supported_mismatch is defined}}",
+ "adjacency_change": "{{True if adjacency_change is defined}}",
+ "lsp_error_detected": "{{True if lsp_error_detected is defined}}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.l2tun.pseudowire_status",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sl2tun\spseudowire-status(?P<pseudowire_status>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps l2tun pseudowire-status",
+ "result": {
+ "traps": {
+
+ "l2tun": {
+ "pseudowire_status": "{{True if pseudowire_status is defined}}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.l2tun.sessions",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sl2tun\ssessions(?P<sessions>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps l2tun sessions",
+ "result": {
+ "traps": {
+
+ "l2tun": {
+ "sessions": "{{True if sessions is defined}}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.l2tun.tunnel_down",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sl2tun\stunnel-down(?P<tunnel_down>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps l2tun tunnel-down",
+ "result": {
+ "traps": {
+
+ "l2tun": {
+ "tunnel_down": "{{True if tunnel_down is defined}}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.l2tun.tunnel_up",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sl2tun\stunnel-up(?P<tunnel_up>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps l2tun tunnel-up",
+ "result": {
+ "traps": {
+
+ "l2tun": {
+ "tunnel_up": "{{True if tunnel_up is defined}}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.l2vpn.all",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sl2vpn\sall(?P<vpnall>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps l2vpn all",
+ "result": {
+ "traps": {
+
+ "l2vpn": {
+ "all": "{{True if vpnall is defined}}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.l2vpn.cisco",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sl2vpn\scisco(?P<cisco>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps l2vpn cisco",
+ "result": {
+ "traps": {
+
+ "l2vpn": {
+ "cisco": "{{True if cisco is defined}}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.l2vpn.vc_up",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sl2vpn\svc-up(?P<vc_up>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps l2vpn vc-up",
+ "result": {
+ "traps": {
+
+ "l2vpn": {
+ "vc_up": "{{True if vc_up is defined}}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.l2vpn.vc_down",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sl2vpn\svc-down(?P<vc_down>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps l2vpn vc-down",
+ "result": {
+ "traps": {
+
+ "l2vpn": {
+ "vc_down": "{{True if vc_down is defined}}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.msdp_peer_state_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\smsdp\speer-state-change(?P<msdp>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps msdp peer-state-change",
+ "result": {
+ "traps": {
+
+ "msdp_peer_state_change": "{{True if msdp is defined }}",
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospf.retransmit.packets",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospf\sretransmit\spackets(?P<packets>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospf retransmit packets",
+ "result": {
+ "traps": {
+
+ "ospf": {
+
+ "retransmit": {
+ "packets": "{{True if packets is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospf.retransmit.virt_packets",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospf\sretransmit\svirt-packets(?P<virt_packets>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospf retransmit virt-packets",
+ "result": {
+ "traps": {
+
+ "ospf": {
+ "retransmit": {
+ "virt_packets": "{{True if virt_packets is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospf.lsa.lsa_maxage",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospf\slsa\slsa-maxage(?P<lsa_maxage>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospf lsa lsa-maxage",
+ "result": {
+ "traps": {
+
+ "ospf": {
+
+ "lsa": {
+ "lsa_maxage": "{{True if lsa_maxage is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospf.lsa.lsa_originate",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospf\slsa\slsa-originate(?P<lsa_originate>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospf lsa lsa-originate",
+ "result": {
+ "traps": {
+
+ "ospf": {
+
+ "lsa": {
+ "lsa_originate": "{{True if lsa_originate is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospf.errors.bad_packet",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospf\serrors\sbad-packet(?P<bad_packet>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospf errors bad-packet",
+ "result": {
+ "traps": {
+
+ "ospf": {
+
+ "errors": {
+ "bad_packet": "{{True if bad_packet is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospf.errors.authentication_failure",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospf\serrors\sauthentication-failure(?P<authentication_failure_ospf>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospf errors authentication-failure",
+ "result": {
+ "traps": {
+
+ "ospf": {
+
+ "errors": {
+ "authentication_failure": "{{True if authentication_failure_ospf is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospf.errors.config_error",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospf\serrors\sconfig-error(?P<config_error>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospf errors config-error",
+ "result": {
+ "traps": {
+
+ "ospf": {
+
+ "errors": {
+ "config_error": "{{True if config_error is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospf.errors.virt_bad_packet",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospf\serrors\svirt-bad-packet(?P<virt_bad_packet>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospf errors virt-bad-packet",
+ "result": {
+ "traps": {
+
+ "ospf": {
+
+ "errors": {
+ "virt_bad_packet": "{{True if virt_bad_packet is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospf.errors.virt_authentication_failure",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospf\serrors\svirt-authentication-failure(?P<virt_authentication_failure>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospf errors virt-authentication-failure",
+ "result": {
+ "traps": {
+
+ "ospf": {
+
+ "errors": {
+ "virt_authentication_failure": "{{True if virt_authentication_failure is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospf.errors.virt_config_error",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospf\serrors\svirt-config-error(?P<virt_config_error>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospf errors virt-config-error",
+ "result": {
+ "traps": {
+
+ "ospf": {
+
+ "errors": {
+ "virt_config_error": "{{True if virt_config_error is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospf.state_change.if_state_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospf\sstate-change\sif-state-change(?P<if_state_change>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospf state-change if-state-change",
+ "result": {
+ "traps": {
+
+ "ospf": {
+
+ "state_change": {
+ "if_state_change": "{{True if if_state_change is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospf.state_change.neighbor_state_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospf\sstate-change\sneighbor-state-change(?P<neighbor_state_change>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospf state-change neighbor-state-change",
+ "result": {
+ "traps": {
+
+ "ospf": {
+
+ "state_change": {
+ "neighbor_state_change": "{{True if neighbor_state_change is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospf.state_change.virtif_state_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospf\sstate-change\svirtif-state-change(?P<virtif_state_change>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospf state-change virtif-state-change",
+ "result": {
+ "traps": {
+
+ "ospf": {
+
+ "state_change": {
+ "virtif_state_change": "{{True if virtif_state_change is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospf.state_change.virtneighbor_state_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospf\sstate-change\svirtneighbor-state-change(?P<virtneighbor_state_change>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospf state-change virtneighbor-state-change",
+ "result": {
+ "traps": {
+
+ "ospf": {
+
+ "state_change": {
+ "virtneighbor_state_change": "{{True if virtneighbor_state_change is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospfv3.errors.bad_packet",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospfv3\serrors\sbad-packet(?P<bad_packet>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospfv3 errors bad-packet",
+ "result": {
+ "traps": {
+
+ "ospfv3": {
+
+ "errors": {
+ "bad_packet": "{{True if bad_packet is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospfv3.errors.authentication_failure",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospfv3\serrors\sauthentication-failure(?P<authentication_failure_ospf>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospfv3 errors authentication-failure",
+ "result": {
+ "traps": {
+
+ "ospfv3": {
+
+ "errors": {
+ "authentication_failure": "{{True if authentication_failure_ospf is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospfv3.errors.config_error",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospfv3\serrors\sconfig-error(?P<config_error>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospfv3 errors config-error",
+ "result": {
+ "traps": {
+
+ "ospfv3": {
+
+ "errors": {
+ "config_error": "{{True if config_error is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospfv3.errors.virt_config_error",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospfv3\serrors\svirt-config-error(?P<virt_config_error>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospfv3 errors virt-config-error",
+ "result": {
+ "traps": {
+
+ "ospfv3": {
+
+ "errors": {
+ "virt_config_error": "{{True if virt_config_error is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospfv3.errors.virt_bad_packet",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospfv3\serrors\svirt-bad-packet(?P<virt_bad_packet>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospfv3 errors virt-bad-packet",
+ "result": {
+ "traps": {
+
+ "ospfv3": {
+
+ "errors": {
+ "virt_bad_packet": "{{True if virt_bad_packet is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospfv3.state_change.if_state_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospfv3\sstate-change\sif-state-change(?P<if_state_change>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospfv3 state-change if-state-change",
+ "result": {
+ "traps": {
+
+ "ospfv3": {
+
+ "state_change": {
+ "if_state_change": "{{True if if_state_change is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospfv3.state_change.neighbor_state_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospfv3\sstate-change\sneighbor-state-change(?P<neighbor_state_change>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospfv3 state-change neighbor-state-change",
+ "result": {
+ "traps": {
+
+ "ospfv3": {
+
+ "state_change": {
+ "neighbor_state_change": "{{True if neighbor_state_change is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospfv3.state_change.virtif_state_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospfv3\sstate-change\svirtif-state-change(?P<virtif_state_change>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospfv3 state-change virtif-state-change",
+ "result": {
+ "traps": {
+
+ "ospfv3": {
+
+ "state_change": {
+ "virtif_state_change": "{{True if virtif_state_change is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospfv3.state_change.virtneighbor_state_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospfv3\sstate-change\svirtneighbor-state-change(?P<virtneighbor_state_change>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospfv3 state-change virtneighbor-state-change",
+ "result": {
+ "traps": {
+
+ "ospfv3": {
+
+ "state_change": {
+ "virtneighbor_state_change": "{{True if virtneighbor_state_change is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospfv3.state_change.restart_status_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospfv3\sstate-change\srestart-status-change(?P<restart_status_change>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospfv3 state-change restart-status-change",
+ "result": {
+ "traps": {
+
+ "ospfv3": {
+
+ "state_change": {
+ "restart_status_change": "{{True if restart_status_change is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospfv3.state_change.restart_helper_status_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospfv3\sstate-change\srestart-helper-status-change(?P<restart_helper_status_change>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospfv3 state-change restart-helper-status-change",
+ "result": {
+ "traps": {
+
+ "ospfv3": {
+
+ "state_change": {
+ "restart_helper_status_change": "{{True if restart_helper_status_change is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospfv3.state_change.restart_virtual_helper_status_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospfv3\sstate-change\srestart-virtual-helper-status-change(?P<restart_virtual_helper_status_change>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospfv3 state-change restart-virtual-helper-status-change",
+ "result": {
+ "traps": {
+
+ "ospfv3": {
+
+ "state_change": {
+ "restart_virtual_helper_status_change": "{{True if restart_virtual_helper_status_change is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.ospfv3.state_change.nssa_state_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sospfv3\sstate-change\snssa-state-change(?P<nssa_state_change>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps ospfv3 state-change nssa-state-change",
+ "result": {
+ "traps": {
+
+ "ospfv3": {
+
+ "state_change": {
+ "nssa_state_change": "{{True if nssa_state_change is defined}}",
+
+ },
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.power",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\spower(?P<power>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps power",
+ "result": {
+ "traps": {
+ "power": "{{True if power is defined }}",
+
+ },
+ },
+ },
+ {
+ "name": "traps.rf",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+
+
+ (\spower(?P<power>))?
+ (\srf(?P<rf>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps rf",
+ "result": {
+ "traps": {
+ "rf": "{{True if rf is defined}}",
+
+ },
+ },
+ },
+ {
+ "name": "traps.pim.neighbor_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\spim\sneighbor-change(?P<neighbor_change>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps pim neighbor-change",
+ "result": {
+ "traps": {
+
+ "pim": {
+
+ "neighbor_change": "{{True if neighbor_change is defined}}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.pim.invalid_message_received",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+
+
+
+ (\spim\sinvalid-message-received(?P<invalid_message_received>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps pim invalid-message-received",
+ "result": {
+ "traps": {
+
+ "pim": {
+
+ "invalid_message_received": "{{True if invalid_message_received is defined}}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.pim.rp_mapping_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+
+
+
+ (\spim\srp-mapping-change(?P<rp_mapping_change>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps pim rp-mapping-change",
+ "result": {
+ "traps": {
+
+ "pim": {
+
+ "rp_mapping_change": "{{True if rp_mapping_change is defined}}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.pim.interface_state_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\spim\sinterface-state-change(?P<interface_state_change>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps pim interface-state-change",
+ "result": {
+ "traps": {
+ "pim": {
+ "interface_state_change": "{{True if interface_state_change is defined}}",
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.rsvp.lost_flow",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\srsvp\slost-flow(?P<lost_flow>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps rsvp lost-flow",
+ "result": {
+ "traps": {
+ "rsvp": {
+ "lost_flow": "{{True if lost_flow is defined}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "traps.rsvp.new_flow",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\srsvp\snew-flow(?P<new_flow>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps rsvp new-flow",
+ "result": {
+ "traps": {
+ "rsvp": {
+ "new_flow": "{{True if new_flow is defined}}",
+ },
+
+ },
+
+ },
+ },
+ {
+ "name": "traps.rsvp.all",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\srsvp\sall(?P<all>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps rsvp all",
+ "result": {
+ "traps": {
+ "rsvp": {
+ "all": "{{True if all is defined}}",
+ },
+
+ },
+
+ },
+ },
+ {
+ "name": "traps.selective_vrf_download_role_change",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\sselective-vrf-download\srole-change(?P<selective_vrf_download_role_change>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps selective-vrf-download role-change",
+ "result": {
+ "traps": {
+ "selective_vrf_download_role_change": "{{True if selective_vrf_download_role_change is defined}}",
+ },
+ },
+ },
+ {
+ "name": "traps.sensor",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\ssensor(?P<sensor>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps sensor",
+ "result": {
+ "traps": {"sensor": "{{True if sensor is defined}}"},
+ },
+ },
+ {
+ "name": "traps.vrrp_events",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\svrrp\sevents(?P<vrrp_events>))?
+
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps vrrp events",
+ "result": {
+
+ "traps": {
+ "vrrp_events": "{{True if vrrp_events is defined}}",
+ },
+ },
+ },
+ {
+ "name": "traps.syslog",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\ssyslog(?P<syslog>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps syslog",
+ "result": {
+ "traps": {"syslog": "{{True if syslog is defined}}"},
+
+ },
+ },
+ {
+ "name": "traps.system",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\ssystem(?P<system>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps system",
+ "result": {
+ "traps": {"system": "{{True if system is defined}}"},
+
+ },
+ },
+ {
+ "name": "traps.subscriber.session_agg_access_interface",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+
+ (\ssubscriber\ssession-agg\saccess-interface(?P<session_agg_access_interface>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps subscriber session-agg access-interface",
+ "result": {
+ "traps": {
+ "subscriber": {
+ "session_agg_access_interface": "{{True if session_agg_access_interface is defined}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "traps.subscriber.session_agg_node",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\ssubscriber\ssession-agg\snode(?P<session_agg_node>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps subscriber session-agg node",
+ "result": {
+ "traps": {
+ "subscriber": {
+ "session_agg_node": "{{True if session_agg_node is defined}}",
+ },
+
+ },
+ },
+
+ },
+ {
+ "name": "traps.vpls.all",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+
+ (\svpls\sall(?P<vpls_all>))?
+
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps vpls all",
+ "result": {
+ "traps": {
+
+ "vpls": {
+ "all": "{{True if vpls_all is defined}}",
+
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.vpls.full_clear",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\svpls\sfull-clear(?P<full_clear>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps vpls full-clear",
+ "result": {
+ "traps": {
+ "vpls": {
+ "full_clear": "{{True if full_clear is defined}}",
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.vpls.full_raise",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\svpls\sfull-raise(?P<full_raise>))?
+
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps vpls full-raise",
+ "result": {
+ "traps": {
+ "vpls": {
+ "full_raise": "{{True if full_raise is defined}}",
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.vpls.status",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\svpls\sstatus(?P<vpls_status>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps vpls status",
+ "result": {
+ "traps": {
+ "vpls": {
+ "status": "{{True if vpls_status is defined}}",
+ },
+
+ },
+ },
+ },
+ {
+ "name": "traps.snmp.linkup",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\ssnmp\slinkup(?P<linkup>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps snmp linkup",
+ "result": {
+ "traps": {
+ "snmp": {
+ "linkup": "{{True if linkup is defined}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "traps.snmp.linkdown",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\ssnmp\slinkdown(?P<linkdown>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps snmp linkdown",
+ "result": {
+ "traps": {
+
+ "snmp": {
+ "linkdown": "{{True if linkdown is defined}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "traps.snmp.coldstart",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\ssnmp\scoldstart(?P<coldstart>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps snmp coldstart",
+ "result": {
+ "traps": {
+
+ "snmp": {
+
+ "coldstart": "{{True if coldstart is defined}}",
+
+ },
+ },
+ },
+ },
+ {
+ "name": "traps.snmp.warmstart",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\ssnmp\swarmstart(?P<warmstart>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps snmp warmstart",
+ "result": {
+ "traps": {
+
+ "snmp": {
+ "warmstart": "{{True if warmstart is defined}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "traps.snmp.authentication",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\straps
+ (\ssnmp\sauthentication(?P<authentication>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server traps snmp authentication",
+ "result": {
+ "traps": {
+
+ "snmp": {
+ "authentication": "{{True if authentication is defined}}",
+ },
+ },
+ },
+ },
+ {
+ "name": "users",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\suser
+ (\s(?P<name>\S+))
+ (\s(?P<group>\S+))
+ (\s(?P<version>v1|v2c|v3))
+ (\sIPv4\s(?P<ipv4>\S+))?
+ (\sIPv6\s(?P<ipv6>\S+))?
+ (\s(?P<v4acl>\S+))?
+ (\sSDROwner\s(?P<sdrowner>))?
+ (\sSystemOwner\s(?P<systemowner>))?
+ $""", re.VERBOSE,
+ ),
+ "setval": user_tmplt,
+ "result": {
+ "users": [
+ {
+ "user": "{{ name }}",
+ "group": "{{ group }}",
+ "acl_v4": "{{ipv4}}",
+ "acl_v6": "{{ipv6}}",
+ "SDROwner": "{{True if sdowner is defined}}",
+ "SystemOwner": "{{True if systemowner is defined }}",
+ "v4_acl": "{{v4acl}}",
+ "version": "{{version}}",
+ },
+ ],
+ },
+ },
+ {
+ "name": "vrfs",
+ "getval": re.compile(
+ r"""
+ ^snmp-server\svrf
+ (\s(?P<vrf>\S+))
+ (\scontext\s(?P<context>\S+))?
+ ((\shost\s(?P<host>\S+))?
+ (\s(?P<traps>traps))?
+ (\s(?P<informs>informs))?
+ (\sversion\s(?P<version>1|2c|3))?
+ (\s(?P<community>\S+))?
+ (\sudp-port\s(?P<port>\d+))?)?
+ $""", re.VERBOSE,
+ ),
+ "setval": "snmp-server vrf {{vrf}}",
+ "result": {
+ "vrfs": {
+ "{{vrf}}": {
+ "vrf": "{{vrf}}",
+ "context": {
+ "name_{{context|d()}}": "{{context}}",
+ },
+ "hosts": [
+ {
+ "host": "{{ host }}",
+ "traps": "{{True if traps is defined}}",
+ "informs": "{{True if informs is defined}}",
+ "community": "{{community}}",
+ "udp_port": "{{port}}",
+ "version": "{{version}}",
+ },
+ ],
+ },
+ },
+ },
+ },
+ ]
+ # fmt: on
diff --git a/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/__init__.py b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/__init__.py
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
new file mode 100644
index 00000000..a4467a48
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/module_utils/network/iosxr/utils/utils.py
@@ -0,0 +1,456 @@
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# utils
+
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+from 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.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,
+)
+
+
+try:
+ import ipaddress
+
+ HAS_IPADDRESS = True
+except ImportError:
+ HAS_IPADDRESS = False
+
+
+def remove_command_from_config_list(interface, cmd, commands):
+ # To delete the passed config
+ if interface not in commands:
+ commands.insert(0, interface)
+ commands.append("no %s" % cmd)
+ return commands
+
+
+def add_command_to_config_list(interface, cmd, commands):
+ # To set the passed config
+ if interface not in commands:
+ commands.insert(0, interface)
+ commands.append(cmd)
+
+
+def dict_to_set(sample_dict):
+ # Generate a set with passed dictionary for comparison
+ test_dict = {}
+ if isinstance(sample_dict, dict):
+ for k, v in iteritems(sample_dict):
+ if v is not None:
+ if isinstance(v, list):
+ if isinstance(v[0], dict):
+ li = []
+ for each in v:
+ for key, value in iteritems(each):
+ if isinstance(value, list):
+ each[key] = tuple(value)
+ li.append(tuple(iteritems(each)))
+ v = tuple(li)
+ else:
+ v = tuple(v)
+ elif isinstance(v, dict):
+ li = []
+ for key, value in iteritems(v):
+ if isinstance(value, list):
+ v[key] = tuple(value)
+ li.extend(tuple(iteritems(v)))
+ v = tuple(li)
+ test_dict.update({k: v})
+ return_set = set(tuple(iteritems(test_dict)))
+ else:
+ return_set = set(sample_dict)
+ return return_set
+
+
+def filter_dict_having_none_value(want, have):
+ # Generate dict with have dict value which is None in want dict
+ test_dict = dict()
+ test_key_dict = dict()
+ name = want.get("name")
+ if name:
+ test_dict["name"] = name
+ diff_ip = False
+ want_ip = ""
+ for k, v in iteritems(want):
+ if isinstance(v, dict):
+ for key, value in iteritems(v):
+ if value is None and k in have and key in have.get(k):
+ dict_val = have.get(k).get(key)
+ test_key_dict.update({key: dict_val})
+ test_dict.update({k: test_key_dict})
+ if isinstance(v, list) and isinstance(v[0], dict):
+ for key, value in iteritems(v[0]):
+ if value is None and k in have and key in have.get(k):
+ dict_val = have.get(k).get(key)
+ test_key_dict.update({key: dict_val})
+ test_dict.update({k: test_key_dict})
+ # below conditions checks are added to check if
+ # secondary IP is configured, if yes then delete
+ # the already configured IP if want and have IP
+ # is different else if it's same no need to delete
+ for each in v:
+ if each.get("secondary"):
+ want_ip = each.get("address").split("/")
+ have_ip = have.get("ipv4")
+ for each in have_ip:
+ if len(want_ip) > 1 and each.get("secondary"):
+ have_ip = each.get("address").split(" ")[0]
+ if have_ip != want_ip[0]:
+ diff_ip = True
+ if each.get("secondary") and diff_ip is True:
+ test_key_dict.update({"secondary": True})
+ test_dict.update({"ipv4": test_key_dict})
+ # Checks if want doesn't have secondary IP but have has secondary IP set
+ elif have.get("ipv4"):
+ if [True for each_have in have.get("ipv4") if "secondary" in each_have]:
+ test_dict.update({"ipv4": {"secondary": True}})
+ if k == "l2protocol":
+ diff = True
+ h_proto = have.get("l2protocol")
+ w_proto = want.get("l2protocol")
+ if h_proto:
+ if w_proto:
+ for h in h_proto:
+ for w in w_proto:
+ if h == w:
+ diff = False
+ if not diff:
+ break
+ else:
+ diff = True
+ if diff:
+ test_dict.update({k: v})
+ if v is None:
+ val = have.get(k)
+ test_dict.update({k: val})
+ return test_dict
+
+
+def remove_duplicate_interface(commands):
+ # Remove duplicate interface from commands
+ set_cmd = []
+ for each in commands:
+ if "interface" in each:
+ if each not in set_cmd:
+ set_cmd.append(each)
+ else:
+ set_cmd.append(each)
+
+ return set_cmd
+
+
+def flatten_dict(x):
+ result = {}
+ if not isinstance(x, dict):
+ return result
+
+ for key, value in iteritems(x):
+ if isinstance(value, dict):
+ result.update(flatten_dict(value))
+ else:
+ result[key] = value
+
+ return result
+
+
+def dict_delete(base, comparable):
+ """
+
+ This function generates a dict containing key, value pairs for keys
+ that are present in the `base` dict but not present in the `comparable`
+ dict.
+
+ :param base: dict object to base the diff on
+ :param comparable: dict object to compare against base
+
+ :returns: new dict object with key, value pairs that needs to be deleted.
+
+ """
+ to_delete = dict()
+
+ for key in base:
+ if isinstance(base[key], dict):
+ sub_diff = dict_delete(base[key], comparable.get(key, {}))
+ if sub_diff:
+ to_delete[key] = sub_diff
+ else:
+ if key not in comparable:
+ to_delete[key] = base[key]
+
+ return to_delete
+
+
+def pad_commands(commands, interface):
+ commands.insert(0, "interface {0}".format(interface))
+
+
+def diff_list_of_dicts(w, h, key="member"):
+ """
+ Returns a list containing diff between
+ two list of dictionaries
+ """
+ if not w:
+ w = []
+ if not h:
+ h = []
+
+ diff = []
+ for w_item in w:
+ h_item = search_obj_in_list(w_item[key], h, key=key) or {}
+ d = dict_diff(h_item, w_item)
+ if d:
+ if key not in d.keys():
+ d[key] = w_item[key]
+ diff.append(d)
+
+ return diff
+
+
+def validate_ipv4(value, module):
+ if value:
+ address = value.split("/")
+ if len(address) != 2:
+ module.fail_json(
+ msg="address format is <ipv4 address>/<mask>, got invalid format {0}".format(
+ value,
+ ),
+ )
+
+ if not is_masklen(address[1]):
+ module.fail_json(
+ msg="invalid value for mask: {0}, mask should be in range 0-32".format(
+ address[1],
+ ),
+ )
+
+
+def validate_ipv6(value, module):
+ if value:
+ address = value.split("/")
+ if len(address) != 2:
+ module.fail_json(
+ msg="address format is <ipv6 address>/<mask>, got invalid format {0}".format(
+ value,
+ ),
+ )
+ else:
+ if not 0 <= int(address[1]) <= 128:
+ module.fail_json(
+ msg="invalid value for mask: {0}, mask should be in range 0-128".format(
+ address[1],
+ ),
+ )
+
+
+def validate_n_expand_ipv4(module, want):
+ # Check if input IPV4 is valid IP and expand IPV4 with its subnet mask
+ ip_addr_want = want.get("address")
+ if len(ip_addr_want.split(" ")) > 1:
+ return ip_addr_want
+ validate_ipv4(ip_addr_want, module)
+ ip = ip_addr_want.split("/")
+ if len(ip) == 2:
+ ip_addr_want = "{0} {1}".format(ip[0], to_netmask(ip[1]))
+
+ return ip_addr_want
+
+
+def normalize_interface(name):
+ """Return the normalized interface name"""
+ if not name:
+ return
+
+ def _get_number(name):
+ digits = ""
+ for char in name:
+ if char.isdigit() or char in "/.":
+ digits += char
+ return digits
+
+ if name.lower().startswith("gi"):
+ if_type = "GigabitEthernet"
+ elif name.lower().startswith("fa"):
+ if_type = "FastEthernet"
+ elif name.lower().startswith("fo"):
+ if_type = "FortyGigE"
+ elif name.lower().startswith("te"):
+ if_type = "TenGigE"
+ elif name.lower().startswith("twe"):
+ if_type = "TwentyFiveGigE"
+ elif name.lower().startswith("hu"):
+ if_type = "HundredGigE"
+ elif name.lower().startswith("vl"):
+ if_type = "Vlan"
+ elif name.lower().startswith("lo"):
+ if_type = "Loopback"
+ elif name.lower().startswith("be"):
+ if_type = "Bundle-Ether"
+ elif name.lower().startswith("bp"):
+ if_type = "Bundle-POS"
+ else:
+ if_type = None
+
+ number_list = name.split(" ")
+ if len(number_list) == 2:
+ number = number_list[-1].strip()
+ else:
+ number = _get_number(name)
+
+ if if_type:
+ proper_interface = if_type + number
+ else:
+ proper_interface = name
+
+ return proper_interface
+
+
+def get_interface_type(interface):
+ """Gets the type of interface"""
+
+ if interface.upper().startswith("GI"):
+ return "GigabitEthernet"
+ elif interface.upper().startswith("FA"):
+ return "FastEthernet"
+ elif interface.upper().startswith("FO"):
+ return "FortyGigE"
+ elif interface.upper().startswith("ET"):
+ return "Ethernet"
+ elif interface.upper().startswith("LO"):
+ return "Loopback"
+ elif interface.upper().startswith("BE"):
+ return "Bundle-Ether"
+ elif interface.upper().startswith("NV"):
+ return "nve"
+ elif interface.upper().startswith("TE"):
+ return "TenGigE"
+ elif interface.upper().startswith("TWE"):
+ return "TwentyFiveGigE"
+ elif interface.upper().startswith("HU"):
+ return "HundredGigE"
+ elif interface.upper().startswith("PRE"):
+ return "preconfigure"
+ else:
+ return "unknown"
+
+
+def isipaddress(data):
+ """
+ Checks if the passed string is
+ a valid IPv4 or IPv6 address
+ """
+ if not HAS_IPADDRESS:
+ raise Exception(missing_required_lib("ipaddress"))
+ isipaddress = True
+
+ try:
+ ipaddress.ip_address(data)
+ except ValueError:
+ isipaddress = False
+
+ return isipaddress
+
+
+def is_ipv4_address(data):
+ """
+ Checks if the passed string is
+ a valid IPv4 address
+ """
+ if not HAS_IPADDRESS:
+ raise Exception(missing_required_lib("ipaddress"))
+ if "/" in data:
+ data = data.split("/")[0]
+
+ if not isipaddress(to_text(data)):
+ raise ValueError("{0} is not a valid IP address".format(data))
+
+ return ipaddress.ip_address(to_text(data)).version == 4
+
+
+def prefix_to_address_wildcard(prefix):
+ """Converts a IPv4 prefix into address and
+ wildcard mask
+
+ :returns: IPv4 address and wildcard mask
+ """
+ if not HAS_IPADDRESS:
+ raise Exception(missing_required_lib("ipaddress"))
+ wildcard = []
+
+ subnet = to_text(ipaddress.IPv4Network(to_text(prefix)).netmask)
+
+ for x in subnet.split("."):
+ component = 255 - int(x)
+ wildcard.append(str(component))
+
+ wildcard = ".".join(wildcard)
+
+ return prefix.split("/")[0], wildcard
+
+
+def flatten_config(data, context):
+ """Flatten different contexts in
+ the running-config for easier parsing.
+ :param data: dict
+ :param context: str
+ :returns: flattened running config
+ """
+ data = data.split("\n")
+ in_cxt = False
+ cur = {}
+
+ for index, x in enumerate(data):
+ cur_indent = len(x) - len(x.lstrip())
+ if x.strip().startswith(context):
+ in_cxt = True
+ cur["context"] = x
+ cur["indent"] = cur_indent
+ elif cur and (cur_indent <= cur["indent"]):
+ in_cxt = False
+ elif in_cxt:
+ data[index] = cur["context"] + " " + x.strip()
+ return "\n".join(data)
+
+
+@total_ordering
+class Version:
+ """Simple class to compare arbitrary versions"""
+
+ def __init__(self, version_string):
+ self.components = version_string.split(".")
+
+ def __eq__(self, other):
+ other = _coerce(other)
+ if not isinstance(other, Version):
+ return NotImplemented
+
+ return self.components == other.components
+
+ def __lt__(self, other):
+ other = _coerce(other)
+ if not isinstance(other, Version):
+ return NotImplemented
+
+ return self.components < other.components
+
+
+def _coerce(other):
+ if isinstance(other, str):
+ other = Version(other)
+ if isinstance(other, (int, float)):
+ other = Version(str(other))
+ return other
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/__init__.py b/ansible_collections/cisco/iosxr/plugins/modules/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_acl_interfaces.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_acl_interfaces.py
new file mode 100644
index 00000000..7dc8df80
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_acl_interfaces.py
@@ -0,0 +1,653 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_acl_interfaces
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_acl_interfaces
+short_description: Resource module to configure ACL interfaces.
+description:
+- This module manages adding and removing Access Control Lists (ACLs) from interfaces
+ on devices running IOS-XR software.
+version_added: 1.0.0
+author: Nilashish Chakraborty (@NilashishC)
+options:
+ config:
+ description: A dictionary of ACL options for interfaces.
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Name/Identifier for the interface
+ type: str
+ required: true
+ access_groups:
+ type: list
+ elements: dict
+ description:
+ - Specifies ACLs attached to the interfaces.
+ suboptions:
+ afi:
+ description:
+ - Specifies the AFI for the ACL(s) to be configured on this interface.
+ type: str
+ choices:
+ - ipv4
+ - ipv6
+ required: true
+ acls:
+ type: list
+ description:
+ - Specifies the ACLs for the provided AFI.
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Specifies the name of the IPv4/IPv6 ACL for the interface.
+ type: str
+ required: true
+ direction:
+ description:
+ - Specifies the direction of packets that the ACL will be applied
+ on.
+ type: str
+ choices:
+ - in
+ - out
+ required: true
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config interface).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state the configuration should be left in.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - gathered
+ - parsed
+ - rendered
+ default: merged
+
+"""
+EXAMPLES = """
+# Using merged
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:22:32.911 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+
+- name: Merge the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_acl_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/0
+ access_groups:
+ - afi: ipv4
+ acls:
+ - name: acl_1
+ direction: in
+ - name: acl_2
+ direction: out
+ - afi: ipv6
+ acls:
+ - name: acl6_1
+ direction: in
+ - name: acl6_2
+ direction: out
+
+ - name: GigabitEthernet0/0/0/1
+ access_groups:
+ - afi: ipv4
+ acls:
+ - name: acl_1
+ direction: out
+ state: merged
+
+# After state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:27:49.378 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 egress
+# !
+
+# Using merged to update interface ACL configuration
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:27:49.378 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 egress
+# !
+#
+
+- name: Update acl_interfaces configuration using merged
+ cisco.iosxr.iosxr_acl_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ access_groups:
+ - afi: ipv4
+ acls:
+ - name: acl_2
+ direction: out
+ - name: acl_1
+ direction: in
+ state: merged
+
+# After state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:27:49.378 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# !
+#
+
+# Using replaced
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:34:56.689 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 egress
+# !
+
+- name: Replace device configurations of listed interface with provided configurations
+ cisco.iosxr.iosxr_acl_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/0
+ access_groups:
+ - afi: ipv6
+ acls:
+ - name: acl6_3
+ direction: in
+ state: replaced
+
+# After state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:34:56.689 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv6 access-group acl6_3 ingress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 egress
+# !
+#
+
+# Using overridden
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:34:56.689 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 egress
+# !
+#
+
+- name: Overridde all interface ACL configuration with provided configuration
+ cisco.iosxr.iosxr_acl_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ access_groups:
+ - afi: ipv4
+ acls:
+ - name: acl_2
+ direction: in
+ - afi: ipv6
+ acls:
+ - name: acl6_3
+ direction: out
+ state: overridden
+
+# After state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:34:56.689 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_2 ingress
+# ipv6 access-group acl6_3 egress
+# !
+#
+
+# Using 'deleted' to delete all ACL attributes of a single interface
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:34:56.689 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 egress
+# !
+#
+
+- name: Delete all ACL attributes of GigabitEthernet0/0/0/1
+ cisco.iosxr.iosxr_acl_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ state: deleted
+
+# After state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:34:56.689 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+#
+
+# Using 'deleted' to remove all ACLs attached to all the interfaces in the device
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:34:56.689 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 egress
+# !
+#
+
+- name: Delete all ACL interfaces configuration from the device
+ cisco.iosxr.iosxr_acl_interfaces:
+ state: deleted
+
+# After state:
+# -------------
+#
+# RP/0/RP0/CPU0:ios#sh running-config interface
+# Wed Jan 15 12:34:56.689 UTC
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+#
+
+# Using parsed
+
+# parsed.cfg
+# ------------
+#
+# interface MgmtEth0/RP0/CPU0/0
+# ipv4 address dhcp
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# ipv4 access-group acl_1 ingress
+# ipv4 access-group acl_2 egress
+# ipv6 access-group acl6_1 ingress
+# ipv6 access-group acl6_2 egress
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# ipv4 access-group acl_1 egress
+# !
+
+# - name: Convert ACL interfaces config to argspec without connecting to the appliance
+# cisco.iosxr.iosxr_acl_interfaces:
+# running_config: "{{ lookup('file', './parsed.cfg') }}"
+# state: parsed
+
+
+# Task Output (redacted)
+# -----------------------
+
+# "parsed": [
+# {
+# "name": "MgmtEth0/RP0/CPU0/0"
+# },
+# {
+# "access_groups": [
+# {
+# "acls": [
+# {
+# "direction": "in",
+# "name": "acl_1"
+# },
+# {
+# "direction": "out",
+# "name": "acl_2"
+# }
+# ],
+# "afi": "ipv4"
+# },
+# {
+# "acls": [
+# {
+# "direction": "in",
+# "name": "acl6_1"
+# },
+# {
+# "direction": "out",
+# "name": "acl6_2"
+# }
+# ],
+# "afi": "ipv6"
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0"
+# },
+# {
+# "access_groups": [
+# {
+# "acls": [
+# {
+# "direction": "out",
+# "name": "acl_1"
+# }
+# ],
+# "afi": "ipv4"
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/1"
+# }
+# ]
+# }
+
+
+# Using gathered
+
+- name: Gather ACL interfaces facts using gathered state
+ cisco.iosxr.iosxr_acl_interfaces:
+ state: gathered
+
+
+# Task Output (redacted)
+# -----------------------
+#
+# "gathered": [
+# {
+# "name": "MgmtEth0/RP0/CPU0/0"
+# },
+# {
+# "access_groups": [
+# {
+# "acls": [
+# {
+# "direction": "in",
+# "name": "acl_1"
+# },
+# {
+# "direction": "out",
+# "name": "acl_2"
+# }
+# ],
+# "afi": "ipv4"
+# }
+# "name": "GigabitEthernet0/0/0/0"
+# },
+# {
+# "access_groups": [
+# {
+# "acls": [
+# {
+# "direction": "in",
+# "name": "acl6_1"
+# }
+# ],
+# "afi": "ipv6"
+# }
+# "name": "GigabitEthernet0/0/0/1"
+# }
+# ]
+
+
+# Using rendered
+
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_acl_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/0
+ access_groups:
+ - afi: ipv4
+ acls:
+ - name: acl_1
+ direction: in
+ - name: acl_2
+ direction: out
+ state: rendered
+
+# Task Output (redacted)
+# -----------------------
+
+# "rendered": [
+# "interface GigabitEthernet0/0/0/0",
+# "ipv4 access-group acl_1 ingress",
+# "ipv4 access-group acl_2 egress"
+# ]
+"""
+RETURN = """
+before:
+ description: The configuration prior to the model invocation.
+ returned: always
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The resulting configuration model invocation.
+ returned: when changed
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample:
+ - "interface GigabitEthernet0/0/0/1"
+ - "ipv4 access-group acl_1 ingress"
+ - "ipv4 access-group acl_2 egress"
+ - "ipv6 access-group acl6_1 ingress"
+ - "interface GigabitEthernet0/0/0/2"
+ - "no ipv4 access-group acl_3 ingress"
+ - "ipv4 access-group acl_4 egress"
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.acl_interfaces.acl_interfaces import (
+ Acl_interfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.acl_interfaces.acl_interfaces import (
+ Acl_interfaces,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+ mutually_exclusive = [("config", "running_config")]
+
+ module = AnsibleModule(
+ argument_spec=Acl_interfacesArgs.argument_spec,
+ required_if=required_if,
+ mutually_exclusive=mutually_exclusive,
+ supports_check_mode=True,
+ )
+
+ result = Acl_interfaces(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_acls.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_acls.py
new file mode 100644
index 00000000..22a7779c
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_acls.py
@@ -0,0 +1,1467 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_acls
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_acls
+short_description: Resource module to configure ACLs.
+description:
+- This module manages Access Control Lists (ACLs) on devices running IOS-XR.
+version_added: 1.0.0
+author: Nilashish Chakraborty (@NilashishC)
+options:
+ config:
+ description: A list of dictionaries specifying ACL configurations.
+ type: list
+ elements: dict
+ suboptions:
+ afi:
+ description:
+ - The Address Family Indicator (AFI) for the Access Control Lists (ACL).
+ type: str
+ required: true
+ choices:
+ - ipv4
+ - ipv6
+ acls:
+ description:
+ - A list of Access Control Lists (ACLs).
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - The name of the Access Control List (ACL).
+ type: str
+ aces:
+ description:
+ - List of Access Control Entries (ACEs) for this Access Control List (ACL).
+ type: list
+ elements: dict
+ suboptions:
+ sequence:
+ description:
+ - Sequence number for the Access Control Entry (ACE).
+ type: int
+ grant:
+ description:
+ - Forward or drop packets matching the Access Control Entry (ACE).
+ type: str
+ choices:
+ - permit
+ - deny
+ remark:
+ description:
+ - Comments or a description for the access list.
+ type: str
+ line:
+ description:
+ - An ACE excluding the sequence number.
+ - This key is mutually exclusive with all the other attributes except
+ 'sequence'.
+ - When used with other attributes, the value of this key will get
+ precedence and the other keys will be ignored.
+ - This should only be used when an attribute doesn't exist in the
+ argspec but is valid for the device.
+ - For fact gathering, any ACE that is not fully parsed, will show
+ up as a value of this attribute, excluding the sequence number,
+ which will be populated as value of the sequence key.
+ type: str
+ aliases:
+ - ace
+ source:
+ description:
+ - Specifies the packet source.
+ type: dict
+ suboptions:
+ host:
+ description:
+ - The host IP address to match.
+ type: str
+ net_group:
+ description:
+ - Name of net-group.
+ type: str
+ port_group:
+ description:
+ - Name of port-group.
+ type: str
+ address:
+ description:
+ - The source IP address to match.
+ type: str
+ wildcard_bits:
+ description:
+ - The Wildcard bits to apply to source address.
+ type: str
+ any:
+ description:
+ - Match any source address.
+ type: bool
+ prefix:
+ description:
+ - Source network prefix.
+ type: str
+ port_protocol:
+ description:
+ - Specify the source port or protocol.
+ type: dict
+ suboptions:
+ eq:
+ description:
+ - Match only packets on a given port number.
+ type: str
+ gt:
+ description:
+ - Match only packets with a greater port number.
+ type: str
+ lt:
+ description:
+ - Match only packets with a lower port number.
+ type: str
+ neq:
+ description:
+ - Match only packets not on a given port number.
+ type: str
+ range:
+ description:
+ - Match only packets in the range of port numbers
+ type: dict
+ suboptions:
+ start:
+ description:
+ - Specify the start of the port range
+ type: str
+ end:
+ description:
+ - Specify the end of the port range
+ type: str
+ destination:
+ description:
+ - Specifies the packet destination.
+ type: dict
+ suboptions:
+ host:
+ description:
+ - The host IP address to match.
+ type: str
+ net_group:
+ description:
+ - Name of net-group.
+ type: str
+ port_group:
+ description:
+ - Name of port-group.
+ type: str
+ address:
+ description:
+ - The destination IP address to match.
+ type: str
+ wildcard_bits:
+ description:
+ - The Wildcard bits to apply to destination address.
+ type: str
+ any:
+ description:
+ - Match any destination address.
+ type: bool
+ prefix:
+ description:
+ - Destination network prefix.
+ type: str
+ port_protocol:
+ description:
+ - Specify the source port or protocol.
+ type: dict
+ suboptions:
+ eq:
+ description:
+ - Match only packets on a given port number.
+ type: str
+ gt:
+ description:
+ - Match only packets with a greater port number.
+ type: str
+ lt:
+ description:
+ - Match only packets with a lower port number.
+ type: str
+ neq:
+ description:
+ - Match only packets not on a given port number.
+ type: str
+ range:
+ description:
+ - Match only packets in the range of port numbers
+ type: dict
+ suboptions:
+ start:
+ description:
+ - Specify the start of the port range
+ type: str
+ end:
+ description:
+ - Specify the end of the port range
+ type: str
+ protocol:
+ description:
+ - Specify the protocol to match.
+ - Refer to vendor documentation for valid values.
+ type: str
+ protocol_options:
+ description:
+ - Additional suboptions for the protocol.
+ type: dict
+ suboptions:
+ icmpv6:
+ description: Internet Control Message Protocol settings for IPv6.
+ type: dict
+ suboptions:
+ address_unreachable:
+ description: Address Unreachable
+ type: bool
+ administratively_prohibited:
+ description: Administratively Prohibited
+ type: bool
+ beyond_scope_of_source_address:
+ description: Administratively Prohibited
+ type: bool
+ destination_unreachable:
+ description: Destination Unreachable
+ type: bool
+ echo:
+ description: Echo
+ type: bool
+ echo_reply:
+ description: Echo Reply
+ type: bool
+ erroneous_header_field:
+ description: Erroneous Header Field
+ type: bool
+ group_membership_query:
+ description: Group Membership Query
+ type: bool
+ group_membership_report:
+ description: Group Membership Report
+ type: bool
+ group_membership_termination:
+ description: Group Membership Termination
+ type: bool
+ host_unreachable:
+ description: Host Unreachable
+ type: bool
+ nd_na:
+ description: Neighbor Discovery - Neighbor Advertisement
+ type: bool
+ nd_ns:
+ description: Neighbor Discovery - Neighbor Solicitation
+ type: bool
+ neighbor_redirect:
+ description: Neighbor Redirect
+ type: bool
+ no_route_to_destination:
+ description: No Route To Destination
+ type: bool
+ node_information_request_is_refused:
+ description: Node Information Request Is Refused
+ type: bool
+ node_information_successful_reply:
+ description: Node Information Successful Reply
+ type: bool
+ packet_too_big:
+ description: Packet Too Big
+ type: bool
+ parameter_problem:
+ description: Parameter Problem
+ type: bool
+ port_unreachable:
+ description: Port Unreachable
+ type: bool
+ query_subject_is_IPv4address:
+ description: Query Subject Is IPv4 address
+ type: bool
+ query_subject_is_IPv6address:
+ description: Query Subject Is IPv6 address
+ type: bool
+ query_subject_is_domainname:
+ description: Query Subject Is Domain name
+ type: bool
+ reassembly_timeout:
+ description: Reassembly Timeout
+ type: bool
+ redirect:
+ description: Redirect
+ type: bool
+ router_advertisement:
+ description: Router Advertisement
+ type: bool
+ router_renumbering:
+ description: Router Renumbering
+ type: bool
+ router_solicitation:
+ description: Router Solicitation
+ type: bool
+ rr_command:
+ description: RR Command
+ type: bool
+ rr_result:
+ description: RR Result
+ type: bool
+ rr_seqnum_reset:
+ description: RR Seqnum Reset
+ type: bool
+ time_exceeded:
+ description: Time Exceeded
+ type: bool
+ ttl_exceeded:
+ description: TTL Exceeded
+ type: bool
+ unknown_query_type:
+ description: Unknown Query Type
+ type: bool
+ unreachable:
+ description: Unreachable
+ type: bool
+ unrecognized_next_header:
+ description: Unrecognized Next Header
+ type: bool
+ unrecognized_option:
+ description: Unrecognized Option
+ type: bool
+ whoareyou_reply:
+ description: Whoareyou Reply
+ type: bool
+ whoareyou_request:
+ description: Whoareyou Request
+ type: bool
+ icmp:
+ description: Internet Control Message Protocol settings.
+ type: dict
+ suboptions:
+ administratively_prohibited:
+ description: Administratively prohibited
+ type: bool
+ alternate_address:
+ description: Alternate address
+ type: bool
+ conversion_error:
+ description: Datagram conversion
+ type: bool
+ dod_host_prohibited:
+ description: Host prohibited
+ type: bool
+ dod_net_prohibited:
+ description: Net prohibited
+ type: bool
+ echo:
+ description: Echo (ping)
+ type: bool
+ echo_reply:
+ description: Echo reply
+ type: bool
+ general_parameter_problem:
+ description: Parameter problem
+ type: bool
+ host_isolated:
+ description: Host isolated
+ type: bool
+ host_precedence_unreachable:
+ description: Host unreachable for precedence
+ type: bool
+ host_redirect:
+ description: Host redirect
+ type: bool
+ host_tos_redirect:
+ description: Host redirect for TOS
+ type: bool
+ host_tos_unreachable:
+ description: Host unreachable for TOS
+ type: bool
+ host_unknown:
+ description: Host unknown
+ type: bool
+ host_unreachable:
+ description: Host unreachable
+ type: bool
+ information_reply:
+ description: Information replies
+ type: bool
+ information_request:
+ description: Information requests
+ type: bool
+ mask_reply:
+ description: Mask replies
+ type: bool
+ mask_request:
+ description: Mask requests
+ type: bool
+ mobile_redirect:
+ description: Mobile host redirect
+ type: bool
+ net_redirect:
+ description: Network redirect
+ type: bool
+ net_tos_redirect:
+ description: Net redirect for TOS
+ type: bool
+ net_tos_unreachable:
+ description: Network unreachable for TOS
+ type: bool
+ net_unreachable:
+ description: Net unreachable
+ type: bool
+ network_unknown:
+ description: Network unknown
+ type: bool
+ no_room_for_option:
+ description: Parameter required but no room
+ type: bool
+ option_missing:
+ description: Parameter required but not present
+ type: bool
+ packet_too_big:
+ description: Fragmentation needed and DF set
+ type: bool
+ parameter_problem:
+ description: All parameter problems
+ type: bool
+ port_unreachable:
+ description: Port unreachable
+ type: bool
+ precedence_unreachable:
+ description: Precedence cutoff
+ type: bool
+ protocol_unreachable:
+ description: Protocol unreachable
+ type: bool
+ reassembly_timeout:
+ description: Reassembly timeout
+ type: bool
+ redirect:
+ description: All redirects
+ type: bool
+ router_advertisement:
+ description: Router discovery advertisements
+ type: bool
+ router_solicitation:
+ description: Router discovery solicitations
+ type: bool
+ source_quench:
+ description: Source quenches
+ type: bool
+ source_route_failed:
+ description: Source route failed
+ type: bool
+ time_exceeded:
+ description: All time exceededs
+ type: bool
+ timestamp_reply:
+ description: Timestamp replies
+ type: bool
+ timestamp_request:
+ description: Timestamp requests
+ type: bool
+ traceroute:
+ description: Traceroute
+ type: bool
+ ttl_exceeded:
+ description: TTL exceeded
+ type: bool
+ unreachable:
+ description: All unreachables
+ type: bool
+ tcp:
+ description: Match TCP packet flags
+ type: dict
+ suboptions:
+ ack:
+ description: Match on the ACK bit
+ type: bool
+ established:
+ description: Match established connections
+ type: bool
+ fin:
+ description: Match on the FIN bit
+ type: bool
+ psh:
+ description: Match on the PSH bit
+ type: bool
+ rst:
+ description: Match on the RST bit
+ type: bool
+ syn:
+ description: Match on the SYN bit
+ type: bool
+ urg:
+ description: Match on the URG bit
+ type: bool
+ igmp:
+ description: Internet Group Management Protocol (IGMP) settings.
+ type: dict
+ suboptions:
+ dvmrp:
+ description: Match Distance Vector Multicast Routing Protocol
+ type: bool
+ host_query:
+ description: Match Host Query
+ type: bool
+ host_report:
+ description: Match Host Report
+ type: bool
+ pim:
+ description: Match Protocol Independent Multicast
+ type: bool
+ trace:
+ description: Multicast trace
+ type: bool
+ mtrace:
+ description: Match mtrace
+ type: bool
+ mtrace_response:
+ description: Match mtrace response
+ type: bool
+ dscp:
+ description:
+ - Match packets with given DSCP value.
+ type: dict
+ suboptions:
+ eq:
+ description: Match only packets on a given dscp value
+ type: str
+ gt:
+ description: Match only packets with a greater dscp value
+ type: str
+ lt:
+ description: Match only packets with a lower dscp value
+ type: str
+ neq:
+ description: Match only packets not on a given dscp value
+ type: str
+ range:
+ description: Match only packets in the range of dscp values
+ type: dict
+ suboptions:
+ start:
+ description: Start of the dscp range
+ type: str
+ end:
+ description: End of the dscp range
+ type: str
+ fragments:
+ description:
+ - Check non-intial fragments.
+ type: bool
+ packet_length:
+ description:
+ - Match packets given packet length.
+ type: dict
+ suboptions:
+ eq:
+ description: Match only packets on a given packet length
+ type: int
+ gt:
+ description: Match only packets with a greater packet length
+ type: int
+ lt:
+ description: Match only packets with a lower packet length
+ type: int
+ neq:
+ description: Match only packets not on a given packet length
+ type: int
+ range:
+ description: Match only packets in the range of packet lengths
+ type: dict
+ suboptions:
+ start:
+ description: Start of the packet length range
+ type: int
+ end:
+ description: End of the packet length range
+ type: int
+ precedence:
+ description: Match packets with given precedence value
+ type: str
+ ttl:
+ description: Match against specified TTL value.
+ type: dict
+ suboptions:
+ eq:
+ description: Match only packets with exact TTL value.
+ type: int
+ gt:
+ description: Match only packets with a greater TTL value.
+ type: int
+ lt:
+ description: Match only packets with a lower TTL value.
+ type: int
+ neq:
+ description: Match only packets that won't have the given TTL
+ value.
+ type: int
+ range:
+ description: Match only packets in the range of given TTL values.
+ type: dict
+ suboptions:
+ start:
+ description: Start of the TTL range.
+ type: int
+ end:
+ description: End of the TTL range.
+ type: int
+ log:
+ description:
+ - Enable/disable log matches against this entry.
+ type: bool
+ log_input:
+ description:
+ - Enable/disable log matches against this entry, including input interface.
+ type: bool
+ icmp_off:
+ description:
+ - Enable/disable the ICMP message for this entry.
+ type: bool
+ capture:
+ description:
+ - Capture matched packet.
+ type: bool
+ destopts:
+ description:
+ - Match if destination opts header is present.
+ type: bool
+ authen:
+ description:
+ - Match if authentication header is present.
+ type: bool
+ routing:
+ description:
+ - Match if routing header is present.
+ type: bool
+ hop_by_hop:
+ description:
+ - Match if hop-by-hop opts header is present.
+ type: bool
+ running_config:
+ description:
+ - The module, by default, will connect to the remote device and retrieve the current
+ running-config to use as a base for comparing against the contents of source.
+ There are times when it is not desirable to have the task get the current running-config
+ for every task in a playbook. The I(running_config) argument allows the implementer
+ to pass in the configuration to use as the base config for comparison. This
+ value of this option should be the output received from device by executing
+ command B(show running-config router static).
+ type: str
+ state:
+ description:
+ - The state the configuration should be left in.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - gathered
+ - rendered
+ - parsed
+ default: merged
+
+"""
+EXAMPLES = """
+# Using merged to add new ACLs
+
+# Before state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:07:45.767 UTC
+# RP/0/RP0/CPU0:ios#
+
+- name: Merge the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_acls:
+ config:
+ - afi: ipv6
+ acls:
+ - name: acl6_1
+ aces:
+ - sequence: 10
+ grant: deny
+ protocol: tcp
+ source:
+ prefix: 2001:db8:1234::/48
+ port_protocol:
+ range:
+ start: ftp
+ end: telnet
+ destination:
+ any: true
+ protocol_options:
+ tcp:
+ syn: true
+ ttl:
+ range:
+ start: 180
+ end: 250
+ routing: true
+ authen: true
+ log: true
+
+ - sequence: 20
+ grant: permit
+ protocol: icmpv6
+ source:
+ any: true
+ destination:
+ any: true
+ protocol_options:
+ icmpv6:
+ router_advertisement: true
+ precedence: network
+ destopts: true
+
+ - afi: ipv4
+ acls:
+ - name: acl_1
+ aces:
+ - sequence: 16
+ remark: TEST_ACL_1_REMARK
+
+ - sequence: 21
+ grant: permit
+ protocol: tcp
+ source:
+ host: 192.0.2.10
+ port_protocol:
+ range:
+ start: pop3
+ end: 121
+ destination:
+ address: 198.51.100.0
+ wildcard_bits: 0.0.0.15
+ protocol_options:
+ tcp:
+ rst: true
+
+ - sequence: 23
+ grant: deny
+ protocol: icmp
+ source:
+ any: true
+ destination:
+ prefix: 198.51.100.0/28
+ protocol_options:
+ icmp:
+ reassembly_timeout: true
+ dscp:
+ lt: af12
+
+ - name: acl_2
+ aces:
+ - sequence: 10
+ remark: TEST_ACL_2_REMARK
+ state: merged
+
+# After state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+# 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+# Using merged to update existing ACLs
+
+# Before state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+# 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+- name: Update existing ACEs
+ cisco.iosxr.iosxr_acls:
+ config:
+ - afi: ipv4
+ acls:
+ - name: acl_1
+ aces:
+ - sequence: 21
+ source:
+ prefix: 198.51.100.32/28
+ port_protocol:
+ range:
+ start: pop3
+ end: 121
+ protocol_options:
+ tcp:
+ syn: true
+
+ - sequence: 23
+ protocol_options:
+ icmp:
+ router_advertisement: true
+ dscp:
+ eq: af23
+
+# After state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:47:18.711 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp 198.51.100.32 0.0.0.15 range pop3 121 198.51.100.0 0.0.0.15 syn
+# 23 deny icmp any 198.51.100.0 0.0.0.15 router-advertisement dscp eq af23
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+# Using replaced to replace a whole ACL
+
+# Before state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+# 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+- name: Replace device configurations of listed ACL with provided configurations
+ cisco.iosxr.iosxr_acls:
+ config:
+ - afi: ipv4
+ acls:
+ - name: acl_2
+ aces:
+ - sequence: 11
+ grant: permit
+ protocol: igmp
+ source:
+ host: 198.51.100.130
+ destination:
+ any: true
+ ttl:
+ eq: 100
+
+ - sequence: 12
+ grant: deny
+ source:
+ any: true
+ destination:
+ any: true
+ protocol: icmp
+ state: replaced
+
+# After state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 06:19:51.496 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp 198.51.100.32 0.0.0.15 range pop3 121 198.51.100.0 0.0.0.15 syn
+# 23 deny icmp any 198.51.100.0 0.0.0.15 router-advertisement dscp eq af23
+# ipv4 access-list acl_2
+# 11 permit igmp host 198.51.100.130 any ttl eq 100
+# 12 deny icmp any any
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+# Using overridden to override all ACLs in the device
+
+# Before state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+# 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+- name: Overridde all ACLs configuration with provided configuration
+ cisco.iosxr.iosxr_acls:
+ config:
+ - afi: ipv4
+ acls:
+ - name: acl_1
+ aces:
+ - sequence: 10
+ grant: permit
+ source:
+ any: true
+ destination:
+ any: true
+ protocol: tcp
+
+ - name: acl_2
+ aces:
+ - sequence: 20
+ grant: permit
+ source:
+ any: true
+ destination:
+ any: true
+ protocol: igmp
+ state: overridden
+
+# After state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 06:31:22.178 UTC
+# ipv4 access-list acl_1
+# 10 permit tcp any any
+# ipv4 access-list acl_2
+# 20 permit igmp any any
+
+# Using deleted to delete an entire ACL
+
+# Before state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+# 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+- name: Delete a single ACL
+ cisco.iosxr.iosxr_acls:
+ config:
+ - afi: ipv6
+ acls:
+ - name: acl6_1
+ state: deleted
+
+# After state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+# 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+
+# Using deleted to delete all ACLs under one AFI
+
+# Before state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+# 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+- name: Delete all ACLs under one AFI
+ cisco.iosxr.iosxr_acls:
+ config:
+ - afi: ipv4
+ state: deleted
+
+# After state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+# Using deleted to delete all ACLs from the device
+
+# Before state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:22:57.021 UTC
+# ipv4 access-list acl_1
+# 16 remark TEST_ACL_1_REMARK
+# 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+# 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+# ipv4 access-list acl_2
+# 10 remark TEST_ACL_2_REMARK
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network destopts
+
+- name: Delete all ACLs from the device
+ cisco.iosxr.iosxr_acls:
+ state: deleted
+
+# After state:
+# -------------
+
+# RP/0/RP0/CPU0:ios#sh access-lists afi-all
+# Thu Feb 20 05:07:45.767 UTC
+# RP/0/RP0/CPU0:ios#
+
+# Using gathered to gather ACL facts from the device
+
+- name: Gather ACL interfaces facts using gathered state
+ cisco.iosxr.iosxr_acls:
+ state: gathered
+
+# Task Output (redacted)
+# -----------------------
+#
+
+# "gathered": [
+# {
+# "acls": [
+# {
+# "aces": [
+# {
+# "remark": "TEST_ACL_1_REMARK",
+# "sequence": 16
+# },
+# {
+# "destination": {
+# "address": "198.51.100.0",
+# "wildcard_bits": "0.0.0.15"
+# },
+# "grant": "permit",
+# "protocol": "tcp",
+# "protocol_options": {
+# "tcp": {
+# "rst": true
+# }
+# },
+# "sequence": 21,
+# "source": {
+# "host": "192.0.2.10",
+# "port_protocol": {
+# "range": {
+# "end": "121",
+# "start": "pop3"
+# }
+# }
+# }
+# },
+# {
+# "destination": {
+# "address": "198.51.100.0",
+# "wildcard_bits": "0.0.0.15"
+# },
+# "dscp": {
+# "lt": "af12"
+# },
+# "grant": "deny",
+# "protocol": "icmp",
+# "protocol_options": {
+# "icmp": {
+# "reassembly_timeout": true
+# }
+# },
+# "sequence": 23,
+# "source": {
+# "any": true
+# }
+# }
+# ],
+# "name": "acl_1"
+# },
+# {
+# "aces": [
+# {
+# "remark": "TEST_ACL_2_REMARK",
+# "sequence": 10
+# }
+# ],
+# "name": "acl_2"
+# }
+# ],
+# "afi": "ipv4"
+# },
+# {
+# "acls": [
+# {
+# "aces": [
+# {
+# "authen": true,
+# "destination": {
+# "any": true
+# },
+# "grant": "deny",
+# "log": true,
+# "protocol": "tcp",
+# "protocol_options": {
+# "tcp": {
+# "syn": true
+# }
+# },
+# "routing": true,
+# "sequence": 10,
+# "source": {
+# "port_protocol": {
+# "range": {
+# "end": "telnet",
+# "start": "ftp"
+# }
+# },
+# "prefix": "2001:db8:1234::/48"
+# },
+# "ttl": {
+# "range": {
+# "end": 250,
+# "start": 180
+# }
+# }
+# },
+# {
+# "destination": {
+# "any": true
+# },
+# "destopts": true,
+# "grant": "permit",
+# "precedence": "network",
+# "protocol": "icmpv6",
+# "protocol_options": {
+# "icmpv6": {
+# "router_advertisement": true
+# }
+# },
+# "sequence": 20,
+# "source": {
+# "any": true
+# }
+# }
+# ],
+# "name": "acl6_1"
+# }
+# ],
+# "afi": "ipv6"
+# }
+# ]
+
+# Using rendered
+
+- name: Render platform specific commands (without connecting to the device)
+ cisco.iosxr.iosxr_acls:
+ config:
+ - afi: ipv4
+ acls:
+ - name: acl_2
+ aces:
+ - sequence: 11
+ grant: permit
+ protocol: igmp
+ source:
+ host: 198.51.100.130
+ destination:
+ any: true
+ ttl:
+ eq: 100
+
+ - sequence: 12
+ grant: deny
+ source:
+ any: true
+ destination:
+ any: true
+ protocol: icmp
+ state: rendered
+
+# Task Output (redacted)
+# -----------------------
+
+# "rendered": [
+# "ipv4 access-list acl_2",
+# "11 permit igmp host 198.51.100.130 any ttl eq 100",
+# "12 deny icmp any any"
+
+# Using parsed
+
+# parsed.cfg
+# ------------
+#
+# ipv4 access-list acl_1
+# 10 remark TEST_ACL_2_REMARK
+# ipv4 access-list acl_2
+# 11 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 authen routing log
+# 21 permit icmpv6 any any router-advertisement precedence network packet-length eq 576 destopts
+# ipv6 access-list acl6_1
+# 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
+# 20 permit icmpv6 any any router-advertisement precedence network packet-length eq 576 destopts
+
+- name: Parse externally provided ACL config to agnostic model
+ cisco.iosxr.iosxr_acls:
+ running_config: "{{ lookup('file', 'parsed.cfg') }}"
+ state: parsed
+
+# Task Output (redacted)
+# -----------------------
+# "parsed": [
+# {
+# "acls": [
+# {
+# "aces": [
+# {
+# "remark": "TEST_ACL_2_REMARK",
+# "sequence": 10
+# }
+# ],
+# "name": "acl_1"
+# },
+# {
+# "aces": [
+# {
+# "authen": true,
+# "destination": {
+# "any": true
+# },
+# "grant": "deny",
+# "log": true,
+# "protocol": "tcp",
+# "protocol_options": {
+# "tcp": {
+# "syn": true
+# }
+# },
+# "routing": true,
+# "sequence": 11,
+# "source": {
+# "port_protocol": {
+# "range": {
+# "end": "telnet",
+# "start": "ftp"
+# }
+# },
+# "prefix": "2001:db8:1234::/48"
+# },
+# "ttl": {
+# "range": {
+# "end": 250,
+# "start": 180
+# }
+# }
+# },
+# {
+# "destination": {
+# "any": true
+# },
+# "destopts": true,
+# "grant": "permit",
+# "packet_length": {
+# "eq": 576
+# },
+# "precedence": "network",
+# "protocol": "icmpv6",
+# "protocol_options": {
+# "icmpv6": {
+# "router_advertisement": true
+# }
+# },
+# "sequence": 21,
+# "source": {
+# "any": true
+# }
+# }
+# ],
+# "name": "acl_2"
+# }
+# ],
+# "afi": "ipv4"
+# },
+# {
+# "acls": [
+# {
+# "aces": [
+# {
+# "authen": true,
+# "destination": {
+# "any": true
+# },
+# "grant": "deny",
+# "log": true,
+# "protocol": "tcp",
+# "protocol_options": {
+# "tcp": {
+# "syn": true
+# }
+# },
+# "routing": true,
+# "sequence": 10,
+# "source": {
+# "port_protocol": {
+# "range": {
+# "end": "telnet",
+# "start": "ftp"
+# }
+# },
+# "prefix": "2001:db8:1234::/48"
+# },
+# "ttl": {
+# "range": {
+# "end": 250,
+# "start": 180
+# }
+# }
+# },
+# {
+# "destination": {
+# "any": true
+# },
+# "destopts": true,
+# "grant": "permit",
+# "packet_length": {
+# "eq": 576
+# },
+# "precedence": "network",
+# "protocol": "icmpv6",
+# "protocol_options": {
+# "icmpv6": {
+# "router_advertisement": true
+# }
+# },
+# "sequence": 20,
+# "source": {
+# "any": true
+# }
+# }
+# ],
+# "name": "acl6_1"
+# }
+# ],
+# "afi": "ipv6"
+# }
+# ]
+"""
+RETURN = """
+before:
+ description: The configuration prior to the model invocation.
+ returned: always
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The resulting configuration model invocation.
+ returned: when changed
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample:
+ - ipv6 access-list acl6_1
+ - 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 authen routing log
+ - 20 permit icmpv6 any any router-advertisement precedence network destopts
+ - ipv4 access-list acl_1
+ - 16 remark TEST_ACL_1_REMARK
+ - 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
+ - 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.acls.acls import (
+ AclsArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.acls.acls import Acls
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+
+ module = AnsibleModule(
+ argument_spec=AclsArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ )
+
+ result = Acls(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_banner.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_banner.py
new file mode 100644
index 00000000..2d80022b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_banner.py
@@ -0,0 +1,285 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright: (c) 2017, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_banner
+author:
+- Trishna Guha (@trishnaguha)
+- Kedar Kekan (@kedarX)
+short_description: Module to configure multiline banners.
+description:
+- This module will configure both exec and motd banners on remote device running Cisco
+ IOS XR. It allows playbooks to add or remove banner text from the running configuration.
+version_added: 1.0.0
+requirements:
+- ncclient >= 0.5.3 when using netconf
+- lxml >= 4.1.1 when using netconf
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+notes:
+- This module works with connection C(network_cli) and C(netconf). See L(the IOS-XR
+ Platform Options,../network/user_guide/platform_iosxr.html).
+options:
+ banner:
+ description:
+ - Specifies the type of banner to configure on remote device.
+ required: true
+ type: str
+ choices:
+ - login
+ - motd
+ text:
+ description:
+ - Banner text to be configured. Accepts multi line string, without empty lines.
+ When using a multi line string, the first and last characters must be the
+ start and end delimiters for the banner
+ Requires I(state=present).
+ type: str
+ state:
+ description:
+ - Existential state of the configuration on the device.
+ default: present
+ type: str
+ choices:
+ - present
+ - absent
+"""
+
+EXAMPLES = """
+- name: configure the login banner
+ cisco.iosxr.iosxr_banner:
+ banner: login
+ text: |
+ @this is my login banner
+ that contains a multiline
+ string@
+ state: present
+- name: remove the motd banner
+ cisco.iosxr.iosxr_banner:
+ banner: motd
+ state: absent
+- name: Configure banner from file
+ cisco.iosxr.iosxr_banner:
+ banner: motd
+ text: "{{ lookup('file', './config_partial/raw_banner.cfg') }}"
+ state: present
+"""
+
+RETURN = """
+commands:
+ description: The list of configuration mode commands sent to device with transport C(cli)
+ returned: always (empty list when no commands to send)
+ type: list
+ sample:
+ - banner login
+ - "@this is my login banner"
+ - that contains a multiline
+ - string@
+
+xml:
+ description: NetConf rpc xml sent to device with transport C(netconf)
+ returned: always (empty list when no xml rpc to send)
+ type: list
+ sample:
+ - '<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <banners xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-infra-infra-cfg">
+ <banner xc:operation="merge">
+ <banner-name>motd</banner-name>
+ <banner-text>Ansible banner example</banner-text>
+ </banner>
+ </banners>
+ </config>'
+"""
+
+import collections
+import re
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ build_xml,
+ etree_find,
+ get_config,
+ is_cliconf,
+ is_netconf,
+ load_config,
+)
+
+
+class ConfigBase(object):
+ def __init__(self, module):
+ self._module = module
+ self._result = {"changed": False, "warnings": []}
+ self._want = {}
+ self._have = {}
+
+ def map_params_to_obj(self):
+ text = self._module.params["text"]
+ if text:
+ text = "{0}".format(str(text).strip())
+ self._want.update(
+ {
+ "banner": self._module.params["banner"],
+ "text": text,
+ "state": self._module.params["state"],
+ },
+ )
+
+
+class CliConfiguration(ConfigBase):
+ def __init__(self, module):
+ super(CliConfiguration, self).__init__(module)
+
+ def map_obj_to_commands(self):
+ commands = list()
+ state = self._module.params["state"]
+ if state == "absent":
+ if self._have.get("state") != "absent" and (
+ "text" in self._have.keys() and self._have["text"]
+ ):
+ commands.append("no banner {0!s}".format(self._module.params["banner"]))
+ elif state == "present":
+ if self._want["text"] and self._want["text"].encode().decode(
+ "unicode_escape",
+ ) != self._have.get("text"):
+ banner_cmd = "banner {0!s} ".format(self._module.params["banner"])
+ banner_cmd += self._want["text"].strip()
+ commands.append(banner_cmd)
+ self._result["commands"] = commands
+ if commands:
+ commit = not self._module.check_mode
+ diff = load_config(self._module, commands, commit=commit)
+ if diff:
+ self._result["diff"] = dict(prepared=diff)
+ self._result["changed"] = True
+
+ def map_config_to_obj(self):
+ cli_filter = "banner {0!s}".format(self._module.params["banner"])
+ output = get_config(self._module, config_filter=cli_filter)
+ match = re.search(r"banner (\S+) (.*)", output, re.DOTALL)
+ if match:
+ text = match.group(2)
+ else:
+ text = None
+ obj = {"banner": self._module.params["banner"], "state": "absent"}
+ if output:
+ obj["text"] = text
+ obj["state"] = "present"
+ self._have.update(obj)
+
+ def run(self):
+ self.map_params_to_obj()
+ self.map_config_to_obj()
+ self.map_obj_to_commands()
+
+ return self._result
+
+
+class NCConfiguration(ConfigBase):
+ def __init__(self, module):
+ super(NCConfiguration, self).__init__(module)
+ self._banners_meta = collections.OrderedDict()
+ self._banners_meta.update(
+ [
+ ("banner", {"xpath": "banners/banner", "tag": True, "attrib": "operation"}),
+ ("a:banner", {"xpath": "banner/banner-name"}),
+ ("a:text", {"xpath": "banner/banner-text", "operation": "edit"}),
+ ],
+ )
+
+ def map_obj_to_xml_rpc(self):
+ state = self._module.params["state"]
+ _get_filter = build_xml(
+ "banners",
+ xmap=self._banners_meta,
+ params=self._module.params,
+ opcode="filter",
+ )
+
+ running = get_config(self._module, source="running", config_filter=_get_filter)
+
+ banner_name = None
+ banner_text = None
+ if etree_find(running, "banner-text") is not None:
+ banner_name = etree_find(running, "banner-name").text
+ banner_text = etree_find(running, "banner-text").text
+
+ opcode = None
+ if state == "absent" and banner_name == self._module.params["banner"] and len(banner_text):
+ opcode = "delete"
+ elif state == "present":
+ opcode = "merge"
+
+ self._result["xml"] = []
+ if opcode:
+ _edit_filter = build_xml(
+ "banners",
+ xmap=self._banners_meta,
+ params=self._module.params,
+ opcode=opcode,
+ )
+
+ if _edit_filter is not None:
+ commit = not self._module.check_mode
+ diff = load_config(
+ self._module,
+ _edit_filter,
+ commit=commit,
+ running=running,
+ nc_get_filter=_get_filter,
+ )
+
+ if diff:
+ self._result["xml"] = _edit_filter
+ if self._module._diff:
+ self._result["diff"] = dict(prepared=diff)
+
+ self._result["changed"] = True
+
+ def run(self):
+ self.map_params_to_obj()
+ self.map_obj_to_xml_rpc()
+
+ return self._result
+
+
+def main():
+ """main entry point for module execution"""
+ argument_spec = dict(
+ banner=dict(required=True, choices=["login", "motd"]),
+ text=dict(),
+ state=dict(default="present", choices=["present", "absent"]),
+ )
+
+ required_if = [("state", "present", ("text",))]
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ )
+
+ config_object = None
+ if is_cliconf(module):
+ # Commenting the below cliconf deprecation support call for Ansible 2.9 as it'll be continued to be supported
+ config_object = CliConfiguration(module)
+ elif is_netconf(module):
+ config_object = NCConfiguration(module)
+
+ result = None
+ if config_object is not None:
+ result = config_object.run()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp.py
new file mode 100644
index 00000000..9a42225a
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp.py
@@ -0,0 +1,365 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# (c) 2019, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_bgp
+author: Nilashish Chakraborty (@NilashishC)
+short_description: Module to configure BGP protocol settings.
+description:
+- This module provides configuration management of global BGP parameters on devices
+ running Cisco IOS-XR
+version_added: 1.0.0
+deprecated:
+ alternative: iosxr_bgp_global
+ why: Updated module released with more functionality.
+ removed_at_date: '2023-01-29'
+notes:
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+options:
+ config:
+ description:
+ - Specifies the BGP related configuration.
+ type: dict
+ suboptions:
+ bgp_as:
+ description:
+ - Specifies the BGP Autonomous System (AS) number to configure on the device.
+ type: int
+ required: true
+ router_id:
+ description:
+ - Configures the BGP routing process router-id value.
+ type: str
+ log_neighbor_changes:
+ description:
+ - Enable/disable logging neighbor up/down and reset reason.
+ type: bool
+ neighbors:
+ description:
+ - Specifies BGP neighbor related configurations.
+ type: list
+ elements: dict
+ suboptions:
+ neighbor:
+ description:
+ - Neighbor router address.
+ type: str
+ required: true
+ remote_as:
+ description:
+ - Remote AS of the BGP neighbor to configure.
+ type: int
+ required: true
+ update_source:
+ description:
+ - Source of the routing updates.
+ type: str
+ password:
+ description:
+ - Password to authenticate the BGP peer connection.
+ type: str
+ enabled:
+ description:
+ - Administratively shutdown or enable a neighbor.
+ type: bool
+ description:
+ description:
+ - Neighbor specific description.
+ type: str
+ advertisement_interval:
+ description:
+ - Specifies the minimum interval (in seconds) between sending BGP routing
+ updates.
+ - The range is from 0 to 600.
+ type: int
+ tcp_mss:
+ description:
+ - Specifies the TCP initial maximum segment size to use.
+ - The range is from 68 to 10000.
+ type: int
+ ebgp_multihop:
+ description:
+ - Specifies the maximum hop count for EBGP neighbors not on directly connected
+ networks.
+ - The range is from 0 to 255.
+ type: int
+ timers:
+ description:
+ - Specifies BGP neighbor timer related configurations.
+ type: dict
+ suboptions:
+ keepalive:
+ description:
+ - Frequency with which the Cisco IOS-XR software sends keepalive messages
+ to its peer.
+ - The range is from 0 to 65535.
+ type: int
+ holdtime:
+ description:
+ - Interval after not receiving a keepalive message that the software
+ declares a peer dead.
+ - The range is from 3 to 65535.
+ type: int
+ min_neighbor_holdtime:
+ description:
+ - Interval specifying the minimum acceptable hold-time from a BGP
+ neighbor.
+ - The minimum acceptable hold-time must be less than, or equal to,
+ the interval specified in the holdtime argument.
+ - The range is from 3 to 65535.
+ type: int
+ address_family:
+ description:
+ - Specifies BGP address family related configurations.
+ type: list
+ elements: dict
+ suboptions:
+ afi:
+ description:
+ - Type of address family to configure.
+ choices:
+ - ipv4
+ - ipv6
+ required: true
+ type: str
+ safi:
+ description:
+ - Specifies the type of cast for the address family.
+ choices:
+ - flowspec
+ - unicast
+ - multicast
+ - labeled-unicast
+ type: str
+ default: unicast
+ redistribute:
+ description:
+ - Specifies the redistribute information from another routing protocol.
+ type: list
+ elements: dict
+ suboptions:
+ protocol:
+ description:
+ - Specifies the protocol for configuring redistribute information.
+ type: str
+ choices:
+ - ospf
+ - ospfv3
+ - eigrp
+ - isis
+ - static
+ - connected
+ - lisp
+ - mobile
+ - rip
+ - subscriber
+ required: true
+ id:
+ description:
+ - Identifier for the routing protocol for configuring redistribute
+ information.
+ - Valid for protocols 'ospf', 'eigrp', 'isis' and 'ospfv3'.
+ type: str
+ metric:
+ description:
+ - Specifies the metric for redistributed routes.
+ type: int
+ route_map:
+ description:
+ - Specifies the route map reference.
+ type: str
+ networks:
+ description:
+ - Specify networks to announce via BGP.
+ - For operation replace, this option is mutually exclusive with root level
+ networks option.
+ type: list
+ elements: dict
+ suboptions:
+ network:
+ description:
+ - Network ID to announce via BGP.
+ required: true
+ aliases:
+ - prefix
+ type: str
+ masklen:
+ description:
+ - Subnet mask length for the network to announce(e.g, 8, 16, 24, etc.).
+ type: int
+ required: true
+ route_map:
+ description:
+ - Route map to modify the attributes.
+ type: str
+ operation:
+ description:
+ - Specifies the operation to be performed on the BGP process configured on the
+ device.
+ - In case of merge, the input configuration will be merged with the existing BGP
+ configuration on the device.
+ - In case of replace, if there is a diff between the existing configuration and
+ the input configuration, the existing configuration will be replaced by the
+ input configuration for every option that has the diff.
+ - In case of override, all the existing BGP configuration will be removed from
+ the device and replaced with the input configuration.
+ - In case of delete the existing BGP configuration will be removed from the device.
+ default: merge
+ type: str
+ choices:
+ - merge
+ - replace
+ - override
+ - delete
+"""
+
+EXAMPLES = """
+- name: configure global bgp as 65000
+ cisco.iosxr.iosxr_bgp:
+ bgp_as: 65000
+ router_id: 1.1.1.1
+ neighbors:
+ - neighbor: 182.168.10.1
+ remote_as: 500
+ description: PEER_1
+ - neighbor: 192.168.20.1
+ remote_as: 500
+ update_source: GigabitEthernet 0/0/0/0
+ address_family:
+ - name: ipv4
+ cast: unicast
+ networks:
+ - network: 192.168.2.0/23
+ - network: 10.0.0.0/8
+ redistribute:
+ - protocol: ospf
+ id: 400
+ metric: 110
+
+- name: remove bgp as 65000 from config
+ ios_bgp:
+ bgp_as: 65000
+ state: absent
+"""
+
+RETURN = """
+commands:
+ description: The list of configuration mode commands to send to the device
+ returned: always
+ type: list
+ sample:
+ - router bgp 65000
+ - bgp router-id 1.1.1.1
+ - neighbor 182.168.10.1 remote-as 500
+ - neighbor 182.168.10.1 description PEER_1
+ - neighbor 192.168.20.1 remote-as 500
+ - neighbor 192.168.20.1 update-source GigabitEthernet0/0/0/0
+ - address-family ipv4 unicast
+ - redistribute ospf 400 metric 110
+ - network 192.168.2.0/23
+ - network 10.0.0.0/8
+ - exit
+"""
+from ansible.module_utils._text import to_text
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers.cli.config.bgp.process import (
+ REDISTRIBUTE_PROTOCOLS,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.providers.module import (
+ NetworkModule,
+)
+
+
+def main():
+ """main entry point for module execution"""
+ network_spec = {
+ "network": dict(aliases=["prefix"], required=True),
+ "masklen": dict(type="int", required=True),
+ "route_map": dict(),
+ }
+
+ redistribute_spec = {
+ "protocol": dict(choices=REDISTRIBUTE_PROTOCOLS, required=True),
+ "id": dict(),
+ "metric": dict(type="int"),
+ "route_map": dict(),
+ }
+
+ timer_spec = {
+ "keepalive": dict(type="int"),
+ "holdtime": dict(type="int"),
+ "min_neighbor_holdtime": dict(type="int"),
+ }
+
+ neighbor_spec = {
+ "neighbor": dict(required=True),
+ "remote_as": dict(type="int", required=True),
+ "update_source": dict(),
+ "password": dict(no_log=True),
+ "enabled": dict(type="bool"),
+ "description": dict(),
+ "advertisement_interval": dict(type="int"),
+ "ebgp_multihop": dict(type="int"),
+ "tcp_mss": dict(type="int"),
+ "timers": dict(type="dict", options=timer_spec),
+ }
+
+ address_family_spec = {
+ "afi": dict(choices=["ipv4", "ipv6"], required=True),
+ "safi": dict(
+ choices=["flowspec", "labeled-unicast", "multicast", "unicast"],
+ default="unicast",
+ ),
+ "networks": dict(type="list", elements="dict", options=network_spec),
+ "redistribute": dict(
+ type="list",
+ elements="dict",
+ options=redistribute_spec,
+ ),
+ }
+
+ config_spec = {
+ "bgp_as": dict(type="int", required=True),
+ "router_id": dict(),
+ "log_neighbor_changes": dict(type="bool"),
+ "neighbors": dict(type="list", elements="dict", options=neighbor_spec),
+ "address_family": dict(
+ type="list",
+ elements="dict",
+ options=address_family_spec,
+ ),
+ }
+
+ argument_spec = {
+ "config": dict(type="dict", options=config_spec),
+ "operation": dict(
+ default="merge",
+ choices=["merge", "replace", "override", "delete"],
+ ),
+ }
+
+ module = NetworkModule(
+ argument_spec=argument_spec,
+ supports_check_mode=True,
+ )
+
+ try:
+ result = module.edit_config(config_filter="router bgp")
+ except Exception as exc:
+ module.fail_json(msg=to_text(exc))
+
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp_address_family.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp_address_family.py
new file mode 100644
index 00000000..3010a2f7
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp_address_family.py
@@ -0,0 +1,945 @@
+#!/usr/bin/python
+# -*- 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)
+
+"""
+The module file for iosxr_bgp_address_family
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+module: iosxr_bgp_address_family
+short_description: Resource module to configure BGP Address family.
+description:
+- This module configures and manages the attributes of BGP address family on Cisco IOS-XR platforms.
+version_added: 2.0.0
+author: Ashwini Mhatre (@amhatre)
+notes:
+- This module works with connection C(network_cli).
+options:
+ config:
+ description: A list of configurations for BGP address family.
+ type: dict
+ suboptions:
+ as_number:
+ description: Autonomous system number.
+ type: str
+ address_family:
+ description: Enable address family and enter its config mode
+ type: list
+ elements: dict
+ suboptions:
+ afi:
+ description: address family.
+ type: str
+ choices: ['ipv4', 'ipv6', 'l2vpn', 'link-state', 'vpnv4', 'vpnv6']
+ safi:
+ description: Address Family modifier
+ type: str
+ choices: [ 'flowspec', 'mdt', 'multicast', 'mvpn', 'rt-filter', 'tunnel', 'unicast', 'evpn', 'mspw', 'vpls-vpws', 'link-state' ]
+ vrf:
+ description: VRF name.
+ type: str
+ additional_paths: &additional_paths
+ description: BGP additional-paths commands
+ type: str
+ choices: [ 'send', 'receive' ]
+ advertise_best_external: &advertise
+ description: Advertise best-external path.
+ type: bool
+ aggregate_address:
+ description: Configure BGP aggregate entries.
+ type: list
+ elements: dict
+ suboptions:
+ value:
+ type: str
+ description: IPv4 Aggregate address and mask or masklength.
+ as_set:
+ type: bool
+ description: Generate AS set path information.
+ as_confed_set:
+ type: bool
+ description: Generate AS confed set path information.
+ summary_only:
+ type: bool
+ description: Filter more specific routes from updates.
+ route_policy:
+ description: Policy to condition advertisement, suppression, and attributes.
+ type: str
+ allocate_label:
+ type: dict
+ description: Allocate labels.
+ suboptions:
+ all:
+ type: bool
+ description: Allocate labels for all prefixes.
+ route_policy:
+ description: Use a route policy to select prefixes for label allocation.
+ type: str
+ as_path_loopcheck_out_disable:
+ type: bool
+ description: Configure AS Path loop checking for outbound updates.
+ bgp:
+ type: dict
+ description: BGP Commands.
+ suboptions:
+ attribute_download: &attribute_download
+ type: bool
+ description: Configure attribute download for this address-family.
+ bestpath:
+ type: dict
+ description: Change default route selection criteria.
+ suboptions:
+ origin_as:
+ description: BGP origin-AS knobs.
+ type: dict
+ suboptions:
+ use:
+ description: BGP origin-AS knobs.
+ type: dict
+ suboptions:
+ validity:
+ description: BGP bestpath selection will use origin-AS validity
+ type: bool
+ allow:
+ description: BGP origin-AS knobs.
+ type: dict
+ suboptions:
+ invalid:
+ description: BGP bestpath selection will allow 'invalid' origin-AS
+ type: bool
+ client_to_client:
+ type: dict
+ description: Configure client to client route reflection.
+ suboptions:
+ reflection:
+ type: dict
+ description: disable client to client reflection of cluster id.
+ suboptions:
+ cluster_id_disable:
+ type: dict
+ description: ID of Cluster for which reflection is to be disabled.
+ suboptions:
+ cluster_id:
+ type: str
+ description: ID of Cluster for which reflection is to be disabled.
+ disable:
+ type: bool
+ description: disable cluster id.
+ disable:
+ type: bool
+ description: disable reflection.
+ dampening:
+ type: dict
+ description: Enable route-flap dampening
+ suboptions:
+ set:
+ type: bool
+ description: Enable dampening.
+ value:
+ type: int
+ description: Half-life time for the penalty
+ route_policy:
+ description: Route policy to specify criteria for dampening.
+ type: str
+ label_delay:
+ type: dict
+ description: Specify delay for batching label processing
+ suboptions:
+ delay_second_parts:
+ type: int
+ description: Delay, seconds part <0-10>.
+ delay_ms_parts:
+ type: int
+ description: milliseconds part <0-999>.
+ import_delay:
+ type: dict
+ description: Specify delay for batching import processing.
+ suboptions:
+ delay_second_parts:
+ type: int
+ description: Delay, seconds part <0-10>.
+ delay_ms_parts:
+ type: int
+ description: milliseconds part <0-999>.
+ origin_as:
+ description: BGP origin-AS knobs.
+ type: dict
+ suboptions:
+ validation:
+ description: BGP origin-AS validation knobs.
+ type: dict
+ suboptions:
+ disable:
+ description: Disable RPKI origin-AS validation.
+ type: bool
+ signal:
+ description: Signal origin-AS validity towards peers.
+ type: dict
+ suboptions:
+ ibgp:
+ description: Signal origin-AS validity towards iBGP peers
+ type: bool
+ scan_time:
+ description: Configure background scanner interval for this address-family Example- <5-3600>.
+ type: int
+ default_martian_check_disable:
+ type: bool
+ description: Martian check default
+ distance: &distance
+ type: dict
+ description: Define an administrative distance.
+ suboptions:
+ routes_external_to_as:
+ type: int
+ description: Distance for routes external to the AS <1-255>.
+ routes_internal_to_as:
+ type: int
+ description: Distance for routes internal to the AS <1-255>.
+ local_routes:
+ type: int
+ description: Distance for local routes <1-255>.
+ dynamic_med:
+ type: int
+ description: Dynamic MED Interval.
+ maximum_paths:
+ type: dict
+ description: Forward packets over multiple paths.
+ suboptions:
+ ibgp:
+ type: dict
+ description: iBGP-multipath.
+ suboptions:
+ max_path_value:
+ type: int
+ description: <2-64> Number of paths (limit includes backup path).
+ order_igp_metric:
+ description: Order candidate multipaths for selection as per configured number(cisco-support).
+ type: bool
+ selective_order_igp_metric:
+ description: Allow multipaths only from marked neighbors
+ type: bool
+ unequal_cost:
+ type: dict
+ description: Allow multipaths to have different BGP nexthop IGP metrics.
+ suboptions:
+ set:
+ type: bool
+ description: set unequal_cost.
+ order_igp_metric:
+ description: Order candidate multipaths for selection as per configured number(cisco-support).
+ type: bool
+ selective_order_igp_metric:
+ description: Allow multipaths only from marked neighbors
+ type: bool
+ ebgp:
+ type: dict
+ description: ebgp-multipath.
+ suboptions:
+ max_path_value:
+ type: int
+ description: <2-64> Number of paths (limit includes backup path).
+ order_igp_metric:
+ description: Order candidate multipaths for selection as per configured number(cisco-support).
+ type: bool
+ selective_order_igp_metric:
+ description: Allow multipaths only from marked neighbors
+ type: bool
+ eibgp:
+ type: dict
+ description: eiBGP-multipath.
+ suboptions:
+ max_path_value:
+ type: int
+ description: <2-64> Number of paths (limit includes backup path).
+ order_igp_metric:
+ description: Order candidate multipaths for selection as per configured number(cisco-support).
+ type: bool
+ selective_order_igp_metric:
+ description: Allow multipaths only from marked neighbors
+ type: bool
+ networks:
+ type: list
+ description: Specify a network to announce via BGP.
+ elements: dict
+ suboptions:
+ network:
+ type: str
+ description: Specify a network to announce via BGP.
+ backdoor_route_policy:
+ type: str
+ description: Specify a BGP backdoor route.
+ route_policy:
+ type: str
+ description: Route-policy to modify the attributes.
+ nexthop:
+ type: dict
+ description: Nexthop
+ suboptions:
+ resolution_prefix_length_minimum:
+ type: int
+ description: Set minimum prefix-length for nexthop resolution.
+ choices: [0,32]
+ route_policy:
+ type: str
+ description: Policy to filter out nexthop notification.
+ trigger_delay_critical:
+ description: For critical notification
+ type: int
+ trigger_delay_non_critical:
+ type: int
+ description: For non critical notification.
+ optimal_route_reflection:
+ type: dict
+ description: Configure optimal-route-reflection group.
+ suboptions:
+ group_name:
+ type: str
+ description: ORR group name - maximum 32 characters.
+ primary_address:
+ type: str
+ description: IPv4 primary address.
+ secondary_address:
+ type: str
+ description: IPv4 secondary address
+ permanent_network_route_policy:
+ type: str
+ description: Name of the policy.
+ retain_local_label:
+ type: int
+ description: Label retention time in minutes <3-60>.
+ table_policy:
+ type: str
+ description: Configure policy for installation of routes to RIB.
+ update:
+ type: dict
+ description: BGP Update generation configuration.
+ suboptions:
+ limit:
+ type: dict
+ description: Update limit.
+ suboptions:
+ sub_group:
+ type: dict
+ description: Update limit for address-family.
+ suboptions:
+ ibgp:
+ type: int
+ description: Update limit for iBGP sub-groups<1-512.
+ ebgp:
+ type: int
+ description: Update limit for eBGP sub-groups<1-512.
+ address_family:
+ type: int
+ description: Update limit for sub-groups.
+ wait_install:
+ type: bool
+ description: Wait for route install.
+ redistribute:
+ type: list
+ elements: dict
+ description: Redistribute information from another routing protocol.
+ suboptions:
+ protocol:
+ description: Specifies the protocol for configuring redistribute information.
+ type: str
+ choices:
+ - ospf
+ - application
+ - eigrp
+ - isis
+ - static
+ - connected
+ - lisp
+ - mobile
+ - rip
+ - subscriber
+ required: true
+ id:
+ type: str
+ description:
+ - Identifier for the routing protocol for configuring redistribute
+ information. Example-application name, eigrp/is-is instance name, ospf tag
+ - Valid for protocols 'ospf', 'eigrp', 'isis' and 'application'.
+ metric:
+ description:
+ - Specifies the metric for redistributed routes.
+ type: int
+ route_policy:
+ description:
+ - Specifies the route policy reference.
+ type: str
+ internal:
+ type: bool
+ description: Redistribute EIGRP internal routes.applicable for eigrp.
+ external:
+ type: bool
+ description: Redistribute EIGRP external routes.applicable for eigrp.
+ level:
+ type: str
+ description:
+ - Redistribute routes from the specified ISIS levels.
+ - Redistribute ISIS level 1 routes
+ - Redistribute ISIS level 1 inter-area routes
+ - Redistribute ISIS level 2 ISIS routes
+ choices: [ '1', '2', '1-inter-area' ]
+ nssa_external:
+ type: bool
+ description: Redistribute OSPF NSSA external routes.applicable for ospf.
+ external_ospf:
+ type: int
+ description: Redistribute OSPF external routes.applicable for ospf.
+ choices: [ 1, 2 ]
+ inter_as_install:
+ type: bool
+ description: Install remote mvpn routes in default vrf.This is applicable for mvpn afi.
+ segmented_multicast:
+ type: bool
+ description: Enable segmented multicast.This is applicable for mvpn afi.
+ global_table_multicast:
+ type: bool
+ description: Enable global table multicast.
+ vrf_all_conf:
+ type: dict
+ description: configuration is for all vrfs and its applicable for afi vpn6 and modifier unicast.
+ suboptions:
+ source_rt_import_policy:
+ type: bool
+ description: Source import route-targets from import-policy.
+ table_policy:
+ type: str
+ description: Configure policy for installation of routes to RIB.
+ label_mode:
+ type: dict
+ description: Label-related configuration.
+ suboptions:
+ per_ce: &per_ce
+ type: bool
+ description: Set per CE label mode
+ per_vrf: &per_vrf
+ type: bool
+ description: Set per VRF label mode.
+ route_policy: &route_policy
+ type: str
+ description: Use a route policy to select prefixes for label allocation mode.
+ weight: &wt
+ type: dict
+ description: Define or modify weight.
+ suboptions:
+ reset_on_import_disable:
+ type: bool
+ description: disable reset_on_import.
+ reset_on_import:
+ type: bool
+ description: set reset_on_import.
+ allow_vpn_default_originate:
+ type: bool
+ description: Allow sending default originate route to VPN neighbor.
+ label_mode:
+ type: dict
+ description: label configuration.
+ suboptions:
+ per_ce: *per_ce
+ per_vrf: *per_vrf
+ route_policy: *route_policy
+ per_prefix:
+ type: bool
+ description: Set per perfix label mode.
+ mvpn_single_forwarder_selection_all:
+ type: bool
+ description: Enable single forwarder selection for all
+ mvpn_single_forwarder_selection_highest_ip_address:
+ type: bool
+ description: Enable single forwarder selection for PE with highest ip address.
+ route_target_download:
+ description: Route target RIB installation.
+ type: bool
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the Iosxr device by
+ executing the command B(show running-config router bgp).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state the configuration should be left in.
+ type: str
+ choices: [deleted, merged, overridden, replaced, gathered, rendered, parsed]
+ default: merged
+"""
+EXAMPLES = """
+# Using merged
+# Before state:
+# -------------
+# RP/0/0/CPU0:iosxr-02#show running-config router bgp
+# Sat Feb 20 03:49:43.618 UTC
+# router bgp 65536
+# bgp router-id 192.0.2.1
+# address-family vpnv4 unicast
+# vrf vrf1
+# rd auto
+- name: Merge the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_bgp_address_family:
+ state: merged
+ config:
+ as_number: "65536"
+ address_family:
+ - afi: "ipv4"
+ safi: "unicast"
+ vrf: vrf1
+ dynamic_med: 9
+ redistribute:
+ - protocol: connected
+ metric: 10
+ - afi: "ipv4"
+ safi: "unicast"
+ dynamic_med: 10
+ redistribute:
+ - protocol: application
+ id: test1
+ metric: 10
+ bgp:
+ scan_time: 20
+ attribute_download: true
+ advertise_best_external: true
+ allocate_label:
+ all: true
+# Task output
+# -------------
+# commands:
+# - router bgp 65536
+# - address-family ipv4 unicast
+# - advertise best-external
+# - allocate-label all
+# - bgp attribute-download
+# - bgp scan-time 20
+# - dynamic-med interval 10
+# - redistribute application test1 metric 10
+# - vrf vrf1
+# - address-family ipv4 unicast
+# - dynamic-med interval 9
+# - redistribute connected metric 10
+#
+#
+# after:
+# as_number: "65536"
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# vrf: vrf1
+# dynamic_med: 9
+# redistribute:
+# - protocol: connected
+# metric: 10
+# - afi: "ipv4"
+# safi: "unicast"
+# dynamic_med: 10
+# redistribute:
+# - protocol: application
+# id: "test1"
+# metric: 10
+# bgp:
+# scan_time: 20
+# attribute_download: true
+# advertise_best_external: true
+# allocate_label:
+# all: true
+#
+# After state:
+# -------------
+# RP/0/0/CPU0:iosxr-02#show running-config router bgp
+# Sat Feb 20 03:49:43.618 UTC
+# router bgp 65536
+# bgp router-id 192.0.1.1
+# address-family ipv4 unicast
+# advertise best-external
+# allocate-label all
+# bgp attribute-download
+# bgp scan-time 20
+# address-family vpnv4 unicast
+# vrf vrf1
+# rd auto
+# address-family ipv4 unicast
+# dynamic-med interval 9
+# redistribute connected metric 10
+#
+# Using replaced
+# Before state:
+# -------------
+# RP/0/0/CPU0:iosxr-02#show running-config router bgp
+# Sat Feb 20 03:49:43.618 UTC
+# router bgp 65536
+# bgp router-id 192.0.1.1
+# address-family ipv4 unicast
+# advertise best-external
+# allocate-label all
+# bgp attribute-download
+# bgp scan-time 20
+# address-family vpnv4 unicast
+# vrf vrf1
+# rd auto
+# address-family ipv4 unicast
+# dynamic-med interval 9
+# redistribute connected metric 10
+#
+#
+- name: Replace the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_bgp_address_family:
+ state: replaced
+ config:
+ as_number: "65536"
+ address_family:
+ - afi: "ipv4"
+ safi: "unicast"
+ vrf: vrf1
+ dynamic_med: 10
+# Task output
+# -------------
+# commands:
+# - router bgp 65536
+# - vrf vrf1
+# - address-family ipv4 unicast
+# - dynamic-med interval 10
+# - no redistribute connected metric 10
+#
+# after:
+# as_number: "65536"
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# vrf: vrf1
+# dynamic_med: 10
+# - afi: "ipv4"
+# safi: "unicast"
+# dynamic_med: 10
+# redistribute:
+# - protocol: application
+# id: "test1"
+# metric: 10
+# bgp:
+# scan_time: 20
+# attribute_download: true
+# advertise_best_external: true
+# allocate_label:
+# all: true
+# After state:
+# -------------
+# RP/0/0/CPU0:iosxr-02#show running-config router bgp
+# Sat Feb 20 03:49:43.618 UTC
+# router bgp 65536
+# bgp router-id 192.0.1.1
+# address-family ipv4 unicast
+# advertise best-external
+# allocate-label all
+# bgp attribute-download
+# bgp scan-time 20
+# address-family vpnv4 unicast
+# vrf vrf1
+# rd auto
+# address-family ipv4 unicast
+# dynamic-med interval 10
+#
+#
+# Using overridden
+# Before state:
+# -------------
+# RP/0/0/CPU0:iosxr-02#show running-config router bgp
+# Sat Feb 20 03:49:43.618 UTC
+# router bgp 65536
+# bgp router-id 192.0.1.1
+# address-family ipv4 unicast
+# advertise best-external
+# allocate-label all
+# bgp attribute-download
+# bgp scan-time 20
+# address-family vpnv4 unicast
+# vrf vrf1
+# rd auto
+# address-family ipv4 unicast
+# dynamic-med interval 9
+# redistribute connected metric 10
+#
+#
+- name: Override the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_bgp_address_family:
+ state: overridden
+ config:
+ as_number: "65536"
+ address_family:
+ - afi: "ipv4"
+ safi: "unicast"
+ vrf: vrf1
+ dynamic_med: 10
+
+# Task output
+# -------------
+# commands:
+# - router bgp 65536
+# - no address-family ipv4 unicast
+# - vrf vrf1
+# - address-family ipv4 unicast
+# - dynamic-med interval 10
+# - no redistribute connected metric 10
+#
+#
+# after:
+# as_number: "65536"
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# vrf: vrf1
+# dynamic_med: 10
+#
+# After state:
+# -------------
+# RP/0/0/CPU0:iosxr-02#show running-config router bgp
+# Sat Feb 20 03:49:43.618 UTC
+# router bgp 65536
+# bgp router-id 192.0.1.1
+# address-family vpnv4 unicast
+# vrf vrf1
+# rd auto
+# address-family ipv4 unicast
+# dynamic-med interval 10
+#
+#
+# Using deleted
+# Before state:
+# -------------
+# RP/0/0/CPU0:iosxr-02#show running-config router bgp
+# Sat Feb 20 03:49:43.618 UTC
+# router bgp 65536
+# bgp router-id 192.0.1.1
+# address-family ipv4 unicast
+# advertise best-external
+# allocate-label all
+# bgp attribute-download
+# bgp scan-time 20
+# address-family vpnv4 unicast
+# vrf vrf1
+# rd auto
+# address-family ipv4 unicast
+# dynamic-med interval 9
+# redistribute connected metric 10
+#
+#
+- name: Delete the provided configuration
+ cisco.iosxr.iosxr_bgp_address_family:
+ state: deleted
+ config:
+
+# Task output
+# -------------
+# commands:
+# - router bgp 65536
+# - no address-family ipv4 unicast
+# - vrf vrf1
+# - no address-family ipv4 unicast
+#
+#
+# after:
+# as_number: "65536"
+#
+#
+# After state:
+# -------------
+# RP/0/0/CPU0:iosxr-02#show running-config router bgp
+# Sat Feb 20 03:49:43.618 UTC
+# router bgp 65536
+# bgp router-id 192.0.1.1
+# address-family vpnv4 unicast
+# vrf vrf1
+# rd auto
+#
+# Using rendered
+# -------------
+#
+- name: rendered state example
+ cisco.iosxr.iosxr_bgp_address_family:
+ state: rendered
+ config:
+ as_number: "65536"
+ address_family:
+ - afi: "ipv4"
+ safi: "unicast"
+ vrf: vrf1
+ dynamic_med: 9
+ redistribute:
+ - protocol: connected
+ metric: 10
+ - afi: "ipv4"
+ safi: "unicast"
+ dynamic_med: 10
+ redistribute:
+ - protocol: application
+ id: test1
+ metric: 10
+ bgp:
+ scan_time: 20
+ attribute_download: true
+ advertise_best_external: true
+ allocate_label:
+ all: true
+# Task output
+# -------------
+# commands:
+# - router bgp 65536
+# - address-family ipv4 unicast
+# - advertise best-external
+# - allocate-label all
+# - bgp attribute-download
+# - bgp scan-time 20
+# - dynamic-med interval 10
+# - redistribute application test1 metric 10
+# - vrf vrf1
+# - address-family ipv4 unicast
+# - dynamic-med interval 9
+# - redistribute connected metric 10
+#
+# Using gathered
+# -------------
+- name: Merge the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_bgp_address_family:
+ state: gathered
+ config:
+ as_number: "65536"
+ address_family:
+ - afi: "ipv4"
+ safi: "unicast"
+ vrf: vrf1
+ dynamic_med: 9
+ redistribute:
+ - protocol: connected
+ metric: 10
+ - afi: "ipv4"
+ safi: "unicast"
+ dynamic_med: 10
+ redistribute:
+ - protocol: application
+ id: test1
+ metric: 10
+ bgp:
+ scan_time: 20
+ attribute_download: true
+ advertise_best_external: true
+ allocate_label:
+ all: true
+# gathered:
+# as_number: "65536"
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# vrf: vrf1
+# dynamic_med: 9
+# redistribute:
+# - protocol: connected
+# metric: 10
+# - afi: "ipv4"
+# safi: "unicast"
+# dynamic_med: 10
+# redistribute:
+# - protocol: application
+# id: "test1"
+# metric: 10
+# bgp:
+# scan_time: 20
+# attribute_download: true
+# advertise_best_external: true
+# allocate_label:
+# all: true
+#
+# Using parsed
+#
+#parsed.cfg
+#------------
+# router bgp 65536
+# bgp router-id 192.0.1.1
+# address-family ipv4 unicast
+# advertise best-external
+# allocate-label all
+# bgp attribute-download
+# bgp scan-time 20
+# address-family vpnv4 unicast
+# vrf vrf1
+# rd auto
+# address-family ipv4 unicast
+# dynamic-med interval 9
+# redistribute connected metric 10
+#
+- name: Parse externally provided BGP neighbor AF config
+ cisco.iosxr.iosxr_bgp_address_family:
+ running_config: "{{ lookup('file', 'parsed.cfg') }}"
+ state: parsed
+
+# Task output (redacted)
+# -----------------------
+# parsed:
+# as_number: "65536"
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# vrf: vrf1
+# dynamic_med: 9
+# redistribute:
+# - protocol: connected
+# metric: 10
+# - afi: "ipv4"
+# safi: "unicast"
+# dynamic_med: 10
+# redistribute:
+# - protocol: application
+# id: "test1"
+# metric: 10
+# bgp:
+# scan_time: 20
+# attribute_download: true
+# advertise_best_external: true
+# allocate_label:
+# all: true
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.bgp_address_family.bgp_address_family import (
+ Bgp_address_familyArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.bgp_address_family.bgp_address_family import (
+ Bgp_address_family,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ module = AnsibleModule(
+ argument_spec=Bgp_address_familyArgs.argument_spec,
+ mutually_exclusive=[["config", "running_config"]],
+ required_if=[
+ ["state", "merged", ["config"]],
+ ["state", "replaced", ["config"]],
+ ["state", "overridden", ["config"]],
+ ["state", "rendered", ["config"]],
+ ["state", "parsed", ["running_config"]],
+ ],
+ supports_check_mode=True,
+ )
+
+ result = Bgp_address_family(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp_global.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp_global.py
new file mode 100644
index 00000000..bddd8789
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp_global.py
@@ -0,0 +1,1328 @@
+#!/usr/bin/python
+# -*- 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)
+
+"""
+The module file for iosxr_bgp_global
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+module: iosxr_bgp_global
+short_description: Resource module to configure BGP.
+description:
+- This module configures and manages the attributes of BGP global on Cisco IOS-XR platforms.
+version_added: 2.0.0
+author: Ashwini Mhatre (@amhatre)
+notes:
+- This module works with connection C(network_cli).
+options:
+ config:
+ description: A list of configurations for BGP global.
+ type: dict
+ suboptions:
+ as_number:
+ description: Autonomous system number of the router.
+ type: str
+ bfd: &bfd
+ description: Configure BFD parameters.
+ type: dict
+ suboptions:
+ minimum_interval: &min_interval
+ description: Specifies the BFD session's minimum-interval value for the neighbor.
+ type: int
+ multiplier: &multiplier
+ description: Specifies the BFD session's multiplier value for the neighbor.
+ type: int
+ bgp: &bgp
+ description: BGP parameters.
+ type: dict
+ suboptions:
+ as_path_loopcheck:
+ description: Enable AS-path loop checking for iBGP peers.
+ type: bool
+ auto_policy_soft_reset: &auto_policy_soft_reset
+ description: Enable automatic soft peer reset on policy reconfiguration.
+ type: dict
+ suboptions:
+ disable:
+ description: Disable an automatic soft reset of Border Gateway Protocol (BGP) peers.
+ type: bool
+ bestpath: &bestpath
+ description: Select the bestpath selection algorithim for BGP routes.
+ type: dict
+ suboptions:
+ as_path:
+ description: Select the bestpath selection based on as-path.
+ type: dict
+ suboptions:
+ ignore:
+ description: ignore
+ type: bool
+ multipath_relax:
+ description: multipath-relax
+ type: bool
+ aigp:
+ description: AIGP attribute
+ type: dict
+ suboptions:
+ ignore:
+ description: Ignore AIGP attribute.
+ type: bool
+ med:
+ description: MED attribute
+ type: dict
+ suboptions:
+ always:
+ description: Allow comparing MED from different neighbors.
+ type: bool
+ confed:
+ description: Compare MED among confederation paths.
+ type: bool
+ missing_as_worst:
+ description: Treat missing MED as the least preferred one.
+ type: bool
+ compare_routerid:
+ description: Compare router-id for identical EBGP paths.
+ type: bool
+ cost_community:
+ description: Cost community.
+ type: dict
+ suboptions:
+ ignore:
+ description: ignore cost_community
+ type: bool
+ origin_as:
+ description: BGP origin-AS knobs.
+ type: dict
+ suboptions:
+ use:
+ description: BGP origin-AS knobs.
+ type: dict
+ suboptions:
+ validity:
+ description: BGP bestpath selection will use origin-AS validity
+ type: bool
+ allow:
+ description: BGP origin-AS knobs.
+ type: dict
+ suboptions:
+ invalid:
+ description: BGP bestpath selection will allow 'invalid' origin-AS
+ type: bool
+ cluster_id: &cluster_id
+ description: Cluster ID of this router acting as a route reflector.
+ type: str
+ confederation: &confederation
+ description: confederation.
+ type: dict
+ suboptions:
+ identifier:
+ description: Set routing domain confederation AS.
+ type: int
+ peers:
+ description: Enter peer ASs in BGP confederation mode.
+ type: list
+ elements: int
+ default: &default
+ description: Configure default value.
+ type: dict
+ suboptions:
+ local_preference:
+ description:
+ - local preferance.
+ - Please refer vendor documentation for valid values
+ type: int
+ enforce_first_as: &enforce_first_as
+ description: Enforce the first AS for EBGP routes
+ type: dict
+ suboptions:
+ disable:
+ description: disable enforce 1st as
+ type: bool
+ fast_external_fallover: &fast_external_fallover
+ description: Immediately reset session if a link to a directly connected external peer goes down.
+ type: dict
+ suboptions:
+ disable:
+ description: disable fast external fallover.
+ type: bool
+ graceful_restart:
+ description: Enable graceful restart support.
+ type: dict
+ suboptions:
+ set:
+ description: Enable graceful-restart.
+ type: bool
+ graceful_reset:
+ description: Reset gracefully if configuration change forces a peer reset.
+ type: bool
+ restart_time: &restart_time
+ description: Restart time advertised to neighbors in seconds <1-4095>.
+ type: int
+ purge_time:
+ description: Time before stale routes are purged in seconds <1-6000>.
+ type: int
+ stalepath_time: &stalepath_time
+ description: Maximum time to wait for restart of GR capable peers in seconds <1-4095>.
+ type: int
+ install:
+ description: Install diversion path to RIB/CEF.
+ type: dict
+ suboptions:
+ diversion:
+ description: Install diversion path to RIB/CEF.
+ type: bool
+ log: &bgp_log
+ description: Log bgp info
+ type: dict
+ suboptions:
+ log_message:
+ description: Log neighbor inbound/outbound message.
+ type: dict
+ suboptions:
+ disable:
+ description: disable inbound outbound messages.
+ type: bool
+ neighbor:
+ description: Log neighbor state info.
+ type: dict
+ suboptions:
+ changes:
+ description: Log neighbor up/down and reset reason.
+ type: dict
+ suboptions:
+ detail:
+ type: bool
+ description: detail
+ disable:
+ type: bool
+ description: disable
+ maximum:
+ description: Maximum number of neighbors that can be configured
+ type: dict
+ suboptions:
+ neighbor:
+ description: Maximum number of neighbors <1-15000>.
+ type: int
+ multipath: &multipath
+ description: Change multipath selection criteria
+ type: dict
+ suboptions:
+ as_path:
+ description: AS path
+ type: dict
+ suboptions:
+ ignore:
+ description: Ignore as-path related check for multipath selection.
+ type: dict
+ suboptions:
+ onwards:
+ description: Ignore everything onwards as-path for multipath selection.
+ type: bool
+ origin_as:
+ description: BGP origin-AS knobs.
+ type: dict
+ suboptions:
+ validation:
+ description: BGP origin-AS validation knobs.
+ type: dict
+ suboptions:
+ disable:
+ description: Disable RPKI origin-AS validation.
+ type: bool
+ signal:
+ description: Signal origin-AS validity towards peers.
+ type: dict
+ suboptions:
+ ibgp:
+ description: Signal origin-AS validity towards iBGP peers
+ type: bool
+ time:
+ description: Time to wait between an RPKI update and a BGP table walk.
+ type: dict
+ suboptions:
+ time_off:
+ description: No automatic prefix validation after an RPKI update.
+ type: bool
+ time_in_second:
+ description: Prefix validation time (in seconds).
+ type: int
+ redistribute_internal: &redistribute_internal
+ description: Redistribute internal BGP routes.
+ type: bool
+ router_id: &router_id
+ description: Configure Router-id. Example- A.B.C.D IPv4 address.
+ type: str
+ scan_time:
+ description: Configure background scanner interval for generic scanner Example- <5-3600>.
+ type: int
+ unsafe_ebgp_policy: &ebgp_policy
+ description: Make eBGP neighbors with no policy pass all routes(cisco-support).
+ type: bool
+ update_delay:
+ description: Set the max initial delay for sending updates Example-<0-3600> in secs.
+ type: int
+ default_information: &default_info
+ description: Control distribution of default information.
+ type: dict
+ suboptions:
+ originate:
+ description: Distribute a default route
+ type: bool
+ default_metric: &default_metric
+ description: Default metric. Example-<1-4294967295>.
+ type: int
+ graceful_maintenance:
+ description: This allows the router to be brought in or out of service gracefully.
+ type: dict
+ suboptions:
+ activate:
+ description: All neighbors with graceful-maintenance config
+ type: str
+ choices: [ 'all-neighbors','retain-routes','all-neighbors retain-routes', '' ]
+ ibgp:
+ description: Set options for iBGP peers.
+ type: dict
+ suboptions:
+ policy:
+ description: Set options for route-policy.
+ type: dict
+ suboptions:
+ out:
+ description: Set options for outbound policy.
+ type: dict
+ suboptions:
+ enforce_modifications:
+ description: Allow policy to modify all attributes.
+ type: bool
+ mpls: &mpls
+ description: Enable mpls parameters.
+ type: dict
+ suboptions:
+ activate:
+ description: Enter mpls interfaces in BGP mpls activate mode.
+ type: dict
+ suboptions:
+ interface:
+ description: Name of interface to enable mpls.
+ type: str
+ mvpn:
+ description: Connect to PIM/PIM6.
+ type: bool
+ neighbors: &neighbors
+ description: Specify a neighbor router.
+ type: list
+ elements: dict
+ suboptions:
+ neighbor_address:
+ description:
+ - Neighbor router address.
+ type: str
+ aliases:
+ - neighbor
+ required: true
+ advertisement_interval:
+ description: Minimum interval between sending BGP routing updates.Example-<0-600>.
+ type: int
+ bfd:
+ description: Configure BFD parameters.
+ type: dict
+ suboptions:
+ fast_detect:
+ description: Enable Fast detection
+ type: dict
+ suboptions:
+ set:
+ description: set fast-detect
+ type: bool
+ disable:
+ description: Prevent bfd settings from being inherited from the parent.
+ type: bool
+ strict_mode:
+ description: Hold down neighbor session until BFD session is up
+ type: bool
+ multiplier: *multiplier
+ minimum_interval: *min_interval
+ bmp_activate: &bmp_activate
+ description: Enable BMP logging for this neighbor.
+ type: dict
+ suboptions:
+ server:
+ description: Enable BMP connection to particular server.Example-<1-8>.
+ type: int
+ capability: &capability
+ description: Advertise capability to the peer.
+ type: dict
+ suboptions:
+ additional_paths:
+ description: BGP additional-paths commands.
+ type: dict
+ suboptions:
+ send:
+ type: dict
+ description: Additional paths Send capability
+ suboptions:
+ set:
+ type: bool
+ description: set send capability
+ disable:
+ type: bool
+ description: set send capability
+ receive:
+ type: dict
+ description: Additional paths receive capability
+ suboptions:
+ set:
+ type: bool
+ description: set receive capability
+ disable:
+ type: bool
+ description: set receive capability
+ suppress:
+ description: Suppress advertising capability to the peer.
+ type: dict
+ suboptions:
+ four_byte_AS:
+ description: 4-byte-as capability
+ type: dict
+ suboptions:
+ set:
+ description: set 4_byte_as.
+ type: bool
+
+ all:
+ description: all capability
+ type: dict
+ suboptions:
+ inheritance_disable:
+ description: Do not inherit this configuration from parent group.
+ type: bool
+ set:
+ description: set all.
+ type: bool
+ cluster_id: *cluster_id
+ description:
+ description: Neighbor specific description.
+ type: str
+ dmz_link_bandwidth: &dmz_link_bw
+ description: Propagate the DMZ link bandwidth.
+ type: dict
+ suboptions:
+ inheritance_disable:
+ description: Do not inherit this configuration from parent group.
+ type: bool
+ set:
+ description: set dmz-link-bandwidth.
+ type: bool
+ dscp:
+ description: Set IP DSCP (DiffServ CodePoint).Please refer vendor document for valid entries.
+ type: str
+ ebgp_multihop:
+ description: Allow EBGP neighbors not on directly connected networks.
+ type: dict
+ suboptions:
+ value:
+ description: maximum hop count.Example-<1-255>.
+ type: int
+ mpls:
+ description: Disable BGP MPLS forwarding.
+ type: bool
+ ebgp_recv_extcommunity_dmz:
+ description: Receive extcommunity dmz link bandwidth from ebgp neighbor.
+ type: dict
+ suboptions:
+ inheritance_disable:
+ description: Prevent ebgp-recv-community-dmz from being inherited from parent
+ type: bool
+ set:
+ description: set ebgp-recv-community-dmz.
+ type: bool
+ ebgp_send_extcommunity_dmz:
+ description: Send extcommunity dmz link bandwidth from ebgp neighbor.
+ type: dict
+ suboptions:
+ inheritance_disable:
+ description: Prevent ebgp-send-community-dmz from being inherited from parent
+ type: bool
+ cumulatie:
+ description: Send cumulative community dmz link bandwidth of all multipaths to ebgp neighbor.
+ type: bool
+ set:
+ description: set ebgp-send-community-dmz.
+ type: bool
+ egress_engineering:
+ type: dict
+ description: Enable egress peer engineering for this neighbor.
+ suboptions:
+ inheritance_disable:
+ description: Prevent egress-engineering from being inherited from parent
+ type: bool
+ set:
+ description: set egress-engineering.
+ type: bool
+ enforce_first_as: *enforce_first_as
+ graceful_maintenance:
+ description:
+ Attributes for Graceful Maintenance. This will cause neighbors to de-prefer routes from this router and
+ choose alternates. This allows the router to be brought in or out of service gracefully.
+ type: dict
+ suboptions:
+ set:
+ description: set graceful maintenance.
+ type: bool
+ activate:
+ description: Routes will be announced with the graceful maintenance attributes while activated either here or under router
+ bgp configuration.
+ type: dict
+ suboptions:
+ inheritance_disable:
+ description: Prevent activate from being inherited from the parent.
+ type: bool
+ set:
+ description: activate.
+ type: bool
+ as_prepends:
+ description: Number of times to prepend the local AS number to the
+ AS path of routes. Default=0
+ type: dict
+ suboptions:
+ inheritance_disable:
+ description: Prevent as prepends from being inherited from the parent.
+ type: bool
+ value:
+ description: Range of values for as prepends.Example-<0-6> .
+ type: int
+ local_preference:
+ description: local preference with which to advertise routes to ibgp neigbors. Default=No Touch
+ type: dict
+ suboptions:
+ value:
+ description: Range of values for Local Preference.Example-<0-4294967295> .
+ type: int
+ inheritance_disable:
+ description: Prevent local preference from being inherited from the parent.
+ type: bool
+ graceful_restart:
+ description: Enable graceful restart support for this neighbor.
+ type: dict
+ suboptions:
+ restart_time: *restart_time
+ stalepath_time: *stalepath_time
+ ignore_connected_check:
+ description: Bypass the directly connected nexthop check for single-hop eBGP peering
+ type: dict
+ suboptions:
+ inheritance_disable:
+ description: Prevent ignore-connected-check from being inherited from the parent
+ type: bool
+ set:
+ description: set ignore-connected-check.
+ type: bool
+ keychain:
+ description: Set keychain based authentication.
+ type: dict
+ suboptions:
+ name:
+ description: Name of the key chain - maximum 32 characters.
+ type: str
+ inheritance_disable:
+ description: Prevent keychain from being inherited from parent.
+ type: bool
+ local:
+ type: dict
+ description: Configure local parameter
+ suboptions:
+ address:
+ description: IPv4 address
+ type: dict
+ suboptions:
+ ipv4_address:
+ description: IPv4 address <A.B.C.D>.
+ type: str
+ inheritance_disable:
+ description: Prevent local address from being inherited from parent.
+ type: bool
+ local_as:
+ description: Specify local AS number.
+ type: dict
+ suboptions:
+ value:
+ description: 2 byte, 4 byte As number
+ type: int
+ inheritance_disable:
+ description: Prevent local AS from being inherited from parent.
+ type: bool
+ log:
+ description: Logging update messages per neighbor.
+ type: dict
+ suboptions:
+ log_message:
+ description: Logging update/notification messages per neighbor.
+ type: dict
+ suboptions:
+ in:
+ description: Inbound log messages
+ type: dict
+ suboptions:
+ value:
+ description: Range for message log buffer size <1-100>.
+ type: int
+ disable:
+ description: Disable inbound message logging.
+ type: bool
+ inheritance_disable:
+ description: Prevents the msg log from being inherited from the parent.
+ type: bool
+ out:
+ description: Outbound log messages
+ type: dict
+ suboptions:
+ value:
+ description: Range for message log buffer size <1-100>.
+ type: int
+ disable:
+ description: Disable inbound message logging.
+ type: bool
+ inheritance_disable:
+ description: Prevents the msg log from being inherited from the parent.
+ type: bool
+ origin_as:
+ description: BGP origin-AS knobs.
+ type: dict
+ suboptions:
+ validation:
+ description: BGP origin-AS validation knobs.
+ type: dict
+ suboptions:
+ disable:
+ description: Disable RPKI origin-AS validation.
+ type: bool
+ receive_buffer_size:
+ description: Set socket and BGP receive buffer size.Example <512-131072>.
+ type: int
+ remote_as:
+ description: Neighbor Autonomous System.
+ type: int
+ send_buffer_size:
+ description: Set socket and BGP send buffer size.Example <4096-131072>.
+ type: int
+ session_open_mode:
+ description: Establish BGP session using this TCP open mode.
+ type: str
+ choices: [ 'active-only', 'both', 'passive-only' ]
+ shutdown:
+ description: Administratively shut down this neighbor.
+ type: dict
+ suboptions:
+ inheritance_disable:
+ description: Prevent shutdown from being inherited from parent
+ type: bool
+ set:
+ description: shutdown.
+ type: bool
+ tcp:
+ description: TCP session configuration commands.
+ type: dict
+ suboptions:
+ mss:
+ description: Maximum Segment Size.
+ type: dict
+ suboptions:
+ value:
+ description: TCP initial maximum segment size.
+ type: int
+ inheritance_disable:
+ description: Prevent mss from being inherited from parent
+ type: bool
+ timers: &timers
+ description: BGP per neighbor timers.
+ type: dict
+ suboptions:
+ keepalive_time:
+ description: keepalive interval <0-65535>.
+ type: int
+ holdtime:
+ description: hold time <3-65535> or 0 Disable hold time.
+ type: int
+ ttl_security:
+ description: Enable EBGP TTL security.
+ type: dict
+ suboptions:
+ inheritance_disable:
+ description: Prevent ttl-security from being inherited from parent
+ type: bool
+ set:
+ description: set ttl-security
+ type: bool
+ update:
+ description: BGP Update configuration.
+ type: dict
+ suboptions:
+ in:
+ description: Inbound update message handling.
+ type: dict
+ suboptions:
+ filtering:
+ description: Inbound update message filtering
+ type: dict
+ suboptions:
+ attribute_filter:
+ description: Attribute-filter configuration.
+ type: dict
+ suboptions:
+ group:
+ description: Name of group.
+ type: str
+ logging:
+ description: Update filtering syslog message.
+ type: dict
+ suboptions:
+ disable:
+ description: Disable update filtering syslog message.
+ type: bool
+ update_message:
+ description: Filtered update messages.
+ type: dict
+ suboptions:
+ buffers:
+ description: Number of buffers to store filtered update messages.
+ type: int
+ update_source:
+ description: Source of routing updates.Refer vendor document for valid values.
+ type: str
+ nsr:
+ description: Enable non-stop-routing support for all neighbors.
+ type: dict
+ suboptions:
+ set:
+ type: bool
+ description: set nsr
+ disable:
+ type: bool
+ description: disable nsr
+ socket: &socket
+ description: set socket parameters.
+ type: dict
+ suboptions:
+ receive_buffer_size:
+ description: socket receive buffer size.Example-<512-131072>.
+ type: int
+ send_buffer_size:
+ description: socket send buffer size.Example- <4096-131072>.
+ type: int
+ timers: *timers
+ update:
+ description: BGP Update configuration.
+ type: dict
+ suboptions:
+ in:
+ description: Inbound update message handling
+ type: dict
+ suboptions:
+ error_handling:
+ description: Inbound update message error handling.
+ type: dict
+ suboptions:
+ basic:
+ description: Inbound update message basic error handling
+ type: dict
+ suboptions:
+ ebgp:
+ type: dict
+ description: Inbound update message basic error handling for EBGP neighbors
+ suboptions:
+ disable:
+ description: disable
+ type: bool
+ ibgp:
+ type: dict
+ description: Inbound update message basic error handling for ibgp neighbors
+ suboptions:
+ disable:
+ description: disable
+ type: bool
+ extended:
+ description: Inbound update message extended error handling
+ type: dict
+ suboptions:
+ ebgp:
+ type: bool
+ description: Inbound update message extended error handling for EBGP neighbors
+
+ ibgp:
+ type: bool
+ description: Inbound update message extended error handling for ibgp neighbors
+ out:
+ description: BGP Update generation configuration.
+ type: dict
+ suboptions:
+ logging:
+ description: Enable logging of update generation events.
+ type: bool
+ limit:
+ description: Upper bound on transient memory usage for update generation.Example-<16-2048>.
+ type: int
+ rpki:
+ description: Configure RPKI.
+ type: dict
+ suboptions:
+ route:
+ description: Configure an RPKI route.A.B.C.D/length or X:X::X/length Network/Minimum prefix length
+ type: dict
+ suboptions:
+ value:
+ description: A.B.C.D/length or X:X::X/length Network/Minimum prefix length.
+ type: str
+ max:
+ description: Maximum prefix length. Example- <1-128> .
+ type: int
+ origin:
+ description: Origin Autonomous System number (in asplain format) Example-<1-4294967295>.
+ type: int
+ servers:
+ description: Configure RPKI cache-servers.
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: address of rpki server.
+ type: str
+ purge_time:
+ type: int
+ description: Time to wait after a cache goes down to clean up stale routes
+ refresh_time:
+ type: dict
+ description: Time between sending serial-queries for the RPKI cache-server
+ suboptions:
+ value:
+ description: Purge time (in seconds) <30-360>
+ type: int
+ time_off:
+ description: Do not send serial-queries periodically
+ type: bool
+ response_time:
+ type: dict
+ description: Time to wait for a response from the RPKI cache-server
+ suboptions:
+ value:
+ description: Purge time (in seconds) <15-3600>
+ type: int
+ time_off:
+ description: Wait indefinitely for a response
+ type: bool
+ shutdown:
+ type: bool
+ description: Shutdown the RPKI cache-server
+ transport:
+ type: dict
+ description: Specify a transport method for the RPKI cache-server
+ suboptions:
+ ssh:
+ description: Connect to the RPKI cache-server using SSH
+ type: dict
+ suboptions:
+ port:
+ description: Specify a port number for the RPKI cache-server transport
+ type: int
+ tcp:
+ description: Connect to the RPKI cache-server using TCP (unencrypted)
+ type: dict
+ suboptions:
+ port:
+ description: Specify a port number for the RPKI cache-server transport
+ type: int
+ vrfs:
+ description: Specify a vrf name.
+ type: list
+ elements: dict
+ suboptions:
+ vrf:
+ description: VRF name.
+ type: str
+ bfd: *bfd
+ bgp:
+ description: BGP commands.
+ type: dict
+ suboptions:
+ auto_policy_soft_reset: *auto_policy_soft_reset
+ bestpath: *bestpath
+ default: *default
+ enforce_first_as: *enforce_first_as
+ fast_external_fallover: *fast_external_fallover
+ log: *bgp_log
+ multipath: *multipath
+ redistribute_internal: *redistribute_internal
+ router_id: *router_id
+ unsafe_ebgp_policy: *ebgp_policy
+ default_information: *default_info
+ default_metric: *default_metric
+ mpls: *mpls
+ neighbors: *neighbors
+ rd:
+ description: route distinguisher.
+ type: dict
+ suboptions:
+ auto:
+ description: Automatic route distinguisher.
+ type: bool
+ socket: *socket
+ timers: *timers
+ running_config:
+ description:
+ The state the configuration should be left in.
+ - State I(purged) removes all the BGP configurations from the
+ target device. Use caution with this state.
+ - State I(deleted) only removes BGP attributes that this modules
+ manages and does not negate the BGP process completely. Thereby, preserving
+ address-family related configurations under BGP context.
+ - Running states I(deleted) and I(replaced) will result in an error if there
+ are address-family configuration lines present under a neighbor,
+ or a vrf context that is to be removed. Please use the
+ M(cisco.iosxr.iosxr_bgp_address_family) or M(cisco.iosxr.iosxr_bgp_neighbor_address_family)
+ modules for prior cleanup.
+ - Refer to examples for more details.
+ type: str
+ state:
+ description:
+ - The state the configuration should be left in.
+ type: str
+ choices: [deleted, merged, replaced, gathered, rendered, parsed, purged]
+ default: merged
+"""
+EXAMPLES = """
+
+##### Using Merged ##########################################
+-----------------------------------------------------------------
+
+# configuration on device Before merge state:
+
+
+#RP/0/0/CPU0:10#show running-config router bgp
+#Thu Feb 4 09:38:36.245 UTC
+#% No such configuration item(s)
+#RP/0/0/CPU0:10#
+
+# --------------Merge state---------------
+# - name: Merge the following configuration
+# cisco.iosxr.iosxr_bgp_global:
+# config:
+# as_number: 65536
+# default_metric: 5
+# socket:
+# receive_buffer_size: 514
+# send_buffer_size: 4098
+# bgp:
+# confederation:
+# identifier: 4
+# bestpath:
+# med:
+# confed: True
+# cluster_id: 5
+# router_id: 192.0.2.10
+# neighbors:
+# - neighbor: 192.0.2.13
+# remote_as: 65538
+# bfd:
+# fast_detect:
+# strict_mode: True
+# multiplier: 6
+# minimum_interval: 20
+# vrfs:
+# - vrf: vrf1
+# default_metric: 5
+# ----------------------------------------
+#
+
+
+# commands:
+# - "router bgp 65536",
+# - "bgp cluster-id 5",
+# - "bgp router-id 192.0.2.10",
+# - "bgp bestpath med confed",
+# - "bgp confederation identifier 4",
+# - "default-metric 5",
+# - "socket receive-buffer-size 514",
+# - "socket send-buffer-size 4098",
+# - "neighbor 192.0.2.13",
+# - "bfd fast-detect strict-mode",
+# - "bfd minimum-interval 20",
+# - "bfd multiplier 6",
+# - "remote-as 65538",
+# - "vrf vrf1",
+# - "default-metric 5"
+
+# Configuration on device After Merge state:
+# --------------------------------------------
+
+# RP/0/0/CPU0:10#show running-config router bgp
+# Thu Feb 4 09:44:32.480 UTC
+# router bgp 65536
+# bgp confederation identifier 4
+# bgp router-id 192.0.2.10
+# bgp cluster-id 5
+# default-metric 5
+# socket send-buffer-size 4098
+# bgp bestpath med confed
+# socket receive-buffer-size 514
+# neighbor 192.0.2.13
+# remote-as 65538
+# bfd fast-detect strict-mode
+# bfd multiplier 6
+# bfd minimum-interval 20
+# !
+# vrf vrf1
+# default-metric 5
+# !
+# !
+
+##### Using replaced ###########################################
+
+# configuration on device before replaced
+# --------------------------------------------
+#
+# RP/0/0/CPU0:10#show running-config router bgp
+# Thu Feb 4 09:44:32.480 UTC
+# router bgp 65536
+# bgp confederation identifier 4
+# bgp router-id 192.0.2.10
+# bgp cluster-id 5
+# default-metric 5
+# socket send-buffer-size 4098
+# bgp bestpath med confed
+# socket receive-buffer-size 514
+# neighbor 192.0.2.13
+# remote-as 65538
+# bfd fast-detect strict-mode
+# bfd multiplier 6
+# bfd minimum-interval 20
+# !
+# vrf vrf1
+# default-metric 5
+# !
+# !
+# --------------Replace state---------------
+# - name: Replace the following configuration
+# cisco.iosxr.iosxr_bgp_global:
+# state: replaced
+# config:
+# as_number: 65536
+# default_metric: 4
+# socket:
+# receive_buffer_size: 514
+# send_buffer_size: 4098
+# bgp:
+# confederation:
+# identifier: 4
+# bestpath:
+# med:
+# confed: True
+# cluster_id: 5
+# router_id: 192.0.2.10
+# neighbors:
+# - neighbor: 192.0.2.14
+# remote_as: 65538
+# bfd:
+# fast_detect:
+# strict_mode: True
+# multiplier: 6
+# minimum_interval: 20
+# vrfs:
+# - vrf: vrf1
+# default_metric: 5
+# -------------------------------------------
+# commands:
+# - "router bgp 65536",
+# - "default-metric 4",
+# - "neighbor 192.0.2.14",
+# - "bfd fast-detect strict-mode",
+# - "bfd minimum-interval 20",
+# - "bfd multiplier 6",
+# - "remote-as 65538",
+# - "no neighbor 192.0.2.13"
+
+# configuration on device After Replaced state:
+# ----------------------------------------------
+
+# RP/0/0/CPU0:10#show running-config router bgp
+# Thu Feb 4 09:54:11.161 UTC
+# router bgp 65536
+# bgp confederation identifier 4
+# bgp router-id 192.0.2.10
+# bgp cluster-id 5
+# default-metric 4
+# socket send-buffer-size 4098
+# bgp bestpath med confed
+# socket receive-buffer-size 514
+# neighbor 192.0.2.14
+# remote-as 65538
+# bfd fast-detect strict-mode
+# bfd multiplier 6
+# bfd minimum-interval 20
+# !
+# vrf vrf1
+# default-metric 5
+# !
+# !
+
+
+##### Using deleted ############################################
+
+# configuration on device Before deleted state
+# ---------------------------------------------
+#
+# RP/0/0/CPU0:10#show running-config router bgp
+# Thu Feb 4 09:54:11.161 UTC
+# router bgp 65536
+# bgp confederation identifier 4
+# bgp router-id 192.0.2.10
+# bgp cluster-id 5
+# default-metric 4
+# socket send-buffer-size 4098
+# bgp bestpath med confed
+# socket receive-buffer-size 514
+# neighbor 192.0.2.14
+# remote-as 65538
+# bfd fast-detect strict-mode
+# bfd multiplier 6
+# bfd minimum-interval 20
+# !
+# vrf vrf1
+# default-metric 5
+# !
+# !
+#
+# --------------------------------------------------------
+# - name: Delete BGP configurations handled by this module
+# cisco.iosxr.iosxr_bgp_global:
+# state: deleted
+# config:
+# as_number: 65536
+#
+# commands:
+# "router bgp 65536",
+# "no bgp cluster-id 5",
+# "no bgp router-id 192.0.2.10",
+# "no bgp bestpath med confed",
+# "no bgp confederation identifier 4",
+# "no default-metric 4",
+# "no socket receive-buffer-size 514",
+# "no socket send-buffer-size 4098",
+# "no neighbor 192.0.2.14",
+# "no vrf vrf1"
+#
+# configuration on device after delete
+# -------------------------------------------
+#
+# RP/0/0/CPU0:10#show running-config router bgp
+# Thu Feb 4 10:01:08.232 UTC
+# router bgp 65536
+# !
+#
+
+
+################# Using Purged ########################################
+
+# configuration on device Before Purged state
+# --------------------------------------------
+#
+# RP/0/0/CPU0:10#show running-config router bgp
+# Thu Feb 4 09:54:11.161 UTC
+# router bgp 65536
+# bgp confederation identifier 4
+# bgp router-id 192.0.2.10
+# bgp cluster-id 5
+# default-metric 4
+# socket send-buffer-size 4098
+# bgp bestpath med confed
+# socket receive-buffer-size 514
+# address-family ipv4 unicast
+# neighbor 192.0.2.14
+# remote-as 65538
+# bfd fast-detect strict-mode
+# bfd multiplier 6
+# bfd minimum-interval 20
+# address-family ipv4 unicast
+# !
+# vrf vrf1
+# default-metric 5
+# !
+# !
+#
+# - name: Purge all BGP configurations from the device
+# cisco.iosxr.iosxr_bgp_global:
+# state: purged
+#
+# commands:
+# - no router bgp 65563
+#
+# configuration on device After purged state:
+# ---------------------------------------------
+#
+# #RP/0/0/CPU0:10#show running-config router bgp
+# #Thu Feb 4 09:38:36.245 UTC
+# #% No such configuration item(s)
+# #RP/0/0/CPU0:10#
+#
+#
+# ################# Using Rendred #######################################################
+#
+# - name: Render platform specific configuration lines (without connecting to the device)
+# cisco.iosxr.iosxr_bgp_global:
+# state: rendered
+# config:
+# as_number: 1
+# default_metric: 4
+# vrfs:
+# - vrf: vrf3
+# bfd:
+# minimum_interval: 20
+# multiplier: 10
+# bgp:
+# fast_external_fallover:
+# disable: True
+# router_id: 1.2.3.4
+# auto_policy_soft_reset:
+# disable: True
+# #rd:
+# # auto: True
+# # #value: 1
+# timers:
+# keepalive_time: 20
+# holdtime: 30
+# - vrf: vrf2
+# bgp:
+# enforce_first_as:
+# disable: True
+# default_metric: 4
+# neighbors:
+# - neighbor: 1.1.1.3
+# remote_as: 2
+# graceful_maintenance:
+# set: True
+# activate:
+# #set: True
+# inheritance_disable: True
+# local_preference:
+# value: 1
+# #inheritance_disable: True
+# as_prepends:
+# value: 2
+# rendered output
+# ------------------------------------
+# "router bgp 1",
+# "default-metric 4",
+# "vrf vrf3",
+# "bfd multiplier 10",
+# "bfd minimum-interval 20",
+# "bgp auto-policy-soft-reset disable",
+# "bgp fast-external-fallover disable",
+# "bgp router-id 1.2.3.4",
+# "timers bgp 20 30",
+# "vrf vrf2",
+# "neighbor 1.1.1.3",
+# "remote-as 2",
+# "graceful-maintenance",
+# "graceful-maintenance activate inheritance-disable",
+# "graceful-maintenance local-preference 1",
+# "graceful-maintenance as-prepends 2",
+# "bgp enforce-first-as disable",
+# "default-metric 4"
+#
+# ############## Using parsed #####################
+# parsed.cfg
+# ------------
+# router bgp 65536
+# bgp confederation identifier 4
+# bgp router-id 192.0.2.10
+# bgp cluster-id 5
+# default-metric 4
+# socket send-buffer-size 4098
+# bgp bestpath med confed
+# socket receive-buffer-size 514
+# neighbor 192.0.2.11
+# remote-as 65537
+# cluster-id 3
+# !
+# neighbor 192.0.2.14
+# remote-as 65538
+# bfd fast-detect strict-mode
+# bfd multiplier 6
+# bfd minimum-interval 20
+# !
+# !
+# ------------------------------------
+#
+# - name: Parse externally provided BGP config
+# cisco.iosxr.iosxr_bgp_global:
+# running_config: "{{ lookup('file', 'parsed.cfg') }}"
+# state: parsed
+#
+# #Task output using parsed
+# as_number: "65536"
+# default_metric: 4
+# socket:
+# receive_buffer_size: 514
+# send_buffer_size: 4098
+# bgp:
+# confederation:
+# identifier: 4
+# bestpath:
+# med:
+# confed: true
+# cluster_id: "5"
+# router_id: "192.0.2.10"
+# neighbors:
+# - neighbor: 192.0.2.11
+# remote_as: 65537
+# cluster_id: "3"
+# - neighbor: "192.0.2.14"
+# remote_as: 65538
+# bfd:
+# fast_detect:
+# strict_mode: true
+# multiplier: 6
+# minimum_interval: 20
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.bgp_global.bgp_global import (
+ Bgp_globalArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.bgp_global.bgp_global import (
+ Bgp_global,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ module = AnsibleModule(
+ argument_spec=Bgp_globalArgs.argument_spec,
+ mutually_exclusive=[["config", "running_config"]],
+ required_if=[
+ ["state", "merged", ["config"]],
+ ["state", "replaced", ["config"]],
+ ["state", "overridden", ["config"]],
+ ["state", "rendered", ["config"]],
+ ["state", "parsed", ["running_config"]],
+ ],
+ supports_check_mode=True,
+ )
+
+ result = Bgp_global(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp_neighbor_address_family.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp_neighbor_address_family.py
new file mode 100644
index 00000000..85903d30
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_bgp_neighbor_address_family.py
@@ -0,0 +1,1197 @@
+#!/usr/bin/python
+# -*- 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)
+
+"""
+The module file for iosxr_bgp_neighbor_address_family
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+module: iosxr_bgp_neighbor_address_family
+short_description: Resource module to configure BGP Neighbor Address family.
+description:
+- This module configures and manages the attributes of BGP global on Cisco IOS-XR platforms.
+version_added: 2.0.0
+author: Ashwini Mhatre (@amhatre)
+notes:
+- This module works with connection C(network_cli).
+options:
+ config:
+ description: BGP neighbor address family configurations.
+ type: dict
+ suboptions:
+ as_number:
+ description: Autonomous system number.
+ type: str
+ neighbors:
+ description: A list of BGP neighbor address family configurations.
+ type: list
+ elements: dict
+ suboptions:
+ neighbor_address:
+ description:
+ - Neighbor router address.
+ type: str
+ required: true
+ address_family:
+ description: Enable address family and enter its config mode
+ type: list
+ elements: dict
+ suboptions:
+ afi:
+ description: address family.
+ type: str
+ choices: [ 'ipv4', 'ipv6', 'l2vpn', 'link-state', 'vpnv4', 'vpnv6']
+ safi:
+ description: Address Family modifier
+ type: str
+ choices: [ 'flowspec', 'mdt', 'multicast', 'mvpn', 'rt-filter', 'tunnel', 'unicast', 'labeled-unicast' ]
+ aigp: &aigp
+ description: AIGP attribute
+ type: dict
+ suboptions:
+ disable:
+ description: Ignore AIGP attribute.
+ type: bool
+ set:
+ description: Set AIGP attribute.
+ type: bool
+ send_cost_community_disable:
+ description: send AIGP attribute.
+ type: bool
+ send_med:
+ description: send med options.
+ type: dict
+ suboptions:
+ set:
+ type: bool
+ description: set Send AIGP value in MED.
+ disable:
+ description: disable Send AIGP value in MED.
+ type: bool
+ allowas_in: &allowas_in
+ type: dict
+ description: Allow as-path with my AS present in it.
+ suboptions:
+ value:
+ type: int
+ description: Number of occurences of AS number 1-10.
+ set:
+ type: bool
+ description: set allowas_in
+ as_override: &as_override
+ type: dict
+ description: Override matching AS-number while sending update
+ suboptions:
+ set:
+ type: bool
+ description: set as_override
+ inheritance_disable:
+ type: bool
+ description: Prevent as-override from being inherited from the parent.
+ bestpath_origin_as_allow_invalid:
+ type: bool
+ description: Change default route selection criteria.Allow BGP origin-AS knobs.
+ capability_orf_prefix: &capability
+ type: str
+ description: Advertise address prefix ORF capability to this neighbor.
+ choices: ['both', 'send', 'none', 'receive']
+ default_originate: &default_originate
+ type: dict
+ description: Originate default route to this neighbor.
+ suboptions:
+ set:
+ type: bool
+ description: set default route.
+ route_policy:
+ type: str
+ description: Route policy to specify criteria to originate default
+ inheritance_disable:
+ type: bool
+ description: Prevent default-originate from being inherited from the parent.
+ long_lived_graceful_restart: &long_lived_graceful_restart
+ type: dict
+ description: Enable long lived graceful restart support.
+ suboptions:
+ capable:
+ type: bool
+ description: Treat neighbor as LLGR capable.
+ stale_time:
+ type: dict
+ description: Maximum time to wait before purging long-lived stale routes.
+ suboptions:
+ send:
+ type: int
+ description: max send time
+ accept:
+ type: int
+ description: max accept time
+ maximum_prefix: &maximum_prefix
+ type: dict
+ description: Maximum number of prefixes to accept from this peer.
+ suboptions:
+ max_limit:
+ type: int
+ description: maximum no. of prefix limit.<1-4294967295.
+ threshold_value:
+ type: int
+ description: hreshold value (%) at which to generate a warning msg <1-100>.
+ restart:
+ type: int
+ description: Restart time interval.
+ warning_only:
+ type: bool
+ description: Only give warning message when limit is exceeded.
+ discard_extra_paths:
+ description: Discard extra paths when limit is exceeded.
+ type: bool
+ multipath: &multipath
+ type: bool
+ description: Paths from this neighbor is eligible for multipath.
+ next_hop_self: &next_hop_self
+ type: dict
+ description: Disable the next hop calculation for this neighbor.
+ suboptions:
+ set:
+ type: bool
+ description: set next hop self.
+ inheritance_disable:
+ type: bool
+ description: Prevent next_hop_self from being inherited from the parent.
+ next_hop_unchanged: &next_hop_unchanged
+ type: dict
+ description: Disable the next hop calculation for this neighbor.
+ suboptions:
+ set:
+ type: bool
+ description: set next hop unchanged.
+ inheritance_disable:
+ type: bool
+ description: Prevent next_hop_unchanged from being inherited from the parent.
+ multipath:
+ type: bool
+ description: Do not overwrite nexthop before advertising multipaths.
+ optimal_route_reflection_group_name: &optimal_route_reflection
+ type: str
+ description: Configure optimal-route-reflection group.
+ orf_route_policy: &orf_rp
+ type: str
+ description: Specify ORF and inbound filtering criteria.'
+ origin_as:
+ description: BGP origin-AS knobs.
+ type: dict
+ suboptions:
+ validation:
+ description: BGP origin-AS validation knobs.
+ type: dict
+ suboptions:
+ disable:
+ description: Disable RPKI origin-AS validation.
+ type: bool
+ remove_private_AS: &remove_private_AS
+ type: dict
+ description: Remove private AS number from outbound updates.
+ suboptions:
+ set:
+ type: bool
+ description: set remove private As.
+ inbound:
+ type: bool
+ description: Remove private AS number from inbound updates.
+ entire_aspath:
+ type: bool
+ description: remove only if all ASes in the path are private.
+ inheritance_disable:
+ type: bool
+ description: Prevent remove-private-AS from being inherited from the parent.
+ route_policy: &route_policy
+ type: dict
+ description: Apply route policy to neighbor.
+ suboptions:
+ inbound:
+ type: str
+ description: Apply route policy to inbound routes.
+ outbound:
+ type: str
+ description: Apply route policy to outbound routes.
+ route_reflector_client: &route_reflector_client
+ type: dict
+ description: Configure a neighbor as Route Reflector client.
+ suboptions:
+ set:
+ type: bool
+ description: set route-reflector-client.
+ inheritance_disable:
+ type: bool
+ description: Prevent route-reflector-client from being inherited from the parent.
+ send_community_ebgp: &send_community_ebgp
+ description: Send community attribute to this external neighbor.
+ type: dict
+ suboptions:
+ set:
+ type: bool
+ description: set send_community_ebgp.
+ inheritance_disable:
+ type: bool
+ description: Prevent send_community_ebgp from being inherited from the parent.
+ send_community_gshut_ebgp: &send_community_gshut_ebgp
+ description: Allow the g-shut community to be sent to this external neighbor.
+ type: dict
+ suboptions:
+ set:
+ type: bool
+ description: set send_community_gshut_ebgp.
+ inheritance_disable:
+ type: bool
+ description: Prevent send_community_gshut_ebgp from being inherited from the parent.
+ send_extended_community_ebgp: &send_extended_community_ebgp
+ description: Send extended community attribute to this external neighbor.
+ type: dict
+ suboptions:
+ set:
+ type: bool
+ description: set send_extended_community_ebgp.
+ inheritance_disable:
+ type: bool
+ description: Prevent send_extended_community_ebgp from being inherited from the parent.
+ send_multicast_attributes:
+ description: Send multicast attributes to this neighbor .
+ type: dict
+ suboptions:
+ set:
+ type: bool
+ description: set send_multicast_attributes.
+ disable:
+ type: bool
+ description: Disable send multicast attributes.
+ soft_reconfiguration: &soft_reconfiguration
+ description: Per neighbor soft reconfiguration.
+ type: dict
+ suboptions:
+ inbound:
+ type: dict
+ description: inbound soft reconfiguration
+ suboptions:
+ set:
+ type: bool
+ description: set inbound
+ always:
+ type: bool
+ description: Allow inbound soft reconfiguration for this neighbor. Always use soft reconfig, even if route refresh is supported.
+ inheritance_disable:
+ type: bool
+ description: Prevent soft_reconfiguration from being inherited from the parent.
+ weight: &wt
+ type: int
+ description: Set default weight for routes from this neighbor.
+ validation: &validation
+ type: dict
+ description: Flowspec Validation for this neighbor.
+ suboptions:
+ set:
+ type: bool
+ description: set validation.
+ redirect:
+ type: bool
+ description: Flowspec Redirect nexthop Validation.
+ disable:
+ type: bool
+ description: disable validation.
+ vrfs:
+ description: Configure BGP neighbor afin a VRF.
+ type: list
+ elements: dict
+ suboptions:
+ vrf:
+ description: VRF name.
+ type: str
+ neighbors:
+ description: A list of BGP neighbor address family configurations.
+ type: list
+ elements: dict
+ suboptions:
+ neighbor_address:
+ description:
+ - Neighbor router address.
+ type: str
+ required: true
+ address_family:
+ description: Enable address family and enter its config mode
+ type: list
+ elements: dict
+ suboptions:
+ afi:
+ description: address family.
+ type: str
+ choices: [ 'ipv4', 'ipv6']
+ safi:
+ description: Address Family modifier
+ type: str
+ choices: [ 'flowspec', 'multicast', 'mvpn', 'unicast', 'labeled-unicast' ]
+ aigp: *aigp
+ allowas_in: *allowas_in
+ as_override:
+ type: dict
+ description: Override matching AS-number while sending update
+ aliases:
+ - as_overrride
+ suboptions:
+ set:
+ type: bool
+ description: set as_override
+ inheritance_disable:
+ type: bool
+ description: Prevent as-override from being inherited from the parent.
+ capability_orf_prefix: *capability
+ default_originate: *default_originate
+ long_lived_graceful_restart: *long_lived_graceful_restart
+ maximum_prefix: *maximum_prefix
+ multipath: *multipath
+ next_hop_self: *next_hop_self
+ next_hop_unchanged: *next_hop_unchanged
+ optimal_route_reflection_group_name: *optimal_route_reflection
+ orf_route_policy: *orf_rp
+ remove_private_AS: *remove_private_AS
+ route_policy: *route_policy
+ route_reflector_client: *route_reflector_client
+ send_community_ebgp: *send_community_ebgp
+ send_community_gshut_ebgp: *send_community_gshut_ebgp
+ send_extended_community_ebgp: *send_extended_community_ebgp
+ soft_reconfiguration: *soft_reconfiguration
+ site_of_origin:
+ description: Site-of-Origin extended community associated with the neighbor.
+ type: str
+ weight: *wt
+ validation: *validation
+
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the Iosxr device by
+ executing the command B(show running-config router bgp).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state the configuration should be left in.
+ type: str
+ choices: [deleted, merged, overridden, replaced, gathered, rendered, parsed]
+ default: merged
+"""
+EXAMPLES = """
+# Using merged
+# Before state:
+# -------------
+# RP/0/0/CPU0:iosxr-02#show running-config router bgp
+# Sat Feb 20 03:49:43.618 UTC
+# router bgp 65536
+# bgp router-id 192.0.2.1
+# address-family ipv4 unicast
+# address-family vpnv4 unicast
+# neighbor 192.0.2.2
+# remote-as 65537
+# neighbor 192.0.2.3
+# remote-as 65538
+# vrf vrf1
+# rd auto
+# neighbor 192.0.2.4
+# remote-as 65539
+# vrf vrf2
+# rd auto
+# neighbor 192.0.2.5
+# remote-as 65540
+
+- name: Merge the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_bgp_neighbor_address_family:
+ state: merged
+ config:
+ as_number: 65536
+ neighbors:
+ - neighbor_address: 192.0.2.2
+ address_family:
+ - afi: "ipv4"
+ safi: "unicast"
+ multipath: true
+ default_originate:
+ set: true
+ weight: 5
+ - neighbor_address: 192.0.2.3
+ address_family:
+ - afi: "ipv4"
+ safi: "unicast"
+ multipath: true
+ default_originate:
+ set: true
+ weight: 4
+ vrfs:
+ - vrf: vrf1
+ neighbors:
+ - neighbor_address: 192.0.2.4
+ address_family:
+ - afi: "ipv4"
+ safi: "unicast"
+ multipath: true
+ default_originate:
+ set: true
+ capability_orf_prefix: both
+ - vrf: vrf2
+ neighbors:
+ - neighbor_address: 192.0.2.5
+ address_family:
+ - afi: "ipv4"
+ safi: "unicast"
+ multipath: true
+ default_originate:
+ set: true
+ capability_orf_prefix: both
+# Task output
+# -------------
+# commands:
+# - router bgp 65536
+# - neighbor 192.0.2.2
+# - address-family ipv4 unicast
+# - default-originate
+# - multipath
+# - weight 5
+# - neighbor 192.0.2.3
+# - address-family ipv4 unicast
+# - default-originate
+# - multipath
+# - weight 4
+# - vrf vrf1
+# - neighbor 192.0.2.4
+# - address-family ipv4 unicast
+# - capability orf prefix both
+# - default-originate
+# - multipath
+# - vrf vrf2
+# - neighbor 192.0.2.5
+# - address-family ipv4 unicast
+# - capability orf prefix both
+# - default-originate
+# - multipath
+#
+#
+# after:
+# as_number: 65536
+# neighbors:
+# - neighbor_address: 192.0.2.2
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# weight: 5
+# - neighbor_address: 192.0.2.3
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# weight: 4
+# vrfs:
+# - vrf: vrf1
+# neighbors:
+# - neighbor_address: 192.0.2.4
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# capability_orf_prefix: both
+# - vrf: vrf2
+# neighbors:
+# - neighbor_address: 192.0.2.5
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# capability_orf_prefix: both
+#
+#
+# After state:
+# -------------
+# RP/0/0/CPU0:iosxr-02#show running-config router bgp
+# Sat Feb 20 03:49:43.618 UTC
+# router bgp 65536
+# bgp router-id 192.0.1.1
+# address-family ipv4 unicast
+# address-family vpnv4 unicast
+# neighbor 192.0.2.2
+# remote-as 65537
+# address-family ipv4 unicast
+# multipath
+# weight 5
+# default-originate
+# neighbor 1.1.1.2
+# remote-as 65538
+# address-family ipv4 unicast
+# multipath
+# weight 5
+# default-originate
+# vrf vrf1
+# rd auto
+# neighbor 192.0.2.4
+# remote-as 65539
+# address-family ipv4 unicast
+# multipath
+# capability orf prefix both
+# default-originate
+# vrf vrf2
+# rd auto
+# neighbor 192.0.2.5
+# remote-as 65540
+# address-family ipv4 unicast
+# multipath
+# capability orf prefix both
+# default-originate
+#
+#
+# Using delete
+# Before state:
+# -------------
+#
+# RP/0/0/CPU0:iosxr-02#show running-config router bgp
+# Sat Feb 20 03:49:43.618 UTC
+# router bgp 65536
+# bgp router-id 192.0.1.1
+# address-family ipv4 unicast
+# address-family vpnv4 unicast
+# neighbor 192.0.2.2
+# remote-as 65537
+# address-family ipv4 unicast
+# multipath
+# weight 5
+# default-originate
+# neighbor 192.0.2.3
+# remote-as 65538
+# address-family ipv4 unicast
+# multipath
+# weight 5
+# default-originate
+# vrf vrf1
+# rd auto
+# neighbor 192.0.2.4
+# remote-as 65539
+# address-family ipv4 unicast
+# multipath
+# capability orf prefix both
+# default-originate
+# vrf vrf2
+# rd auto
+# neighbor 192.0.2.5
+# remote-as 65540
+# address-family ipv4 unicast
+# multipath
+# capability orf prefix both
+# default-originate
+
+- name: Delete the provided configuration
+ cisco.iosxr.iosxr_bgp_neighbor_address_family:
+ state: deleted
+ config:
+ as_number: 65536
+ neighbors:
+ - neighbor_address: 192.0.2.2
+ address_family:
+ - afi: "ipv4"
+ safi: "unicast"
+ multipath: true
+ default_originate:
+ set: true
+ weight: 5
+
+# Task output
+# -------------
+#
+# commands:
+# - router bgp 65536
+# - neighbor 192.0.2.2
+# - no address-family ipv4 unicast
+#
+#
+# after:
+# as_number: 65536
+# neighbors:
+# - neighbor_address: 192.0.2.3
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# weight: 4
+# vrfs:
+# - vrf: vrf1
+# neighbors:
+# - neighbor_address: 192.0.2.4
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# capability_orf_prefix: both
+# - neighbor_address: 192.0.2.5
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# capability_orf_prefix: both
+#
+#
+# Using Replaced
+# Before state:
+# -------------
+#
+# RP/0/0/CPU0:iosxr-02#show running-config router bgp
+# Sat Feb 20 03:49:43.618 UTC
+# router bgp 65536
+# bgp router-id 192.0.1.1
+# address-family ipv4 unicast
+# address-family vpnv4 unicast
+# neighbor 192.0.2.2
+# remote-as 65537
+# address-family ipv4 unicast
+# multipath
+# weight 5
+# default-originate
+# neighbor 192.0.2.3
+# remote-as 65538
+# address-family ipv4 unicast
+# multipath
+# weight 5
+# default-originate
+# vrf vrf1
+# rd auto
+# neighbor 192.0.2.4
+# remote-as 65539
+# address-family ipv4 unicast
+# multipath
+# capability orf prefix both
+# default-originate
+# vrf vrf2
+# rd auto
+# neighbor 192.0.2.5
+# remote-as 65540
+# address-family ipv4 unicast
+# multipath
+# capability orf prefix both
+# default-originate
+
+- name: Replace the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_bgp_neighbor_address_family:
+ state: replaced
+ config:
+ as_number: 65536
+ neighbors:
+ - neighbor_address: 192.0.2.2
+ address_family:
+ - afi: "ipv4"
+ safi: "unicast"
+ default_originate:
+ set: true
+ weight: 4
+# Task output
+# -------------
+# commands:
+# - router bgp 65536
+# - neighbor 192.0.2.2
+# - address-family ipv4 unicast
+# - no multipath
+# - weight 4
+#
+# after:
+# as_number: 65536
+# neighbors:
+# - neighbor_address: 192.0.2.2
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# weight: 4
+# - neighbor_address: 192.0.2.3
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# weight: 5
+# vrfs:
+# - vrf: vrf1
+# neighbors:
+# - neighbor_address: 192.0.2.4
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# capability_orf_prefix: both
+# - neighbor_address: 192.0.2.5
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# capability_orf_prefix: both
+#
+# After state:
+# -------------
+# Nexus9000v# show running-config router bgp
+# router bgp 65536
+# bgp router-id 192.0.1.1
+# address-family ipv4 unicast
+# address-family vpnv4 unicast
+# neighbor 192.0.2.2
+# remote-as 65537
+# address-family ipv4 unicast
+# multipath
+# weight 4
+# default-originate
+# neighbor 192.0.2.3
+# remote-as 65538
+# address-family ipv4 unicast
+# multipath
+# weight 5
+# default-originate
+# vrf vrf1
+# rd auto
+# neighbor 192.0.2.4
+# remote-as 65539
+# address-family ipv4 unicast
+# multipath
+# capability orf prefix both
+# default-originate
+# vrf vrf2
+# rd auto
+# neighbor 192.0.2.5
+# remote-as 65540
+# address-family ipv4 unicast
+# multipath
+# capability orf prefix both
+# default-originate
+#
+#
+# Using overridden
+# Before state:
+# -------------
+# RP/0/0/CPU0:iosxr-02#show running-config router bgp
+# Sat Feb 20 03:49:43.618 UTC
+# router bgp 65536
+# bgp router-id 192.0.1.1
+# address-family ipv4 unicast
+# address-family vpnv4 unicast
+# neighbor 192.0.2.2
+# remote-as 65537
+# address-family ipv4 unicast
+# multipath
+# weight 5
+# default-originate
+# neighbor 192.0.2.3
+# remote-as 65538
+# address-family ipv4 unicast
+# multipath
+# weight 5
+# default-originate
+# vrf vrf1
+# rd auto
+# neighbor 192.0.2.4
+# remote-as 65539
+# address-family ipv4 unicast
+# multipath
+# capability orf prefix both
+# default-originate
+# vrf vrf2
+# rd auto
+# neighbor 192.0.2.5
+# remote-as 65540
+# address-family ipv4 unicast
+# multipath
+# capability orf prefix both
+# default-originate
+
+- name: override the provided configuration
+ cisco.iosxr.iosxr_bgp_neighbor_address_family:
+ state: overridden
+ config:
+ as_number: 65536
+ neighbors:
+ - neighbor_address: 192.0.2.2
+ address_family:
+ - afi: "ipv4"
+ safi: "unicast"
+ multipath: true
+ default_originate:
+ set: true
+ weight: 5
+# Task output
+# -------------
+#
+# commands:
+# - router bgp 65536
+# - neighbor 192.0.2.3
+# - no address-family ipv4 unicast
+# - vrf vrf1
+# - neighbor 192.0.2.4
+# - no address-family ipv4 unicast
+# - vrf vrf1
+# - neighbor 192.0.2.5
+# - no address-family ipv4 unicast
+#
+#
+#
+# after:
+# as_number: 65536
+# neighbors:
+# - neighbor_address: 192.0.2.2
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# weight: 5
+#
+# After state:
+# -------------
+# RP/0/0/CPU0:iosxr-02#show running-config router bgp
+# Sat Feb 20 03:49:43.618 UTC
+# router bgp 65536
+# bgp router-id 192.0.1.1
+# address-family ipv4 unicast
+# address-family vpnv4 unicast
+# neighbor 192.0.2.2
+# remote-as 65537
+# address-family ipv4 unicast
+# multipath
+# weight 5
+# default-originate
+#
+#
+#
+# Using rendered
+# Before state:
+# -------------
+# RP/0/0/CPU0:iosxr-02#show running-config router bgp
+# Sat Feb 20 03:49:43.618 UTC
+# router bgp 65536
+# bgp router-id 192.0.2.1
+# address-family ipv4 unicast
+# address-family vpnv4 unicast
+# neighbor 192.0.2.2
+# remote-as 65537
+# neighbor 192.0.2.3
+# remote-as 65538
+# vrf vrf1
+# rd auto
+# neighbor 192.0.2.4
+# remote-as 65539
+# vrf vrf2
+# rd auto
+# neighbor 192.0.2.5
+# remote-as 65540
+
+- name: Render platform specific configuration lines with state rendered (without connecting to the device)
+ cisco.iosxr.iosxr_bgp_neighbor_address_family:
+ state: rendered
+ config:
+ as_number: 65536
+ neighbors:
+ - neighbor_address: 192.0.2.2
+ address_family:
+ - afi: "ipv4"
+ safi: "unicast"
+ multipath: true
+ default_originate:
+ set: true
+ weight: 5
+ - neighbor_address: 192.0.2.3
+ address_family:
+ - afi: "ipv4"
+ safi: "unicast"
+ multipath: true
+ default_originate:
+ set: true
+ weight: 4
+ vrfs:
+ - vrf: vrf1
+ neighbors:
+ - neighbor_address: 192.0.2.4
+ address_family:
+ - afi: "ipv4"
+ safi: "unicast"
+ multipath: true
+ default_originate:
+ set: true
+ capability_orf_prefix: both
+ - vrf: vrf2
+ neighbors:
+ - neighbor_address: 192.0.2.5
+ address_family:
+ - afi: "ipv4"
+ safi: "unicast"
+ multipath: true
+ default_originate:
+ set: true
+ capability_orf_prefix: both
+# Task output
+# -------------
+# commands:
+# - router bgp 65536
+# - neighbor 192.0.2.2
+# - address-family ipv4 unicast
+# - default-originate
+# - multipath
+# - weight 5
+# - neighbor 192.0.2.3
+# - address-family ipv4 unicast
+# - default-originate
+# - multipath
+# - weight 4
+# - vrf vrf1
+# - neighbor 192.0.2.4
+# - address-family ipv4 unicast
+# - capability orf prefix both
+# - default-originate
+# - multipath
+# - vrf vrf2
+# - neighbor 192.0.2.5
+# - address-family ipv4 unicast
+# - capability orf prefix both
+# - default-originate
+# - multipath
+#
+# Using parsed
+#
+#parsed.cfg
+#------------
+# router bgp 65536
+# bgp router-id 192.0.1.1
+# address-family ipv4 unicast
+# address-family vpnv4 unicast
+# neighbor 192.0.2.2
+# remote-as 65537
+# address-family ipv4 unicast
+# multipath
+# weight 5
+# default-originate
+# neighbor 1.1.1.2
+# remote-as 65538
+# address-family ipv4 unicast
+# multipath
+# weight 5
+# default-originate
+# vrf vrf1
+# rd auto
+# neighbor 192.0.2.4
+# remote-as 65539
+# address-family ipv4 unicast
+# multipath
+# capability orf prefix both
+# default-originate
+# vrf vrf2
+# rd auto
+# neighbor 192.0.2.5
+# remote-as 65540
+# address-family ipv4 unicast
+# multipath
+# capability orf prefix both
+# default-originate
+
+- name: Parse externally provided BGP neighbor AF config
+ cisco.iosxr.iosxr_bgp_neighbor_address_family:
+ running_config: "{{ lookup('file', 'parsed.cfg') }}"
+ state: parsed
+# Task output (redacted)
+# -----------------------
+# parsed:
+# as_number: 65536
+# neighbors:
+# - neighbor_address: 192.0.2.2
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# weight: 5
+# - neighbor_address: 192.0.2.3
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# weight: 4
+# vrfs:
+# - vrf: vrf1
+# neighbors:
+# - neighbor_address: 192.0.2.4
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# capability_orf_prefix: both
+# - vrf: vrf2
+# neighbors:
+# - neighbor_address: 192.0.2.5
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# capability_orf_prefix: both
+#
+#
+#Using Gathered
+#-----------------
+# Before state state:
+# -------------
+# RP/0/0/CPU0:iosxr-02#show running-config router bgp
+# Sat Feb 20 03:49:43.618 UTC
+# router bgp 65536
+# bgp router-id 192.0.1.1
+# address-family ipv4 unicast
+# address-family vpnv4 unicast
+# neighbor 192.0.2.2
+# remote-as 65537
+# address-family ipv4 unicast
+# multipath
+# weight 5
+# default-originate
+# neighbor 1.1.1.2
+# remote-as 65538
+# address-family ipv4 unicast
+# multipath
+# weight 5
+# default-originate
+# vrf vrf1
+# rd auto
+# neighbor 192.0.2.4
+# remote-as 65539
+# address-family ipv4 unicast
+# multipath
+# capability orf prefix both
+# default-originate
+# vrf vrf2
+# rd auto
+# neighbor 192.0.2.5
+# remote-as 65540
+# address-family ipv4 unicast
+# multipath
+# capability orf prefix both
+# default-originate
+#
+#
+#
+- name: Gathered the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_bgp_neighbor_address_family:
+ config:
+ state: gathered
+
+
+# Task output
+# -----------------------
+# gathered:
+# as_number: 65536
+# neighbors:
+# - neighbor_address: 192.0.2.2
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# weight: 5
+# - neighbor_address: 192.0.2.3
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# weight: 4
+# vrfs:
+# - vrf: vrf1
+# neighbors:
+# - neighbor_address: 192.0.2.4
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# capability_orf_prefix: both
+# - vrf: vrf2
+# neighbors:
+# - neighbor_address: 192.0.2.5
+# address_family:
+# - afi: "ipv4"
+# safi: "unicast"
+# multipath: true
+# default_originate:
+# set: true
+# capability_orf_prefix: both
+#
+
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.bgp_neighbor_address_family.bgp_neighbor_address_family import (
+ Bgp_neighbor_address_familyArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.bgp_neighbor_address_family.bgp_neighbor_address_family import (
+ Bgp_neighbor_address_family,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ module = AnsibleModule(
+ argument_spec=Bgp_neighbor_address_familyArgs.argument_spec,
+ mutually_exclusive=[["config", "running_config"]],
+ required_if=[
+ ["state", "merged", ["config"]],
+ ["state", "replaced", ["config"]],
+ ["state", "overridden", ["config"]],
+ ["state", "rendered", ["config"]],
+ ["state", "parsed", ["running_config"]],
+ ],
+ supports_check_mode=True,
+ )
+
+ result = Bgp_neighbor_address_family(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_command.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_command.py
new file mode 100644
index 00000000..5838de0d
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_command.py
@@ -0,0 +1,217 @@
+#!/usr/bin/python
+#
+# Copyright: Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+module: iosxr_command
+author: Ricardo Carrillo Cruz (@rcarrillocruz)
+short_description: Module to run commands on remote devices.
+description:
+- Sends arbitrary commands to an IOS XR node and returns the results read from the
+ device. This module includes an argument that will cause the module to wait for
+ a specific condition before returning or timing out if the condition is not met.
+- This module does not support running commands in configuration mode. Please use
+ M(cisco.iosxr.iosxr_config) to configure iosxr devices.
+version_added: 1.0.0
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+notes:
+- Make sure the user has been authorized to execute commands terminal length 0, terminal
+ width 512 and terminal exec prompt no-timestamp.
+- This module works with C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+- This module does not support C(netconf) connection.
+options:
+ commands:
+ description:
+ - List of commands to send to the remote iosxr device over the configured provider.
+ The resulting output from the command is returned. If the I(wait_for) argument
+ is provided, the module is not returned until the condition is satisfied or
+ the number of retries has expired.
+ - If a command sent to the device requires answering a prompt, it is possible to pass
+ a dict containing command, answer and prompt. Common answers are 'y' or "\\r"
+ (carriage return, must be double quotes). See examples
+ type: list
+ elements: raw
+ required: true
+ wait_for:
+ description:
+ - List of conditions to evaluate against the output of the command. The task will
+ wait for each condition to be true before moving forward. If the conditional
+ is not true within the configured number of retries, the task fails. See examples.
+ aliases:
+ - waitfor
+ type: list
+ elements: str
+ match:
+ description:
+ - The I(match) argument is used in conjunction with the I(wait_for) argument to
+ specify the match policy. Valid values are C(all) or C(any). If the value
+ is set to C(all) then all conditionals in the wait_for must be satisfied. If
+ the value is set to C(any) then only one of the values must be satisfied.
+ default: all
+ choices:
+ - any
+ - all
+ type: str
+ retries:
+ description:
+ - Specifies the number of retries a command should by tried before it is considered
+ failed. The command is run on the target device every retry and evaluated against
+ the I(wait_for) conditions.
+ default: 10
+ type: int
+ interval:
+ description:
+ - Configures the interval in seconds to wait between retries of the command. If
+ the command does not pass the specified conditions, the interval indicates how
+ long to wait before trying the command again.
+ default: 1
+ type: int
+"""
+
+EXAMPLES = """
+- name: run show version on remote devices
+ cisco.iosxr.iosxr_command:
+ commands: show version
+
+- name: run show version and check to see if output contains iosxr
+ cisco.iosxr.iosxr_command:
+ commands: show version
+ wait_for: result[0] contains IOS-XR
+
+- name: run multiple commands on remote nodes
+ cisco.iosxr.iosxr_command:
+ commands:
+ - show version
+ - show interfaces
+ - {command: example command that prompts, prompt: expected prompt, answer: yes}
+
+- name: run multiple commands and evaluate the output
+ cisco.iosxr.iosxr_command:
+ commands:
+ - show version
+ - show interfaces
+ wait_for:
+ - result[0] contains IOS-XR
+ - result[1] contains Loopback0
+
+- name: multiple prompt, multiple answer (mandatory check for all prompts)
+ cisco.iosxr.iosxr_command:
+ commands:
+ - command: key config-key password-encryption
+ prompt:
+ - "Enter old key :"
+ - "Enter new key :"
+ - "Enter confirm key :"
+ answer:
+ - "test1234"
+ - "test12345"
+ - "test12345"
+ check_all: true
+"""
+
+RETURN = """
+stdout:
+ description: The set of responses from the commands
+ returned: always apart from low level errors (such as action plugin)
+ type: list
+ sample: ['...', '...']
+stdout_lines:
+ description: The value of stdout split into a list
+ returned: always apart from low level errors (such as action plugin)
+ type: list
+ sample: [['...', '...'], ['...'], ['...']]
+failed_conditions:
+ description: The list of conditionals that have failed
+ returned: failed
+ type: list
+ sample: ['...', '...']
+"""
+import time
+
+from ansible.module_utils._text import to_text
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.parsing import (
+ Conditional,
+)
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import to_lines
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import run_commands
+
+
+def parse_commands(module, warnings):
+ commands = module.params["commands"]
+ for item in list(commands):
+ try:
+ command = item["command"]
+ except Exception:
+ command = item
+ if module.check_mode and not command.startswith("show"):
+ warnings.append(
+ "Only show commands are supported when using check mode, not "
+ "executing %s" % command,
+ )
+ commands.remove(item)
+
+ return commands
+
+
+def main():
+ argument_spec = dict(
+ commands=dict(type="list", required=True, elements="raw"),
+ wait_for=dict(type="list", aliases=["waitfor"], elements="str"),
+ match=dict(default="all", choices=["all", "any"]),
+ retries=dict(default=10, type="int"),
+ interval=dict(default=1, type="int"),
+ )
+
+ module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
+
+ warnings = list()
+ result = {"changed": False, "warnings": warnings}
+ commands = parse_commands(module, warnings)
+ wait_for = module.params["wait_for"] or list()
+
+ try:
+ conditionals = [Conditional(c) for c in wait_for]
+ except AttributeError as exc:
+ module.fail_json(msg=to_text(exc))
+
+ retries = module.params["retries"]
+ interval = module.params["interval"]
+ match = module.params["match"]
+
+ while retries > 0:
+ responses = run_commands(module, commands)
+
+ for item in list(conditionals):
+ if item(responses):
+ if match == "any":
+ conditionals = list()
+ break
+ conditionals.remove(item)
+
+ if not conditionals:
+ break
+
+ time.sleep(interval)
+ retries -= 1
+
+ if conditionals:
+ failed_conditions = [item.raw for item in conditionals]
+ msg = "One or more conditional statements have not been satisfied"
+ module.fail_json(msg=msg, failed_conditions=failed_conditions)
+
+ result.update({"stdout": responses, "stdout_lines": list(to_lines(responses))})
+
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_config.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_config.py
new file mode 100644
index 00000000..f723b569
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_config.py
@@ -0,0 +1,489 @@
+#!/usr/bin/python
+#
+# Copyright: Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_config
+author: Ricardo Carrillo Cruz (@rcarrillocruz)
+short_description: Module to manage configuration sections.
+description:
+- Cisco IOS XR configurations use a simple block indent file syntax for segmenting
+ configuration into sections. This module provides an implementation for working
+ with IOS XR configuration sections in a deterministic way.
+version_added: 1.0.0
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+notes:
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+- This module does not support C(netconf) connection
+- Abbreviated commands are NOT idempotent, see L(Network FAQ,../network/user_guide/faq.html
+ #why-do-the-config-modules-always-return-changed-true-with-abbreviated-commands).
+- Avoid service disrupting changes (viz. Management IP) from config replace.
+- Do not use C(end) in the replace config file.
+- To ensure idempotency and correct diff the configuration lines in the relevant module options should be similar to how they
+ appear if present in the running configuration on device including the indentation.
+options:
+ lines:
+ description:
+ - The ordered set of commands that should be configured in the section. The commands
+ must be the exact same commands as found in the device running-config as found in the
+ device running-config to ensure idempotency and correct diff. Be sure to note the
+ configuration command syntax as some commands are automatically modified by the
+ device config parser.
+ type: list
+ elements: str
+ aliases:
+ - commands
+ parents:
+ description:
+ - The ordered set of parents that uniquely identify the section or hierarchy the
+ commands should be checked against. If the parents argument is omitted, the
+ commands are checked against the set of top level or global commands.
+ type: list
+ elements: str
+ src:
+ description:
+ - Specifies the source path to the file that contains the configuration or configuration
+ template to load. The path to the source file can either be the full path on
+ the Ansible control host or a relative path from the playbook or role root directory. This
+ argument is mutually exclusive with I(lines), I(parents). The configuration lines in the
+ source file should be similar to how it will appear if present in the running-configuration
+ of the device to ensure idempotency and correct diff.
+ type: path
+ before:
+ description:
+ - The ordered set of commands to push on to the command stack if a change needs
+ to be made. This allows the playbook designer the opportunity to perform configuration
+ commands prior to pushing any changes without affecting how the set of commands
+ are matched against the system.
+ type: list
+ elements: str
+ after:
+ description:
+ - The ordered set of commands to append to the end of the command stack if a change
+ needs to be made. Just like with I(before) this allows the playbook designer
+ to append a set of commands to be executed after the command set.
+ type: list
+ elements: str
+ match:
+ description:
+ - Instructs the module on the way to perform the matching of the set of commands
+ against the current device config. If match is set to I(line), commands are
+ matched line by line. If match is set to I(strict), command lines are matched
+ with respect to position. If match is set to I(exact), command lines must be
+ an equal match. Finally, if match is set to I(none), the module will not attempt
+ to compare the source configuration with the running configuration on the remote
+ device.
+ type: str
+ default: line
+ choices:
+ - line
+ - strict
+ - exact
+ - none
+ replace:
+ description:
+ - Instructs the module on the way to perform the configuration on the device. If
+ the replace argument is set to I(line) then the modified lines are pushed to
+ the device in configuration mode. If the replace argument is set to I(block)
+ then the entire command block is pushed to the device in configuration mode
+ if any line is not correct.
+ type: str
+ default: line
+ choices:
+ - line
+ - block
+ - config
+ force:
+ description:
+ - The force argument instructs the module to not consider the current devices
+ running-config. When set to true, this will cause the module to push the contents
+ of I(src) into the device without first checking if already configured.
+ - Note this argument should be considered deprecated. To achieve the equivalent,
+ set the C(match=none) which is idempotent. This argument will be removed in
+ a future release.
+ type: bool
+ default: no
+ config:
+ description:
+ - The module, by default, will connect to the remote device and retrieve the current
+ running-config to use as a base for comparing against the contents of source. There
+ are times when it is not desirable to have the task get the current running-config
+ for every task in a playbook. The I(config) argument allows the implementer
+ to pass in the configuration to use as the base config for comparison.
+ The configuration lines for this option should be similar to how it will appear if present
+ in the running-configuration of the device to ensure idempotency and correct diff.
+ type: str
+ backup:
+ description:
+ - This argument will cause the module to create a full backup of the current C(running-config)
+ from the remote device before any changes are made. If the C(backup_options)
+ value is not given, the backup file is written to the C(backup) folder in the
+ playbook root directory or role root directory, if playbook is part of an ansible
+ role. If the directory does not exist, it is created.
+ type: bool
+ default: no
+ comment:
+ description:
+ - Allows a commit description to be specified to be included when the configuration
+ is committed. If the configuration is not changed or committed, this argument
+ is ignored.
+ type: str
+ default: configured by iosxr_config
+ admin:
+ description:
+ - Enters into administration configuration mode for making config changes to the
+ device.
+ type: bool
+ default: no
+ label:
+ description:
+ - Allows a commit label to be specified to be included when the configuration
+ is committed. A valid label must begin with an alphabet and not exceed 30 characters,
+ only alphabets, digits, hyphens and underscores are allowed. If the configuration
+ is not changed or committed, this argument is ignored.
+ type: str
+ backup_options:
+ description:
+ - This is a dict object containing configurable options related to backup file
+ path. The value of this option is read only when C(backup) is set to I(yes),
+ if C(backup) is set to I(no) this option will be silently ignored.
+ suboptions:
+ filename:
+ description:
+ - The filename to be used to store the backup configuration. If the filename
+ is not given it will be generated based on the hostname, current time and
+ date in format defined by <hostname>_config.<current-date>@<current-time>
+ type: str
+ dir_path:
+ description:
+ - This option provides the path ending with directory name in which the backup
+ configuration file will be stored. If the directory does not exist it will
+ be first created and the filename is either the value of C(filename) or
+ default filename as described in C(filename) options description. If the
+ path value is not given in that case a I(backup) directory will be created
+ in the current working directory and backup configuration will be copied
+ in C(filename) within I(backup) directory.
+ type: path
+ type: dict
+ exclusive:
+ description:
+ - Enters into exclusive configuration mode that locks out all users from committing
+ configuration changes until the exclusive session ends.
+ type: bool
+ default: false
+ disable_default_comment:
+ description:
+ - disable default comment when set to True.
+ type: bool
+ default: false
+"""
+
+EXAMPLES = """
+- name: configure top level configuration
+ cisco.iosxr.iosxr_config:
+ lines: hostname {{ inventory_hostname }}
+
+- name: configure interface settings
+ cisco.iosxr.iosxr_config:
+ lines:
+ - description test interface
+ - ip address 172.31.1.1 255.255.255.0
+ parents: interface GigabitEthernet0/0/0/0
+
+- name: load a config from disk and replace the current config
+ cisco.iosxr.iosxr_config:
+ src: config.cfg
+ replace: config
+ backup: yes
+
+- name: for idempotency, use full-form commands
+ cisco.iosxr.iosxr_config:
+ lines:
+ # - shut
+ - shutdown
+ # parents: int g0/0/0/1
+ parents: interface GigabitEthernet0/0/0/1
+
+- name: configurable backup path
+ cisco.iosxr.iosxr_config:
+ src: config.cfg
+ backup: yes
+ backup_options:
+ filename: backup.cfg
+ dir_path: /home/user
+"""
+
+RETURN = """
+commands:
+ description: The set of commands that will be pushed to the remote device
+ returned: If there are commands to run against the host
+ type: list
+ sample: ['hostname foo', 'router ospf 1', 'router-id 1.1.1.1']
+backup_path:
+ description: The full path to the backup file
+ returned: when backup is yes
+ type: str
+ sample: /playbooks/ansible/backup/iosxr01_config.2016-07-16@22:28:34
+filename:
+ description: The name of the backup file
+ returned: when backup is yes and filename is not specified in backup options
+ type: str
+ sample: iosxr01_config.2016-07-16@22:28:34
+shortname:
+ description: The full path to the backup file excluding the timestamp
+ returned: when backup is yes and filename is not specified in backup options
+ type: str
+ sample: /playbooks/ansible/backup/iosxr01_config
+date:
+ description: The date extracted from the backup file name
+ returned: when backup is yes
+ type: str
+ sample: "2016-07-16"
+time:
+ description: The time extracted from the backup file name
+ returned: when backup is yes
+ type: str
+ sample: "22:28:34"
+"""
+import os
+import re
+import tempfile
+
+from ansible.module_utils._text import to_bytes, to_text
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import ConnectionError
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import (
+ NetworkConfig,
+ dumps,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ copy_file,
+ get_config,
+ get_connection,
+ load_config,
+)
+
+
+DEFAULT_COMMIT_COMMENT = "configured by iosxr_config"
+
+
+def copy_file_to_node(module):
+ """Copy config file to IOS-XR node. We use SFTP because older IOS-XR versions don't handle SCP very well."""
+ file = tempfile.NamedTemporaryFile("wb", delete=False)
+ src = os.path.realpath(file.name)
+ file.write(to_bytes(module.params["src"], errors="surrogate_or_strict"))
+ file.close()
+
+ dst = "/harddisk:/ansible_config.txt"
+ copy_file(module, src, dst, "sftp")
+
+ os.remove(src)
+
+ return True
+
+
+def check_args(module, warnings):
+ if module.params["comment"]:
+ if len(module.params["comment"]) > 60:
+ module.fail_json(msg="comment argument cannot be more than 60 characters")
+ if module.params["label"]:
+ label = module.params["label"]
+ if len(label) > 30:
+ module.fail_json(msg="label argument cannot be more than 30 characters")
+ if not label[0].isalpha():
+ module.fail_json(msg="label argument must begin with an alphabet")
+ valid_chars = re.match(r"[\w-]*$", label)
+ if not valid_chars:
+ module.fail_json(
+ msg="label argument must only contain alphabets,"
+ + "digits, underscores or hyphens",
+ )
+ if module.params["force"]:
+ warnings.append(
+ "The force argument is deprecated, please use "
+ "match=none instead. This argument will be "
+ "removed in the future",
+ )
+
+
+def get_running_config(module):
+ contents = module.params["config"]
+ if not contents:
+ contents = get_config(module)
+ return contents
+
+
+def get_candidate(module):
+ candidate = ""
+ if module.params["src"]:
+ candidate = module.params["src"]
+ elif module.params["lines"]:
+ candidate_obj = NetworkConfig(indent=1, comment_tokens=["!"])
+ parents = module.params["parents"] or list()
+ candidate_obj.add(module.params["lines"], parents=parents)
+ candidate = dumps(candidate_obj, "raw")
+ return candidate
+
+
+def run(module, result):
+ match = module.params["match"]
+ replace = module.params["replace"]
+ replace_config = replace == "config"
+ path = module.params["parents"]
+ comment = module.params["comment"]
+ admin = module.params["admin"]
+ exclusive = module.params["exclusive"]
+ check_mode = module.check_mode
+ label = module.params["label"]
+
+ candidate_config = get_candidate(module)
+ running_config = get_running_config(module)
+
+ commands = None
+ replace_file_path = None
+ connection = get_connection(module)
+ try:
+ response = connection.get_diff(
+ candidate=candidate_config,
+ running=running_config,
+ diff_match=match,
+ path=path,
+ diff_replace=replace,
+ )
+ except ConnectionError as exc:
+ module.fail_json(msg=to_text(exc, errors="surrogate_then_replace"))
+
+ config_diff = response.get("config_diff")
+
+ if replace_config:
+ running_base_diff_resp = connection.get_diff(
+ candidate=running_config,
+ running=candidate_config,
+ diff_match=match,
+ path=path,
+ diff_replace=replace,
+ )
+ if config_diff or running_base_diff_resp["config_diff"]:
+ ret = copy_file_to_node(module)
+ if not ret:
+ module.fail_json(msg="Copy of config file to the node failed")
+
+ commands = ["load harddisk:/ansible_config.txt"]
+ replace_file_path = "harddisk:/ansible_config.txt"
+
+ if config_diff or commands:
+ if not replace_config:
+ commands = config_diff.split("\n")
+
+ if any((module.params["lines"], module.params["src"])):
+ if module.params["before"]:
+ commands[:0] = module.params["before"]
+
+ if module.params["after"]:
+ commands.extend(module.params["after"])
+
+ result["commands"] = commands
+
+ commit = not check_mode
+ diff = load_config(
+ module,
+ commands,
+ commit=commit,
+ replace=replace_file_path,
+ comment=comment,
+ admin=admin,
+ exclusive=exclusive,
+ label=label,
+ )
+ if diff:
+ result["diff"] = dict(prepared=diff)
+
+ result["changed"] = True
+
+
+def main():
+ """main entry point for module execution"""
+ backup_spec = dict(filename=dict(), dir_path=dict(type="path"))
+ argument_spec = dict(
+ src=dict(type="path"),
+ lines=dict(aliases=["commands"], type="list", elements="str"),
+ parents=dict(type="list", elements="str"),
+ before=dict(type="list", elements="str"),
+ after=dict(type="list", elements="str"),
+ match=dict(default="line", choices=["line", "strict", "exact", "none"]),
+ replace=dict(default="line", choices=["line", "block", "config"]),
+ # this argument is deprecated in favor of setting match: none
+ # it will be removed in a future version
+ force=dict(default=False, type="bool"),
+ config=dict(),
+ backup=dict(type="bool", default=False),
+ backup_options=dict(type="dict", options=backup_spec),
+ comment=dict(default=DEFAULT_COMMIT_COMMENT),
+ admin=dict(type="bool", default=False),
+ disable_default_comment=dict(type="bool", default=False),
+ exclusive=dict(type="bool", default=False),
+ label=dict(),
+ )
+
+ mutually_exclusive = [("lines", "src"), ("parents", "src")]
+
+ required_if = [
+ ("match", "strict", ["lines"]),
+ ("match", "exact", ["lines"]),
+ ("replace", "block", ["lines"]),
+ ("replace", "config", ["src"]),
+ ]
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ mutually_exclusive=mutually_exclusive,
+ required_if=required_if,
+ supports_check_mode=True,
+ )
+
+ if module.params["force"] is True:
+ module.params["match"] = "none"
+ if (
+ module.params["disable_default_comment"] is True
+ and module.params["comment"] == DEFAULT_COMMIT_COMMENT
+ ):
+ module.params["comment"] = None
+ warnings = list()
+
+ check_args(module, warnings)
+
+ result = dict(changed=False, warnings=warnings)
+
+ if module.params["backup"]:
+ result["__backup__"] = get_config(module)
+
+ if any((module.params["src"], module.params["lines"])):
+ run(module, result)
+
+ if result.get("changed") and any((module.params["src"], module.params["lines"])):
+ msg = (
+ "To ensure idempotency and correct diff the input configuration lines should be"
+ " similar to how they appear if present in"
+ " the running configuration on device"
+ )
+ if module.params["src"]:
+ msg += " including the indentation"
+ if "warnings" in result:
+ result["warnings"].append(msg)
+ else:
+ result["warnings"] = msg
+
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_facts.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_facts.py
new file mode 100644
index 00000000..38925b98
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_facts.py
@@ -0,0 +1,217 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+"""
+The module file for iosxr_facts
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_facts
+short_description: Module to collect facts from remote devices.
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+description:
+- Collects facts from network devices running the iosxr operating system. This module
+ places the facts gathered in the fact tree keyed by the respective resource name. The
+ facts module will always collect a base set of facts from the device and can enable
+ or disable collection of additional facts.
+version_added: 1.0.0
+notes:
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+author:
+- Ricardo Carrillo Cruz (@rcarrillocruz)
+- Nilashish Chakraborty (@Nilashishc)
+options:
+ gather_subset:
+ description:
+ - When supplied, this argument will restrict the facts collected to a given subset. Possible
+ values for this argument include all, hardware, config, and interfaces. Can
+ specify a list of values to include a larger subset. Values can also be used
+ with an initial C(!) to specify that a specific subset should not be collected.
+ required: false
+ default: 'min'
+ type: list
+ elements: str
+ gather_network_resources:
+ description:
+ - When supplied, this argument will restrict the facts collected to a given subset.
+ Possible values for this argument include all and the resources like interfaces,
+ lacp etc. Can specify a list of values to include a larger subset. Values can
+ also be used with an initial C(!) to specify that a specific subset should
+ not be collected. Valid subsets are 'all', 'lacp', 'lacp_interfaces', 'lldp_global',
+ 'lldp_interfaces', 'interfaces', 'l2_interfaces', 'l3_interfaces', 'lag_interfaces',
+ 'acls', 'acl_interfaces', 'static_routes', 'ospfv2'.
+ required: false
+ type: list
+ elements: str
+ available_network_resources:
+ description: When 'True' a list of network resources for which resource modules are available will be provided.
+ type: bool
+ default: false
+"""
+
+EXAMPLES = """
+# Gather all facts
+- cisco.iosxr.iosxr_facts:
+ gather_subset: all
+ gather_network_resources: all
+
+# Collect only the config and default facts
+- cisco.iosxr.iosxr_facts:
+ gather_subset:
+ - config
+
+# Do not collect hardware facts
+- cisco.iosxr.iosxr_facts:
+ gather_subset:
+ - '!hardware'
+
+# Collect only the lacp facts
+- cisco.iosxr.iosxr_facts:
+ gather_subset:
+ - '!all'
+ - '!min'
+ gather_network_resources:
+ - lacp
+
+# Do not collect lacp_interfaces facts
+- cisco.iosxr.iosxr_facts:
+ gather_network_resources:
+ - '!lacp_interfaces'
+
+# Collect lacp and minimal default facts
+- cisco.iosxr.iosxr_facts:
+ gather_subset: min
+ gather_network_resources: lacp
+
+# Collect only the interfaces facts
+- cisco.iosxr.iosxr_facts:
+ gather_subset:
+ - '!all'
+ - '!min'
+ gather_network_resources:
+ - interfaces
+ - l2_interfaces
+"""
+
+RETURN = """
+ansible_net_gather_subset:
+ description: The list of fact subsets collected from the device
+ returned: always
+ type: list
+
+# default
+ansible_net_version:
+ description: The operating system version running on the remote device
+ returned: always
+ type: str
+ansible_net_hostname:
+ description: The configured hostname of the device
+ returned: always
+ type: str
+ansible_net_image:
+ description: The image file the device is running
+ returned: always
+ type: str
+ansible_net_api:
+ description: The name of the transport
+ returned: always
+ type: str
+ansible_net_python_version:
+ description: The Python version Ansible controller is using
+ returned: always
+ type: str
+ansible_net_model:
+ description: The model name returned from the device
+ returned: always
+ type: str
+
+# hardware
+ansible_net_filesystems:
+ description: All file system names available on the device
+ returned: when hardware is configured
+ type: list
+ansible_net_memfree_mb:
+ description: The available free memory on the remote device in Mb
+ returned: when hardware is configured
+ type: int
+ansible_net_memtotal_mb:
+ description: The total memory on the remote device in Mb
+ returned: when hardware is configured
+ type: int
+
+# config
+ansible_net_config:
+ description: The current active config from the device
+ returned: when config is configured
+ type: str
+
+# interfaces
+ansible_net_all_ipv4_addresses:
+ description: All IPv4 addresses configured on the device
+ returned: when interfaces is configured
+ type: list
+ansible_net_all_ipv6_addresses:
+ description: All IPv6 addresses configured on the device
+ returned: when interfaces is configured
+ type: list
+ansible_net_interfaces:
+ description: A hash of all interfaces running on the system
+ returned: when interfaces is configured
+ type: dict
+ansible_net_neighbors:
+ description: The list of LLDP neighbors from the remote device
+ returned: when interfaces is configured
+ type: dict
+
+# network resources
+ansible_net_gather_network_resources:
+ description: The list of fact resource subsets collected from the device
+ returned: always
+ type: list
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.facts.facts import (
+ FactsArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.facts.facts import (
+ FACT_RESOURCE_SUBSETS,
+ Facts,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: ansible_facts
+ """
+ argument_spec = FactsArgs.argument_spec
+
+ module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
+
+ warnings = []
+
+ ansible_facts = {}
+ if module.params.get("available_network_resources"):
+ ansible_facts["available_network_resources"] = sorted(FACT_RESOURCE_SUBSETS.keys())
+ result = Facts(module).get_facts()
+ additional_facts, additional_warnings = result
+ ansible_facts.update(additional_facts)
+ warnings.extend(additional_warnings)
+
+ module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_hostname.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_hostname.py
new file mode 100644
index 00000000..a41aaf77
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_hostname.py
@@ -0,0 +1,318 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2022 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+"""
+The module file for iosxr_hostname
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+---
+module: iosxr_hostname
+short_description: Resource module to configure hostname.
+description: This module configures and manages the attributes of hostname on Cisco
+ IOSXR platforms.
+version_added: 2.7.0
+author: Ashwini Mhatre (@amhatre)
+notes:
+- Tested against Cisco Iosxr 7.0.2
+- This module works with connection C(network_cli).
+options:
+ config:
+ description: Hostname configuration.
+ type: dict
+ suboptions:
+ hostname:
+ description: hostname of iosxr box.
+ type: str
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOSXR device by
+ executing the command B(show running-config hostname).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state the configuration should be left in
+ - The states I(rendered), I(gathered) and I(parsed) does not perform any change
+ on the device.
+ - The state I(rendered) will transform the configuration in C(config) option to
+ platform specific CLI commands which will be returned in the I(rendered) key
+ within the result. For state I(rendered) active connection to remote host is
+ not required.
+ - The states I(merged), I(replaced) and I(overridden) have identical
+ behaviour for this module.
+ - The state I(gathered) will fetch the running configuration from device and transform
+ it into structured data in the format as per the resource module argspec and
+ the value is returned in the I(gathered) key within the result.
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into JSON format as per the resource module parameters and the
+ value is returned in the I(parsed) key within the result. The value of C(running_config)
+ option should be the same format as the output of command
+ I(show running-config hostname) executed on device. For state I(parsed) active
+ connection to remote host is not required.
+ choices: [deleted, merged, overridden, replaced, gathered, rendered, parsed]
+ default: merged
+ type: str
+"""
+
+EXAMPLES = """
+# Using state: merged
+# Before state:
+# -------------
+
+#RP/0/RP0/CPU0:ios#show running-config hostname
+#Thu Jan 20 19:48:56.011 UTC
+#hostname ios
+
+# Merged play:
+# ------------
+
+- name: Apply the provided configuration
+ cisco.iosxr.iosxr_hostname:
+ config:
+ hostname: Router1
+ state: merged
+
+# Commands Fired:
+# ---------------
+# "commands": [
+# "hostname Router1",
+# ],
+
+# After state:
+# ------------
+
+# RP/0/0/CPU0:Router1#show running-config hostname
+#Thu Jan 20 19:48:56.011 UTC
+# hostname Router1
+
+
+# Using state: deleted
+# Before state:
+# -------------
+
+# RP/0/0/CPU0:Router1#show running-config hostname
+#Thu Jan 20 19:48:56.011 UTC
+# hostname Router1
+
+# Deleted play:
+# -------------
+
+- name: Remove all existing configuration
+ cisco.iosxr.iosxr_hostname:
+ state: deleted
+
+# Commands Fired:
+# ---------------
+
+# "commands": [
+# "no hostname Router1",
+# ],
+
+# After state:
+# ------------
+#RP/0/RP0/CPU0:ios#show running-config hostname
+#Thu Jan 20 19:55:12.971 UTC
+#hostname ios
+
+# Using state: overridden
+# Before state:
+# -------------
+
+# RP/0/0/CPU0:ios#show running-config hostname
+# hostname ios
+
+# Overridden play:
+# ----------------
+
+- name: Override commands with provided configuration
+ cisco.iosxr.iosxr_hostname:
+ config:
+ hostname: RouterTest
+ state: overridden
+
+# Commands Fired:
+# ---------------
+# "commands": [
+# "hostname RouterTest",
+# ],
+
+# After state:
+# ------------
+
+#RP/0/RP0/CPU0:RouterTest#show running-config hostname
+#Thu Jan 20 19:48:56.011 UTC
+#hostname RouterTest
+
+# Using state: replaced
+# Before state:
+# -------------
+
+#RP/0/RP0/CPU0:RouterTest#show running-config hostname
+#Thu Jan 20 19:48:56.011 UTC
+#hostname RouterTest
+
+# Replaced play:
+# --------------
+
+- name: Replace commands with provided configuration
+ cisco.iosxr.iosxr_hostname:
+ config:
+ hostname: RouterTest
+ state: replaced
+
+# Commands Fired:
+# ---------------
+# "commands": [],
+
+# After state:
+# ------------
+# RP/0/0/CPU0:RouterTest#show running-config hostname
+# hostname RouterTest
+
+# Using state: gathered
+# Before state:
+# -------------
+
+#RP/0/RP0/CPU0:RouterTest#show running-config hostname
+#Thu Jan 20 19:48:56.011 UTC
+#hostname RouterTest
+
+# Gathered play:
+# --------------
+
+- name: Gather listed hostname config
+ cisco.iosxr.iosxr_hostname:
+ state: gathered
+
+# Module Execution Result:
+# ------------------------
+# "gathered": {
+# "hostname": "RouterTest"
+# },
+
+# Using state: rendered
+# Rendered play:
+# --------------
+
+- name: Render the commands for provided configuration
+ cisco.iosxr.iosxr_hostname:
+ config:
+ hostname: RouterTest
+ state: rendered
+
+# Module Execution Result:
+# ------------------------
+# "rendered": [
+# "hostname RouterTest",
+# ]
+
+# Using state: parsed
+# File: parsed.cfg
+# ----------------
+
+# hostname RouterTest
+# Parsed play:
+# ------------
+
+- name: Parse the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_hostname:
+ running_config: "{{ lookup('file', 'parsed.cfg') }}"
+ state: parsed
+
+# Module Execution Result:
+# ------------------------
+# "parsed": {
+# "hostname": "RouterTest"
+# }
+"""
+
+RETURN = """
+before:
+ description: The configuration prior to the module execution.
+ returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged)
+ type: dict
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+after:
+ description: The resulting configuration after module execution.
+ returned: when changed
+ type: dict
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged)
+ type: list
+ sample:
+ - hostname Router1
+rendered:
+ description: The provided configuration in the task rendered in device-native format (offline).
+ returned: when I(state) is C(rendered)
+ type: list
+ sample:
+ - hostname Router1
+gathered:
+ description: Facts about the network resource gathered from the remote device as structured data.
+ returned: when I(state) is C(gathered)
+ type: list
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+parsed:
+ description: The device native config provided in I(running_config) option parsed into structured data as per module argspec.
+ returned: when I(state) is C(parsed)
+ type: list
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.hostname.hostname import (
+ HostnameArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.hostname.hostname import (
+ Hostname,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ module = AnsibleModule(
+ argument_spec=HostnameArgs.argument_spec,
+ mutually_exclusive=[["config", "running_config"]],
+ required_if=[
+ ["state", "merged", ["config"]],
+ ["state", "replaced", ["config"]],
+ ["state", "overridden", ["config"]],
+ ["state", "rendered", ["config"]],
+ ["state", "parsed", ["running_config"]],
+ ],
+ supports_check_mode=True,
+ )
+
+ result = Hostname(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_interfaces.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_interfaces.py
new file mode 100644
index 00000000..b1c169cb
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_interfaces.py
@@ -0,0 +1,559 @@
+#!/usr/bin/python
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+
+"""
+The module file for iosxr_interfaces
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+DOCUMENTATION = """
+module: iosxr_interfaces
+short_description: Resource module to configure interfaces.
+description: This module manages the interface attributes on Cisco IOS-XR network
+ devices.
+version_added: 1.0.0
+author:
+- Sumit Jaiswal (@justjais)
+- Rohit Thakur (@rohitthakur2590)
+notes:
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+options:
+ config:
+ description: A dictionary of interface options
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Full name of the interface to configure in C(type + path) format. e.g. C(GigabitEthernet0/0/0/0)
+ type: str
+ required: true
+ description:
+ description:
+ - Interface description.
+ type: str
+ enabled:
+ default: true
+ description:
+ - Administrative state of the interface.
+ - Set the value to C(True) to administratively enable the interface or C(False)
+ to disable it.
+ type: bool
+ speed:
+ description:
+ - Configure the speed for an interface. Default is auto-negotiation when not
+ configured.
+ type: int
+ mtu:
+ description:
+ - Sets the MTU value for the interface. Applicable for Ethernet interfaces
+ only.
+ - Refer to vendor documentation for valid values.
+ type: int
+ duplex:
+ description:
+ - Configures the interface duplex mode. Default is auto-negotiation when not
+ configured.
+ type: str
+ choices:
+ - full
+ - half
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config interface).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ choices:
+ - merged
+ - parsed
+ - deleted
+ - replaced
+ - rendered
+ - gathered
+ - overridden
+ default: merged
+ description:
+ - The state of the configuration after module completion
+ type: str
+"""
+
+EXAMPLES = """
+# Using merged
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# vrf custB
+# ipv4 address 178.18.169.23 255.255.255.0
+# dot1q native vlan 30
+# !
+# interface GigabitEthernet0/0/0/3
+# description Replaced by Ansible Team
+# mtu 2000
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# dot1q native vlan 1021
+# !
+- name: Configure Ethernet interfaces
+ cisco.iosxr.iosxr_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/2
+ description: Configured by Ansible
+ enabled: true
+ - name: GigabitEthernet0/0/0/3
+ description: Configured by Ansible Network
+ enabled: false
+ duplex: full
+ state: merged
+# After state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# description Configured and Merged by Ansible Network
+# vrf custB
+# ipv4 address 178.18.169.23 255.255.255.0
+# dot1q native vlan 30
+# !
+# interface GigabitEthernet0/0/0/3
+# description Configured and Merged by Ansible Network
+# mtu 2600
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex full
+# shutdown
+# dot1q native vlan 1021
+# !
+# Using replaced
+# Before state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# description Configured by Ansible
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# description Test
+# vrf custB
+# ipv4 address 178.18.169.23 255.255.255.0
+# dot1q native vlan 30
+# !
+# interface GigabitEthernet0/0/0/3
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# dot1q native vlan 1021
+# !
+- name: Configure following interfaces and replace their existing config
+ cisco.iosxr.iosxr_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/2
+ description: Configured by Ansible
+ enabled: true
+ mtu: 2000
+ - name: GigabitEthernet0/0/0/3
+ description: Configured by Ansible Network
+ enabled: false
+ duplex: auto
+ state: replaced
+# After state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# description Configured by Ansible
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# description Configured and Replaced by Ansible
+# mtu 2000
+# vrf custB
+# ipv4 address 178.18.169.23 255.255.255.0
+# dot1q native vlan 30
+# !
+# interface GigabitEthernet0/0/0/3
+# description Configured and Replaced by Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# dot1q native vlan 1021
+# !
+# Using overridden
+# Before state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# description Configured by Ansible
+# vrf custB
+# ipv4 address 178.18.169.23 255.255.255.0
+# dot1q native vlan 30
+# !
+# interface GigabitEthernet0/0/0/3
+# description Configured by Ansible
+# mtu 2600
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex full
+# shutdown
+# dot1q native vlan 1021
+# !
+- name: Override interfaces
+ cisco.iosxr.iosxr_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/2
+ description: Configured by Ansible
+ enabled: true
+ duplex: auto
+ - name: GigabitEthernet0/0/0/3
+ description: Configured by Ansible Network
+ enabled: false
+ speed: 1000
+ state: overridden
+# After state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# description Configured and Overridden by Ansible Network
+# vrf custB
+# ipv4 address 178.18.169.23 255.255.255.0
+# speed 1000
+# dot1q native vlan 30
+# !
+# interface GigabitEthernet0/0/0/3
+# description Configured and Overridden by Ansible Network
+# mtu 2000
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex full
+# shutdown
+# dot1q native vlan 1021
+# !
+# Using deleted
+# Before state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# description Configured and Overridden by Ansible Network
+# vrf custB
+# ipv4 address 178.18.169.23 255.255.255.0
+# speed 1000
+# dot1q native vlan 30
+# !
+# interface GigabitEthernet0/0/0/3
+# description Configured and Overridden by Ansible Network
+# mtu 2000
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex full
+# shutdown
+# dot1q native vlan 1021
+# !
+- name: Delete IOSXR interfaces as in given arguments
+ cisco.iosxr.iosxr_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/2
+ - name: GigabitEthernet0/0/0/3
+ state: deleted
+# After state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# vrf custB
+# ipv4 address 178.18.169.23 255.255.255.0
+# dot1q native vlan 30
+# !
+# interface GigabitEthernet0/0/0/3
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# dot1q native vlan 1021
+# !
+# Using parsed
+# parsed.cfg
+# ------------
+#
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 110
+# ipv4 address 172.31.1.1 255.255.255.0
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# !
+# - name: Convert ACL interfaces config to argspec without connecting to the appliance
+# cisco.iosxr.iosxr_interfaces:
+# running_config: "{{ lookup('file', './parsed.cfg') }}"
+# state: parsed
+# Task Output (redacted)
+# -----------------------
+# "parsed": [
+# {
+# "name": "MgmtEth0/RP0/CPU0/0"
+# },
+# {
+# "access_groups": [
+# {
+# "acls": [
+# {
+# "direction": "in",
+# "name": "acl_1"
+# },
+# {
+# "direction": "out",
+# "name": "acl_2"
+# }
+# ],
+# "afi": "ipv4"
+# },
+# {
+# "acls": [
+# {
+# "direction": "in",
+# "name": "acl6_1"
+# },
+# {
+# "direction": "out",
+# "name": "acl6_2"
+# }
+# ],
+# "afi": "ipv6"
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0"
+# },
+# {
+# "access_groups": [
+# {
+# "acls": [
+# {
+# "direction": "out",
+# "name": "acl_1"
+# }
+# ],
+# "afi": "ipv4"
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/1"
+# }
+# ]
+# }
+# Using rendered
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/0
+ description: Configured and Merged by Ansible-Network
+ mtu: 110
+ enabled: true
+ duplex: half
+ - name: GigabitEthernet0/0/0/1
+ description: Configured and Merged by Ansible-Network
+ mtu: 2800
+ enabled: false
+ speed: 100
+ duplex: full
+ state: rendered
+# Task Output (redacted)
+# -----------------------
+# "rendered": [
+# "interface GigabitEthernet0/0/0/0",
+# "description Configured and Merged by Ansible-Network",
+# "mtu 110",
+# "duplex half",
+# "no shutdown",
+# "interface GigabitEthernet0/0/0/1",
+# "description Configured and Merged by Ansible-Network",
+# "mtu 2800",
+# "speed 100",
+# "duplex full",
+# "shutdown"
+# ]
+# Using gathered
+# Before state:
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config interface
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 110
+# ipv4 address 172.31.1.1 255.255.255.0
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# !
+- name: Gather IOSXR interfaces as in given arguments
+ cisco.iosxr.iosxr_interfaces:
+ config:
+ state: gathered
+# Task Output (redacted)
+# -----------------------
+#
+# "gathered": [
+# {
+# "description": "test for ansible",
+# "enabled": false,
+# "name": "Loopback888"
+# },
+# {
+# "description": "Configured and Merged by Ansible-Network",
+# "duplex": "half",
+# "enabled": true,
+# "mtu": 110,
+# "name": "GigabitEthernet0/0/0/0"
+# },
+# {
+# "enabled": false,
+# "name": "GigabitEthernet0/0/0/3"
+# },
+# {
+# "enabled": false,
+# "name": "GigabitEthernet0/0/0/4"
+# }
+# ]
+# After state:
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config interface
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 110
+# ipv4 address 172.31.1.1 255.255.255.0
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# !
+"""
+
+RETURN = """
+before:
+ description: The configuration as structured data prior to module invocation.
+ returned: always
+ type: list
+ sample: The configuration returned will always be in the same format of the parameters above.
+after:
+ description: The configuration as structured data after module completion.
+ returned: when changed
+ type: list
+ sample: The configuration returned will always be in the same format of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device
+ returned: always
+ type: list
+ sample: ['interface GigabitEthernet0/0/0/2', 'description: Configured by Ansible', 'shutdown']
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.interfaces.interfaces import (
+ InterfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.interfaces.interfaces import (
+ Interfaces,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=InterfacesArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = Interfaces(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_l2_interfaces.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_l2_interfaces.py
new file mode 100644
index 00000000..2c5da2d4
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_l2_interfaces.py
@@ -0,0 +1,706 @@
+#!/usr/bin/python
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+GENERATOR_VERSION = "1.0"
+
+
+DOCUMENTATION = """
+module: iosxr_l2_interfaces
+short_description: Resource Module to configure L2 interfaces.
+description: This module manages the Layer-2 interface attributes on Cisco IOS-XR
+ devices.
+version_added: 1.0.0
+author:
+- Sumit Jaiswal (@justjais)
+- Rohit Thakur (@rohitthakur2590)
+notes:
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+options:
+ config:
+ description: A dictionary of Layer-2 interface options
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Full name of the interface/sub-interface excluding any logical unit number,
+ e.g. GigabitEthernet0/0/0/1 or GigabitEthernet0/0/0/1.100.
+ type: str
+ required: true
+ native_vlan:
+ description:
+ - Configure a native VLAN ID for the trunk
+ type: int
+ l2transport:
+ description:
+ - Switchport mode access command to configure the interface as a layer 2 access
+ type: bool
+ l2protocol:
+ description:
+ - Configures Layer 2 protocol tunneling and protocol data unit (PDU) filtering
+ on an interface.
+ type: list
+ elements: dict
+ suboptions:
+ cdp:
+ description:
+ - Cisco Discovery Protocol (CDP) tunneling and data unit parameters.
+ choices:
+ - drop
+ - forward
+ - tunnel
+ type: str
+ pvst:
+ description:
+ - Configures the per-VLAN Spanning Tree Protocol (PVST) tunneling and
+ data unit parameters.
+ choices:
+ - drop
+ - forward
+ - tunnel
+ type: str
+ stp:
+ description:
+ - Spanning Tree Protocol (STP) tunneling and data unit parameters.
+ choices:
+ - drop
+ - forward
+ - tunnel
+ type: str
+ vtp:
+ description:
+ - VLAN Trunk Protocol (VTP) tunneling and data unit parameters.
+ choices:
+ - drop
+ - forward
+ - tunnel
+ type: str
+ cpsv:
+ description:
+ - CDP, PVST+, STP, and VTP protocols.
+ choices:
+ - drop
+ - reverse-tunnel
+ - tunnel
+ type: str
+ encapsulation:
+ description: Specify which packets will be matched by this sub-interface.
+ type: dict
+ suboptions:
+ dot1q:
+ type: int
+ description: IEEE 802.1Q VLAN-tagged packets.
+ second_dot1q:
+ type: int
+ description: IEEE 802.1Q VLAN-tagged packets.
+ q_vlan:
+ description:
+ - 802.1Q VLAN configuration. Note that it can accept either 2 VLAN IDs when
+ configuring Q-in-Q VLAN, or it will accept 1 VLAN ID and 'any' as input
+ list when configuring Q-in-any vlan as input. Note, that this option is
+ valid only with respect to Sub-Interface and is not valid when configuring
+ for Interface.
+ type: list
+ elements: int
+ propagate:
+ description:
+ - Propagate Layer 2 transport events. Note that it will work only when the
+ I(l2tranport) option is set to TRUE
+ type: bool
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config interface).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - rendered
+ - gathered
+ - parsed
+ default: merged
+ description:
+ - The state of the configuration after module completion
+ type: str
+"""
+
+EXAMPLES = """
+# Using merged
+#
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# !
+
+- name: Merge provided configuration with device configuration
+ cisco.iosxr.iosxr_l2_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/3
+ native_vlan: 20
+ - name: GigabitEthernet0/0/0/4
+ native_vlan: 40
+ l2transport: true
+ l2protocol:
+ - stp: tunnel
+ - name: GigabitEthernet0/0/0/3.900
+ l2transport: true
+ q_vlan:
+ - 20
+ - 40
+ state: merged
+
+# After state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# dot1q native vlan 20
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# dot1q native vlan 10
+# l2transport
+# l2protocol stp tunnel
+# !
+# !
+# interface GigabitEthernet0/0/0/3.900 l2transport
+# dot1q vlan 20 40
+# !
+
+# Using replaced
+#
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# dot1q native vlan 20
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# dot1q native vlan 10
+# l2transport
+# l2protocol stp tunnel
+# !
+# !
+# interface GigabitEthernet0/0/0/3.900 l2transport
+# dot1q vlan 20 40
+# !
+
+- name: Replaces device configuration of listed interfaces with provided configuration
+ cisco.iosxr.iosxr_l2_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/4
+ native_vlan: 40
+ l2transport: true
+ l2protocol:
+ - stp: forward
+ - name: GigabitEthernet0/0/0/3.900
+ q_vlan:
+ - 20
+ - any
+ state: replaced
+
+# After state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# dot1q native vlan 20
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# dot1q native vlan 40
+# l2transport
+# l2protocol stp forward
+# !
+# !
+# interface GigabitEthernet0/0/0/3.900 l2transport
+# dot1q vlan 20 any
+# !
+
+# Using overridden
+#
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# dot1q native vlan 20
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# dot1q native vlan 10
+# l2transport
+# l2protocol stp tunnel
+# !
+# !
+# interface GigabitEthernet0/0/0/3.900 l2transport
+# dot1q vlan 20 40
+# !
+
+- name: Override device configuration of all interfaces with provided configuration
+ cisco.iosxr.iosxr_l2_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/4
+ native_vlan: 40
+ l2transport: true
+ l2protocol:
+ - stp: forward
+ - name: GigabitEthernet0/0/0/3.900
+ q_vlan:
+ - 20
+ - any
+ state: overridden
+
+# After state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# dot1q native vlan 40
+# l2transport
+# l2protocol stp forward
+# !
+# !
+# interface GigabitEthernet0/0/0/3.900
+# dot1q vlan 20 any
+# !
+
+# Using deleted
+#
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# dot1q native vlan 20
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# dot1q native vlan 10
+# l2transport
+# l2protocol stp tunnel
+# !
+# !
+#
+
+- name: "Delete L2 attributes of given interfaces (Note: This won't delete the interface itself)"
+ cisco.iosxr.iosxr_l2_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/4
+ state: deleted
+
+# After state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# dot1q native vlan 20
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# !
+
+# Using Deleted without any config passed
+# "(NOTE: This will delete all of configured resource module attributes from each configured interface)"
+#
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# dot1q native vlan 20
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# dot1q native vlan 10
+# l2transport
+# l2protocol stp tunnel
+# !
+# !
+
+- name: "Delete L2 attributes of all interfaces (Note: This won't delete the interface itself)"
+ cisco.iosxr.iosxr_l2_interfaces:
+ state: deleted
+
+# After state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/3
+# description Ansible Network
+# vrf custB
+# ipv4 address 10.10.0.2 255.255.255.0
+# duplex half
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# description Test description
+# !
+
+
+# Using parsed
+# parsed.cfg
+# ------------
+#
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 110
+# ipv4 address 172.31.1.1 255.255.255.0
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/1
+# dot1q native vlan 10
+# l2transport
+# l2protocol cdp forward
+# l2protocol pvst tunnel
+# propagate remote-status
+# !
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.900
+# encapsulation dot1q 20 second-dot1q 40
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# dot1q native vlan 40
+# !
+- name: Convert L2 interfaces config to argspec without connecting to the appliance
+ cisco.iosxr.iosxr_l2_interfaces:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+# Task Output (redacted)
+# -----------------------
+# "parsed": [
+# {
+# "name": "GigabitEthernet0/0/0/0"
+# },
+# {
+# "l2protocol": [
+# {
+# "cdp": "forward"
+# },
+# {
+# "pvst": "tunnel"
+# }
+# ],
+# "l2transport": true,
+# "name": "GigabitEthernet0/0/0/1",
+# "native_vlan": 10,
+# "propagate": true
+# },
+# {
+# "name": "GigabitEthernet0/0/0/3"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/3.900",
+# "q_vlan": [
+# 20,
+# 40
+# ]
+# },
+# {
+# "name": "GigabitEthernet0/0/0/4",
+# "native_vlan": 40
+# }
+# ]
+
+
+# Using rendered
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_l2_interfaces:
+ config:
+
+ - name: GigabitEthernet0/0/0/1
+ native_vlan: 10
+ l2transport: true
+ l2protocol:
+
+ - pvst: tunnel
+
+ - cdp: forward
+ propagate: true
+
+ - name: GigabitEthernet0/0/0/3.900
+ q_vlan:
+ - 20
+ - 40
+
+ - name: GigabitEthernet0/0/0/4
+ native_vlan: 40
+ state: rendered
+# Task Output (redacted)
+# -----------------------
+# "rendered": [
+# "interface GigabitEthernet0/0/0/1",
+# "dot1q native vlan 10",
+# "l2transport l2protocol pvst tunnel",
+# "l2transport l2protocol cdp forward",
+# "l2transport propagate remote-status",
+# "interface GigabitEthernet0/0/0/3.900",
+# "dot1q vlan 20 40",
+# "interface GigabitEthernet0/0/0/4",
+# "dot1q native vlan 40"
+# ]
+
+
+# Using gathered
+# Before state:
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config interface
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 110
+# ipv4 address 172.31.1.1 255.255.255.0
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/1
+# dot1q native vlan 10
+# l2transport
+# l2protocol cdp forward
+# l2protocol pvst tunnel
+# propagate remote-status
+# !
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.900
+# encapsulation dot1q 20 second-dot1q 40
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# dot1q native vlan 40
+# !
+- name: Gather IOSXR l2 interfaces as in given arguments
+ cisco.iosxr.iosxr_l2_interfaces:
+ config:
+ state: gathered
+# Task Output (redacted)
+# -----------------------
+#
+# "gathered": [
+# {
+# "name": "GigabitEthernet0/0/0/0"
+# },
+# {
+# "l2protocol": [
+# {
+# "cdp": "forward"
+# },
+# {
+# "pvst": "tunnel"
+# }
+# ],
+# "l2transport": true,
+# "name": "GigabitEthernet0/0/0/1",
+# "native_vlan": 10,
+# "propagate": true
+# },
+# {
+# "name": "GigabitEthernet0/0/0/3"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/3.900",
+# "q_vlan": [
+# 20,
+# 40
+# ]
+# },
+# {
+# "name": "GigabitEthernet0/0/0/4",
+# "native_vlan": 40
+# }
+# ]
+# After state:
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config interface
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 110
+# ipv4 address 172.31.1.1 255.255.255.0
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/1
+# dot1q native vlan 10
+# l2transport
+# l2protocol cdp forward
+# l2protocol pvst tunnel
+# propagate remote-status
+# !
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.900
+# encapsulation dot1q 20 second-dot1q 40
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# dot1q native vlan 40
+# !
+
+
+
+"""
+
+RETURN = """
+before:
+ description: The configuration as structured data prior to module invocation.
+ returned: always
+ type: list
+ sample: The configuration returned will always be in the same format of the parameters above.
+after:
+ description: The configuration as structured data after module completion.
+ returned: when changed
+ type: list
+ sample: The configuration returned will always be in the same format of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device
+ returned: always
+ type: list
+ sample: ['interface GigabitEthernet0/0/0/2', 'l2transport l2protocol pvst tunnel']
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.l2_interfaces.l2_interfaces import (
+ L2_InterfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.l2_interfaces.l2_interfaces import (
+ L2_Interfaces,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=L2_InterfacesArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = L2_Interfaces(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_l3_interfaces.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_l3_interfaces.py
new file mode 100644
index 00000000..98785f6b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_l3_interfaces.py
@@ -0,0 +1,672 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat Inc.
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+##############################################
+# WARNING
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#
+##############################################
+
+"""
+The module file for ios_l3_interfaces
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_l3_interfaces
+short_description: Resource module to configure L3 interfaces.
+description: This module provides declarative management of Layer-3 interface on Cisco
+ IOS-XR devices.
+version_added: 1.0.0
+author:
+- Sumit Jaiswal (@justjais)
+- Rohit Thakur (@rohitthakur2590)
+notes:
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+options:
+ config:
+ description: A dictionary of Layer-3 interface options
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Full name of the interface excluding any logical unit number, i.e. GigabitEthernet0/1.
+ type: str
+ required: true
+ ipv4:
+ description:
+ - IPv4 address to be set for the Layer-3 interface mentioned in I(name) option.
+ - The address format is <ipv4 address>/<mask>, the mask is number in range
+ 0-32 eg. 192.168.0.1/24
+ type: list
+ elements: dict
+ suboptions:
+ address:
+ description:
+ - Configures the IPv4 address for Interface.
+ type: str
+ secondary:
+ description:
+ - Configures the IP address as a secondary address.
+ type: bool
+ ipv6:
+ description:
+ - IPv6 address to be set for the Layer-3 interface mentioned in I(name) option.
+ - The address format is <ipv6 address>/<mask>, the mask is number in range
+ 0-128 eg. fd5d:12c9:2201:1::1/64
+ type: list
+ elements: dict
+ suboptions:
+ address:
+ description:
+ - Configures the IPv6 address for Interface.
+ type: str
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config interface).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - parsed
+ - rendered
+ - gathered
+ default: merged
+ description:
+ - The state of the configuration after module completion
+ type: str
+"""
+
+EXAMPLES = """
+# Using merged
+
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv4 address 192.168.0.2 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# !
+# interface GigabitEthernet0/0/0/4
+# ipv6 address fd5d:12c9:2201:1::1/64
+# shutdown
+# !
+
+- name: Merge provided configuration with device configuration
+ cisco.iosxr.iosxr_l3_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/2
+ ipv4:
+ - address: 192.168.0.1/24
+ - name: GigabitEthernet0/0/0/3
+ ipv4:
+ - address: 192.168.2.1/24
+ secondary: true
+ state: merged
+
+# After state:
+# ------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# ipv4 address 192.168.0.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv4 address 192.168.1.0 255.255.255.0
+# ipv4 address 192.168.2.1 255.255.255.0 secondary
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# !
+# interface GigabitEthernet0/0/0/4
+# ipv6 address fd5d:12c9:2201:1::1/64
+# shutdown
+# !
+
+# Using overridden
+
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# ipv4 address 192.168.0.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv4 address 192.168.1.0 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# !
+# interface GigabitEthernet0/0/0/4
+# ipv6 address fd5d:12c9:2201:1::1/64
+# shutdown
+# !
+
+- name: Override device configuration of all interfaces with provided configuration
+ cisco.iosxr.iosxr_l3_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/3
+ ipv4:
+ - address: 192.168.0.1/24
+ - name: GigabitEthernet0/0/0/3.700
+ ipv4:
+ - address: 192.168.0.2/24
+ - address: 192.168.2.1/24
+ secondary: true
+ state: overridden
+
+# After state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv4 address 192.168.0.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# ipv4 address 192.168.0.2 255.255.255.0
+# ipv4 address 192.168.2.1 255.255.255.0 secondary
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# !
+
+# Using replaced
+
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv4 address 192.168.0.2 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# ipv4 address 192.168.0.1 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/4
+# ipv6 address fd5d:12c9:2201:1::1/64
+# shutdown
+# !
+
+- name: Replaces device configuration of listed interfaces with provided configuration
+ cisco.iosxr.iosxr_l3_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/3
+ ipv6:
+ - address: fd5d:12c9:2201:1::1/64
+ - name: GigabitEthernet0/0/0/4
+ ipv4:
+ - address: 192.168.0.2/24
+ state: replaced
+
+# After state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv6 address fd5d:12c9:2201:1::1/64
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# ipv4 address 192.168.0.1 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/4
+# ipv4 address 192.168.0.2 255.255.255.0
+# shutdown
+# !
+
+# Using deleted
+
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# ipv4 address 192.168.2.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# ipv4 address 192.168.3.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv4 address 192.168.0.2 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# ipv4 address 192.168.0.1 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/4
+# ipv6 address fd5d:12c9:2201:1::1/64
+# shutdown
+# !
+
+- name: "Delete L3 attributes of given interfaces (Note: This won't delete the interface itself)"
+ cisco.iosxr.iosxr_l3_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/3
+ - name: GigabitEthernet0/0/0/4
+ - name: GigabitEthernet0/0/0/3.700
+ state: deleted
+
+# After state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# ipv4 address 192.168.2.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# ipv4 address 192.168.3.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# !
+
+# Using Deleted without any config passed
+# "(NOTE: This will delete all of configured resource module attributes from each configured interface)"
+
+# Before state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# ipv4 address 192.168.2.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# ipv4 address 192.168.3.1 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv4 address 192.168.0.2 255.255.255.0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# ipv4 address 192.168.0.1 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/4
+# ipv6 address fd5d:12c9:2201:1::1/64
+# shutdown
+# !
+
+
+- name: "Delete L3 attributes of all interfaces (Note: This won't delete the interface itself)"
+ cisco.iosxr.iosxr_l3_interfaces:
+ state: deleted
+
+# After state:
+# -------------
+#
+# viosxr#show running-config interface
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3.700
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# !
+
+
+# Using parsed
+# parsed.cfg
+# ------------
+#
+# nterface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 66
+# ipv4 address 192.0.2.1 255.255.255.0
+# ipv4 address 192.0.2.2 255.255.255.0 secondary
+# ipv6 address 2001:db8:0:3::/64
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/1
+# description Configured and Merged by Ansible-Network
+# mtu 66
+# speed 100
+# duplex full
+# dot1q native vlan 10
+# l2transport
+# l2protocol cdp forward
+# l2protocol pvst tunnel
+# propagate remote-status
+# !
+# !
+# interface GigabitEthernet0/0/0/3
+# ipv4 address 192.0.22.1 255.255.255.0
+# ipv4 address 192.0.23.1 255.255.255.0
+# !
+# - name: Convert L3 interfaces config to argspec without connecting to the appliance
+# cisco.iosxr.iosxr_l3_interfaces:
+# running_config: "{{ lookup('file', './parsed.cfg') }}"
+# state: parsed
+# Task Output (redacted)
+# -----------------------
+# "parsed": [
+# {
+# "ipv4": [
+# {
+# "address": "192.0.2.1 255.255.255.0"
+# },
+# {
+# "address": "192.0.2.2 255.255.255.0",
+# "secondary": true
+# }
+# ],
+# "ipv6": [
+# {
+# "address": "2001:db8:0:3::/64"
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/1"
+# },
+# {
+# "ipv4": [
+# {
+# "address": "192.0.22.1 255.255.255.0"
+# },
+# {
+# "address": "192.0.23.1 255.255.255.0"
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/3"
+# }
+# ]
+
+
+# Using rendered
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_l3_interfaces:
+ config:
+
+ - name: GigabitEthernet0/0/0/0
+ ipv4:
+
+ - address: 198.51.100.1/24
+
+ - name: GigabitEthernet0/0/0/1
+ ipv6:
+
+ - address: 2001:db8:0:3::/64
+ ipv4:
+
+ - address: 192.0.2.1/24
+
+ - address: 192.0.2.2/24
+ secondary: true
+ state: rendered
+# Task Output (redacted)
+# -----------------------
+# "rendered": [
+# "interface GigabitEthernet0/0/0/0",
+# "ipv4 address 198.51.100.1 255.255.255.0",
+# "interface GigabitEthernet0/0/0/1",
+# "ipv4 address 192.0.2.2 255.255.255.0 secondary",
+# "ipv4 address 192.0.2.1 255.255.255.0",
+# "ipv6 address 2001:db8:0:3::/64"
+# ]
+# Using gathered
+# Before state:
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config interface
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 66
+# ipv4 address 192.0.2.1 255.255.255.0
+# ipv4 address 192.0.2.2 255.255.255.0 secondary
+# ipv6 address 2001:db8:0:3::/64
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/1
+# description Configured and Merged by Ansible-Network
+# mtu 66
+# speed 100
+# duplex full
+# dot1q native vlan 10
+# l2transport
+# l2protocol cdp forward
+# l2protocol pvst tunnel
+# propagate remote-status
+# !
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# dot1q native vlan 40
+# !
+- name: Gather IOSXR l3 interfaces as in given arguments
+ cisco.iosxr.iosxr_l3_interfaces:
+ config:
+ state: gathered
+# Task Output (redacted)
+# -----------------------
+#
+# "gathered": [
+# {
+# "name": "Loopback888"
+# },
+# {
+# "ipv4": [
+# {
+# "address": "192.0.2.1 255.255.255.0"
+# },
+# {
+# "address": "192.0.2.2 255.255.255.0",
+# "secondary": true
+# }
+# ],
+# "ipv6": [
+# {
+# "address": "2001:db8:0:3::/64"
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/1"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/3"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/4"
+# }
+# ]
+# After state:
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config interface
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.70 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# description Configured and Merged by Ansible-Network
+# mtu 66
+# ipv4 address 192.0.2.1 255.255.255.0
+# ipv4 address 192.0.2.2 255.255.255.0 secondary
+# ipv6 address 2001:db8:0:3::/64
+# duplex half
+# !
+# interface GigabitEthernet0/0/0/1
+# description Configured and Merged by Ansible-Network
+# mtu 66
+# speed 100
+# duplex full
+# dot1q native vlan 10
+# l2transport
+# l2protocol cdp forward
+# l2protocol pvst tunnel
+# propagate remote-status
+# !
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# dot1q native vlan 40
+# !
+
+
+"""
+
+RETURN = """
+before:
+ description: The configuration as structured data prior to module invocation.
+ returned: always
+ type: list
+ sample: The configuration returned will always be in the same format of the parameters above.
+after:
+ description: The configuration as structured data after module completion.
+ returned: when changed
+ type: list
+ sample: The configuration returned will always be in the same format of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device
+ returned: always
+ type: list
+ sample: ['interface GigabitEthernet0/0/0/1', 'ipv4 address 192.168.0.1 255.255.255.0']
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.l3_interfaces.l3_interfaces import (
+ L3_InterfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.l3_interfaces.l3_interfaces import (
+ L3_Interfaces,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=L3_InterfacesArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = L3_Interfaces(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lacp.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lacp.py
new file mode 100644
index 00000000..7d54d992
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lacp.py
@@ -0,0 +1,391 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_lacp
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_lacp
+short_description: Resource module to configure LACP.
+description:
+- This module manages Global Link Aggregation Control Protocol (LACP) on IOS-XR devices.
+version_added: 1.0.0
+author:
+- Nilashish Chakraborty (@nilashishc)
+- Rohit Thakur (@rohitthakur2590)
+notes:
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+options:
+ config:
+ description: The provided configurations.
+ type: dict
+ suboptions:
+ system:
+ description: This option sets the default system parameters for LACP bundles.
+ type: dict
+ suboptions:
+ priority:
+ description:
+ - The system priority to use in LACP negotiations.
+ - Lower value is higher priority.
+ - Refer to vendor documentation for valid values.
+ type: int
+ mac:
+ type: dict
+ description:
+ - The system MAC related configuration for LACP.
+ suboptions:
+ address:
+ description:
+ - The system ID to use in LACP negotiations.
+ type: str
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config lacp).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state of the configuration after module completion.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - deleted
+ - parsed
+ - rendered
+ - gathered
+ default: merged
+"""
+EXAMPLES = """
+# Using merged
+#
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:iosxr01#show running-config lacp
+# Tue Jul 16 17:46:08.147 UTC
+# % No such configuration item(s)
+#
+#
+
+- name: Merge provided configuration with device configuration
+ cisco.iosxr.iosxr_lacp:
+ config:
+ system:
+ priority: 10
+ mac:
+ address: 00c1.4c00.bd15
+ state: merged
+
+#
+#
+# -----------------------
+# Module Execution Result
+# -----------------------
+#
+# "before": {}
+#
+#
+# "commands": [
+# "lacp system priority 10",
+# "lacp system mac 00c1.4c00.bd15"
+# ]
+#
+#
+# "after": {
+# "system": {
+# "mac": {
+# "address": "00c1.4c00.bd15"
+# },
+# "priority": 10
+# }
+# }
+#
+# -----------
+# After state
+# -----------
+#
+#
+# RP/0/0/CPU0:iosxr01#sh run lacp
+# Tue Jul 16 17:51:29.365 UTC
+# lacp system mac 00c1.4c00.bd15
+# lacp system priority 10
+#
+#
+
+# Using replaced
+#
+#
+# -------------
+# Before state
+# -------------
+#
+#
+# RP/0/0/CPU0:iosxr01#sh run lacp
+# Tue Jul 16 17:53:59.904 UTC
+# lacp system mac 00c1.4c00.bd15
+# lacp system priority 10
+#
+
+- name: Replace device global lacp configuration with the given configuration
+ cisco.iosxr.iosxr_lacp:
+ config:
+ system:
+ priority: 11
+ state: replaced
+#
+#
+# -----------------------
+# Module Execution Result
+# -----------------------
+# "before": {
+# "system": {
+# "mac": {
+# "address": "00c1.4c00.bd15"
+# },
+# "priority": 10
+# }
+# }
+#
+#
+# "commands": [
+# "no lacp system mac",
+# "lacp system priority 11"
+# ]
+#
+#
+# "after": {
+# "system": {
+# "priority": 11
+# }
+# }
+#
+# -----------
+# After state
+# -----------
+#
+#
+# RP/0/0/CPU0:iosxr01#sh run lacp
+# Tue Jul 16 18:02:40.379 UTC
+# lacp system priority 11
+#
+#
+
+# Using deleted
+#
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:iosxr01#sh run lacp
+# Tue Jul 16 18:37:09.727 UTC
+# lacp system mac 00c1.4c00.bd15
+# lacp system priority 11
+#
+#
+
+- name: Delete global LACP configurations from the device
+ cisco.iosxr.iosxr_lacp:
+ state: deleted
+
+#
+#
+# -----------------------
+# Module Execution Result
+# -----------------------
+# "before": {
+# "system": {
+# "mac": {
+# "address": "00c1.4c00.bd15"
+# },
+# "priority": 11
+# }
+# }
+#
+#
+# "commands": [
+# "no lacp system mac",
+# "no lacp system priority"
+# ]
+#
+#
+# "after": {}
+#
+# ------------
+# After state
+# ------------
+#
+#
+# RP/0/0/CPU0:iosxr01#sh run lacp
+# Tue Jul 16 18:39:44.116 UTC
+# % No such configuration item(s)
+#
+#
+
+
+# Using parsed
+# parsed.cfg
+# ------------
+#
+# lacp system mac 00c1.4c00.bd15
+# lacp system priority 11
+# - name: Convert LACP config to argspec without connecting to the appliance
+# cisco.iosxr.iosxr_lacp:
+# running_config: "{{ lookup('file', './parsed.cfg') }}"
+# state: parsed
+# Task Output (redacted)
+# -----------------------
+# "parsed": {
+# "system": {
+# "mac": {
+# "address": "00c1.4c00.bd15"
+# },
+# "priority": 11
+# }
+# }
+
+
+# Using rendered
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_lacp:
+ config:
+ system:
+ priority: 11
+ mac:
+ address: 00c1.4c00.bd15
+ state: rendered
+# Task Output (redacted)
+# -----------------------
+# "rendered": [
+# "lacp system priority 11",
+# "lacp system mac 00c1.4c00.bd15"
+# ]
+
+
+# Using gathered
+# Before state:
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config lacp
+# lacp system mac 00c1.4c00.bd15
+# lacp system priority 11
+- name: Gather IOSXR LACP configuration
+ cisco.iosxr.iosxr_lacp:
+ config:
+ state: gathered
+# Task Output (redacted)
+# -----------------------
+#
+# "gathered": {
+# "system": {
+# "mac": {
+# "address": "00c1.4c00.bd15"
+# },
+# "priority": 11
+# }
+# }
+# After state:
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config lacp
+# lacp system mac 00c1.4c00.bd15
+# lacp system priority
+
+
+"""
+RETURN = """
+before:
+ description: The configuration as structured data prior to module invocation.
+ returned: always
+ type: dict
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The configuration as structured data after module completion.
+ returned: when changed
+ type: dict
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample: ['lacp system priority 10', 'lacp system mac 00c1.4c00.bd15']
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lacp.lacp import (
+ LacpArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.lacp.lacp import Lacp
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=LacpArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = Lacp(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lacp_interfaces.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lacp_interfaces.py
new file mode 100644
index 00000000..1ebeaae8
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lacp_interfaces.py
@@ -0,0 +1,653 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_lacp_interfaces
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_lacp_interfaces
+short_description: Resource module to configure LACP interfaces.
+description:
+- This module manages Link Aggregation Control Protocol (LACP) attributes of interfaces
+ on IOS-XR devices.
+version_added: 1.0.0
+notes:
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+author: Nilashish Chakraborty (@nilashishc)
+options:
+ config:
+ description: A dictionary of LACP interfaces options.
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Name/Identifier of the interface or Ether-Bundle.
+ type: str
+ churn_logging:
+ description:
+ - Specifies the parameter for logging of LACP churn events.
+ - Valid only for ether-bundles.
+ - Mode 'actor' logs actor churn events only.
+ - Mode 'partner' logs partner churn events only.
+ - Mode 'both' logs actor and partner churn events only.
+ type: str
+ choices:
+ - actor
+ - partner
+ - both
+ collector_max_delay:
+ description:
+ - Specifies the collector max delay to be signaled to the LACP partner.
+ - Valid only for ether-bundles.
+ - Refer to vendor documentation for valid values.
+ type: int
+ period:
+ description:
+ - Specifies the rate at which packets are sent or received.
+ - For ether-bundles, this specifies the period to be used by its member links.
+ - Refer to vendor documentation for valid values.
+ type: int
+ switchover_suppress_flaps:
+ description:
+ - Specifies the time for which to suppress flaps during a LACP switchover.
+ - Valid only for ether-bundles.
+ - Refer to vendor documentation for valid values.
+ type: int
+ system:
+ description:
+ - This dict object contains configurable options related to LACP system parameters
+ for ether-bundles.
+ type: dict
+ suboptions:
+ priority:
+ description:
+ - Specifies the system priority to use in LACP negotiations for the bundle.
+ - Refer to vendor documentation for valid values.
+ type: int
+ mac:
+ description:
+ - Specifies the system ID to use in LACP negotiations for the bundle,
+ encoded as a MAC address.
+ type: str
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config int).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state of the configuration after module completion.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - parsed
+ - gathered
+ - rendered
+ default: merged
+
+"""
+EXAMPLES = """
+# Using merged
+#
+#
+# ------------
+# Before state
+# ------------
+#
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh running-config interface
+# Sun Jul 21 18:01:35.079 UTC
+# interface Bundle-Ether10
+# !
+# interface Bundle-Ether11
+# !
+# interface Bundle-Ether12
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1'
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+#
+
+- name: Merge provided configuration with device configuration
+ cisco.iosxr.iosxr_lacp_interfaces:
+ config:
+ - name: Bundle-Ether10
+ churn_logging: actor
+ collector_max_delay: 100
+ switchover_suppress_flaps: 500
+
+ - name: Bundle-Ether11
+ system:
+ mac: 00c2.4c00.bd15
+
+ - name: GigabitEthernet0/0/0/1
+ period: 200
+ state: merged
+
+#
+#
+# -----------
+# After state
+# -----------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run int
+# Sun Jul 21 18:24:52.413 UTC
+# interface Bundle-Ether10
+# lacp churn logging actor
+# lacp switchover suppress-flaps 500
+# lacp collector-max-delay 100
+# !
+# interface Bundle-Ether11
+# lacp system mac 00c2.4c00.bd15
+# !
+# interface Bundle-Ether12
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# lacp period 200
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+
+
+# Using replaced
+#
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run int
+# Sun Jul 21 18:24:52.413 UTC
+# interface Bundle-Ether10
+# lacp churn logging actor
+# lacp switchover suppress-flaps 500
+# lacp collector-max-delay 100
+# !
+# interface Bundle-Ether11
+# lacp system mac 00c2.4c00.bd15
+# !
+# interface Bundle-Ether12
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# lacp period 200
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+
+- name: Replace LACP configuration of listed interfaces with provided configuration
+ cisco.iosxr.iosxr_lacp_interfaces:
+ config:
+ - name: Bundle-Ether10
+ churn_logging: partner
+
+ - name: GigabitEthernet0/0/0/2
+ period: 300
+ state: replaced
+
+#
+#
+# -----------
+# After state
+# -----------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run int
+# Sun Jul 21 18:50:21.929 UTC
+# interface Bundle-Ether10
+# lacp churn logging partner
+# !
+# interface Bundle-Ether11
+# lacp system mac 00c2.4c00.bd15
+# !
+# interface Bundle-Ether12
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# lacp period 200
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# lacp period 300
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+#
+
+
+# Using overridden
+#
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run int
+# Sun Jul 21 18:24:52.413 UTC
+# interface Bundle-Ether10
+# lacp churn logging actor
+# lacp switchover suppress-flaps 500
+# lacp collector-max-delay 100
+# !
+# interface Bundle-Ether11
+# lacp system mac 00c2.4c00.bd15
+# !
+# interface Bundle-Ether12
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# lacp period 200
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# lacp period 200
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+#
+
+- name: Override all interface LACP configuration with provided configuration
+ cisco.iosxr.iosxr_lacp_interfaces:
+ config:
+ - name: Bundle-Ether12
+ churn_logging: both
+ collector_max_delay: 100
+ switchover_suppress_flaps: 500
+
+ - name: GigabitEthernet0/0/0/1
+ period: 300
+ state: overridden
+
+#
+#
+# -----------
+# After state
+# -----------
+#
+#
+# RP/0/0/CPU0:an-iosxr(config-if)#do sh run int
+# Sun Jul 21 19:32:36.115 UTC
+# interface Bundle-Ether10
+# !
+# interface Bundle-Ether11
+# !
+# interface Bundle-Ether12
+# lacp churn logging both
+# lacp switchover suppress-flaps 500
+# lacp collector-max-delay 100
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# lacp period 300
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+
+
+# Using deleted
+#
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run int
+# Sun Jul 21 18:24:52.413 UTC
+# interface Bundle-Ether10
+# lacp churn logging actor
+# lacp switchover suppress-flaps 500
+# lacp collector-max-delay 100
+# !
+# interface Bundle-Ether11
+# lacp non-revertive
+# !
+# interface Bundle-Ether12
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# lacp period 200
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# lacp period 300
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+
+- name: Deleted LACP configurations of provided interfaces (Note - This won't delete
+ the interface itself)
+ cisco.iosxr.iosxr_lacp_interfaces:
+ config:
+ - name: Bundle-Ether10
+ - name: Bundle-Ether11
+ - name: GigabitEthernet0/0/0/1
+ - name: GigabitEthernet0/0/0/2
+ state: deleted
+
+#
+#
+# -----------
+# After state
+# -----------
+#
+#
+# Using parsed:
+
+# parsed.cfg
+# interface Bundle-Ether10
+# lacp churn logging actor
+# lacp switchover suppress-flaps 500
+# lacp collector-max-delay 100
+# !
+# interface Bundle-Ether11
+# lacp system mac 00c2.4c00.bd15
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# lacp period 200
+# !
+#
+
+- name: Convert lacp interfaces config to argspec without connecting to the appliance
+ cisco.iosxr.iosxr_lacp_interfaces:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+
+# --------------
+# Output:
+# --------------
+
+# parsed:
+# - name: Bundle-Ether10
+# churn_logging: actor
+# collector_max_delay: 100
+# switchover_suppress_flaps: 500
+#
+# - name: Bundle-Ether11
+# system:
+# mac: 00c2.4c00.bd15
+#
+# - name: GigabitEthernet0/0/0/1
+# period: 200
+#
+#
+
+# Using gathered:
+
+# Native config:
+# interface Bundle-Ether10
+# lacp churn logging actor
+# lacp switchover suppress-flaps 500
+# lacp collector-max-delay 100
+# !
+# interface Bundle-Ether11
+# lacp system mac 00c2.4c00.bd15
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# lacp period 200
+# !
+#
+
+- name: Gather IOSXR lacp interfaces configuration
+ cisco.iosxr.iosxr_lacp_interfaces:
+ config:
+ state: gathered
+
+# ----------
+# Output
+# ---------
+# gathered:
+# - name: Bundle-Ether10
+# churn_logging: actor
+# collector_max_delay: 100
+# switchover_suppress_flaps: 500
+#
+# - name: Bundle-Ether11
+# system:
+# mac: 00c2.4c00.bd15
+#
+# - name: GigabitEthernet0/0/0/1
+# period: 200
+
+# Using rendered:
+
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_lacp_interfaces:
+ config:
+ - name: Bundle-Ether10
+ churn_logging: actor
+ collector_max_delay: 100
+ switchover_suppress_flaps: 500
+
+ - name: Bundle-Ether11
+ system:
+ mac: 00c2.4c00.bd15
+
+ - name: GigabitEthernet0/0/0/1
+ period: 200
+ state: rendered
+
+# -------------
+# Output
+# -------------
+# rendered: [
+# - "interface Bundle-Ether10"
+# - " lacp churn logging actor"
+# - " lacp switchover suppress-flaps 500"
+# - " lacp collector-max-delay 100"
+# - "interface Bundle-Ether11"
+# - " lacp system mac 00c2.4c00.bd15"
+# - "interface MgmtEth0/0/CPU0/0"
+# - " ipv4 address 192.0.2.11 255.255.255.0"
+# - "interface GigabitEthernet0/0/0/1"
+# - " lacp period 200"
+#
+
+
+"""
+RETURN = """
+before:
+ description: The configuration as structured data prior to module invocation.
+ returned: always
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The configuration as structured data after module completion.
+ returned: when changed
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample: ['interface Bundle-Ether10', 'lacp churn logging partner', 'lacp period 150']
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lacp_interfaces.lacp_interfaces import (
+ Lacp_interfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.lacp_interfaces.lacp_interfaces import (
+ Lacp_interfaces,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=Lacp_interfacesArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = Lacp_interfaces(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lag_interfaces.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lag_interfaces.py
new file mode 100644
index 00000000..6d1dacec
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lag_interfaces.py
@@ -0,0 +1,854 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_lag_interfaces
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+DOCUMENTATION = """
+module: iosxr_lag_interfaces
+short_description: Resource module to configure LAG interfaces.
+description:
+- This module manages the attributes of LAG/Ether-Bundle interfaces on IOS-XR devices.
+version_added: 1.0.0
+notes:
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+author: Nilashish Chakraborty (@NilashishC)
+options:
+ config:
+ description: A provided Link Aggregation Group (LAG) configuration.
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Name/Identifier of the LAG/Ether-Bundle to configure.
+ type: str
+ required: true
+ members:
+ description:
+ - List of member interfaces for the LAG/Ether-Bundle.
+ type: list
+ elements: dict
+ suboptions:
+ member:
+ description:
+ - Name of the member interface.
+ type: str
+ mode:
+ description:
+ - Specifies the mode of the operation for the member interface.
+ - Mode 'active' runs LACP in active mode.
+ - Mode 'on' does not run LACP over the port.
+ - Mode 'passive' runs LACP in passive mode over the port.
+ - Mode 'inherit' runs LACP as configured in the bundle.
+ type: str
+ choices: ["on", "active", "passive", "inherit"]
+ mode:
+ description:
+ - LAG mode.
+ - Mode 'active' runs LACP in active mode over the port.
+ - Mode 'on' does not run LACP over the port.
+ - Mode 'passive' runs LACP in passive mode over the port.
+ type: str
+ choices: ["on", "active", "passive"]
+ links:
+ description:
+ - This dict contains configurable options related to LAG/Ether-Bundle links.
+ type: dict
+ suboptions:
+ max_active:
+ description:
+ - Specifies the limit on the number of links that can be active in the LAG/Ether-Bundle.
+ - Refer to vendor documentation for valid values.
+ type: int
+ min_active:
+ description:
+ - Specifies the minimum number of active links needed to bring up the LAG/Ether-Bundle.
+ - Refer to vendor documentation for valid values.
+ type: int
+ load_balancing_hash:
+ description:
+ - Specifies the hash function used for traffic forwarded over the LAG/Ether-Bundle.
+ - Option 'dst-ip' uses the destination IP as the hash function.
+ - Option 'src-ip' uses the source IP as the hash function.
+ type: str
+ choices: ["dst-ip", "src-ip"]
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config int).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state of the configuration after module completion.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - parsed
+ - rendered
+ - gathered
+ default: merged
+
+"""
+EXAMPLES = """
+# Using merged
+#
+#
+# ------------
+# Before state
+# ------------
+#
+# RP/0/0/CPU0:iosxr01#show run int
+# Sun Jul 7 19:42:59.416 UTC
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description "GigabitEthernet - 1"
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+#
+- name: Merge provided configuration with device configuration
+ cisco.iosxr.iosxr_lag_interfaces:
+ config:
+ - name: Bundle-Ether10
+ members:
+ - member: GigabitEthernet0/0/0/1
+ mode: inherit
+ - member: GigabitEthernet0/0/0/3
+ mode: inherit
+ mode: active
+ links:
+ max_active: 5
+ min_active: 2
+ load_balancing_hash: src-ip
+
+ - name: Bundle-Ether12
+ members:
+ - member: GigabitEthernet0/0/0/2
+ mode: passive
+ - member: GigabitEthernet0/0/0/4
+ mode: passive
+ load_balancing_hash: dst-ip
+ state: merged
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/0/CPU0:iosxr01#show run int
+# Sun Jul 7 20:51:17.685 UTC
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash src-ip
+# bundle maximum-active links 5
+# bundle minimum-active links 2
+# !
+# interface Bundle-Ether12
+# bundle load-balancing hash dst-ip
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# bundle id 12 mode passive
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# bundle id 12 mode passive
+# !
+#
+
+
+# Using replaced
+#
+#
+# -------------
+# Before state
+# -------------
+#
+#
+# RP/0/0/CPU0:iosxr01#sho run int
+# Sun Jul 7 20:58:06.527 UTC
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash src-ip
+# bundle maximum-active links 5
+# bundle minimum-active links 2
+# !
+# interface Bundle-Ether12
+# bundle load-balancing hash dst-ip
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# bundle id 12 mode passive
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# bundle id 12 mode passive
+# !
+#
+#
+- name: Replace device configuration of listed Bundles with provided configurations
+ cisco.iosxr.iosxr_lag_interfaces:
+ config:
+ - name: Bundle-Ether12
+ members:
+ - name: GigabitEthernet0/0/0/2
+ mode: passive
+
+ - name: Bundle-Ether11
+ members:
+ - name: GigabitEthernet0/0/0/4
+ load_balancing_hash: src-ip
+ state: replaced
+#
+#
+# -----------
+# After state
+# -----------
+#
+#
+# RP/0/0/CPU0:iosxr01#sh run int
+# Sun Jul 7 21:22:27.397 UTC
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash src-ip
+# bundle maximum-active links 5
+# bundle minimum-active links 2
+# !
+# interface Bundle-Ether11
+# bundle load-balancing hash src-ip
+# !
+# interface Bundle-Ether12
+# lacp mode passive
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# bundle id 12 mode on
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# bundle id 11 mode on
+# !
+#
+#
+
+
+# Using overridden
+#
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:iosxr01#sh run int
+# Sun Jul 7 21:22:27.397 UTC
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash src-ip
+# bundle maximum-active links 5
+# bundle minimum-active links 2
+# !
+# interface Bundle-Ether11
+# bundle load-balancing hash src-ip
+# !
+# interface Bundle-Ether12
+# lacp mode passive
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# bundle id 12 mode on
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# bundle id 11 mode on
+# !
+#
+#
+
+- name: Overrides all device configuration with provided configuration
+ cisco.iosxr.iosxr_lag_interfaces:
+ config:
+ - name: Bundle-Ether10
+ members:
+ - member: GigabitEthernet0/0/0/1
+ mode: inherit
+ - member: GigabitEthernet0/0/0/2
+ mode: inherit
+ mode: active
+ load_balancing_hash: dst-ip
+ state: overridden
+#
+#
+# ------------
+# After state
+# ------------
+#
+#
+# RP/0/0/CPU0:iosxr01#sh run int
+# Sun Jul 7 21:43:04.802 UTC
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash dst-ip
+# !
+# interface Bundle-Ether11
+# !
+# interface Bundle-Ether12
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+#
+
+
+# Using deleted
+#
+#
+# ------------
+# Before state
+# ------------
+#
+# RP/0/0/CPU0:iosxr01#sh run int
+# Sun Jul 7 21:22:27.397 UTC
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash src-ip
+# bundle maximum-active links 5
+# bundle minimum-active links 2
+# !
+# interface Bundle-Ether11
+# bundle load-balancing hash src-ip
+# !
+# interface Bundle-Ether12
+# lacp mode passive
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# bundle id 12 mode on
+# !n
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# bundle id 11 mode on
+# !
+#
+#
+
+- name: Delete attributes of given bundles and removes member interfaces from them
+ (Note - This won't delete the bundles themselves)
+ cisco.iosxr.iosxr_lag_interfaces:
+ config:
+ - name: Bundle-Ether10
+ - name: Bundle-Ether11
+ - name: Bundle-Ether12
+ state: deleted
+
+#
+#
+# ------------
+# After state
+# ------------
+#
+# RP/0/0/CPU0:iosxr01#sh run int
+# Sun Jul 7 21:49:50.004 UTC
+# interface Bundle-Ether10
+# !
+# interface Bundle-Ether11
+# !
+# interface Bundle-Ether12
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# !
+#
+#
+
+# Using deleted (without config)
+#
+#
+# ------------
+# Before state
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr#sh run int
+# Sun Aug 18 19:49:51.908 UTC
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash src-ip
+# bundle maximum-active links 10
+# bundle minimum-active links 2
+# !
+# interface Bundle-Ether11
+# bundle load-balancing hash dst-ip
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/1
+# bundle id 10 mode inherit
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# bundle id 10 mode passive
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# bundle id 11 mode passive
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# bundle id 11 mode passive
+# shutdown
+# !
+#
+
+- name: Delete attributes of all bundles and removes member interfaces from them (Note
+ - This won't delete the bundles themselves)
+ cisco.iosxr.iosxr_lag_interfaces:
+ state: deleted
+
+#
+#
+# ------------
+# After state
+# ------------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run int
+# Sun Aug 18 19:54:22.389 UTC
+# interface Bundle-Ether10
+# !
+# interface Bundle-Ether11
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 10.8.38.69 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/0
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/1
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/2
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/3
+# shutdown
+# !
+# interface GigabitEthernet0/0/0/4
+# shutdown
+# !
+
+# Using parsed:
+
+# parsed.cfg
+
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash src-ip
+# bundle maximum-active links 5
+# bundle minimum-active links 2
+# !
+# interface Bundle-Ether12
+# bundle load-balancing hash dst-ip
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# bundle id 12 mode passive
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# bundle id 12 mode passive
+# !
+#
+- name: Convert lag interfaces config to argspec without connecting to the appliance
+ cisco.iosxr.iosxr_lag_interfaces:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+
+# --------------
+# Output
+# --------------
+# parsed:
+# - name: Bundle-Ether10
+# members:
+# - member: GigabitEthernet0/0/0/1
+# mode: inherit
+# - member: GigabitEthernet0/0/0/3
+# mode: inherit
+# mode: active
+# links:
+# max_active: 5
+# min_active: 2
+# load_balancing_hash: src-ip
+
+# - name: Bundle-Ether12
+# members:
+# - member: GigabitEthernet0/0/0/2
+# mode: passive
+# - member: GigabitEthernet0/0/0/4
+# mode: passive
+# load_balancing_hash: dst-ip
+
+# using gathered
+
+# Device Config:
+# -------------
+
+# interface Bundle-Ether10
+# lacp mode active
+# bundle load-balancing hash src-ip
+# bundle maximum-active links 5
+# bundle minimum-active links 2
+# !
+# interface Bundle-Ether12
+# bundle load-balancing hash dst-ip
+# !
+# interface Loopback888
+# description test for ansible
+# shutdown
+# !
+# interface MgmtEth0/0/CPU0/0
+# ipv4 address 192.0.2.11 255.255.255.0
+# !
+# interface GigabitEthernet0/0/0/1
+# description 'GigabitEthernet - 1"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/2
+# description "GigabitEthernet - 2"
+# bundle id 12 mode passive
+# !
+# interface GigabitEthernet0/0/0/3
+# description "GigabitEthernet - 3"
+# bundle id 10 mode inherit
+# !
+# interface GigabitEthernet0/0/0/4
+# description "GigabitEthernet - 4"
+# bundle id 12 mode passive
+# !
+#
+
+- name: Gather IOSXR lag interfaces configuration
+ cisco.iosxr.iosxr_lag_interfaces:
+ config:
+ state: gathered
+
+# --------------
+# Output
+# --------------
+# gathered:
+# - name: Bundle-Ether10
+# members:
+# - member: GigabitEthernet0/0/0/1
+# mode: inherit
+# - member: GigabitEthernet0/0/0/3
+# mode: inherit
+# mode: active
+# links:
+# max_active: 5
+# min_active: 2
+# load_balancing_hash: src-ip
+
+# - name: Bundle-Ether12
+# members:
+# - member: GigabitEthernet0/0/0/2
+# mode: passive
+# - member: GigabitEthernet0/0/0/4
+# mode: passive
+# load_balancing_hash: dst-ip
+
+# Using rendered:
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_lag_interfaces:
+ config:
+ - name: Bundle-Ether10
+ members:
+ - member: GigabitEthernet0/0/0/1
+ mode: inherit
+ - member: GigabitEthernet0/0/0/3
+ mode: inherit
+ mode: active
+ links:
+ max_active: 5
+ min_active: 2
+ load_balancing_hash: src-ip
+
+ - name: Bundle-Ether12
+ members:
+ - member: GigabitEthernet0/0/0/2
+ mode: passive
+ - member: GigabitEthernet0/0/0/4
+ mode: passive
+ load_balancing_hash: dst-ip
+ state: rendered
+
+# Output:
+
+# rendered:
+# [
+# - "interface Bundle-Ether10"
+# - " lacp mode active"
+# - " bundle load-balancing hash src-ip"
+# - " bundle maximum-active links 5"
+# - " bundle minimum-active links 2"
+# - "interface Bundle-Ether12"
+# - " bundle load-balancing hash dst-ip"
+# - "interface Loopback888"
+# - " description test for ansible"
+# - " shutdown"
+# - "interface MgmtEth0/0/CPU0/0"
+# - " ipv4 address 192.0.2.11 255.255.255.0"
+# - "interface GigabitEthernet0/0/0/1"
+# - " description 'GigabitEthernet - 1""
+# - " bundle id 10 mode inherit"
+# - "interface GigabitEthernet0/0/0/2"
+# - " description "GigabitEthernet - 2""
+# - " bundle id 12 mode passive"
+# - "interface GigabitEthernet0/0/0/3"
+# - " description "GigabitEthernet - 3""
+# - " bundle id 10 mode inherit"
+# - "interface GigabitEthernet0/0/0/4"
+# - " description "GigabitEthernet - 4""
+# - " bundle id 12 mode passive"
+# ]
+#
+#
+
+
+"""
+RETURN = """
+before:
+ description: The configuration as structured data prior to module invocation.
+ returned: always
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The configuration as structured data after module completion.
+ returned: when changed
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample: ['interface Bundle-Ether10', 'bundle minimum-active links 2', 'bundle load-balancing hash src-ip']
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lag_interfaces.lag_interfaces import (
+ Lag_interfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.lag_interfaces.lag_interfaces import (
+ Lag_interfaces,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=Lag_interfacesArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = Lag_interfaces(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lldp_global.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lldp_global.py
new file mode 100644
index 00000000..9c99fc8a
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lldp_global.py
@@ -0,0 +1,490 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_lldp_global
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_lldp_global
+short_description: Resource module to configure LLDP.
+description:
+- This module manages Global Link Layer Discovery Protocol (LLDP) settings on IOS-XR
+ devices.
+version_added: 1.0.0
+notes:
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+author: Nilashish Chakraborty (@NilashishC)
+options:
+ config:
+ description: The provided global LLDP configuration.
+ type: dict
+ suboptions:
+ holdtime:
+ description:
+ - Specifies the holdtime (in sec) to be sent in packets.
+ type: int
+ reinit:
+ description:
+ - Specifies the delay (in sec) for LLDP initialization on any interface.
+ type: int
+ subinterfaces:
+ description:
+ - Enable or disable LLDP over sub-interfaces.
+ type: bool
+ timer:
+ description:
+ - Specifies the rate at which LLDP packets are sent (in sec).
+ type: int
+ tlv_select:
+ description:
+ - Specifies the LLDP TLVs to enable or disable.
+ type: dict
+ suboptions:
+ management_address:
+ description:
+ - Enable or disable management address TLV.
+ type: bool
+ port_description:
+ description:
+ - Enable or disable port description TLV.
+ type: bool
+ system_capabilities:
+ description:
+ - Enable or disable system capabilities TLV.
+ type: bool
+ system_description:
+ description:
+ - Enable or disable system description TLV.
+ type: bool
+ system_name:
+ description:
+ - Enable or disable system name TLV.
+ type: bool
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config lldp).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state of the configuration after module completion.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - deleted
+ - parsed
+ - gathered
+ - rendered
+ default: merged
+
+"""
+EXAMPLES = """
+# Using merged
+#
+#
+# -------------
+# Before State
+# -------------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run lldp
+# Tue Aug 6 19:27:54.933 UTC
+# % No such configuration item(s)
+#
+#
+
+- name: Merge provided LLDP configuration with the existing configuration
+ cisco.iosxr.iosxr_lldp_global:
+ config:
+ holdtime: 100
+ reinit: 2
+ timer: 3000
+ subinterfaces: true
+ tlv_select:
+ management_address: false
+ system_description: false
+ state: merged
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {}
+#
+# "commands": [
+# "lldp subinterfaces enable",
+# "lldp holdtime 100",
+# "lldp reinit 2",
+# "lldp tlv-select system-description disable",
+# "lldp tlv-select management-address disable",
+# "lldp timer 3000"
+# ]
+#
+# "after": {
+# "holdtime": 100,
+# "reinit": 2,
+# "subinterfaces": true,
+# "timer": 3000,
+# "tlv_select": {
+# "management_address": false,
+# "system_description": false
+# }
+# }
+#
+#
+# ------------
+# After state
+# ------------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run lldp
+# Tue Aug 6 21:31:10.587 UTC
+# lldp
+# timer 3000
+# reinit 2
+# subinterfaces enable
+# holdtime 100
+# tlv-select
+# management-address disable
+# system-description disable
+# !
+# !
+#
+#
+
+
+# Using replaced
+#
+#
+# -------------
+# Before State
+# -------------
+#
+# RP/0/0/CPU0:an-iosxr#sh run lldp
+# Tue Aug 6 21:31:10.587 UTC
+# lldp
+# timer 3000
+# reinit 2
+# subinterfaces enable
+# holdtime 100
+# tlv-select
+# management-address disable
+# system-description disable
+# !
+# !
+#
+#
+
+- name: Replace existing LLDP device configuration with provided configuration
+ cisco.iosxr.iosxr_lldp_global:
+ config:
+ holdtime: 100
+ tlv_select:
+ port_description: false
+ system_description: true
+ management_description: true
+ state: replaced
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {
+# "holdtime": 100,
+# "reinit": 2,
+# "subinterfaces": true,
+# "timer": 3000,
+# "tlv_select": {
+# "management_address": false,
+# "system_description": false
+# }
+# }
+#
+# "commands": [
+# "no lldp reinit 2",
+# "no lldp subinterfaces enable",
+# "no lldp timer 3000",
+# "no lldp tlv-select management-address disable",
+# "no lldp tlv-select system-description disable",
+# "lldp tlv-select port-description disable"
+# ]
+#
+# "after": {
+# "holdtime": 100,
+# "tlv_select": {
+# "port_description": false
+# }
+# }
+#
+#
+# ------------
+# After state
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr#sh run lldp
+# Tue Aug 6 21:53:08.407 UTC
+# lldp
+# holdtime 100
+# tlv-select
+# port-description disable
+# !
+# !
+#
+#
+
+
+# Using deleted
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:an-iosxr#sh run lldp
+# Tue Aug 6 21:31:10.587 UTC
+# lldp
+# timer 3000
+# reinit 2
+# subinterfaces enable
+# holdtime 100
+# tlv-select
+# management-address disable
+# system-description disable
+# !
+# !
+#
+#
+
+- name: Deleted existing LLDP configurations from the device
+ cisco.iosxr.iosxr_lldp_global:
+ state: deleted
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {
+# "holdtime": 100,
+# "reinit": 2,
+# "subinterfaces": true,
+# "timer": 3000,
+# "tlv_select": {
+# "management_address": false,
+# "system_description": false
+# }
+# },
+#
+# "commands": [
+# "no lldp holdtime 100",
+# "no lldp reinit 2",
+# "no lldp subinterfaces enable",
+# "no lldp timer 3000",
+# "no lldp tlv-select management-address disable",
+# "no lldp tlv-select system-description disable"
+# ]
+#
+# "after": {}
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/0/CPU0:an-iosxr#sh run lldp
+# Tue Aug 6 21:38:31.187 UTC
+# lldp
+# !
+#
+# Using parsed:
+
+# parsed.cfg
+# lldp
+# timer 3000
+# reinit 2
+# subinterfaces enable
+# holdtime 100
+# tlv-select
+# management-address disable
+# system-description disable
+# !
+# !
+
+- name: Convert lldp global config to argspec without connecting to the appliance
+ cisco.iosxr.iosxr_lldp_global:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+
+# ------------------------
+# Module Execution Result
+# ------------------------
+# parsed:
+# holdtime: 100
+# reinit: 2
+# timer: 3000
+# subinterfaces: True
+# tlv_select:
+# management_address: False
+# system_description: False
+
+# using gathered:
+
+# Device config:
+# lldp
+# timer 3000
+# reinit 2
+# subinterfaces enable
+# holdtime 100
+# tlv-select
+# management-address disable
+# system-description disable
+# !
+# !
+
+- name: Gather IOSXR lldp global configuration
+ cisco.iosxr.iosxr_lldp_global:
+ config:
+ state: gathered
+
+
+# ------------------------
+# Module Execution Result
+# ------------------------
+# gathered:
+# holdtime: 100
+# reinit: 2
+# timer: 3000
+# subinterfaces: True
+# tlv_select:
+# management_address: False
+# system_description: False
+
+# using rendered:
+
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_lldp_global:
+ config:
+ holdtime: 100
+ reinit: 2
+ timer: 3000
+ subinterfaces: true
+ tlv_select:
+ management_address: false
+ system_description: false
+ state: rendered
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "rendered": [
+# "lldp subinterfaces enable",
+# "lldp holdtime 100",
+# "lldp reinit 2",
+# "lldp tlv-select system-description disable",
+# "lldp tlv-select management-address disable",
+# "lldp timer 3000"
+# ]
+
+
+
+"""
+RETURN = """
+before:
+ description: The configuration as structured data prior to module invocation.
+ returned: always
+ type: dict
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The configuration as structured data after module completion.
+ returned: when changed
+ type: dict
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample: ['lldp subinterfaces enable', 'lldp holdtime 100', 'no lldp tlv-select management-address disable']
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lldp_global.lldp_global import (
+ Lldp_globalArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.lldp_global.lldp_global import (
+ Lldp_global,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=Lldp_globalArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = Lldp_global(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lldp_interfaces.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lldp_interfaces.py
new file mode 100644
index 00000000..f88d132e
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_lldp_interfaces.py
@@ -0,0 +1,725 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_lldp_interfaces
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_lldp_interfaces
+short_description: Resource module to configure LLDP interfaces.
+description:
+- This module manages Link Layer Discovery Protocol (LLDP) attributes of interfaces
+ on IOS-XR devices.
+version_added: 1.0.0
+notes:
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+author: Nilashish Chakraborty (@nilashishc)
+options:
+ config:
+ description: A dictionary of LLDP interfaces options.
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Name/Identifier of the interface or Ether-Bundle.
+ type: str
+ destination:
+ description:
+ - Specifies LLDP destination configuration on the interface.
+ suboptions:
+ mac_address:
+ description:
+ - Specifies the LLDP destination mac address on the interface.
+ type: str
+ choices:
+ - ieee-nearest-bridge
+ - ieee-nearest-non-tmpr-bridge
+ type: dict
+ receive:
+ description:
+ - Enable/disable LLDP RX on an interface.
+ type: bool
+ transmit:
+ description:
+ - Enable/disable LLDP TX on an interface.
+ type: bool
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config int).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state of the configuration after module completion.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - parsed
+ - rendered
+ - gathered
+ default: merged
+
+"""
+EXAMPLES = """
+# Using merged
+#
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 12:40:23.104 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# !
+#
+#
+
+- name: Merge provided configuration with running configuration
+ cisco.iosxr.iosxr_lldp_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ destination:
+ mac_address: ieee-nearest-non-tmpr-bridge
+ transmit: false
+
+ - name: GigabitEthernet0/0/0/2
+ destination:
+ mac_address: ieee-nearest-bridge
+ receive: false
+ state: merged
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+#
+# "before": [
+# {
+# "name": "TenGigE0/0/0/0"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/1"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/2"
+# }
+# ]
+#
+# "commands": [
+# "interface GigabitEthernet0/0/0/2",
+# "lldp destination mac-address ieee-nearest-non-tmpr-bridge",
+# "lldp transmit disable",
+# "interface GigabitEthernet0/0/0/1",
+# "lldp receive disable",
+# "lldp destination mac-address ieee-nearest-bridge"
+# ]
+#
+# "after": [
+# {
+# "name": "TenGigE0/0/0/0"
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/1",
+# "receive": false
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-non-tmpr-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/2",
+# "transmit": false
+# }
+# ]
+#
+#
+# ------------
+# After state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 12:49:51.517 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# lldp
+# receive disable
+# destination mac-address
+# ieee-nearest-bridge
+# !
+# !
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# lldp
+# transmit disable
+# destination mac-address
+# ieee-nearest-non-tmpr-bridge
+# !
+# !
+# !
+#
+#
+
+
+# Using replaced
+#
+#
+# -------------
+# Before state
+# -------------
+#
+#
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 12:49:51.517 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# lldp
+# receive disable
+# destination mac-address
+# ieee-nearest-bridge
+# !
+# !
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# lldp
+# transmit disable
+# destination mac-address
+# ieee-nearest-non-tmpr-bridge
+# !
+# !
+# !
+#
+#
+
+- name: Replace existing LLDP configurations of specified interfaces with provided
+ configuration
+ cisco.iosxr.iosxr_lldp_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ destination:
+ mac_address: ieee-nearest-non-tmpr-bridge
+ state: replaced
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": [
+# {
+# "name": "TenGigE0/0/0/0"
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/1",
+# "receive": false
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-non-tmpr-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/2",
+# "transmit": false
+# }
+# ]
+#
+#
+# "commands": [
+# "interface GigabitEthernet0/0/0/1",
+# "no lldp receive disable",
+# "lldp destination mac-address ieee-nearest-non-tmpr-bridge"
+# ]
+#
+#
+# "after": [
+# {
+# "name": "TenGigE0/0/0/0"
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-non-tmpr-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/1"
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-non-tmpr-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/2",
+# "transmit": false
+# }
+# ]
+#
+#
+# ------------
+# After state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 13:02:57.062 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# lldp
+# destination mac-address
+# ieee-nearest-non-tmpr-bridge
+# !
+# !
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# lldp
+# transmit disable
+# destination mac-address
+# ieee-nearest-non-tmpr-bridge
+# !
+# !
+# !
+#
+#
+
+
+# Using overridden
+#
+#
+# -------------
+# Before state
+# -------------
+#
+#
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 13:15:40.465 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# lldp
+# receive disable
+# destination mac-address
+# ieee-nearest-bridge
+# !
+# !
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# lldp
+# transmit disable
+# destination mac-address
+# ieee-nearest-non-tmpr-bridge
+# !
+# !
+# !
+#
+#
+
+- name: Override the LLDP configurations of all the interfaces with provided configurations
+ cisco.iosxr.iosxr_lldp_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ transmit: false
+ state: overridden
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+#
+# "before": [
+# {
+# "name": "TenGigE0/0/0/0"
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/1",
+# "receive": false
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-non-tmpr-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/2",
+# "transmit": false
+# }
+# ]
+#
+# "commands": [
+# "interface GigabitEthernet0/0/0/2",
+# "no lldp destination mac-address ieee-nearest-non-tmpr-bridge",
+# "no lldp transmit disable",
+# "interface GigabitEthernet0/0/0/1",
+# "no lldp destination mac-address ieee-nearest-bridge",
+# "no lldp receive disable",
+# "lldp transmit disable"
+# ]
+#
+#
+# "after": [
+# {
+# "name": "TenGigE0/0/0/0"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/1",
+# "transmit": false
+# },
+# {
+# "name": "GigabitEthernet0/0/0/2"
+# }
+# ]
+#
+#
+# ------------
+# After state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 13:22:25.604 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# lldp
+# transmit disable
+# !
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# !
+#
+#
+
+
+# Using deleted
+#
+#
+# -------------
+# Before state
+# -------------
+#
+#
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 13:26:21.498 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# lldp
+# receive disable
+# destination mac-address
+# ieee-nearest-bridge
+# !
+# !
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# lldp
+# transmit disable
+# destination mac-address
+# ieee-nearest-non-tmpr-bridge
+# !
+# !
+# !
+#
+#
+
+- name: Delete LLDP configurations of all interfaces (Note - This won't delete the
+ interfaces themselves)
+ cisco.iosxr.iosxr_lldp_interfaces:
+ state: deleted
+
+#
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+#
+# "before": [
+# {
+# "name": "TenGigE0/0/0/0"
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/1",
+# "receive": false
+# },
+# {
+# "destination": {
+# "mac_address": "ieee-nearest-non-tmpr-bridge"
+# },
+# "name": "GigabitEthernet0/0/0/2",
+# "transmit": false
+# }
+# ]
+#
+#
+# "commands": [
+# "interface GigabitEthernet0/0/0/1",
+# "no lldp destination mac-address ieee-nearest-bridge",
+# "no lldp receive disable",
+# "interface GigabitEthernet0/0/0/2",
+# "no lldp destination mac-address ieee-nearest-non-tmpr-bridge",
+# "no lldp transmit disable"
+# ]
+#
+#
+# "after": [
+# {
+# "name": "TenGigE0/0/0/0"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/1"
+# },
+# {
+# "name": "GigabitEthernet0/0/0/2"
+# }
+# ]
+#
+#
+# ------------
+# After state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 13:30:14.618 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# !
+#
+#
+# Using parsed:
+# parsed.cfg
+
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# lldp
+# receive disable
+# destination mac-address
+# ieee-nearest-bridge
+# !
+# !
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# lldp
+# transmit disable
+# destination mac-address
+# ieee-nearest-non-tmpr-bridge
+
+- name: Convert lacp interfaces config to argspec without connecting to the appliance
+ cisco.iosxr.iosxr_lldp_interfaces:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+
+# ------------------------
+# Module Execution Result
+# ------------------------
+
+# parsed: [
+# - name: GigabitEthernet0/0/0/1
+# destination:
+# mac_address: ieee-nearest-non-tmpr-bridge
+# transmit: False
+
+# - name: GigabitEthernet0/0/0/2
+# destination:
+# mac_address: ieee-nearest-bridge
+# receive: False
+# ]
+
+# Using gathered:
+# Device config:
+
+# RP/0/RP0/CPU0:ios#sh run int
+# Mon Aug 12 12:49:51.517 UTC
+# interface TenGigE0/0/0/0
+# ipv4 address 192.0.2.11 255.255.255.192
+# !
+# interface preconfigure GigabitEthernet0/0/0/1
+# lldp
+# receive disable
+# destination mac-address
+# ieee-nearest-bridge
+# !
+# !
+# !
+# interface preconfigure GigabitEthernet0/0/0/2
+# lldp
+# transmit disable
+# destination mac-address
+# ieee-nearest-non-tmpr-bridge
+
+- name: Gather IOSXR lldp interfaces configuration
+ cisco.iosxr.iosxr_lldp_interfaces:
+ config:
+ state: gathered
+
+# ------------------------
+# Module Execution Result
+# ------------------------
+
+# gathered:
+# - name: GigabitEthernet0/0/0/1
+# destination:
+# mac_address: ieee-nearest-non-tmpr-bridge
+# transmit: False
+
+# - name: GigabitEthernet0/0/0/2
+# destination:
+# mac_address: ieee-nearest-bridge
+# receive: False
+
+# Using rendred:
+- name: Render platform specific commands from task input using rendered state
+ cisco.iosxr.iosxr_lldp_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ destination:
+ mac_address: ieee-nearest-non-tmpr-bridge
+ transmit: false
+
+ - name: GigabitEthernet0/0/0/2
+ destination:
+ mac_address: ieee-nearest-bridge
+ receive: false
+ state: rendered
+
+# ------------------------
+# Module Execution Result
+# ------------------------
+
+# "rendered": [
+# "interface GigabitEthernet0/0/0/2",
+# "lldp destination mac-address ieee-nearest-non-tmpr-bridge",
+# "lldp transmit disable",
+# "interface GigabitEthernet0/0/0/1",
+# "lldp receive disable",
+# "lldp destination mac-address ieee-nearest-bridge"
+# ]
+
+"""
+RETURN = """
+before:
+ description: The configuration as structured data prior to module invocation.
+ returned: always
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The configuration as structured data after module completion.
+ returned: when changed
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample: ['interface GigabitEthernet0/0/0/1', 'lldp destination mac-address ieee-nearest-non-tmpr-bridge', 'no lldp transmit disable']
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.lldp_interfaces.lldp_interfaces import (
+ Lldp_interfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.lldp_interfaces.lldp_interfaces import (
+ Lldp_interfaces,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=Lldp_interfacesArgs.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+
+ result = Lldp_interfaces(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_logging.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_logging.py
new file mode 100644
index 00000000..9889f568
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_logging.py
@@ -0,0 +1,1270 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# (c) 2017, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_logging
+author:
+- Trishna Guha (@trishnaguha)
+- Kedar Kekan (@kedarX)
+short_description: (deprecated, removed after 2023-08-01) Configuration management of system logging services on network
+ devices
+description:
+- This module provides declarative management configuration of system logging (syslog)
+ on Cisco IOS XR devices.
+version_added: 1.0.0
+deprecated:
+ alternative: iosxr_logging_global
+ why: Updated module released with more functionality.
+ removed_at_date: '2023-08-01'
+requirements:
+- ncclient >= 0.5.3 when using netconf
+- lxml >= 4.1.1 when using netconf
+notes:
+- This module works with connection C(network_cli) and C(netconf). See L(the IOS-XR
+ Platform Options,../network/user_guide/platform_iosxr.html).
+options:
+ dest:
+ description:
+ - Destination for system logging (syslog) messages.
+ choices:
+ - host
+ - console
+ - monitor
+ - buffered
+ - file
+ type: str
+ name:
+ description:
+ - When C(dest) = I(file) name indicates file-name
+ - When C(dest) = I(host) name indicates the host-name or ip-address of syslog
+ server.
+ type: str
+ vrf:
+ description:
+ - vrf name when syslog server is configured, C(dest) = C(host)
+ type: str
+ default: default
+ size:
+ description:
+ - Size of buffer when C(dest) = C(buffered). The acceptable value is in the range
+ I(307200 to 125000000 bytes). Default 307200
+ - Size of file when C(dest) = C(file). The acceptable value is in the range I(1
+ to 2097152)KB. Default 2 GB
+ type: int
+ facility:
+ description:
+ - To configure the type of syslog facility in which system logging (syslog) messages
+ are sent to syslog servers Optional config for C(dest) = C(host)
+ default: local7
+ type: str
+ hostnameprefix:
+ description:
+ - To append a hostname prefix to system logging (syslog) messages logged to syslog
+ servers. Optional config for C(dest) = C(host)
+ type: str
+ level:
+ description:
+ - Specifies the severity level for the logging.
+ type: str
+ default: debugging
+ aliases:
+ - severity
+ choices: ["emergencies", "alerts", "critical", "errors", "warning", "notifications", "informational", "debugging"]
+ path:
+ description:
+ Set file path.
+ type: str
+ aggregate:
+ description: List of syslog logging configuration definitions.
+ type: list
+ elements: dict
+ suboptions:
+ dest:
+ description:
+ - Destination for system logging (syslog) messages.
+ choices:
+ - host
+ - console
+ - monitor
+ - buffered
+ - file
+ type: str
+ name:
+ description:
+ - When C(dest) = I(file) name indicates file-name
+ - When C(dest) = I(host) name indicates the host-name or ip-address of syslog
+ server.
+ type: str
+ path:
+ description:
+ Set file path.
+ type: str
+ vrf:
+ description:
+ - vrf name when syslog server is configured, C(dest) = C(host)
+ type: str
+ size:
+ description:
+ - Size of buffer when C(dest) = C(buffered). The acceptable value is in the range
+ I(307200 to 125000000 bytes). Default 307200
+ - Size of file when C(dest) = C(file). The acceptable value is in the range I(1
+ to 2097152)KB. Default 2 GB
+ type: int
+ facility:
+ description:
+ - To configure the type of syslog facility in which system logging (syslog) messages
+ are sent to syslog servers Optional config for C(dest) = C(host)
+ type: str
+ hostnameprefix:
+ description:
+ - To append a hostname prefix to system logging (syslog) messages logged to syslog
+ servers. Optional config for C(dest) = C(host)
+ type: str
+ level:
+ description:
+ - Specifies the severity level for the logging.
+ type: str
+ aliases:
+ - severity
+ choices: ["emergencies", "alerts", "critical", "errors", "warning", "notifications", "informational", "debugging"]
+ state:
+ description:
+ - Existential state of the logging configuration on the node.
+ choices:
+ - present
+ - absent
+ type: str
+ state:
+ description:
+ - Existential state of the logging configuration on the node.
+ default: present
+ choices:
+ - present
+ - absent
+ type: str
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+"""
+
+EXAMPLES = """
+- name: configure logging for syslog server host
+ cisco.iosxr.iosxr_logging:
+ dest: host
+ name: 10.10.10.1
+ level: critical
+ state: present
+
+- name: add hostnameprefix configuration
+ cisco.iosxr.iosxr_logging:
+ hostnameprefix: host1
+ state: absent
+
+- name: add facility configuration
+ cisco.iosxr.iosxr_logging:
+ facility: local1
+ state: present
+
+- name: configure console logging level
+ cisco.iosxr.iosxr_logging:
+ dest: console
+ level: debugging
+ state: present
+
+- name: configure monitor logging level
+ cisco.iosxr.iosxr_logging:
+ dest: monitor
+ level: errors
+ state: present
+
+- name: configure syslog to a file
+ cisco.iosxr.iosxr_logging:
+ dest: file
+ name: file_name
+ size: 2048
+ level: errors
+ state: present
+
+- name: configure buffered logging with size
+ cisco.iosxr.iosxr_logging:
+ dest: buffered
+ size: 5100000
+
+- name: Configure logging using aggregate
+ cisco.iosxr.iosxr_logging:
+ aggregate:
+ - {dest: console, level: warning}
+ - {dest: buffered, size: 4800000}
+ - {dest: file, name: file3, size: 2048}
+ - {dest: host, name: host3, level: critical}
+
+- name: Delete logging using aggregate
+ cisco.iosxr.iosxr_logging:
+ aggregate:
+ - {dest: console, level: warning}
+ - {dest: buffered, size: 4800000}
+ - {dest: file, name: file3, size: 2048}
+ - {dest: host, name: host3, level: critical}
+ state: absent
+"""
+
+RETURN = """
+commands:
+ description: The list of configuration mode commands to send to the device
+ returned: always (empty list when no commands to send)
+ type: list
+ sample:
+ - logging 10.10.10.1 vrf default severity debugging
+ - logging facility local7
+ - logging hostnameprefix host1
+ - logging console critical
+ - logging buffered 2097153
+ - logging buffered warnings
+ - logging monitor errors
+ - logging file log_file maxfilesize 1024 severity info
+xml:
+ description: NetConf rpc xml sent to device with transport C(netconf)
+ returned: always (empty list when no xml rpc to send)
+ type: list
+ sample:
+ - '<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <syslog xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-infra-syslog-cfg">
+ <files>
+ <file xc:operation="delete">
+ <file-name>file1</file-name>
+ <file-log-attributes>
+ <max-file-size>2097152</max-file-size>
+ <severity>2</severity>
+ </file-log-attributes>
+ </file>
+ </files>
+ </syslog>
+ </config>'
+"""
+
+import collections
+import re
+
+from copy import deepcopy
+
+from ansible.module_utils._text import to_text
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ remove_default_spec,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ build_xml,
+ etree_find,
+ etree_findall,
+ get_capabilities,
+ get_config,
+ get_os_version,
+ is_cliconf,
+ is_netconf,
+ load_config,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import Version
+
+
+severity_level = {
+ "emergency": "0",
+ "alert": "1",
+ "critical": "2",
+ "error": "3",
+ "warning": "4",
+ "notice": "5",
+ "info": "6",
+ "debug": "7",
+ "disable": "15",
+}
+
+severity_transpose = {
+ "emergencies": "emergency",
+ "alerts": "alert",
+ "critical": "critical",
+ "errors": "error",
+ "warning": "warning",
+ "notifications": "notice",
+ "informational": "info",
+ "debugging": "debug",
+}
+
+
+class ConfigBase(object):
+ def __init__(self, module):
+ self._flag = None
+ self._module = module
+ self._result = {"changed": False, "warnings": []}
+ self._want = list()
+ self._have = list()
+
+ def validate_size(self, value, type=None):
+ if value:
+ if type == "buffer":
+ if value and not int(307200) <= value <= int(125000000):
+ self._module.fail_json(
+ msg="buffer size must be between 307200 and 125000000",
+ )
+ elif type == "file":
+ if value and not int(1) <= value <= int(2097152):
+ self._module.fail_json(
+ msg="file size must be between 1 and 2097152",
+ )
+ return value
+
+ def map_params_to_obj(self, required_if=None):
+ aggregate = self._module.params.get("aggregate")
+ if aggregate:
+ for item in aggregate:
+ for key in item:
+ if item.get(key) is None:
+ item[key] = self._module.params[key]
+
+ d = item.copy()
+
+ if d["dest"] not in ("host", "file"):
+ d["name"] = None
+
+ if d["dest"] == "buffered":
+ if d["size"] is not None:
+ d["size"] = str(
+ self.validate_size(d["size"], "buffer"),
+ )
+ else:
+ d["size"] = str(307200)
+ elif d["dest"] == "file":
+ if d["size"] is not None:
+ d["size"] = str(self.validate_size(d["size"], "file"))
+ else:
+ d["size"] = str(2097152)
+ else:
+ d["size"] = None
+
+ if self._flag == "NC":
+ d["level"] = severity_transpose[d["level"]]
+
+ self._want.append(d)
+
+ else:
+ params = self._module.params
+ if params["dest"] not in ("host", "file"):
+ params["name"] = None
+
+ if params["dest"] == "buffered":
+ if params["size"] is not None:
+ params["size"] = str(
+ self.validate_size(params["size"], "buffer"),
+ )
+ else:
+ params["size"] = str(307200)
+ elif params["dest"] == "file":
+ if params["size"] is not None:
+ params["size"] = str(
+ self.validate_size(params["size"], "file"),
+ )
+ else:
+ params["size"] = str(2097152)
+ else:
+ params["size"] = None
+
+ if self._flag == "NC":
+ params["level"] = severity_transpose[params["level"]]
+
+ self._want.append(
+ {
+ "dest": params["dest"],
+ "name": params["name"],
+ "vrf": params["vrf"],
+ "size": params["size"],
+ "path": params["path"],
+ "facility": params["facility"],
+ "level": params["level"],
+ "hostnameprefix": params["hostnameprefix"],
+ "state": params["state"],
+ },
+ )
+
+
+class CliConfiguration(ConfigBase):
+ def __init__(self, module):
+ super(CliConfiguration, self).__init__(module)
+ self._file_list = set()
+ self._host_list = set()
+
+ def map_obj_to_commands(self, os_version):
+ commands = list()
+ for want_item in self._want:
+ dest = want_item["dest"]
+ name = want_item["name"]
+ size = want_item["size"]
+ path = want_item["path"]
+ facility = want_item["facility"]
+ level = want_item["level"]
+ vrf = want_item["vrf"]
+ hostnameprefix = want_item["hostnameprefix"]
+ state = want_item["state"]
+ del want_item["state"]
+
+ have_size = None
+ have_console_level = None
+ have_monitor_level = None
+ have_prefix = None
+ have_facility = None
+
+ for item in self._have:
+ if item["dest"] == "buffered":
+ have_size = item["size"]
+ if item["dest"] == "console":
+ have_console_level = item["level"]
+ if item["dest"] == "monitor":
+ have_monitor_level = item["level"]
+ if item["dest"] is None and item["hostnameprefix"] is not None:
+ have_prefix = item["hostnameprefix"]
+ if (
+ item["dest"] is None
+ and item["hostnameprefix"] is None
+ and item["facility"] is not None
+ ):
+ have_facility = item["facility"]
+
+ if state == "absent":
+ if dest == "host" and name in self._host_list:
+ commands.append("no logging {0} vrf {1}".format(name, vrf))
+ elif dest == "file" and name in self._file_list:
+ commands.append("no logging file {0}".format(name))
+ elif dest == "console" and have_console_level is not None:
+ commands.append("no logging {0}".format(dest))
+ elif dest == "monitor" and have_monitor_level:
+ commands.append("no logging {0}".format(dest))
+ elif dest == "buffered" and have_size:
+ commands.append("no logging {0}".format(dest))
+
+ if dest is None and hostnameprefix is not None and have_prefix == hostnameprefix:
+ commands.append(
+ "no logging hostnameprefix {0}".format(hostnameprefix),
+ )
+ if dest is None and facility is not None and have_facility == facility:
+ commands.append("no logging facility {0}".format(facility))
+
+ if state == "present":
+ if dest == "host" and name not in self._host_list:
+ if level == "errors" or level == "informational":
+ level = severity_transpose[level]
+ commands.append(
+ "logging {0} vrf {1} severity {2}".format(
+ name,
+ vrf,
+ level,
+ ),
+ )
+ elif dest == "file" and name not in self._file_list:
+ if level == "errors" or level == "informational":
+ level = severity_transpose[level]
+ if os_version and Version(os_version) > Version("7.0"):
+ commands.append(
+ "logging file {0} path {1} maxfilesize {2} severity {3}".format(
+ name,
+ path,
+ size,
+ level,
+ ),
+ )
+ else:
+ commands.append(
+ "logging file {0} maxfilesize {1} severity {2}".format(
+ name,
+ size,
+ level,
+ ),
+ )
+ elif dest == "buffered" and (
+ have_size is None or (have_size is not None and size != have_size)
+ ):
+ commands.append("logging buffered {0}".format(size))
+ elif dest == "console" and (
+ have_console_level is None
+ or (have_console_level is not None and have_console_level != level)
+ ):
+ commands.append("logging console {0}".format(level))
+ elif dest == "monitor" and (
+ have_monitor_level is None
+ or (have_monitor_level is not None and have_monitor_level != level)
+ ):
+ commands.append("logging monitor {0}".format(level))
+
+ if (
+ dest is None
+ and hostnameprefix is not None
+ and (
+ have_prefix is None
+ or (have_prefix is not None and hostnameprefix != have_prefix)
+ )
+ ):
+ commands.append(
+ "logging hostnameprefix {0}".format(hostnameprefix),
+ )
+ if dest is None and hostnameprefix is None and facility != have_facility:
+ commands.append("logging facility {0}".format(facility))
+
+ self._result["commands"] = commands
+ if commands:
+ commit = not self._module.check_mode
+ diff = load_config(self._module, commands, commit=commit)
+ if diff:
+ self._result["diff"] = dict(prepared=diff)
+ self._result["changed"] = True
+
+ def parse_facility(self, line):
+ match = re.search(r"logging facility (\S+)", line, re.M)
+ facility = None
+ if match:
+ facility = match.group(1)
+
+ return facility
+
+ def parse_size(self, line, dest):
+ size = None
+
+ if dest == "buffered":
+ match = re.search(r"logging buffered (\S+)", line, re.M)
+ if match:
+ try:
+ int_size = int(match.group(1))
+ except ValueError:
+ int_size = None
+
+ if int_size is not None:
+ if isinstance(int_size, int):
+ size = str(match.group(1))
+ if dest == "file":
+ match = re.search(
+ r"logging file (\S+) (path\s\S+\s)?maxfilesize (\S+)",
+ line,
+ re.M,
+ )
+ if match:
+ try:
+ if "path" in line:
+ int_size = int(match.group(2))
+ else:
+ int_size = int(match.group(1))
+ except ValueError:
+ int_size = None
+
+ if int_size is not None:
+ if isinstance(int_size, int):
+ size = str(int_size)
+
+ return size
+
+ def parse_path(self, line, dest):
+ path = None
+
+ if dest == "file":
+ match = re.search(r"logging file (\S+) (path\s\S+\s)", line, re.M)
+ if match:
+ try:
+ path = to_text(
+ match.group(2),
+ errors="surrogate_or_strict",
+ )
+ except ValueError:
+ path = None
+
+ return path
+
+ def parse_hostnameprefix(self, line):
+ prefix = None
+ match = re.search(r"logging hostnameprefix (\S+)", line, re.M)
+ if match:
+ prefix = match.group(1)
+ return prefix
+
+ def parse_name(self, line, dest):
+ name = None
+ if dest == "file":
+ match = re.search(r"logging file (\S+)", line, re.M)
+ if match:
+ name = match.group(1)
+ elif dest == "host":
+ match = re.search(r"logging (\S+)", line, re.M)
+ if match:
+ name = match.group(1)
+
+ return name
+
+ def parse_level(self, line, dest):
+ level_group = (
+ "emergencies",
+ "alerts",
+ "critical",
+ "errors",
+ "warning",
+ "notifications",
+ "informational",
+ "debugging",
+ )
+
+ level = None
+ match = re.search(r"logging {0} (\S+)".format(dest), line, re.M)
+ if match:
+ if match.group(1) in level_group:
+ level = match.group(1)
+
+ return level
+
+ def parse_dest(self, line, group):
+ dest_group = ("console", "monitor", "buffered", "file")
+ dest = None
+ if group in dest_group:
+ dest = group
+ elif "vrf" in line:
+ dest = "host"
+
+ return dest
+
+ def parse_vrf(self, line, dest):
+ vrf = None
+ if dest == "host":
+ match = re.search(r"logging (\S+) vrf (\S+)", line, re.M)
+ if match:
+ vrf = match.group(2)
+ return vrf
+
+ def map_config_to_obj(self):
+ data = get_config(self._module, config_filter="logging")
+ lines = data.split("\n")
+
+ for line in lines:
+ match = re.search(r"logging (\S+)", line, re.M)
+ if match:
+ dest = self.parse_dest(line, match.group(1))
+ name = self.parse_name(line, dest)
+ if dest == "host" and name is not None:
+ self._host_list.add(name)
+ if dest == "file" and name is not None:
+ self._file_list.add(name)
+
+ self._have.append(
+ {
+ "dest": dest,
+ "name": name,
+ "size": self.parse_size(line, dest),
+ "path": self.parse_path(line, dest),
+ "facility": self.parse_facility(line),
+ "level": self.parse_level(line, dest),
+ "vrf": self.parse_vrf(line, dest),
+ "hostnameprefix": self.parse_hostnameprefix(line),
+ },
+ )
+
+ def run(self, os_version):
+ self.map_params_to_obj()
+ self.map_config_to_obj()
+ self.map_obj_to_commands(os_version)
+
+ return self._result
+
+
+class NCConfiguration(ConfigBase):
+ def __init__(self, module):
+ super(NCConfiguration, self).__init__(module)
+ self._flag = "NC"
+ self._log_file_meta = collections.OrderedDict()
+ self._log_host_meta = collections.OrderedDict()
+ self._log_console_meta = collections.OrderedDict()
+ self._log_monitor_meta = collections.OrderedDict()
+ self._log_buffered_meta = collections.OrderedDict()
+ self._log_facility_meta = collections.OrderedDict()
+ self._log_prefix_meta = collections.OrderedDict()
+
+ def map_obj_to_xml_rpc(self, os_version):
+ file_attribute_path = "file-log-attributes"
+ if os_version and Version(os_version) > Version("7.0.0"):
+ file_attribute_path = "file-specification"
+ self._log_file_meta.update(
+ [
+ (
+ "files",
+ {
+ "xpath": "syslog/files",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "file",
+ {
+ "xpath": "syslog/files/file",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:name",
+ {
+ "xpath": "syslog/files/file/file-name",
+ "operation": "edit",
+ },
+ ),
+ (
+ "file-attrib",
+ {
+ "xpath": "syslog/files/file/" + file_attribute_path,
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:size",
+ {
+ "xpath": "syslog/files/file/" + file_attribute_path + "/max-file-size",
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:level",
+ {
+ "xpath": "syslog/files/file/" + file_attribute_path + "/severity",
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:path",
+ {
+ "xpath": "syslog/files/file/" + file_attribute_path + "/path",
+ "operation": "edit",
+ },
+ ),
+ ],
+ )
+ else:
+ self._log_file_meta.update(
+ [
+ (
+ "files",
+ {
+ "xpath": "syslog/files",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "file",
+ {
+ "xpath": "syslog/files/file",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:name",
+ {
+ "xpath": "syslog/files/file/file-name",
+ "operation": "edit",
+ },
+ ),
+ (
+ "file-attrib",
+ {
+ "xpath": "syslog/files/file/" + file_attribute_path,
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:size",
+ {
+ "xpath": "syslog/files/file/" + file_attribute_path + "/max-file-size",
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:level",
+ {
+ "xpath": "syslog/files/file/" + file_attribute_path + "/severity",
+ "operation": "edit",
+ },
+ ),
+ ],
+ )
+ self._log_host_meta.update(
+ [
+ (
+ "host-server",
+ {
+ "xpath": "syslog/host-server",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "vrfs",
+ {
+ "xpath": "syslog/host-server/vrfs",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "vrf",
+ {
+ "xpath": "syslog/host-server/vrfs/vrf",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:vrf",
+ {
+ "xpath": "syslog/host-server/vrfs/vrf/vrf-name",
+ "operation": "edit",
+ },
+ ),
+ (
+ "ipv4s",
+ {
+ "xpath": "syslog/host-server/vrfs/vrf/ipv4s",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "ipv4",
+ {
+ "xpath": "syslog/host-server/vrfs/vrf/ipv4s/ipv4",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:name",
+ {
+ "xpath": "syslog/host-server/vrfs/vrf/ipv4s/ipv4/address",
+ "operation": "edit",
+ },
+ ),
+ (
+ "ipv4-sev",
+ {
+ "xpath": "syslog/host-server/vrfs/vrf/ipv4s/ipv4/ipv4-severity-port",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:level",
+ {
+ "xpath": "syslog/host-server/vrfs/vrf/ipv4s/ipv4/ipv4-severity-port/severity",
+ "operation": "edit",
+ },
+ ),
+ ],
+ )
+ self._log_console_meta.update(
+ [
+ (
+ "a:enable-console",
+ {
+ "xpath": "syslog/enable-console-logging",
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "console",
+ {
+ "xpath": "syslog/console-logging",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:console-level",
+ {
+ "xpath": "syslog/console-logging/logging-level",
+ "operation": "edit",
+ },
+ ),
+ ],
+ )
+ self._log_monitor_meta.update(
+ [
+ (
+ "monitor",
+ {
+ "xpath": "syslog/monitor-logging",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:monitor-level",
+ {
+ "xpath": "syslog/monitor-logging/logging-level",
+ "operation": "edit",
+ },
+ ),
+ ],
+ )
+ self._log_buffered_meta.update(
+ [
+ (
+ "buffered",
+ {
+ "xpath": "syslog/buffered-logging",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:size",
+ {
+ "xpath": "syslog/buffered-logging/buffer-size",
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:level",
+ {
+ "xpath": "syslog/buffered-logging/logging-level",
+ "operation": "edit",
+ },
+ ),
+ ],
+ )
+ self._log_facility_meta.update(
+ [
+ (
+ "facility",
+ {
+ "xpath": "syslog/logging-facilities",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:facility",
+ {
+ "xpath": "syslog/logging-facilities/facility-level",
+ "operation": "edit",
+ },
+ ),
+ ],
+ )
+ self._log_prefix_meta.update(
+ [
+ (
+ "a:hostnameprefix",
+ {
+ "xpath": "syslog/host-name-prefix",
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ ],
+ )
+
+ state = self._module.params["state"]
+
+ _get_filter = build_xml("syslog", opcode="filter")
+ running = get_config(
+ self._module,
+ source="running",
+ config_filter=_get_filter,
+ )
+
+ file_ele = etree_findall(running, "file")
+ file_list = list()
+ if len(file_ele):
+ for file in file_ele:
+ file_name = etree_find(file, "file-name")
+ file_list.append(
+ file_name.text if file_name is not None else None,
+ )
+ vrf_ele = etree_findall(running, "vrf")
+ host_list = list()
+ for vrf in vrf_ele:
+ host_ele = etree_findall(vrf, "ipv4")
+ for host in host_ele:
+ host_name = etree_find(host, "address")
+ host_list.append(
+ host_name.text if host_name is not None else None,
+ )
+
+ console_ele = etree_find(running, "console-logging")
+ console_level = (
+ etree_find(console_ele, "logging-level") if console_ele is not None else None
+ )
+ have_console = console_level.text if console_level is not None else None
+
+ monitor_ele = etree_find(running, "monitor-logging")
+ monitor_level = (
+ etree_find(monitor_ele, "logging-level") if monitor_ele is not None else None
+ )
+ have_monitor = monitor_level.text if monitor_level is not None else None
+
+ buffered_ele = etree_find(running, "buffered-logging")
+ buffered_size = (
+ etree_find(buffered_ele, "buffer-size") if buffered_ele is not None else None
+ )
+ have_buffered = buffered_size.text if buffered_size is not None else None
+
+ facility_ele = etree_find(running, "logging-facilities")
+ facility_level = (
+ etree_find(facility_ele, "facility-level") if facility_ele is not None else None
+ )
+ have_facility = facility_level.text if facility_level is not None else None
+
+ prefix_ele = etree_find(running, "host-name-prefix")
+ have_prefix = prefix_ele.text if prefix_ele is not None else None
+
+ file_params = list()
+ host_params = list()
+ console_params = dict()
+ monitor_params = dict()
+ buffered_params = dict()
+ facility_params = dict()
+ prefix_params = dict()
+
+ opcode = None
+ if state == "absent":
+ opcode = "delete"
+ for item in self._want:
+ if item["dest"] == "file" and item["name"] in file_list:
+ item["level"] = severity_level[item["level"]]
+ file_params.append(item)
+ elif item["dest"] == "host" and item["name"] in host_list:
+ item["level"] = severity_level[item["level"]]
+ host_params.append(item)
+ elif item["dest"] == "console" and have_console:
+ console_params.update({"console-level": item["level"]})
+ elif item["dest"] == "monitor" and have_monitor:
+ monitor_params.update({"monitor-level": item["level"]})
+ elif item["dest"] == "buffered" and have_buffered:
+ buffered_params["size"] = str(item["size"]) if item["size"] else None
+ buffered_params["level"] = item["level"] if item["level"] else None
+ elif (
+ item["dest"] is None
+ and item["hostnameprefix"] is None
+ and item["facility"] is not None
+ and have_facility
+ ):
+ facility_params.update({"facility": item["facility"]})
+ elif item["dest"] is None and item["hostnameprefix"] is not None and have_prefix:
+ prefix_params.update(
+ {"hostnameprefix": item["hostnameprefix"]},
+ )
+ elif state == "present":
+ opcode = "merge"
+ for item in self._want:
+ if item["dest"] == "file":
+ item["level"] = severity_level[item["level"]]
+ file_params.append(item)
+ elif item["dest"] == "host":
+ item["level"] = severity_level[item["level"]]
+ host_params.append(item)
+ elif item["dest"] == "console":
+ console_params.update({"console-level": item["level"]})
+ elif item["dest"] == "monitor":
+ monitor_params.update({"monitor-level": item["level"]})
+ elif item["dest"] == "buffered":
+ buffered_params["size"] = str(item["size"]) if item["size"] else None
+ buffered_params["level"] = item["level"] if item["level"] else None
+ elif (
+ item["dest"] is None
+ and item["hostnameprefix"] is None
+ and item["facility"] is not None
+ ):
+ facility_params.update({"facility": item["facility"]})
+ elif item["dest"] is None and item["hostnameprefix"] is not None:
+ prefix_params.update(
+ {"hostnameprefix": item["hostnameprefix"]},
+ )
+
+ self._result["xml"] = []
+ _edit_filter_list = list()
+ if opcode:
+ if len(file_params):
+ _edit_filter_list.append(
+ build_xml(
+ "syslog",
+ xmap=self._log_file_meta,
+ params=file_params,
+ opcode=opcode,
+ ),
+ )
+ if len(host_params):
+ _edit_filter_list.append(
+ build_xml(
+ "syslog",
+ xmap=self._log_host_meta,
+ params=host_params,
+ opcode=opcode,
+ ),
+ )
+ if len(console_params):
+ _edit_filter_list.append(
+ build_xml(
+ "syslog",
+ xmap=self._log_console_meta,
+ params=console_params,
+ opcode=opcode,
+ ),
+ )
+ if len(monitor_params):
+ _edit_filter_list.append(
+ build_xml(
+ "syslog",
+ xmap=self._log_monitor_meta,
+ params=monitor_params,
+ opcode=opcode,
+ ),
+ )
+ if len(buffered_params):
+ _edit_filter_list.append(
+ build_xml(
+ "syslog",
+ xmap=self._log_buffered_meta,
+ params=buffered_params,
+ opcode=opcode,
+ ),
+ )
+ if len(facility_params):
+ _edit_filter_list.append(
+ build_xml(
+ "syslog",
+ xmap=self._log_facility_meta,
+ params=facility_params,
+ opcode=opcode,
+ ),
+ )
+ if len(prefix_params):
+ _edit_filter_list.append(
+ build_xml(
+ "syslog",
+ xmap=self._log_prefix_meta,
+ params=prefix_params,
+ opcode=opcode,
+ ),
+ )
+
+ diff = None
+ if len(_edit_filter_list):
+ commit = not self._module.check_mode
+ diff = load_config(
+ self._module,
+ _edit_filter_list,
+ commit=commit,
+ running=running,
+ nc_get_filter=_get_filter,
+ )
+ if diff:
+ if self._module._diff:
+ self._result["diff"] = dict(prepared=diff)
+
+ self._result["xml"] = _edit_filter_list
+ self._result["changed"] = True
+
+ def run(self, os_version):
+ self.map_params_to_obj()
+ self.map_obj_to_xml_rpc(os_version)
+
+ return self._result
+
+
+def main():
+ """main entry point for module execution"""
+ element_spec = dict(
+ dest=dict(
+ type="str",
+ choices=["host", "console", "monitor", "buffered", "file"],
+ ),
+ name=dict(type="str"),
+ size=dict(type="int"),
+ path=dict(type="str"),
+ vrf=dict(type="str", default="default"),
+ facility=dict(type="str", default="local7"),
+ hostnameprefix=dict(type="str"),
+ level=dict(
+ type="str",
+ default="debugging",
+ aliases=["severity"],
+ choices=[
+ "emergencies",
+ "alerts",
+ "critical",
+ "errors",
+ "warning",
+ "notifications",
+ "informational",
+ "debugging",
+ ],
+ ),
+ state=dict(default="present", choices=["present", "absent"]),
+ )
+
+ aggregate_spec = deepcopy(element_spec)
+
+ # remove default in aggregate spec, to handle common arguments
+ remove_default_spec(aggregate_spec)
+
+ mutually_exclusive = [("dest", "facility", "hostnameprefix")]
+
+ required_if = [
+ ("dest", "host", ["name"]),
+ ("dest", "file", ["name"]),
+ ("dest", "buffered", ["size"]),
+ ("dest", "console", ["level"]),
+ ("dest", "monitor", ["level"]),
+ ]
+
+ argument_spec = dict(
+ aggregate=dict(
+ type="list",
+ elements="dict",
+ options=aggregate_spec,
+ mutually_exclusive=mutually_exclusive,
+ required_if=required_if,
+ ),
+ )
+
+ argument_spec.update(element_spec)
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ mutually_exclusive=mutually_exclusive,
+ required_if=required_if,
+ supports_check_mode=True,
+ )
+ config_object = None
+ if is_cliconf(module):
+ config_object = CliConfiguration(module)
+ os_version = get_os_version(module)
+ elif is_netconf(module):
+ config_object = NCConfiguration(module)
+ os_version = get_capabilities(module).get("device_info").get("network_os_version")
+
+ if config_object:
+ result = config_object.run(os_version)
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_logging_global.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_logging_global.py
new file mode 100644
index 00000000..4d25dcaa
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_logging_global.py
@@ -0,0 +1,1407 @@
+#!/usr/bin/python
+# -*- 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)
+
+"""
+The module file for iosxr_logging_global
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+module: iosxr_logging_global
+version_added: 2.4.0
+short_description: Resource module to configure logging.
+description: This module manages the logging attributes of Cisco IOSXR network devices
+notes:
+- Tested against IOSXR 7.0.2.
+- This module works with connection C(network_cli).
+author: Ashwini Mhatre (@amhatre)
+options:
+ config:
+ description: A dictionary of logging options.
+ type: dict
+ suboptions:
+ archive:
+ description: logging to a persistent device(disk/harddisk)
+ type: dict
+ suboptions:
+ device:
+ type: str
+ description: Configure the archive device
+ archive_length:
+ type: int
+ description: The maximum no of weeks of log to maintain.
+ archive_size:
+ type: int
+ description: The total size of the archive.
+ file_size:
+ type: int
+ description: The maximum file size for a single log file..
+ frequency:
+ type: str
+ description: The collection interval for logs.
+ choices: ["daily", "weekly"]
+ severity: &severity
+ description: Logging severity level
+ type: str
+ choices:
+ - alerts
+ - critical
+ - debugging
+ - emergencies
+ - errors
+ - informational
+ - notifications
+ - warnings
+ threshold:
+ type: int
+ description: Threshold percent <1-99>.
+ buffered:
+ description: Set buffered logging parameters
+ type: dict
+ suboptions:
+ size: &size
+ description: Logging buffer size
+ type: int
+ severity: *severity
+ discriminator: &discriminator
+ description: Establish MD-Buffer association
+ type: list
+ elements: dict
+ suboptions:
+ match_params:
+ type: str
+ description: Set match/no-match discriminator.
+ choices: ["match1", "match2", "match3", "nomatch1", "nomatch2", "nomatch3"]
+ name:
+ type: str
+ description: discriminator name.
+ console:
+ description: Set console logging parameters
+ type: dict
+ suboptions:
+ state: &state
+ description: Enable or disable logging.
+ type: str
+ choices: [ "enabled", "disabled" ]
+ severity: &severity1
+ description: Logging severity level
+ type: str
+ choices:
+ - alerts
+ - critical
+ - debugging
+ - emergencies
+ - errors
+ - informational
+ - notifications
+ - warning
+ discriminator: *discriminator
+ correlator:
+ description: Configure properties of the event correlator
+ type: dict
+ suboptions:
+ buffer_size:
+ type: int
+ description: Configure size of the correlator buffer.
+ rules:
+ type: list
+ elements: dict
+ description: Configure a specified correlation rule.
+ suboptions:
+ rule_name:
+ type: str
+ description: name of rule.
+ rule_type:
+ type: str
+ choices: ["stateful", "nonstateful"]
+ description: type of rule - stateful or nonstateful.
+ timeout:
+ type: int
+ description: Specify timeout.
+ timeout_rootcause:
+ type: int
+ description: Specify timeout for root-cause.
+ context_correlation:
+ type: bool
+ description: Specify enable correlation on context.
+ reissue_nonbistate:
+ type: bool
+ description: Specify reissue of non-bistate alarms on parent clear.This option is allowed for the rules whose type is stateful.
+ reparent:
+ type: bool
+ description: Specify reparent of alarm on parent clear.This option is allowed for the rules whose type is stateful.
+ rule_sets:
+ type: list
+ elements: dict
+ description: Configure a specified correlation ruleset.
+ suboptions:
+ name:
+ type: str
+ description: Name of the ruleset
+ rulename:
+ type: list
+ elements: str
+ description: Name of the rule
+ events:
+ type: dict
+ description: Configure event monitoring parameters.
+ suboptions:
+ buffer_size:
+ type: int
+ description: Set size of the local event buffer.
+ display_location:
+ type: bool
+ description: Include alarm source location in message text.
+ filter_match:
+ type: list
+ elements: str
+ description: Configure filter.
+ severity: *severity
+ threshold:
+ type: int
+ description: Capacity alarm threshold.
+ facility:
+ description: Facility parameter for syslog messages
+ type: str
+ choices:
+ - auth
+ - cron
+ - daemon
+ - kern
+ - local0
+ - local1
+ - local2
+ - local3
+ - local4
+ - local5
+ - local6
+ - local7
+ - lpr
+ - mail
+ - news
+ - sys10
+ - sys11
+ - sys12
+ - sys13
+ - sys14
+ - sys9
+ - syslog
+ - user
+ - uucp
+ files:
+ type: list
+ elements: dict
+ description: Set file logging.
+ suboptions:
+ name:
+ description: name of file.
+ type: str
+ path:
+ description: Set file path.
+ type: str
+ maxfilesize:
+ type: int
+ description: Set max file size.
+ severity:
+ description: Logging severity level
+ type: str
+ choices:
+ - alerts
+ - critical
+ - debugging
+ - emergencies
+ - errors
+ - info
+ - notifications
+ - warning
+ format:
+ type: bool
+ description: Enable to send the syslog message rfc5424 format .
+ history:
+ description: Configure syslog history table
+ type: dict
+ suboptions:
+ state: *state
+ size: *size
+ severity:
+ description: Logging severity level
+ type: str
+ choices:
+ - alerts
+ - critical
+ - debugging
+ - emergencies
+ - errors
+ - informational
+ - notifications
+ - warnings
+ hostnameprefix:
+ type: str
+ description: Hostname prefix to add on msgs to servers.
+ ipv4: &ip
+ description: Mark the dscp/precedence bit for ipv4 packets.
+ type: dict
+ suboptions:
+ dscp:
+ description: Set IP DSCP (DiffServ CodePoint).Please refer vendor document for valid entries.
+ type: str
+ precedence:
+ description: Set precedence Please refer vendor document for valid entries.
+ type: str
+ ipv6: *ip
+ localfilesize:
+ type: int
+ description: Set size of the local log file
+ monitor:
+ description: Set terminal line (monitor) logging parameters
+ type: dict
+ suboptions:
+ state: *state
+ discriminator: *discriminator
+ severity: *severity1
+ source_interfaces:
+ description: Specify interface for source address in logging transactions
+ type: list
+ elements: dict
+ suboptions:
+ interface:
+ description: Interface name with number
+ type: str
+ vrf:
+ description: VPN Routing/Forwarding instance name
+ type: str
+ suppress:
+ type: dict
+ description: Suppress logging behaviour.
+ suboptions:
+ apply_rule:
+ type: str
+ description: Apply suppression rule.
+ duplicates:
+ type: bool
+ description: Suppress consecutive duplicate messages.
+ tls_servers:
+ type: list
+ elements: dict
+ description: Secure server over tls.
+ suboptions:
+ name:
+ type: str
+ description: Name for the tls peer configuration.
+ severity: *severity
+ tls_hostname:
+ type: str
+ description: Name of the logging host.
+ trustpoint:
+ type: str
+ description: Name of the trustpoint configured.
+ vrf:
+ type: str
+ description: name of vrf.
+ trap:
+ description: Set syslog server logging level
+ type: dict
+ suboptions:
+ state: *state
+ severity: *severity1
+ hosts:
+ description: Set syslog server IP address and parameters
+ type: list
+ elements: dict
+ suboptions:
+ severity:
+ description: Logging severity level
+ type: str
+ choices:
+ - alerts
+ - critical
+ - debugging
+ - emergencies
+ - error
+ - info
+ - notifications
+ - warning
+ host:
+ description: IPv4/Ipv6 address or hostname of the syslog server
+ type: str
+ port:
+ description: Set <0-65535> non-default Port.
+ type: str
+ default: default
+ vrf:
+ description: Set VRF option
+ type: str
+ default: default
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS device by
+ executing the command B(show running-config | include logging).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - gathered
+ - parsed
+ - rendered
+ default: merged
+ description:
+ - The state the configuration should be left in
+ type: str
+"""
+EXAMPLES = """
+# Using merged
+#-----------------
+# Before state
+#RP/0/0/CPU0:10#show running-config logging
+#Thu Feb 4 09:38:36.245 UTC
+#% No such configuration item(s)
+#RP/0/0/CPU0:10#
+#
+#
+- name: Merge the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_logging_global:
+ config:
+ buffered:
+ size: 2097152
+ severity: warnings
+ correlator:
+ buffer_size: 1024
+ events:
+ display_location: True
+ files:
+ - maxfilesize: '1024'
+ name: test
+ path: test
+ severity: info
+ hostnameprefix: test
+ hosts:
+ - host: 1.1.1.1
+ port: default
+ severity: critical
+ vrf: default
+ ipv4:
+ dscp: af11
+ localfilesize: 1024
+ monitor:
+ severity: errors
+ source_interfaces:
+ - interface: GigabitEthernet0/0/0/0
+ vrf: test
+ tls_servers:
+ - name: test
+ tls_hostname: test2
+ trustpoint: test2
+ vrf: test
+ trap:
+ severity: informational
+ state: merged
+#
+#
+# After state:
+#-------------------------------------------
+#RP/0/0/CPU0:10#show running-config logging
+# Tue Jul 20 18:09:18.491 UTC
+# logging tls-server test
+# vrf test
+# trustpoint test2
+# tls-hostname test2
+# !
+# logging file test path test maxfilesize 1024 severity info
+# logging ipv4 dscp af11
+# logging trap informational
+# logging events display-location
+# logging monitor errors
+# logging buffered 2097152
+# logging buffered warnings
+# logging 1.1.1.1 vrf default severity critical port default
+# logging correlator buffer-size 1024
+# logging localfilesize 1024
+# logging source-interface GigabitEthernet0/0/0/0 vrf test
+# logging hostnameprefix test
+#------------------------------------------------
+#Module execution
+#
+# "after": {
+# "buffered": {
+# "severity": "errors"
+# },
+# "correlator": {
+# "buffer_size": 1024
+# },
+# "files": [
+# {
+# "maxfilesize": "1024",
+# "name": "test",
+# "path": "test1",
+# "severity": "info"
+# }
+# ],
+# "hostnameprefix": "test1",
+# "hosts": [
+# {
+# "host": "1.1.1.3",
+# "port": "default",
+# "severity": "critical",
+# "vrf": "default"
+# }
+# ],
+# "ipv6": {
+# "dscp": "af11"
+# },
+# "localfilesize": 1024,
+# "source_interfaces": [
+# {
+# "interface": "GigabitEthernet0/0/0/0",
+# "vrf": "test1"
+# }
+# ],
+# "tls_servers": [
+# {
+# "name": "test",
+# "tls_hostname": "test2",
+# "trustpoint": "test",
+# "vrf": "test"
+# }
+# ]
+# },
+# "before": {},
+# "changed": true,
+# "commands": [
+# "logging buffered errors",
+# "logging correlator buffer-size 1024",
+# "logging hostnameprefix test1",
+# "logging ipv6 dscp af11",
+# "logging localfilesize 1024",
+# "logging trap disable",
+# "logging monitor disable",
+# "logging history disable",
+# "logging console disable",
+# "logging 1.1.1.3 vrf default severity critical port default",
+# "logging file test path test1 maxfilesize 1024 severity info",
+# "logging source-interface GigabitEthernet0/0/0/0 vrf test1",
+# "logging tls-server test tls-hostname test2",
+# "logging tls-server test trustpoint test",
+# "logging tls-server test vrf test"
+# ],
+# "invocation": {
+# "module_args": {
+# "config": {
+# "archive": null,
+# "buffered": {
+# "discriminator": null,
+# "severity": "errors",
+# "size": null
+# },
+# "console": {
+# "discriminator": null,
+# "severity": null,
+# "state": "disabled"
+# },
+# "correlator": {
+# "buffer_size": 1024,
+# "rule_set": null,
+# "rules": null
+# },
+# "events": null,
+# "facility": null,
+# "files": [
+# {
+# "maxfilesize": "1024",
+# "name": "test",
+# "path": "test1",
+# "severity": "info"
+# }
+# ],
+# "format": null,
+# "history": {
+# "severity": null,
+# "size": null,
+# "state": "disabled"
+# },
+# "hostnameprefix": "test1",
+# "hosts": [
+# {
+# "host": "1.1.1.3",
+# "port": "default",
+# "severity": "critical",
+# "vrf": "default"
+# }
+# ],
+# "ipv4": null,
+# "ipv6": {
+# "dscp": "af11",
+# "precedence": null
+# },
+# "localfilesize": 1024,
+# "monitor": {
+# "discriminator": null,
+# "severity": null,
+# "state": "disabled"
+# },
+# "source_interfaces": [
+# {
+# "interface": "GigabitEthernet0/0/0/0",
+# "vrf": "test1"
+# }
+# ],
+# "suppress": null,
+# "tls_servers": [
+# {
+# "name": "test",
+# "severity": null,
+# "tls_hostname": "test2",
+# "trustpoint": "test",
+# "vrf": "test"
+# }
+# ],
+# "trap": {
+# "severity": null,
+# "state": "disabled"
+# }
+# },
+# "running_config": null,
+# "state": "merged"
+# }
+# }
+# }
+#
+# Using replaced:
+# -----------------------------------------------------------
+#
+#Before state
+#RP/0/0/CPU0:10#show running-config logging
+# Tue Jul 20 18:09:18.491 UTC
+# logging tls-server test
+# vrf test
+# trustpoint test2
+# tls-hostname test2
+# !
+# logging file test path test maxfilesize 1024 severity info
+# logging ipv4 dscp af11
+# logging trap informational
+# logging events display-location
+# logging monitor errors
+# logging buffered 2097152
+# logging buffered warnings
+# logging 1.1.1.1 vrf default severity critical port default
+# logging correlator buffer-size 1024
+# logging localfilesize 1024
+# logging source-interface GigabitEthernet0/0/0/0 vrf test
+# logging hostnameprefix test
+#-----------------------------------------------------------
+#
+- name: Replace BGP configuration with provided configuration
+ cisco.iosxr.iosxr_logging_global:
+ state: replaced
+ config:
+ buffered:
+ severity: errors
+ correlator:
+ buffer_size: 1024
+ files:
+ - maxfilesize: '1024'
+ name: test
+ path: test1
+ severity: info
+ hostnameprefix: test1
+ hosts:
+ - host: 1.1.1.3
+ port: default
+ severity: critical
+ vrf: default
+ ipv6:
+ dscp: af11
+ localfilesize: 1024
+ monitor:
+ severity: errors
+ tls_servers:
+ - name: test
+ tls_hostname: test2
+ trustpoint: test
+ vrf: test
+ trap:
+ severity: critical
+#
+# After state:
+#RP/0/0/CPU0:10#show running-config logging
+# Tue Jul 20 18:31:51.709 UTC
+# logging tls-server test
+# vrf test
+# trustpoint test
+# tls-hostname test2
+# !
+# logging file test path test1 maxfilesize 1024 severity info
+# logging ipv6 dscp af11
+# logging trap critical
+# logging monitor errors
+# logging buffered errors
+# logging 1.1.1.3 vrf default severity critical port default
+# logging correlator buffer-size 1024
+# logging localfilesize 1024
+# logging hostnameprefix test1
+#-----------------------------------------------------------------
+#
+# Module Execution:
+# "after": {
+# "buffered": {
+# "severity": "errors"
+# },
+# "correlator": {
+# "buffer_size": 1024
+# },
+# "files": [
+# {
+# "maxfilesize": "1024",
+# "name": "test",
+# "path": "test1",
+# "severity": "info"
+# }
+# ],
+# "hostnameprefix": "test1",
+# "hosts": [
+# {
+# "host": "1.1.1.3",
+# "port": "default",
+# "severity": "critical",
+# "vrf": "default"
+# }
+# ],
+# "ipv6": {
+# "dscp": "af11"
+# },
+# "localfilesize": 1024,
+# "monitor": {
+# "severity": "errors"
+# },
+# "tls_servers": [
+# {
+# "name": "test",
+# "tls_hostname": "test2",
+# "trustpoint": "test",
+# "vrf": "test"
+# }
+# ],
+# "trap": {
+# "severity": "critical"
+# }
+# },
+# "before": {
+# "buffered": {
+# "severity": "warnings",
+# "size": 2097152
+# },
+# "correlator": {
+# "buffer_size": 1024
+# },
+# "events": {
+# "display_location": true
+# },
+# "files": [
+# {
+# "maxfilesize": "1024",
+# "name": "test",
+# "path": "test",
+# "severity": "info"
+# }
+# ],
+# "hostnameprefix": "test",
+# "hosts": [
+# {
+# "host": "1.1.1.1",
+# "port": "default",
+# "severity": "critical",
+# "vrf": "default"
+# }
+# ],
+# "ipv4": {
+# "dscp": "af11"
+# },
+# "localfilesize": 1024,
+# "monitor": {
+# "severity": "errors"
+# },
+# "source_interfaces": [
+# {
+# "interface": "GigabitEthernet0/0/0/0",
+# "vrf": "test"
+# }
+# ],
+# "tls_servers": [
+# {
+# "name": "test",
+# "tls_hostname": "test2",
+# "trustpoint": "test2",
+# "vrf": "test"
+# }
+# ],
+# "trap": {
+# "severity": "informational"
+# }
+# },
+# "changed": true,
+# "commands": [
+# "no logging buffered 2097152",
+# "no logging events display-location",
+# "no logging ipv4 dscp af11",
+# "no logging 1.1.1.1 vrf default severity critical port default",
+# "no logging source-interface GigabitEthernet0/0/0/0 vrf test",
+# "logging buffered errors",
+# "logging hostnameprefix test1",
+# "logging ipv6 dscp af11",
+# "logging trap critical",
+# "logging 1.1.1.3 vrf default severity critical port default",
+# "logging file test path test1 maxfilesize 1024 severity info",
+# "logging tls-server test trustpoint test"
+# ],
+#
+#
+#
+# Using deleted:
+# -----------------------------------------------------------
+# Before state:
+#RP/0/0/CPU0:10#show running-config logging
+# Tue Jul 20 18:09:18.491 UTC
+# logging tls-server test
+# vrf test
+# trustpoint test2
+# tls-hostname test2
+# !
+# logging file test path test maxfilesize 1024 severity info
+# logging ipv4 dscp af11
+# logging trap informational
+# logging events display-location
+# logging monitor errors
+# logging buffered 2097152
+# logging buffered warnings
+# logging 1.1.1.1 vrf default severity critical port default
+# logging correlator buffer-size 1024
+# logging localfilesize 1024
+# logging source-interface GigabitEthernet0/0/0/0 vrf test
+# logging hostnameprefix test
+#
+#-----------------------------------------------------------
+- name: Delete given logging_global configuration
+ cisco.iosxr.iosxr_logging_global:
+ state: deleted
+#
+# After state:
+#RP/0/0/CPU0:10#show running-config
+#
+#-------------------------------------------------------------
+# Module Execution:
+#
+# "after": {},
+# "before": {
+# "buffered": {
+# "severity": "warnings",
+# "size": 2097152
+# },
+# "correlator": {
+# "buffer_size": 1024
+# },
+# "events": {
+# "display_location": true
+# },
+# "files": [
+# {
+# "maxfilesize": "1024",
+# "name": "test",
+# "path": "test",
+# "severity": "info"
+# }
+# ],
+# "hostnameprefix": "test",
+# "hosts": [
+# {
+# "host": "1.1.1.1",
+# "port": "default",
+# "severity": "critical",
+# "vrf": "default"
+# }
+# ],
+# "ipv4": {
+# "dscp": "af11"
+# },
+# "localfilesize": 1024,
+# "monitor": {
+# "severity": "errors"
+# },
+# "source_interfaces": [
+# {
+# "interface": "GigabitEthernet0/0/0/0",
+# "vrf": "test"
+# }
+# ],
+# "tls_servers": [
+# {
+# "name": "test",
+# "tls_hostname": "test2",
+# "trustpoint": "test2",
+# "vrf": "test"
+# }
+# ],
+# "trap": {
+# "severity": "informational"
+# }
+# },
+# "changed": true,
+# "commands": [
+# "no logging buffered 2097152",
+# "no logging buffered warnings",
+# "no logging correlator buffer-size 1024",
+# "no logging events display-location",
+# "no logging hostnameprefix test",
+# "no logging ipv4 dscp af11",
+# "no logging localfilesize 1024",
+# "no logging monitor errors",
+# "no logging trap informational",
+# "no logging 1.1.1.1 vrf default severity critical port default",
+# "no logging file test path test maxfilesize 1024 severity info",
+# "no logging source-interface GigabitEthernet0/0/0/0 vrf test",
+# "no logging tls-server test"
+# ],
+# "invocation": {
+# "module_args": {
+# "config": null,
+# "running_config": null,
+# "state": "deleted"
+# }
+# }
+#
+#
+#
+# using gathered:
+# ------------------------------------------------------------
+# Before state:
+#RP/0/0/CPU0:10#show running-config logging
+# Tue Jul 20 18:09:18.491 UTC
+# logging tls-server test
+# vrf test
+# trustpoint test2
+# tls-hostname test2
+# !
+# logging file test path test maxfilesize 1024 severity info
+# logging ipv4 dscp af11
+# logging trap informational
+# logging events display-location
+# logging monitor errors
+# logging buffered 2097152
+# logging buffered warnings
+# logging 1.1.1.1 vrf default severity critical port default
+# logging correlator buffer-size 1024
+# logging localfilesize 1024
+# logging source-interface GigabitEthernet0/0/0/0 vrf test
+# logging hostnameprefix test
+#
+#
+- name: Gather iosxr_logging_global facts using gathered state
+ cisco.iosxr.iosxr_logging_global:
+ state: gathered
+#
+#-------------------------------------------------------------
+# Module Execution:
+#
+# "changed": false,
+# "gathered": {
+# "buffered": {
+# "severity": "warnings",
+# "size": 2097152
+# },
+# "correlator": {
+# "buffer_size": 1024
+# },
+# "events": {
+# "display_location": true
+# },
+# "files": [
+# {
+# "maxfilesize": "1024",
+# "name": "test",
+# "path": "test",
+# "severity": "info"
+# }
+# ],
+# "hostnameprefix": "test",
+# "hosts": [
+# {
+# "host": "1.1.1.1",
+# "port": "default",
+# "severity": "critical",
+# "vrf": "default"
+# }
+# ],
+# "ipv4": {
+# "dscp": "af11"
+# },
+# "localfilesize": 1024,
+# "monitor": {
+# "severity": "errors"
+# },
+# "source_interfaces": [
+# {
+# "interface": "GigabitEthernet0/0/0/0",
+# "vrf": "test"
+# }
+# ],
+# "tls_servers": [
+# {
+# "name": "test",
+# "tls_hostname": "test2",
+# "trustpoint": "test2",
+# "vrf": "test"
+# }
+# ],
+# "trap": {
+# "severity": "informational"
+# }
+# },
+# "invocation": {
+# "module_args": {
+# "config": null,
+# "running_config": null,
+# "state": "gathered"
+# }
+# }
+#
+#
+# Using parsed:
+#---------------------------------------------------------------
+#
+# parsed.cfg
+#
+# logging tls-server test
+# vrf test
+# trustpoint test2
+# tls-hostname test2
+# !
+# logging file test path test maxfilesize 1024 severity info
+# logging ipv4 dscp af11
+# logging trap informational
+# logging events display-location
+# logging monitor errors
+# logging buffered 2097152
+# logging buffered warnings
+# logging 1.1.1.1 vrf default severity critical port default
+# logging correlator buffer-size 1024
+# logging localfilesize 1024
+# logging source-interface GigabitEthernet0/0/0/0 vrf test
+# logging hostnameprefix test
+#
+#
+- name: Parse externally provided Logging global config to agnostic model
+ cisco.iosxr.iosxr_logging_global:
+ running_config: "{{ lookup('file', './fixtures/parsed.cfg') }}"
+ state: parsed
+#----------------------------------------------------------------
+# Module execution:
+# "changed": false,
+# "parsed": {
+# "buffered": {
+# "severity": "warnings",
+# "size": 2097152
+# },
+# "correlator": {
+# "buffer_size": 1024
+# },
+# "events": {
+# "display_location": true
+# },
+# "files": [
+# {
+# "maxfilesize": "1024",
+# "name": "test",
+# "path": "test",
+# "severity": "info"
+# }
+# ],
+# "hostnameprefix": "test",
+# "hosts": [
+# {
+# "host": "1.1.1.1",
+# "port": "default",
+# "severity": "critical",
+# "vrf": "default"
+# }
+# ],
+# "ipv4": {
+# "dscp": "af11"
+# },
+# "localfilesize": 1024,
+# "monitor": {
+# "severity": "errors"
+# },
+# "source_interfaces": [
+# {
+# "interface": "GigabitEthernet0/0/0/0",
+# "vrf": "test"
+# }
+# ],
+# "tls_servers": [
+# {
+# "name": "test",
+# "tls_hostname": "test2",
+# "trustpoint": "test2",
+# "vrf": "test"
+# }
+# ],
+# "trap": {
+# "severity": "informational"
+# }
+# }
+#
+#
+# Using rendered:
+# ----------------------------------------------------------------------------
+- name: Render platform specific configuration lines with state rendered (without connecting to the device)
+ cisco.iosxr.iosxr_logging_global:
+ state: rendered
+ config:
+ buffered:
+ size: 2097152
+ severity: warnings
+ correlator:
+ buffer_size: 1024
+ events:
+ display_location: True
+ files:
+ - maxfilesize: '1024'
+ name: test
+ path: test
+ severity: info
+ hostnameprefix: test
+ hosts:
+ - host: 1.1.1.1
+ port: default
+ severity: critical
+ vrf: default
+ ipv4:
+ dscp: af11
+ localfilesize: 1024
+ monitor:
+ severity: errors
+ source_interfaces:
+ - interface: GigabitEthernet0/0/0/0
+ vrf: test
+ tls_servers:
+ - name: test
+ tls_hostname: test2
+ trustpoint: test2
+ vrf: test
+ trap:
+ severity: informational
+#----------------------------------------------------------------
+# Module Execution:
+# "rendered": [
+# "logging buffered errors",
+# "logging correlator buffer-size 1024",
+# "logging hostnameprefix test1",
+# "logging ipv6 dscp af11",
+# "logging localfilesize 1024",
+# "logging trap disable",
+# "logging monitor disable",
+# "logging history disable",
+# "logging console disable",
+# "logging 1.1.1.3 vrf default severity critical port default",
+# "logging file test path test1 maxfilesize 1024 severity info",
+# "logging source-interface GigabitEthernet0/0/0/0 vrf test1",
+# "logging tls-server test tls-hostname test2",
+# "logging tls-server test trustpoint test",
+# "logging tls-server test vrf test"
+# ]
+#
+# Using overridden:
+# ---------------------------------------------------------------------------------
+# Before state:
+#RP/0/0/CPU0:10#show running-config logging
+# Tue Jul 20 18:09:18.491 UTC
+# logging tls-server test
+# vrf test
+# trustpoint test2
+# tls-hostname test2
+# !
+# logging file test path test maxfilesize 1024 severity info
+# logging ipv4 dscp af11
+# logging trap informational
+# logging events display-location
+# logging monitor errors
+# logging buffered 2097152
+# logging buffered warnings
+# logging 1.1.1.1 vrf default severity critical port default
+# logging correlator buffer-size 1024
+# logging localfilesize 1024
+# logging source-interface GigabitEthernet0/0/0/0 vrf test
+# logging hostnameprefix test
+#
+#-----------------------------------------------------------
+#
+- name: Overridde logging global configuration with provided configuration
+ cisco.iosxr.iosxr_logging_global:
+ state: overridden
+ config:
+ buffered:
+ severity: errors
+ correlator:
+ buffer_size: 1024
+ files:
+ - maxfilesize: '1024'
+ name: test
+ path: test1
+ severity: info
+ hostnameprefix: test1
+ hosts:
+ - host: 1.1.1.3
+ port: default
+ severity: critical
+ vrf: default
+ ipv6:
+ dscp: af11
+ localfilesize: 1024
+ monitor:
+ severity: errors
+ tls_servers:
+ - name: test
+ tls_hostname: test2
+ trustpoint: test
+ vrf: test
+ trap:
+ severity: critical
+#
+# After state:
+#RP/0/0/CPU0:10#show running-config logging
+# Tue Jul 20 18:31:51.709 UTC
+# logging tls-server test
+# vrf test
+# trustpoint test
+# tls-hostname test2
+# !
+# logging file test path test1 maxfilesize 1024 severity info
+# logging ipv6 dscp af11
+# logging trap critical
+# logging monitor errors
+# logging buffered errors
+# logging 1.1.1.3 vrf default severity critical port default
+# logging correlator buffer-size 1024
+# logging localfilesize 1024
+# logging hostnameprefix test1
+#-----------------------------------------------------------------
+#
+# Module Execution:
+# "after": {
+# "buffered": {
+# "severity": "errors"
+# },
+# "correlator": {
+# "buffer_size": 1024
+# },
+# "files": [
+# {
+# "maxfilesize": "1024",
+# "name": "test",
+# "path": "test1",
+# "severity": "info"
+# }
+# ],
+# "hostnameprefix": "test1",
+# "hosts": [
+# {
+# "host": "1.1.1.3",
+# "port": "default",
+# "severity": "critical",
+# "vrf": "default"
+# }
+# ],
+# "ipv6": {
+# "dscp": "af11"
+# },
+# "localfilesize": 1024,
+# "monitor": {
+# "severity": "errors"
+# },
+# "tls_servers": [
+# {
+# "name": "test",
+# "tls_hostname": "test2",
+# "trustpoint": "test",
+# "vrf": "test"
+# }
+# ],
+# "trap": {
+# "severity": "critical"
+# }
+# },
+# "before": {
+# "buffered": {
+# "severity": "warnings",
+# "size": 2097152
+# },
+# "correlator": {
+# "buffer_size": 1024
+# },
+# "events": {
+# "display_location": true
+# },
+# "files": [
+# {
+# "maxfilesize": "1024",
+# "name": "test",
+# "path": "test",
+# "severity": "info"
+# }
+# ],
+# "hostnameprefix": "test",
+# "hosts": [
+# {
+# "host": "1.1.1.1",
+# "port": "default",
+# "severity": "critical",
+# "vrf": "default"
+# }
+# ],
+# "ipv4": {
+# "dscp": "af11"
+# },
+# "localfilesize": 1024,
+# "monitor": {
+# "severity": "errors"
+# },
+# "source_interfaces": [
+# {
+# "interface": "GigabitEthernet0/0/0/0",
+# "vrf": "test"
+# }
+# ],
+# "tls_servers": [
+# {
+# "name": "test",
+# "tls_hostname": "test2",
+# "trustpoint": "test2",
+# "vrf": "test"
+# }
+# ],
+# "trap": {
+# "severity": "informational"
+# }
+# },
+# "changed": true,
+# "commands": [
+# "no logging buffered 2097152",
+# "no logging events display-location",
+# "no logging ipv4 dscp af11",
+# "no logging 1.1.1.1 vrf default severity critical port default",
+# "no logging source-interface GigabitEthernet0/0/0/0 vrf test",
+# "logging buffered errors",
+# "logging hostnameprefix test1",
+# "logging ipv6 dscp af11",
+# "logging trap critical",
+# "logging 1.1.1.3 vrf default severity critical port default",
+# "logging file test path test1 maxfilesize 1024 severity info",
+# "logging tls-server test trustpoint test"
+# ],
+#
+"""
+
+RETURN = """
+before:
+ description: The configuration prior to the module execution.
+ returned: when state is I(merged), I(replaced), I(overridden), I(deleted) or I(purged)
+ type: dict
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+after:
+ description: The resulting configuration after module execution.
+ returned: when changed
+ type: dict
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: when state is I(merged), I(replaced), I(overridden), I(deleted) or I(purged)
+ type: list
+ sample:
+ - "logging file test path test1 maxfilesize 1024 severity info"
+ - "logging ipv6 dscp af11"
+ - "logging trap critical"
+ - "logging monitor errors"
+ - "logging buffered errors"
+ - "logging 1.1.1.3 vrf default severity critical port default"
+rendered:
+ description: The provided configuration in the task rendered in device-native format (offline).
+ returned: when state is I(rendered)
+ type: list
+ sample:
+ - "logging buffered errors"
+ - "logging correlator buffer-size 1024"
+ - "logging hostnameprefix test1"
+ - "logging ipv6 dscp af11"
+ - "logging localfilesize 1024"
+ - "logging trap disable"
+ - "logging monitor disable"
+ - "logging history disable"
+ - "logging console disable"
+gathered:
+ description: Facts about the network resource gathered from the remote device as structured data.
+ returned: when state is I(gathered)
+ type: list
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+parsed:
+ description: The device native config provided in I(running_config) option parsed into structured data as per module argspec.
+ returned: when state is I(parsed)
+ type: list
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.logging_global.logging_global import (
+ Logging_globalArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.logging_global.logging_global import (
+ Logging_global,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ module = AnsibleModule(
+ argument_spec=Logging_globalArgs.argument_spec,
+ mutually_exclusive=[["config", "running_config"]],
+ required_if=[
+ ["state", "merged", ["config"]],
+ ["state", "replaced", ["config"]],
+ ["state", "overridden", ["config"]],
+ ["state", "rendered", ["config"]],
+ ["state", "parsed", ["running_config"]],
+ ],
+ supports_check_mode=True,
+ )
+
+ result = Logging_global(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_netconf.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_netconf.py
new file mode 100644
index 00000000..e9a1c7c7
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_netconf.py
@@ -0,0 +1,206 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# (c) 2017, Ansible by Red Hat, Inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_netconf
+author: Kedar Kekan (@kedarX)
+short_description: Configures NetConf sub-system service on Cisco IOS-XR devices
+description:
+- This module provides an abstraction that enables and configures the netconf system
+ service running on Cisco IOS-XR Software. This module can be used to easily enable
+ the Netconf API. Netconf provides a programmatic interface for working with configuration
+ and state resources as defined in RFC 6242.
+version_added: 1.0.0
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+options:
+ netconf_port:
+ description:
+ - This argument specifies the port the netconf service should listen on for SSH
+ connections. The default port as defined in RFC 6242 is 830.
+ required: false
+ type: int
+ default: 830
+ aliases:
+ - listens_on
+ netconf_vrf:
+ description:
+ - netconf vrf name
+ required: false
+ type: str
+ default: default
+ aliases:
+ - vrf
+ state:
+ description:
+ - Specifies the state of the C(iosxr_netconf) resource on the remote device. If
+ the I(state) argument is set to I(present) the netconf service will be configured. If
+ the I(state) argument is set to I(absent) the netconf service will be removed
+ from the configuration.
+ type: str
+ required: false
+ default: present
+ choices:
+ - present
+ - absent
+notes:
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html).
+"""
+
+EXAMPLES = """
+- name: enable netconf service on port 830
+ cisco.iosxr.iosxr_netconf:
+ listens_on: 830
+ state: present
+
+- name: disable netconf service
+ cisco.iosxr.iosxr_netconf:
+ state: absent
+"""
+
+RETURN = """
+commands:
+ description: Returns the command sent to the remote device
+ returned: when changed is True
+ type: str
+ sample: 'ssh server netconf port 830'
+"""
+import re
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.six import iteritems
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ get_config,
+ load_config,
+)
+
+
+USE_PERSISTENT_CONNECTION = True
+
+
+def map_obj_to_commands(updates):
+ want, have = updates
+ commands = list()
+
+ if want["state"] == "absent":
+ if have["state"] == "present":
+ commands.append("no netconf-yang agent ssh")
+
+ if "netconf_port" in have:
+ commands.append("no ssh server netconf port %s" % have["netconf_port"])
+
+ if have["netconf_vrf"]:
+ for vrf in have["netconf_vrf"]:
+ commands.append("no ssh server netconf vrf %s" % vrf)
+ else:
+ if have["state"] == "absent":
+ commands.append("netconf-yang agent ssh")
+
+ if want["netconf_port"] is not None and (want["netconf_port"] != have.get("netconf_port")):
+ commands.append("ssh server netconf port %s" % want["netconf_port"])
+ if want["netconf_vrf"] is not None and (want["netconf_vrf"] not in have["netconf_vrf"]):
+ commands.append("ssh server netconf vrf %s" % want["netconf_vrf"])
+
+ return commands
+
+
+def parse_vrf(config):
+ match = re.search(r"vrf (\w+)", config)
+ if match:
+ return match.group(1)
+
+
+def parse_port(config):
+ match = re.search(r"port (\d+)", config)
+ if match:
+ return int(match.group(1))
+
+
+def map_config_to_obj(module):
+ obj = {"state": "absent"}
+
+ netconf_config = get_config(module, config_filter="netconf-yang agent")
+
+ ssh_config = get_config(module, config_filter="ssh server")
+ ssh_config = [
+ config_line
+ for config_line in (line.strip() for line in ssh_config.splitlines())
+ if config_line
+ ]
+ obj["netconf_vrf"] = []
+ for config in ssh_config:
+ if "netconf port" in config:
+ obj.update({"netconf_port": parse_port(config)})
+ if "netconf vrf" in config:
+ obj["netconf_vrf"].append(parse_vrf(config))
+ if "ssh" in netconf_config and ("netconf_port" in obj or obj["netconf_vrf"]):
+ obj.update({"state": "present"})
+
+ if "ssh" in netconf_config and "netconf_port" not in obj:
+ obj.update({"netconf_port": 830})
+
+ return obj
+
+
+def validate_netconf_port(value, module):
+ if not 1 <= value <= 65535:
+ module.fail_json(msg="netconf_port must be between 1 and 65535")
+
+
+def map_params_to_obj(module):
+ obj = {
+ "netconf_port": module.params["netconf_port"],
+ "netconf_vrf": module.params["netconf_vrf"],
+ "state": module.params["state"],
+ }
+
+ for key, value in iteritems(obj):
+ # validate the param value (if validator func exists)
+ validator = globals().get("validate_%s" % key)
+ if callable(validator):
+ validator(value, module)
+
+ return obj
+
+
+def main():
+ """main entry point for module execution"""
+ argument_spec = dict(
+ netconf_port=dict(type="int", default=830, aliases=["listens_on"]),
+ netconf_vrf=dict(aliases=["vrf"], default="default"),
+ state=dict(default="present", choices=["present", "absent"]),
+ )
+
+ module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
+
+ warnings = list()
+
+ result = {"changed": False, "warnings": warnings}
+
+ want = map_params_to_obj(module)
+ have = map_config_to_obj(module)
+ commands = map_obj_to_commands((want, have))
+ result["commands"] = commands
+
+ if commands:
+ commit = not module.check_mode
+ diff = load_config(module, commands, commit=commit)
+ if diff:
+ result["diff"] = dict(prepared=diff)
+ result["changed"] = True
+
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ntp_global.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ntp_global.py
new file mode 100644
index 00000000..94ca24f4
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ntp_global.py
@@ -0,0 +1,1096 @@
+#!/usr/bin/python
+# -*- 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)
+
+"""
+The module file for iosxr_ntp_global
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+---
+module: iosxr_ntp_global
+short_description: Resource module to configure NTP.
+description: This module configures and manages the attributes of ntp on Cisco
+ IOSXR platforms.
+version_added: 2.5.0
+author: Ashwini Mhatre (@amhatre)
+notes:
+ - Tested against IOSXR 7.0.2.
+ - This module works with connection C(network_cli).
+options:
+ config:
+ description: A dictionary of ntp options
+ type: dict
+ suboptions:
+ access_group:
+ description: Control NTP access
+ type: dict
+ suboptions:
+ ipv4: &ipv4
+ type: dict
+ description: Configure IPv4 access
+ suboptions:
+ peer: &peer
+ type: str
+ description: Provide full access
+ query_only: &query_only
+ type: str
+ description: Allow only control queries.
+ serve: &serve
+ type: str
+ description: Provide server and query access.
+ serve_only: &serve_only
+ type: str
+ description: Provide only server access.
+ ipv6: &ipv6
+ type: dict
+ description: Configure IPv6 access
+ suboptions:
+ peer: *peer
+ query_only: *query_only
+ serve: *serve
+ serve_only: *serve_only
+ vrfs:
+ type: list
+ elements: dict
+ description: Specify non-default VRF.
+ suboptions:
+ name:
+ type: str
+ description: Specify non-default VRF.
+ ipv4: *ipv4
+ ipv6: *ipv6
+ authenticate:
+ description: Authenticate time sources
+ type: bool
+ authentication_keys:
+ description: Authentication key for trusted time sources
+ type: list
+ elements: dict
+ suboptions:
+ id:
+ description: <1-65535> Key number
+ type: int
+ key:
+ description: Authentication key.
+ type: str
+ encryption:
+ description: Type of key encrypted or clear-text.
+ type: bool
+ broadcastdelay:
+ type: int
+ description: Estimated round-trip delay in microseconds.
+ drift:
+ type: dict
+ description: Drift(cisco-support)
+ suboptions:
+ aging_time:
+ type: int
+ description: Aging time in hours.
+ file:
+ description: File for drift values.
+ type: str
+ interfaces:
+ type: list
+ elements: dict
+ description: Configure NTP on an interface.
+ suboptions:
+ name:
+ type: str
+ description: Name of the interface.
+ vrf:
+ type: str
+ description: Name of the vrf.
+ broadcast_client:
+ type: bool
+ description: Listen to NTP broadcasts
+ broadcast_destination:
+ type: str
+ description: Configure broadcast destination address.
+ broadcast_key:
+ type: int
+ description: Broadcast key number.
+ broadcast_version:
+ type: int
+ description: <2-4> NTP version number.
+ multicast_key:
+ type: int
+ description: Configure multicast authentication key.
+ multicast_ttl:
+ type: int
+ description: Configure TTL to use.
+ multicast_client:
+ type: str
+ description: Configure multicast client
+ multicast_destination:
+ type: str
+ description: Configure multicast destination
+ multicast_version:
+ type: int
+ description: <2-4> NTP version number.
+ ipv4: &ip
+ description: Mark the dscp/precedence bit for ipv4 packets.
+ type: dict
+ suboptions:
+ dscp:
+ description: Set IP DSCP (DiffServ CodePoint).Please refer vendor document for valid entries.
+ type: str
+ precedence:
+ description: Set precedence Please refer vendor document for valid entries.
+ type: str
+ choices: [ "critical", "flash", "flash-override", "immediate", "internet", "network", "priority", "routine" ]
+ ipv6: *ip
+ log_internal_sync:
+ type: bool
+ description: Logs internal synchronization changes.
+ master:
+ description: Act as NTP master clock
+ type: dict
+ suboptions:
+ stratum:
+ description: Use NTP as clock source with stratum number <1-15>
+ type: int
+ max_associations:
+ type: int
+ description: <0-4294967295> Number of associations.
+ passive:
+ type: bool
+ description: Enable the passive associations.
+ trusted_keys:
+ type: list
+ elements: dict
+ description: list of Key numbers for trusted time sources.
+ suboptions:
+ key_id:
+ type: int
+ description: Key numbers for trusted time sources.
+ update_calendar:
+ type: bool
+ description: Periodically update calendar with NTP time.
+ source_interface:
+ type: str
+ description: Configure default interface.
+ source_vrfs:
+ type: list
+ elements: dict
+ description: Configure default interface.
+ suboptions:
+ name:
+ type: str
+ description: Name of source interface.
+ vrf:
+ type: str
+ description: vrf name.
+ servers:
+ description: Configure NTP server.
+ type: list
+ elements: dict
+ suboptions:
+ vrf: &vrf
+ description: vrf name.
+ type: str
+ server: &host
+ description: Hostname or A.B.C.D or A:B:C:D:E:F:G:H.
+ type: str
+ required: True
+ burst: &burst
+ description: Use burst mode.
+ type: bool
+ iburst: &iburst
+ description: Use initial burst mode.
+ type: bool
+ key_id: &key
+ description: SConfigure peer authentication key
+ type: int
+ source: &source
+ description: Interface for source address.
+ type: str
+ maxpoll: &maxpoll
+ description: configure Maximum poll interval.
+ type: int
+ minpoll: &minpoll
+ description: configure Minimum poll interval.
+ type: int
+ prefer: &prefer
+ description: Prefer this peer when possible
+ type: bool
+ version: &version
+ description: NTP version.
+ type: int
+ peers:
+ description: Configure NTP peer.
+ type: list
+ elements: dict
+ suboptions:
+ vrf: *vrf
+ peer: *host
+ burst: *burst
+ iburst: *iburst
+ key_id: *key
+ source: *source
+ maxpoll: *maxpoll
+ minpoll: *minpoll
+ prefer: *prefer
+ version: *version
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOSXR device by
+ executing the command B(show running-config ntp).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state the configuration should be left in.
+ type: str
+ choices:
+ - deleted
+ - merged
+ - overridden
+ - replaced
+ - gathered
+ - rendered
+ - parsed
+ default: merged
+"""
+
+EXAMPLES = """
+# Using state: merged
+# Before state:
+# -------------
+# RP/0/0/CPU0:10#show running-config ntp
+# --------------------- EMPTY -----------------
+# Merged play:
+# ------------
+- name: Merge the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_ntp_global:
+ config:
+ access_group:
+ ipv4:
+ peer: PeerAcl1
+ query_only: QueryOnlyAcl1
+ serve: ServeAcl1
+ serve_only: ServeOnlyAcl1
+ vrfs:
+ - ipv4:
+ peer: PeerAcl3
+ serve: ServeAcl2
+ name: siteA
+ authenticate: true
+ broadcastdelay: 1
+ drift:
+ aging_time: 0
+ file: apphost
+ interfaces:
+ - name: GigabitEthernet0/0/0/0
+ multicast_client: 224.0.0.8
+ multicast_destination: 224.0.0.8
+ broadcast_client: true
+ ipv4:
+ dscp: af11
+ ipv6:
+ precedence: routine
+ log_internal_sync: true
+ master: 1
+ max_associations: 10
+ passive: true
+ peers:
+ - iburst: true
+ peer: 192.0.2.1
+ vrf: siteC
+ servers:
+ - burst: true
+ server: 192.0.2.2
+ vrf: siteD
+ source: GigabitEthernet0/0/0/0
+ source_vrfs:
+ - name: GigabitEthernet0/0/0/0
+ vrf: siteE
+ trusted_keys:
+ - key_id: 1
+ update_calendar: true
+# Commands Fired:
+# ------------
+# "commands": [
+# "ntp peer vrf siteC 192.0.2.1 iburst ",
+# "ntp server vrf siteD 192.0.2.2 burst ",
+# "ntp trusted-key 1",
+# "ntp interface GigabitEthernet0/0/0/0 broadcast client",
+# "ntp interface GigabitEthernet0/0/0/0 multicast destination 224.0.0.8",
+# "ntp interface GigabitEthernet0/0/0/0 multicast client 224.0.0.8",
+# "ntp vrf siteE source GigabitEthernet0/0/0/0",
+# "ntp access-group vrf siteA ipv4 serve ServeAcl2",
+# "ntp access-group vrf siteA ipv4 peer PeerAcl3",
+# "ntp access-group ipv4 peer PeerAcl1",
+# "ntp access-group ipv4 serve ServeAcl1",
+# "ntp access-group ipv4 serve-only ServeOnlyAcl1",
+# "ntp access-group ipv4 query-only QueryOnlyAcl1",
+# "ntp authenticate",
+# "ntp log-internal-sync",
+# "ntp broadcastdelay 1",
+# "ntp drift aging time 0",
+# "ntp drift file apphost",
+# "ntp ipv4 dscp af11",
+# "ntp ipv6 precedence routine",
+# "ntp max-associations 10",
+# "ntp master 1",
+# "ntp passive",
+# "ntp update-calendar",
+# "ntp source GigabitEthernet0/0/0/0"
+# ],
+# After state:
+# ------------
+# RP/0/0/CPU0:10#show running-config ntp
+# ntp
+# max-associations 10
+# interface GigabitEthernet0/0/0/0
+# broadcast client
+# multicast client 224.0.0.8
+# multicast destination 224.0.0.8
+# !
+# authenticate
+# trusted-key 1
+# ipv4 dscp af11
+# ipv6 precedence routine
+# peer vrf siteC 192.0.2.1 iburst
+# server vrf siteD 192.0.2.2 burst
+# drift file apphost
+# drift aging time 0
+# master 1
+# access-group vrf siteA ipv4 peer PeerAcl3
+# access-group vrf siteA ipv4 serve ServeAcl2
+# access-group ipv4 peer PeerAcl1
+# access-group ipv4 serve ServeAcl1
+# access-group ipv4 serve-only ServeOnlyAcl1
+# access-group ipv4 query-only QueryOnlyAcl1
+# source vrf siteE GigabitEthernet0/0/0/0
+# source GigabitEthernet0/0/0/0
+# passive
+# broadcastdelay 1
+# update-calendar
+# log-internal-sync
+# !
+# Using state: deleted
+# Before state:
+# -------------
+# RP/0/0/CPU0:10#show running-config ntp
+# ntp
+# max-associations 10
+# interface GigabitEthernet0/0/0/0
+# broadcast client
+# multicast client 224.0.0.8
+# multicast destination 224.0.0.8
+# !
+# authenticate
+# trusted-key 1
+# ipv4 dscp af11
+# ipv6 precedence routine
+# peer vrf siteC 192.0.2.1 iburst
+# server vrf siteD 192.0.2.2 burst
+# drift file apphost
+# drift aging time 0
+# master 1
+# access-group vrf siteA ipv4 peer PeerAcl3
+# access-group vrf siteA ipv4 serve ServeAcl2
+# access-group ipv4 peer PeerAcl1
+# access-group ipv4 serve ServeAcl1
+# access-group ipv4 serve-only ServeOnlyAcl1
+# access-group ipv4 query-only QueryOnlyAcl1
+# source vrf siteE GigabitEthernet0/0/0/0
+# source GigabitEthernet0/0/0/0
+# passive
+# broadcastdelay 1
+# update-calendar
+# log-internal-sync
+# !
+# Deleted play:
+# -------------
+- name: Remove all existing configuration
+ cisco.iosxr.iosxr_ntp_global:
+ state: deleted
+# Commands Fired:
+# ---------------
+# "commands": [
+# "no ntp peer vrf siteC 192.0.2.1 iburst ",
+# "no ntp server vrf siteD 192.0.2.2 burst ",
+# "no ntp trusted-key 1",
+# "no ntp interface GigabitEthernet0/0/0/0",
+# "no ntp vrf siteE source GigabitEthernet0/0/0/0",
+# "no ntp access-group vrf siteA ipv4 serve ServeAcl2",
+# "no ntp access-group vrf siteA ipv4 peer PeerAcl3",
+# "no ntp access-group ipv4 peer PeerAcl1",
+# "no ntp access-group ipv4 serve ServeAcl1",
+# "no ntp access-group ipv4 serve-only ServeOnlyAcl1",
+# "no ntp access-group ipv4 query-only QueryOnlyAcl1",
+# "no ntp authenticate",
+# "no ntp log-internal-sync",
+# "no ntp broadcastdelay 1",
+# "no ntp drift aging time 0",
+# "no ntp drift file apphost",
+# "no ntp ipv4 dscp af11",
+# "no ntp ipv6 precedence routine",
+# "no ntp max-associations 10",
+# "no ntp master 1",
+# "no ntp passive",
+# "no ntp update-calendar",
+# "no ntp source GigabitEthernet0/0/0/0"
+# ],
+# After state:
+# ------------
+# RP/0/0/CPU0:10#show running-config ntp
+# --------------------- EMPTY -----------------
+# Using state: overridden
+# Before state:
+# -------------
+# RP/0/0/CPU0:10#show running-config ntp
+# ntp
+# max-associations 10
+# interface GigabitEthernet0/0/0/0
+# broadcast client
+# multicast client 224.0.0.8
+# multicast destination 224.0.0.8
+# !
+# authenticate
+# trusted-key 1
+# ipv4 dscp af11
+# ipv6 precedence routine
+# peer vrf siteC 192.0.2.1 iburst
+# server vrf siteD 192.0.2.2 burst
+# drift file apphost
+# drift aging time 0
+# master 1
+# access-group vrf siteA ipv4 peer PeerAcl3
+# access-group vrf siteA ipv4 serve ServeAcl2
+# access-group ipv4 peer PeerAcl1
+# access-group ipv4 serve ServeAcl1
+# access-group ipv4 serve-only ServeOnlyAcl1
+# access-group ipv4 query-only QueryOnlyAcl1
+# source vrf siteE GigabitEthernet0/0/0/0
+# source GigabitEthernet0/0/0/0
+# passive
+# broadcastdelay 1
+# update-calendar
+# log-internal-sync
+# !
+# Overridden play:
+# ----------------
+- name: Override BGP configuration with provided configuration
+ cisco.iosxr.iosxr_ntp_global:
+ state: overridden
+ config:
+ access_group:
+ ipv4:
+ peer: PeerAcl1
+ query_only: QueryOnlyAcl1
+ serve: ServeAcl4
+ serve_only: ServeOnlyAcl1
+ vrfs:
+ - ipv4:
+ peer: PeerAcl3
+ serve: ServeAcl2
+ name: siteA
+ authenticate: true
+ broadcastdelay: 1
+ drift:
+ aging_time: 0
+ file: apphost
+ interfaces:
+ - name: GigabitEthernet0/0/0/1
+ multicast_client: 224.0.0.8
+ multicast_destination: 224.0.0.8
+ broadcast_client: true
+ ipv4:
+ dscp: af12
+ ipv6:
+ precedence: routine
+ log_internal_sync: true
+ master: 1
+ max_associations: 10
+ passive: true
+ peers:
+ - iburst: true
+ peer: 192.0.2.3
+ vrf: siteC
+ servers:
+ - burst: true
+ server: 192.0.2.2
+ vrf: siteD
+ source: GigabitEthernet0/0/0/1
+ source_vrfs:
+ - name: GigabitEthernet0/0/0/0
+ vrf: siteE
+ trusted_keys:
+ - key_id: 1
+ update_calendar: true
+# Commands Fired:
+# ---------------
+# "commands": [
+# "no ntp peer vrf siteC 192.0.2.1 iburst ",
+# "no ntp interface GigabitEthernet0/0/0/0",
+# "ntp peer vrf siteC 192.0.2.3 iburst ",
+# "ntp interface GigabitEthernet0/0/0/1 broadcast client",
+# "ntp interface GigabitEthernet0/0/0/1 multicast destination 224.0.0.8",
+# "ntp interface GigabitEthernet0/0/0/1 multicast client 224.0.0.8",
+# "ntp access-group ipv4 serve ServeAcl4",
+# "ntp ipv4 dscp af12",
+# "ntp source GigabitEthernet0/0/0/1"
+# ],
+# After state:
+# ------------
+# RP/0/RP0/CPU0:ios#show running-config ntp
+# Mon Sep 13 10:38:22.690 UTC
+# ntp
+# max-associations 10
+# interface GigabitEthernet0/0/0/1
+# broadcast client
+# multicast client 224.0.0.8
+# multicast destination 224.0.0.8
+# !
+# authentication-key 1 md5 encrypted testkey
+# authenticate
+# trusted-key 1
+# ipv4 dscp af12
+# ipv6 precedence routine
+# peer vrf siteC 192.0.2.3 iburst
+# server vrf siteD 192.0.2.2 burst
+# drift file apphost
+# drift aging time 0
+# master 1
+# access-group vrf siteA ipv4 peer PeerAcl3
+# access-group vrf siteA ipv4 serve ServeAcl2
+# access-group ipv4 peer PeerAcl1
+# access-group ipv4 serve ServeAcl4
+# access-group ipv4 serve-only ServeOnlyAcl1
+# access-group ipv4 query-only QueryOnlyAcl1
+# source vrf siteE GigabitEthernet0/0/0/0
+# source GigabitEthernet0/0/0/1
+# passive
+# broadcastdelay 1
+# update-calendar
+# log-internal-sync
+# !
+#
+# Using state: replaced
+# Before state:
+# -------------
+# RP/0/0/CPU0:10#show running-config ntp
+# ntp
+# max-associations 10
+# interface GigabitEthernet0/0/0/0
+# broadcast client
+# multicast client 224.0.0.8
+# multicast destination 224.0.0.8
+# !
+# authenticate
+# trusted-key 1
+# ipv4 dscp af11
+# ipv6 precedence routine
+# peer vrf siteC 192.0.2.1 iburst
+# server vrf siteD 192.0.2.2 burst
+# drift file apphost
+# drift aging time 0
+# master 1
+# access-group vrf siteA ipv4 peer PeerAcl3
+# access-group vrf siteA ipv4 serve ServeAcl2
+# access-group ipv4 peer PeerAcl1
+# access-group ipv4 serve ServeAcl1
+# access-group ipv4 serve-only ServeOnlyAcl1
+# access-group ipv4 query-only QueryOnlyAcl1
+# source vrf siteE GigabitEthernet0/0/0/0
+# source GigabitEthernet0/0/0/0
+# passive
+# broadcastdelay 1
+# update-calendar
+# log-internal-sync
+# !
+# Replaced play:
+# ----------------
+- name: Replaced BGP configuration with provided configuration
+ cisco.iosxr.iosxr_ntp_global:
+ state: replaced
+ config:
+ access_group:
+ ipv4:
+ peer: PeerAcl1
+ query_only: QueryOnlyAcl1
+ serve: ServeAcl4
+ serve_only: ServeOnlyAcl1
+ vrfs:
+ - ipv4:
+ peer: PeerAcl3
+ serve: ServeAcl2
+ name: siteA
+ authenticate: true
+ broadcastdelay: 1
+ drift:
+ aging_time: 0
+ file: apphost
+ interfaces:
+ - name: GigabitEthernet0/0/0/1
+ multicast_client: 224.0.0.8
+ multicast_destination: 224.0.0.8
+ broadcast_client: true
+ ipv4:
+ dscp: af12
+ ipv6:
+ precedence: routine
+ log_internal_sync: true
+ master: 1
+ max_associations: 10
+ passive: true
+ peers:
+ - iburst: true
+ peer: 192.0.2.3
+ vrf: siteC
+ servers:
+ - burst: true
+ server: 192.0.2.2
+ vrf: siteD
+ source: GigabitEthernet0/0/0/1
+ source_vrfs:
+ - name: GigabitEthernet0/0/0/0
+ vrf: siteE
+ trusted_keys:
+ - key_id: 1
+ update_calendar: true
+# Commands Fired:
+# ---------------
+# "commands": [
+# "no ntp peer vrf siteC 192.0.2.1 iburst ",
+# "no ntp interface GigabitEthernet0/0/0/0",
+# "ntp peer vrf siteC 192.0.2.3 iburst ",
+# "ntp interface GigabitEthernet0/0/0/1 broadcast client",
+# "ntp interface GigabitEthernet0/0/0/1 multicast destination 224.0.0.8",
+# "ntp interface GigabitEthernet0/0/0/1 multicast client 224.0.0.8",
+# "ntp access-group ipv4 serve ServeAcl4",
+# "ntp ipv4 dscp af12",
+# "ntp source GigabitEthernet0/0/0/1"
+# ],
+# After state:
+# ------------
+# RP/0/RP0/CPU0:ios#show running-config ntp
+# Mon Sep 13 10:38:22.690 UTC
+# ntp
+# max-associations 10
+# interface GigabitEthernet0/0/0/1
+# broadcast client
+# multicast client 224.0.0.8
+# multicast destination 224.0.0.8
+# !
+# authentication-key 1 md5 encrypted testkey
+# authenticate
+# trusted-key 1
+# ipv4 dscp af12
+# ipv6 precedence routine
+# peer vrf siteC 192.0.2.3 iburst
+# server vrf siteD 192.0.2.2 burst
+# drift file apphost
+# drift aging time 0
+# master 1
+# access-group vrf siteA ipv4 peer PeerAcl3
+# access-group vrf siteA ipv4 serve ServeAcl2
+# access-group ipv4 peer PeerAcl1
+# access-group ipv4 serve ServeAcl4
+# access-group ipv4 serve-only ServeOnlyAcl1
+# access-group ipv4 query-only QueryOnlyAcl1
+# source vrf siteE GigabitEthernet0/0/0/0
+# source GigabitEthernet0/0/0/1
+# passive
+# broadcastdelay 1
+# update-calendar
+# log-internal-sync
+# !
+# Using state: gathered
+# Before state:
+# -------------
+# RP/0/0/CPU0:10#show running-config ntp
+# ntp
+# max-associations 10
+# interface GigabitEthernet0/0/0/0
+# broadcast client
+# multicast client 224.0.0.8
+# multicast destination 224.0.0.8
+# !
+# authenticate
+# trusted-key 1
+# ipv4 dscp af11
+# ipv6 precedence routine
+# peer vrf siteC 192.0.2.1 iburst
+# server vrf siteD 192.0.2.2 burst
+# drift file apphost
+# drift aging time 0
+# master 1
+# access-group vrf siteA ipv4 peer PeerAcl3
+# access-group vrf siteA ipv4 serve ServeAcl2
+# access-group ipv4 peer PeerAcl1
+# access-group ipv4 serve ServeAcl1
+# access-group ipv4 serve-only ServeOnlyAcl1
+# access-group ipv4 query-only QueryOnlyAcl1
+# source vrf siteE GigabitEthernet0/0/0/0
+# source GigabitEthernet0/0/0/0
+# passive
+# broadcastdelay 1
+# update-calendar
+# log-internal-sync
+# !
+# Gathered play:
+# --------------
+- name: Gather listed ntp config
+ cisco.iosxr.iosxr_ntp_global:
+ state: gathered
+# Module Execution Result:
+# ------------------------
+# "gathered":{
+# "access_group": {
+# "ipv4": {
+# "peer": "PeerAcl1",
+# "query_only": "QueryOnlyAcl1",
+# "serve": "ServeAcl1",
+# "serve_only": "ServeOnlyAcl1"
+# },
+# "vrfs": [
+# {
+# "ipv4": {
+# "peer": "PeerAcl3",
+# "serve": "ServeAcl2"
+# },
+# "name": "siteA"
+# }
+# ]
+# },
+# "authenticate": true,
+# "broadcastdelay": 1,
+# "drift": {
+# "aging_time": 0,
+# "file": "apphost"
+# },
+# "interfaces": [
+# {
+# "broadcast_client": true,
+# "multicast_client": "224.0.0.8",
+# "multicast_destination": "224.0.0.8",
+# "name": "GigabitEthernet0/0/0/0"
+# }
+# ],
+# "ipv4": {
+# "dscp": "af11"
+# },
+# "ipv6": {
+# "precedence": "routine"
+# },
+# "log_internal_sync": true,
+# "master": 1,
+# "max_associations": 10,
+# "passive": true,
+# "peers": [
+# {
+# "iburst": true,
+# "peer": "192.0.2.1",
+# "vrf": "siteC"
+# }
+# ],
+# "servers": [
+# {
+# "burst": true,
+# "server": "192.0.2.2",
+# "vrf": "siteD"
+# }
+# ],
+# "source": "GigabitEthernet0/0/0/0",
+# "source_vrfs": [
+# {
+# "name": "GigabitEthernet0/0/0/0",
+# "vrf": "siteE"
+# }
+# ],
+# "trusted_keys": [
+# {
+# "key_id": 1
+# }
+# ],
+# "update_calendar": true
+# }
+# Using state: rendered
+# Rendered play:
+# --------------
+- name: Render platform specific configuration lines with state rendered (without connecting to the device)
+ cisco.iosxr.iosxr_ntp_global:
+ state: rendered
+ config:
+ access_group:
+ ipv4:
+ peer: PeerAcl1
+ query_only: QueryOnlyAcl1
+ serve: ServeAcl1
+ serve_only: ServeOnlyAcl1
+ vrfs:
+ - ipv4:
+ peer: PeerAcl3
+ serve: ServeAcl2
+ name: siteA
+ authenticate: true
+ broadcastdelay: 1
+ drift:
+ aging_time: 0
+ file: apphost
+ interfaces:
+ - name: GigabitEthernet0/0/0/0
+ multicast_client: 224.0.0.8
+ multicast_destination: 224.0.0.8
+ broadcast_client: true
+ ipv4:
+ dscp: af11
+ ipv6:
+ precedence: routine
+ log_internal_sync: true
+ master: 1
+ max_associations: 10
+ passive: true
+ peers:
+ - iburst: true
+ peer: 192.0.2.1
+ vrf: siteC
+ servers:
+ - burst: true
+ server: 192.0.2.2
+ vrf: siteD
+ source: GigabitEthernet0/0/0/0
+ source_vrfs:
+ - name: GigabitEthernet0/0/0/0
+ vrf: siteE
+ trusted_keys:
+ - key_id: 1
+ update_calendar: true
+ register: result
+# Module Execution Result:
+# ------------------------
+# "rendered": [
+# "ntp peer vrf siteC 192.0.2.1 iburst ",
+# "ntp server vrf siteD 192.0.2.2 burst ",
+# "ntp trusted-key 1",
+# "ntp interface GigabitEthernet0/0/0/0 broadcast client",
+# "ntp interface GigabitEthernet0/0/0/0 multicast destination 224.0.0.8",
+# "ntp interface GigabitEthernet0/0/0/0 multicast client 224.0.0.8",
+# "ntp vrf siteE source GigabitEthernet0/0/0/0",
+# "ntp access-group vrf siteA ipv4 serve ServeAcl2",
+# "ntp access-group vrf siteA ipv4 peer PeerAcl3",
+# "ntp access-group ipv4 peer PeerAcl1",
+# "ntp access-group ipv4 serve ServeAcl1",
+# "ntp access-group ipv4 serve-only ServeOnlyAcl1",
+# "ntp access-group ipv4 query-only QueryOnlyAcl1",
+# "ntp authenticate",
+# "ntp log-internal-sync",
+# "ntp broadcastdelay 1",
+# "ntp drift aging time 0",
+# "ntp drift file apphost",
+# "ntp ipv4 dscp af11",
+# "ntp ipv6 precedence routine",
+# "ntp max-associations 10",
+# "ntp master 1",
+# "ntp passive",
+# "ntp update-calendar",
+# "ntp source GigabitEthernet0/0/0/0"
+# ],
+# Using state: parsed
+# File: parsed.cfg
+# ----------------
+# ntp
+# max-associations 10
+# interface GigabitEthernet0/0/0/0
+# broadcast client
+# multicast client 224.0.0.8
+# multicast destination 224.0.0.8
+# !
+# authenticate
+# trusted-key 1
+# ipv4 dscp af11
+# ipv6 precedence routine
+# peer vrf siteC 192.0.2.1 iburst
+# server vrf siteD 192.0.2.2 burst
+# drift file apphost
+# drift aging time 0
+# master 1
+# access-group vrf siteA ipv4 peer PeerAcl3
+# access-group vrf siteA ipv4 serve ServeAcl2
+# access-group ipv4 peer PeerAcl1
+# access-group ipv4 serve ServeAcl1
+# access-group ipv4 serve-only ServeOnlyAcl1
+# access-group ipv4 query-only QueryOnlyAcl1
+# source vrf siteE GigabitEthernet0/0/0/0
+# source GigabitEthernet0/0/0/0
+# passive
+# broadcastdelay 1
+# update-calendar
+# log-internal-sync
+# !
+# Parsed play:
+# ------------
+- name: Parse the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_ntp_global:
+ running_config: "{{ lookup('file', 'parsed.cfg') }}"
+ state: parsed
+# Module Execution Result:
+# ------------------------
+# "parsed":{
+# "access_group": {
+# "ipv4": {
+# "peer": "PeerAcl1",
+# "query_only": "QueryOnlyAcl1",
+# "serve": "ServeAcl1",
+# "serve_only": "ServeOnlyAcl1"
+# },
+# "vrfs": [
+# {
+# "ipv4": {
+# "peer": "PeerAcl3",
+# "serve": "ServeAcl2"
+# },
+# "name": "siteA"
+# }
+# ]
+# },
+# "authenticate": true,
+# "broadcastdelay": 1,
+# "drift": {
+# "aging_time": 0,
+# "file": "apphost"
+# },
+# "interfaces": [
+# {
+# "broadcast_client": true,
+# "multicast_client": "224.0.0.8",
+# "multicast_destination": "224.0.0.8",
+# "name": "GigabitEthernet0/0/0/0"
+# }
+# ],
+# "ipv4": {
+# "dscp": "af11"
+# },
+# "ipv6": {
+# "precedence": "routine"
+# },
+# "log_internal_sync": true,
+# "master": 1,
+# "max_associations": 10,
+# "passive": true,
+# "peers": [
+# {
+# "iburst": true,
+# "peer": "192.0.2.1",
+# "vrf": "siteC"
+# }
+# ],
+# "servers": [
+# {
+# "burst": true,
+# "server": "192.0.2.2",
+# "vrf": "siteD"
+# }
+# ],
+# "source": "GigabitEthernet0/0/0/0",
+# "source_vrfs": [
+# {
+# "name": "GigabitEthernet0/0/0/0",
+# "vrf": "siteE"
+# }
+# ],
+# "trusted_keys": [
+# {
+# "key_id": 1
+# }
+# ],
+# "update_calendar": true
+# }
+"""
+
+RETURN = """
+before:
+ description: The configuration prior to the module execution.
+ returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged)
+ type: dict
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+after:
+ description: The resulting configuration after module execution.
+ returned: when changed
+ type: dict
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged)
+ type: list
+ sample:
+ - sample command 1
+ - sample command 2
+ - sample command 3
+rendered:
+ description: The provided configuration in the task rendered in device-native format (offline).
+ returned: when I(state) is C(rendered)
+ type: list
+ sample:
+ - sample command 1
+ - sample command 2
+ - sample command 3
+gathered:
+ description: Facts about the network resource gathered from the remote device as structured data.
+ returned: when I(state) is C(gathered)
+ type: list
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+parsed:
+ description: The device native config provided in I(running_config) option parsed into structured data as per module argspec.
+ returned: when I(state) is C(parsed)
+ type: list
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.ntp_global.ntp_global import (
+ Ntp_globalArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.ntp_global.ntp_global import (
+ Ntp_global,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ module = AnsibleModule(
+ argument_spec=Ntp_globalArgs.argument_spec,
+ mutually_exclusive=[["config", "running_config"]],
+ required_if=[
+ ["state", "merged", ["config"]],
+ ["state", "replaced", ["config"]],
+ ["state", "overridden", ["config"]],
+ ["state", "rendered", ["config"]],
+ ["state", "parsed", ["running_config"]],
+ ],
+ supports_check_mode=True,
+ )
+
+ result = Ntp_global(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospf_interfaces.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospf_interfaces.py
new file mode 100644
index 00000000..02ec5acb
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospf_interfaces.py
@@ -0,0 +1,1211 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+"""
+The module file for iosxr_ospf_interfaces
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+module: iosxr_ospf_interfaces
+version_added: 1.2.0
+short_description: Resource module to configure OSPF interfaces.
+description:
+ - This module manages OSPF(v2/v3) configuration of interfaces on devices running Cisco IOS-XR.
+author: Rohit Thakur (@rohitthakur2590)
+notes:
+ - This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html)
+options:
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config router ospf').
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ config:
+ description: A list of OSPF configuration for interfaces.
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - Name/Identifier of the interface.
+ type: str
+ required: True
+ type:
+ description:
+ - Type of the interface.
+ type: str
+ required: True
+ address_family:
+ description:
+ - OSPF settings on the interfaces in address-family context.
+ type: list
+ elements: dict
+ suboptions:
+ afi:
+ description:
+ - Address Family Identifier (AFI) for OSPF settings on the interfaces.
+ type: str
+ choices: ['ipv4', 'ipv6']
+ required: True
+ processes:
+ description:
+ - Interfaces configuration for an OSPF process.
+ type: list
+ elements: dict
+ suboptions:
+ process_id:
+ description:
+ - OSPF process tag.
+ type: str
+ required: True
+ area:
+ description: Specify the area-id
+ type: dict
+ suboptions:
+ area_id:
+ description:
+ - OSPF interfaces area ID as a decimal value. Please
+ refer vendor documentation of Valid values.
+ - OSPF interfaces area ID in IP address format(e.g.
+ A.B.C.D)
+ type: str
+ apply_group_option:
+ description: Specify configuration from a group
+ type: dict
+ suboptions:
+ group_name:
+ description: Specify the name of the group
+ type: str
+ operation:
+ description: Specify the group config operation
+ type: str
+ choices: [add, remove, append]
+ authentication:
+ description: Enable authentication
+ type: dict
+ suboptions:
+ message_digest:
+ description: Use message-digest authentication
+ type: dict
+ suboptions:
+ keychain:
+ description: Specify keychain name
+ type: str
+ null_auth:
+ description: Use no authentication
+ type: bool
+ authentication_key:
+ description: Specify authentication password (key)
+ type: dict
+ suboptions:
+ password:
+ description: The OSPFv2 password (key)
+ type: str
+ clear:
+ description: Specifies an UNENCRYPTED password (key) will follow
+ type: str
+ encrypted:
+ description: Specifies an ENCRYPTED password (key) will follow
+ type: str
+ bfd:
+ description: Configure BFD parameters
+ type: dict
+ suboptions:
+ fast_detect:
+ description: Configure fast detection
+ type: dict
+ suboptions:
+ set:
+ description: Enable fast detection only
+ type: bool
+ strict_mode:
+ description: Hold down neighbor session until BFD session is up
+ type: bool
+ minimum_interval:
+ description: Hello interval in milli-seconds
+ type: int
+ multiplier:
+ description: Detect multiplier
+ type: int
+ cost:
+ description: Specify Interface cost
+ type: int
+ cost_fallback:
+ description: Specify Cost when cumulative bandwidth goes below the theshold
+ type: dict
+ suboptions:
+ cost:
+ description: Specify cost w.r.t cummulative bandwidth
+ type: int
+ threshold:
+ description: Specify threshold bandwidth when cost-fallback is applied
+ type: int
+ database_filter:
+ description: Filter OSPF LSAs during synchronization and flooding
+ type: dict
+ suboptions:
+ all_outgoing_lsa:
+ description: Filter all outgoing LSA
+ type: bool
+ dead_interval:
+ description: Specify interval after which a neighbor is declared dead
+ type: int
+ demand_circuit:
+ description: Enable/Disable demand circuits
+ type: bool
+ fast_reroute:
+ description: Specify IP Fast Reroute
+ type: dict
+ suboptions:
+ disabled:
+ description: Disable IP fast reroute
+ type: bool
+ per_link:
+ description: Specify per-prefix computation
+ type: dict
+ suboptions:
+ information_type:
+ description: Specify per-link LFA exclusion or FRR LFA candidate information
+ type: str
+ choices: ["exclude", "lfa_candidate"]
+ use_candidate_only:
+ description: Enable/Disable backup selection from candidate-list only
+ type: bool
+ interface:
+ description: Specify Per-link LFA exclusion information
+ type: dict
+ suboptions:
+ bvi:
+ description: Specify Bridge-Group Virtual Interface
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ bundle_ether:
+ description: Specify Aggregated Ethernet interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ pos_int:
+ description: Specify Aggregated pos interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ fast_ethernet:
+ description: Specify FastEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ fiftygige:
+ description: Specify FiftyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ fortygige:
+ description: Specify FortyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ fourhundredgige:
+ description: Specify FourHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ gigabitethernet:
+ description: Specify GigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ hundredgige:
+ description: Specify HundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ mgmteth:
+ description: Specify MgmtEth/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ multilink:
+ description: Specify Multilink network interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ pw_ether:
+ description: Specify PWHE Ethernet Interface
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ pw_iw:
+ description: Specify PWHE VC11 IP Interworking Interface
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ srp:
+ description: Specify SRP interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ serial:
+ description: Specify Serial network interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ tengige:
+ description: Specify TenGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ twentyfivegige:
+ description: Specify TwentyFiveGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ twohundredgige:
+ description: Specify TwoHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ nve:
+ description: Specify Network Virtualization Endpoint Interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ tunnel_ip:
+ description: Specify GRE/IPinIP Tunnel Interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ tunnel_ipsec:
+ description: Specify IPSec Tunnel interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ tunnel_mte:
+ description: Specify MPLS Traffic Engineering P2MP Tunnel interface(s)
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: int
+ tunnel_mpls:
+ description: MPLS Transport Protocol Tunnel interface
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify the interface id
+ type: str
+ flood_reduction:
+ description: Enable/Disable flood reduction
+ type: bool
+ hello_interval:
+ description: Specify Time between HELLO packets
+ type: int
+ link_down_fast_detect:
+ description: Configure interface down parameters
+ type: bool
+ message_digest_key:
+ description: Message digest authentication password (key)
+ type: dict
+ suboptions:
+ id:
+ description: Key ID
+ type: int
+ required: true
+ md5:
+ description: Use MD5 Algorithm
+ type: dict
+ required: true
+ suboptions:
+ password:
+ description: The OSPFv2 password (key)
+ type: str
+ clear:
+ description: Specifies an UNENCRYPTED password (key) will follow
+ type: bool
+ encrypted:
+ description: Specifies an ENCRYPTED password (key) will follow
+ type: bool
+ mpls_ldp_sync:
+ description: Enable/Disable MPLS LDP Sync
+ type: bool
+ mtu_ignore:
+ description: Enable/Disable ignoring of MTU in DBD packets
+ type: bool
+ network:
+ description: Specify Network type
+ type: str
+ choices: ["broadcast", "non-broadcast", "point-to-multipoint", "point-to-point"]
+ neighbors:
+ description: Specify a neighbor routers
+ type: list
+ elements: dict
+ suboptions:
+ neighbor_id:
+ description: Specify Neighbor address (name)
+ type: str
+ cost:
+ description: Specify OSPF cost for point-to-multipoint neighbor
+ type: int
+ db_filter_all_out:
+ description: Specify Filter OSPF LSA during synchronization and flooding for point-to-multipoint neighbor
+ type: bool
+ poll_interval:
+ description: Specify OSPF dead-router polling interval
+ type: int
+ priority:
+ description: Specify OSPF priority of non-broadcast neighbor
+ type: int
+ packet_size:
+ description: Customize size of OSPF packets upto MTU
+ type: int
+ passive:
+ description: Enable/Disable passive
+ type: bool
+ prefix_suppression:
+ description: Suppress advertisement of the prefixes
+ type: bool
+ priority:
+ description: Specify Router priority
+ type: int
+ retransmit_interval:
+ description: Specify time between retransmitting lost link state advertisements
+ type: int
+ security_ttl:
+ description: Enable security
+ type: dict
+ suboptions:
+ set:
+ description: Enable ttl security
+ type: bool
+ hops:
+ description: Maximum number of IP hops allowed <1-254>
+ type: int
+ transmit_delay:
+ description: Specify estimated time needed to send link-state update packet
+ type: int
+ state:
+ description:
+ - The state the configuration should be left in.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - gathered
+ - parsed
+ - rendered
+ default: merged
+"""
+EXAMPLES = """
+# Using merged
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# % No such configuration item(s)
+#
+
+- name: Merge provided OSPF interfaces configuration with the existing configuration
+ cisco.iosxr.iosxr_ospf_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/0
+ type: gigabitethernet
+ address_family:
+ - afi: ipv4
+ processes:
+ - process_id: "LAB3"
+ area:
+ area_id: 0.0.0.3
+ cost: 20
+ authentication:
+ message_digest:
+ keychain: cisco
+ - afi: ipv6
+ processes:
+ - process_id: "LAB3"
+ area:
+ area_id: 0.0.0.2
+ cost: 30
+ state: merged
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": []
+#
+# "commands": [
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 cost 20",
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest",
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest keychain cisco",
+# "router ospfv3 LAB3 area 0.0.0.2 interface GigabitEthernet 0/0/0/0 cost 30"
+# ]
+#
+# "after": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "authentication": {
+# "message_digest": {
+# "keychain": "cisco"
+# }
+# },
+# "cost": 20,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.3"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# },
+# {
+# "afi": "ipv6",
+# "cost": 30,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.2"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0",
+# "type": "gigabitethernet"
+# }
+# ]
+#
+#
+# ------------
+# After state
+# ------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config router ospf
+# Thu Oct 23 06:00:57.217 UTC
+# router ospf LAB
+# area 0.0.0.0
+# !
+# area 0.0.0.9
+# !
+# !
+# router ospf LAB1
+# area 0.0.0.1
+# !
+# area 0.0.0.3
+# !
+# !
+# router ospf LAB3
+# area 0.0.0.3
+# interface GigabitEthernet0/0/0/0
+# cost 20
+# authentication message-digest keychain cisco
+# !
+# !
+# !
+# router ospf ipv4
+# !
+
+# Using replaced
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config router ospf
+# Thu Oct 23 06:00:57.217 UTC
+# router ospf LAB
+# area 0.0.0.0
+# !
+# area 0.0.0.9
+# !
+# !
+# router ospf LAB1
+# area 0.0.0.1
+# !
+# area 0.0.0.3
+# !
+# !
+# router ospf LAB3
+# area 0.0.0.3
+# interface GigabitEthernet0/0/0/0
+# cost 20
+# authentication message-digest keychain cisco
+# !
+# !
+# !
+# router ospf ipv4
+# !
+
+- name: Replace OSPF interfaces configuration
+ cisco.iosxr.iosxr_ospf_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/0
+ type: gigabitethernet
+ address_family:
+ - afi: ipv4
+ processes:
+ - process_id: "LAB3"
+ area:
+ area_id: 0.0.0.3
+ cost: 30
+ authentication:
+ message_digest:
+ keychain: ciscoiosxr
+ - afi: ipv6
+ processes:
+ - process_id: "LAB3"
+ area:
+ area_id: 0.0.0.2
+ cost: 30
+ state: replaced
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "authentication": {
+# "message_digest": {
+# "keychain": "cisco"
+# }
+# },
+# "cost": 20,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.3"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# },
+# {
+# "afi": "ipv6",
+# "cost": 30,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.2"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0",
+# "type": "gigabitethernet"
+# }
+# ]
+#
+# "commands": [
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 cost 30",
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest",
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest keychain ciscoiosxr"
+# ]
+#
+# "after": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "authentication": {
+# "message_digest": {
+# "keychain": "ciscoiosxr"
+# }
+# },
+# "cost": 30,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.3"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# },
+# {
+# "afi": "ipv6",
+# "cost": 30,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.2"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0",
+# "type": "gigabitethernet"
+# }
+# ]
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config router ospf
+# Thu Oct 23 06:10:39.827 UTC
+# router ospf LAB
+# area 0.0.0.0
+# !
+# area 0.0.0.9
+# !
+# !
+# router ospf LAB1
+# area 0.0.0.1
+# !
+# area 0.0.0.3
+# !
+# !
+# router ospf LAB3
+# area 0.0.0.3
+# interface GigabitEthernet0/0/0/0
+# cost 30
+# authentication message-digest keychain ciscoiosxr
+# !
+# !
+# !
+# router ospf ipv4
+# !
+
+- name: Override existing OSPF interfaces configuration
+ cisco.iosxr.iosxr_ospf_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ type: gigabitethernet
+ address_family:
+ - afi: ipv4
+ processes:
+ - process_id: "LAB1"
+ area:
+ area_id: 0.0.0.3
+ cost: 10
+ authentication:
+ message_digest:
+ keychain: iosxr
+ state: overridden
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "authentication": {
+# "message_digest": {
+# "keychain": "ciscoiosxr"
+# }
+# },
+# "cost": 30,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.3"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# },
+# {
+# "afi": "ipv6",
+# "cost": 30,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.2"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0",
+# "type": "gigabitethernet"
+# }
+# ]
+#
+# "commands": [
+# "no router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0",
+# "no router ospfv3 LAB3 area 0.0.0.2 interface GigabitEthernet 0/0/0/0",
+# "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 cost 10",
+# "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 authentication message-digest",
+# "router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1 authentication message-digest keychain iosxr"
+# ]
+#
+# "after": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "authentication": {
+# "message_digest": {
+# "keychain": "iosxr"
+# }
+# },
+# "cost": 10,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.3"
+# },
+# "process_id": "LAB1"
+# }
+# ]
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/1",
+# "type": "gigabitethernet"
+# }
+# ]
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config router ospf
+# Thu Oct 23 06:28:15.025 UTC
+# router ospf LAB
+# area 0.0.0.0
+# !
+# area 0.0.0.9
+# !
+# !
+# router ospf LAB1
+# area 0.0.0.1
+# !
+# area 0.0.0.3
+# interface GigabitEthernet0/0/0/1
+# cost 10
+# authentication message-digest keychain iosxr
+# !
+# !
+# !
+# router ospf LAB3
+# area 0.0.0.3
+# !
+# !
+# router ospf ipv4
+# !
+
+# Using deleted
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config router ospf
+# Thu Oct 23 06:28:15.025 UTC
+# router ospf LAB
+# area 0.0.0.0
+# !
+# area 0.0.0.9
+# !
+# !
+# router ospf LAB1
+# area 0.0.0.1
+# !
+# area 0.0.0.3
+# interface GigabitEthernet0/0/0/1
+# cost 10
+# authentication message-digest keychain iosxr
+# !
+# !
+# !
+# router ospf LAB3
+# area 0.0.0.3
+# !
+# !
+# router ospf ipv4
+# !
+
+- name: Deleted existing OSPF interfaces from the device
+ cisco.iosxr.iosxr_ospf_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/1
+ type: gigabitethernet
+ state: deleted
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "authentication": {
+# "message_digest": {
+# "keychain": "iosxr"
+# }
+# },
+# "cost": 10,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.3"
+# },
+# "process_id": "LAB1"
+# }
+# ]
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/1",
+# "type": "gigabitethernet"
+# }
+# ],
+#
+# "commands": [
+# "no router ospf LAB1 area 0.0.0.3 interface GigabitEthernet 0/0/0/1"
+# ]
+#
+# "after": []
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config router ospf
+# Thu Oct 23 06:34:38.319 UTC
+# router ospf LAB
+# area 0.0.0.0
+# !
+# area 0.0.0.9
+# !
+# !
+# router ospf LAB1
+# area 0.0.0.1
+# !
+# area 0.0.0.3
+# !
+# !
+# router ospf LAB3
+# area 0.0.0.3
+# !
+# !
+# router ospf ipv4
+# !
+
+# Using parsed
+# parsed.cfg
+# ------------
+# router ospf LAB
+# area 0.0.0.0
+# !
+# area 0.0.0.9
+# !
+# !
+# router ospf LAB1
+# area 0.0.0.1
+# !
+# area 0.0.0.3
+# !
+# !
+# router ospf LAB3
+# area 0.0.0.3
+# interface GigabitEthernet0/0/0/0
+# cost 20
+# authentication message-digest keychain cisco
+# !
+# !
+# !
+# router ospf ipv4
+# !
+- name: Parsed the device configuration to get output commands
+ cisco.iosxr.iosxr_ospf_interfaces:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+#
+# "parsed": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "authentication": {
+# "message_digest": {
+# "keychain": "cisco"
+# }
+# },
+# "cost": 20,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.3"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0",
+# "type": "gigabitethernet"
+# }
+# ]
+#
+# Using rendered
+#
+#
+- name: Render the commands for provided configuration
+ cisco.iosxr.iosxr_ospf_interfaces:
+ config:
+ - name: GigabitEthernet0/0/0/0
+ type: gigabitethernet
+ address_family:
+ - afi: ipv4
+ processes:
+ - process_id: "LAB3"
+ area:
+ area_id: 0.0.0.3
+ cost: 20
+ authentication:
+ message_digest:
+ keychain: cisco
+ - afi: ipv6
+ processes:
+ - process_id: "LAB3"
+ area:
+ area_id: 0.0.0.2
+ cost: 30
+ state: rendered
+
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+#
+# "rendered": [
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 cost 20",
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest",
+# "router ospf LAB3 area 0.0.0.3 interface GigabitEthernet 0/0/0/0 authentication message-digest keychain cisco",
+# "router ospfv3 LAB3 area 0.0.0.2 interface GigabitEthernet 0/0/0/0 cost 30"
+# ]
+
+
+# Using gathered
+#
+# Before state:
+# -------------
+#
+# RP/0/0/CPU0:an-iosxr-02#show running-config router ospf
+# Thu Oct 23 06:50:38.743 UTC
+# router ospf LAB
+# area 0.0.0.0
+# !
+# area 0.0.0.9
+# !
+# !
+# router ospf LAB1
+# area 0.0.0.1
+# !
+# area 0.0.0.3
+# !
+# !
+# router ospf LAB3
+# area 0.0.0.3
+# interface GigabitEthernet0/0/0/0
+# cost 20
+# authentication message-digest keychain cisco
+# !
+# !
+# !
+# router ospf ipv4
+# !
+
+
+- name: Gather ospf_interfaces routes configuration
+ cisco.iosxr.iosxr_ospf_interfaces:
+ state: gathered
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+# "gathered": [
+# {
+# "address_family": [
+# {
+# "afi": "ipv4",
+# "authentication": {
+# "message_digest": {
+# "keychain": "cisco"
+# }
+# },
+# "cost": 20,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.3"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# },
+# {
+# "afi": "ipv6",
+# "cost": 30,
+# "processes": [
+# {
+# "area": {
+# "area_id": "0.0.0.2"
+# },
+# "process_id": "LAB3"
+# }
+# ]
+# }
+# ],
+# "name": "GigabitEthernet0/0/0/0",
+# "type": "gigabitethernet"
+# }
+# ]
+#
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.ospf_interfaces.ospf_interfaces import (
+ Ospf_interfacesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.ospf_interfaces.ospf_interfaces import (
+ Ospf_interfaces,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ module = AnsibleModule(
+ argument_spec=Ospf_interfacesArgs.argument_spec,
+ mutually_exclusive=[["config", "running_config"]],
+ required_if=[
+ ["state", "merged", ["config"]],
+ ["state", "replaced", ["config"]],
+ ["state", "overridden", ["config"]],
+ ["state", "rendered", ["config"]],
+ ["state", "parsed", ["running_config"]],
+ ],
+ supports_check_mode=True,
+ )
+
+ result = Ospf_interfaces(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospfv2.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospfv2.py
new file mode 100644
index 00000000..4b41338d
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospfv2.py
@@ -0,0 +1,2545 @@
+#!/usr/bin/python
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+
+"""
+The module file for iosxr_ospfv2
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+module: iosxr_ospfv2
+short_description: Resource module to configure OSPFv2.
+description: This module manages global OSPFv2 configuration on devices running Cisco
+ IOS-XR
+version_added: 1.0.0
+author:
+- Rohit Thakur (@rohitthakur2590)
+notes:
+- This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html)
+options:
+ config:
+ description: A list of OSPFv2 process configuration
+ type: dict
+ suboptions:
+ processes:
+ description: A list of OSPFv2 instances configuration
+ type: list
+ elements: dict
+ suboptions:
+ address_family_unicast:
+ description: Enable unicast topology for ipv4 address family
+ type: bool
+ adjacency_stagger:
+ description: Stagger OSPFv2 adjacency bring up
+ type: dict
+ suboptions:
+ min_adjacency:
+ description: Initial number of neighbors to bring up per area (default
+ 2)
+ type: int
+ max_adjacency:
+ description: Maximum simultaneous neighbors to bring up
+ type: int
+ disable:
+ description: Disable stagger OSPFv2 adjacency
+ type: bool
+ authentication:
+ description: Enable authentication
+ type: dict
+ suboptions:
+ keychain:
+ description: Specify keychain name
+ type: str
+ message_digest:
+ description: Use message-digest authentication
+ type: dict
+ suboptions:
+ set:
+ description: Specify message-digest selection
+ type: bool
+ keychain:
+ description: Specify keychain name
+ type: str
+ no_auth:
+ description: Use no authentication
+ type: bool
+ apply_weight:
+ description: Enable weights configured under interfaces for load sharing
+ type: dict
+ suboptions:
+ bandwidth:
+ description: Reference bandwidth to use for calculation (Mbits/sec)
+ type: int
+ default_weight:
+ description: Specify default weight value to use when it is not configured
+ under interface
+ type: int
+ areas:
+ description: Configure OSPFv2 areas' properties
+ type: list
+ elements: dict
+ suboptions:
+ area_id:
+ description: Area ID as IP address or integer
+ type: str
+ required: true
+ authentication:
+ description: Enable authentication
+ type: dict
+ suboptions:
+ keychain:
+ description: Specify keychain name
+ type: str
+ message_digest:
+ description: Use message-digest authentication
+ type: dict
+ suboptions:
+ keychain:
+ description: Specify keychain name
+ type: str
+ no_auth:
+ description: Use no authentication
+ type: bool
+ authentication_key:
+ description: Used to mention authentication password (key)
+ type: dict
+ suboptions:
+ password:
+ description: The OSPFv2 password (key)
+ type: str
+ clear:
+ description: Specifies an UNENCRYPTED password (key) will follow
+ type: str
+ encrypted:
+ description: Specifies an ENCRYPTED password (key) will follow
+ type: str
+ default_cost:
+ description: Set the summary default-cost of a NSSA/stub area. Stub's
+ advertised external route metric
+ type: int
+ cost:
+ description: Interface cost
+ type: int
+ dead_interval:
+ description: Interval after which a neighbor is declared dead
+ type: int
+ hello_interval:
+ description: Time between HELLO packets
+ type: int
+ transmit_delay:
+ description: Estimated time needed to send link-state update packet
+ type: int
+ mpls:
+ description: Configure MPLS routing protocol parameters
+ type: dict
+ suboptions:
+ traffic_eng:
+ description: Configure an ospf area to run MPLS Traffic Engineering
+ type: bool
+ ldp:
+ description: Configure LDP parameters
+ type: dict
+ suboptions:
+ auto_config:
+ description: Enable LDP IGP interface auto-configuration
+ type: bool
+ sync:
+ description: Enable LDP IGP synchronization
+ type: bool
+ sync_igp_shortcuts:
+ description: LDP sync for igp-shortcut tunnels
+ type: bool
+ mtu_ignore:
+ description: Enable/Disable ignoring of MTU in DBD packets
+ type: str
+ choices:
+ - enable
+ - disable
+ bfd:
+ description: Configure BFD parameters
+ type: dict
+ suboptions:
+ fast_detect:
+ description: Configure fast detection
+ type: dict
+ suboptions:
+ set:
+ description: Enable fast detection only
+ type: bool
+ strict_mode:
+ description: Hold down neighbor session until BFD session is up
+ type: bool
+ minimum_interval:
+ description: Hello interval in milli-seconds
+ type: int
+ multiplier:
+ description: Detect multiplier
+ type: int
+ nssa:
+ description:
+ - NSSA settings for the area
+ type: dict
+ suboptions:
+ set:
+ description: Configure area as NSSA
+ type: bool
+ default_information_originate:
+ description: Originate default Type 7 LSA
+ type: dict
+ suboptions:
+ metric:
+ description: OSPFv2 default metric
+ type: int
+ metric_type:
+ description: Metric type for default routes
+ type: int
+ no_redistribution:
+ description: Do not send redistributed LSAs into NSSA area
+ type: bool
+ no_summary:
+ description: Do not send summary LSAs into NSSA area
+ type: bool
+ translate:
+ description: Translate LSA
+ type: dict
+ suboptions:
+ type7:
+ description:
+ - Translate from Type 7 to Type 5
+ type: dict
+ suboptions:
+ always:
+ description:
+ - Always translate LSAs
+ type: bool
+ ranges:
+ description: Summarize routes matching address/mask (border routers
+ only)
+ type: list
+ elements: dict
+ suboptions:
+ address:
+ description: IP in Prefix format (x.x.x.x/len)
+ type: str
+ required: true
+ advertise:
+ description: Advertise this range (default)
+ type: bool
+ not_advertise:
+ description: DoNotAdvertise this range
+ type: bool
+ route_policy:
+ description: Specify the route-policy to filter type 3 LSAs (list
+ can have one inbound and/or one outbound policy only)
+ type: list
+ elements: dict
+ suboptions:
+ parameters:
+ description: Specify parameter values for the policy
+ type: list
+ elements: str
+ direction:
+ description: Specify inbound or outbound
+ type: str
+ choices:
+ - in
+ - out
+ stub:
+ description:
+ - Settings for configuring the area as a stub
+ type: dict
+ suboptions:
+ set:
+ description:
+ - Configure the area as a stub
+ type: bool
+ no_summary:
+ description:
+ - Do not send summary LSA into stub area
+ type: bool
+ virtual_link:
+ description: Define a virtual link
+ type: list
+ elements: dict
+ suboptions:
+ id:
+ description: Router-ID of virtual link neighbor (A.B.C.D)
+ type: str
+ required: true
+ authentication:
+ description: Enable authentication
+ type: dict
+ suboptions:
+ keychain:
+ description: Specify keychain name
+ type: str
+ message_digest:
+ description: Use message-digest authentication
+ type: dict
+ suboptions:
+ keychain:
+ description: Specify keychain name
+ type: str
+ no_auth:
+ description: Use no authentication
+ type: bool
+ authentication_key:
+ description: Used to mention authentication password (key)
+ type: dict
+ suboptions:
+ password:
+ description: The OSPFv2 password (key)
+ type: str
+ clear:
+ description: Specifies an UNENCRYPTED password (key) will
+ follow
+ type: str
+ encrypted:
+ description: Specifies an ENCRYPTED password (key) will follow
+ type: str
+ dead_interval:
+ description: Interval after which a neighbor is declared dead
+ type: int
+ hello_interval:
+ description: Time between HELLO packets
+ type: int
+ retransmit_interval:
+ description: Delay between LSA retransmissions
+ type: int
+ transmit_delay:
+ description: Link state transmit delay
+ type: int
+ message_digest_key:
+ description: Message digest authentication password (key)
+ type: dict
+ suboptions:
+ id:
+ description: Key ID (1-255)
+ type: int
+ required: true
+ md5:
+ description: Use MD5 Algorithm
+ type: dict
+ suboptions:
+ password:
+ description: The OSPFv2 password (key)
+ type: str
+ clear:
+ description: Specifies an UNENCRYPTED password (key) will
+ follow
+ type: bool
+ encrypted:
+ description: Specifies an ENCRYPTED password (key) will
+ follow
+ type: bool
+
+ authentication_key:
+ description: Used to mention authentication password (key)
+ type: dict
+ suboptions:
+ password:
+ description: The OSPFv2 password (key)
+ type: str
+ clear:
+ description: Specifies an UNENCRYPTED password (key) will follow
+ type: bool
+ encrypted:
+ description: Specifies an ENCRYPTED password (key) will follow
+ type: bool
+ auto_cost:
+ description: Calculate OSPFv2 interface cost according to bandwidth
+ type: dict
+ suboptions:
+ reference_bandwidth:
+ description: Specify reference bandwidth in megabits per sec
+ type: int
+ disable:
+ description: Assign OSPFv2 cost based on interface type
+ type: bool
+ bfd:
+ description: Configure BFD parameters
+ type: dict
+ suboptions:
+ fast_detect:
+ description: Configure fast detection
+ type: dict
+ suboptions:
+ set:
+ description: Enable fast detection only
+ type: bool
+ strict_mode:
+ description: Hold down neighbor session until BFD session is up
+ type: bool
+ minimum_interval:
+ description: Hello interval in milli-seconds
+ type: int
+ multiplier:
+ description: Detect multiplier
+ type: int
+ capability:
+ description: Enable specific OSPFv2 feature
+ type: dict
+ suboptions:
+ type7:
+ description: NSSA capability
+ type: str
+ opaque:
+ description: Configure opaque LSA
+ type: dict
+ suboptions:
+ disable:
+ description: Disable Opaque LSA capability
+ type: bool
+ set:
+ description: Enable opaque LSA
+ type: bool
+ cost:
+ description: Interface cost (1-65535)
+ type: int
+ database_filter:
+ description: Filter OSPFv2 LSA during synchronization and flooding (all
+ outgoing LSA). Enable/Disable filtering
+ type: str
+ choices: [enable, disable]
+ dead_interval:
+ description: Interval after which a neighbor is declared dead
+ type: int
+ default_information_originate:
+ description: Distribute default route
+ type: dict
+ suboptions:
+ always:
+ description: Always advertise default route
+ type: bool
+ metric:
+ description: OSPFv2 default metric
+ type: int
+ metric_type:
+ description: OSPFv2 metric type for default routes
+ type: int
+ route_policy:
+ description: Apply route-policy to default-information origination
+ type: str
+ set:
+ description: Enable distribution of default route
+ type: bool
+ default_metric:
+ description: Set metric of redistributed routes
+ type: int
+ demand_circuit:
+ description: Enable/Disable OSPFv2 demand circuit
+ type: str
+ choices: [enable, disable]
+ distance:
+ description: Define an administrative distance
+ type: dict
+ suboptions:
+ admin_distance:
+ description: Administrative distance
+ type: list
+ elements: dict
+ suboptions:
+ value:
+ description: Distance value
+ type: int
+ source:
+ description: Source IP address
+ type: str
+ wildcard:
+ description: IP wild card bits (A.B.C.D)
+ type: str
+ access_list:
+ description: Access list name
+ type: str
+ ospf_distance:
+ description: OSPFv2 administrative distance
+ type: dict
+ suboptions:
+ external:
+ description: Distance for external routes
+ type: int
+ inter_area:
+ description: Distance for inter-area routes
+ type: int
+ intra_area:
+ description: Distance for intra-area routes
+ type: int
+ distribute_link_state:
+ description: Enable Distribution of LSAs to external services
+ type: dict
+ suboptions:
+ instance_id:
+ description: Set distribution process instance identifier
+ type: int
+ throttle:
+ description: Throttle time between successive LSA updates
+ type: int
+ distribute_bgp_ls:
+ description: Enable Distribution of LSAs to external services
+ type: dict
+ suboptions:
+ instance_id:
+ description: Set distribution process instance identifier
+ type: int
+ throttle:
+ description: Throttle time between successive LSA updates
+ type: int
+ distribute_list:
+ description: Filter networks in routing updates (list can have one inbound
+ and/or one outbound policy only)
+ type: list
+ elements: dict
+ suboptions:
+ access_list:
+ description: Inbound/outbound access-list
+ type: str
+ direction:
+ description: Filter incoming/outgoing routing updates
+ type: str
+ choices:
+ - in
+ - out
+ outgoing_params:
+ description: Specify additional parameters for outgoing updates only
+ type: dict
+ suboptions:
+ route_type:
+ description: Type of routes
+ type: str
+ choices:
+ - bgp
+ - connected
+ - dagr
+ - ospf
+ - static
+ id:
+ description:
+ - For BGP, specify AS number. 2-byte AS number (or) 4-byte AS
+ number in asdot (X.Y) format (or) 4-byte AS number in asplain
+ format
+ - For OSPF, specify OSPFv2 instance name
+ type: str
+ route_policy:
+ description: Route Policy to filter OSPFv2 prefixes (for incoming
+ updates only)
+ type: str
+ external_out:
+ description: Enable/Disable advertisement of intra-area prefixes as external
+ type: str
+ choices:
+ - enable
+ - disable
+ flood_reduction:
+ description: Enable/Disable OSPFv2 Flood Reduction
+ type: str
+ choices:
+ - enable
+ - disable
+ hello_interval:
+ description: Time between HELLO packets (<1-65535> seconds)
+ type: int
+ ignore_lsa_mospf:
+ description: Do not complain upon receiving MOSPFv2 Type 6 LSA
+ type: bool
+ link_down_fast_detect:
+ description: Enable fast or early detection of link-down events
+ type: bool
+ log_adjacency_changes:
+ description: Log adjacency state changes
+ type: dict
+ suboptions:
+ set:
+ description: Set log adjacency
+ type: bool
+ disable:
+ description: Disable log adjacency changes
+ type: bool
+ detail:
+ description: Log all state changes
+ type: bool
+ loopback_stub_network:
+ description: Advertise loopback as a stub network
+ type: str
+ choices:
+ - enable
+ - disable
+ max_lsa:
+ description:
+ - Feature to limit the number of non-self-originated LSAs
+ type: dict
+ suboptions:
+ threshold:
+ description:
+ - Threshold value (%) at which to generate a warning message
+ type: int
+ ignore_count:
+ description:
+ - Set count on how many times adjacencies can be suppressed
+ type: int
+ ignore_time:
+ description:
+ - Set number of minutes during which all adjacencies are suppressed
+ type: int
+ reset_time:
+ description:
+ - Set number of minutes after which ignore-count is reset to zero
+ type: int
+ warning_only:
+ description:
+ - Log a warning message when limit is exceeded
+ type: bool
+ max_metric:
+ description: Set maximum metric
+ type: dict
+ suboptions:
+ router_lsa:
+ description: Maximum metric in self-originated router-LSAs
+ type: dict
+ suboptions:
+ set:
+ description: Set router-lsa attribute
+ type: bool
+ external_lsa:
+ description: External LSA configuration
+ type: dict
+ suboptions:
+ set:
+ description: Set external-lsa attribute
+ type: bool
+ max_metric_value:
+ description: Set max metric value for external LSAs
+ type: int
+ include_stub:
+ description:
+ - Advertise Max metric for Stub links as well
+ type: bool
+ on_startup:
+ description:
+ - Effective only at startup
+ type: dict
+ suboptions:
+ set:
+ description:
+ - Set on-startup attribute
+ type: bool
+ wait_period:
+ description:
+ - Wait period in seconds after startup
+ type: int
+ wait_for_bgp_asn:
+ description:
+ - ASN of BGP to wait for
+ type: int
+ summary_lsa:
+ description:
+ - Summary LSAs configuration
+ type: dict
+ suboptions:
+ set:
+ description:
+ - Set summary-lsa attribute
+ type: bool
+ max_metric_value:
+ description:
+ - Max metric value for summary LSAs
+ type: int
+ message_digest_key:
+ description: Message digest authentication password (key)
+ type: dict
+ suboptions:
+ id:
+ description: Key ID
+ type: int
+ required: true
+ md5:
+ description: Use MD5 Algorithm
+ type: dict
+ required: true
+ suboptions:
+ password:
+ description: The OSPFv2 password (key)
+ type: str
+ clear:
+ description: Specifies an UNENCRYPTED password (key) will follow
+ type: bool
+ encrypted:
+ description: Specifies an ENCRYPTED password (key) will follow
+ type: bool
+ microloop_avoidance:
+ description: Avoid microloops
+ type: dict
+ suboptions:
+ protected:
+ description: Avoid microloops for protected prefixes only)
+ type: bool
+ rib_update_delay:
+ description: Delay to introduce between SPF and RIB updates
+ type: int
+ segment_routing:
+ description: Enable segment routing microloop avoidance
+ type: bool
+ monitor_convergence:
+ description: Enables OSPFv2 route convergence monitoring
+ type: dict
+ suboptions:
+ prefix_list:
+ description: Enables Individual Prefix Monitoring
+ type: str
+ track_external_routes:
+ description: Enables Tracking External(Type-5/7) Prefix monitoring
+ type: bool
+ track_ip_frr:
+ description: Enables Tracking IP-Frr Convergence
+ type: bool
+ track_summary_routes:
+ description: Enables Tracking Summary(Inter-Area) Prefix monitoring
+ type: bool
+ mpls:
+ description: Configure MPLS routing protocol parameters
+ type: dict
+ suboptions:
+ traffic_eng:
+ description: Routing protocol commands for MPLS Traffic Engineering
+ type: dict
+ suboptions:
+ autoroute_exclude:
+ description: Exclude IP address destinations from using TE tunnels
+ type: dict
+ suboptions:
+ route_policy:
+ description: Policy name
+ type: str
+ parameters:
+ description: Specify parameter values for the policy
+ type: list
+ elements: str
+ igp_intact:
+ description: Retain one or more IPv4 nexthops with tunnel nexthops
+ type: bool
+ ldp_sync_update:
+ description: Enable LDP sync induced metric propagation
+ type: bool
+ multicast_intact:
+ description: Publish multicast-intact paths to RIB
+ type: bool
+ router_id:
+ description: Traffic Engineering stable IP address for system
+ type: str
+ ldp:
+ description: Configure LDP parameters
+ type: dict
+ suboptions:
+ auto_config:
+ description: Enable LDP IGP interface auto-configuration
+ type: bool
+ sync:
+ description: Enable LDP IGP synchronization
+ type: bool
+ sync_igp_shortcuts:
+ description: LDP sync for igp-shortcut tunnels
+ type: bool
+ mtu_ignore:
+ description: Enable/Disable ignoring of MTU in DBD packets
+ type: str
+ choices:
+ - enable
+ - disable
+ network:
+ description: Network type
+ type: dict
+ suboptions:
+ broadcast:
+ description: Specify OSPFv2 broadcast multi-access network
+ type: bool
+ non_broadcast:
+ description: Specify OSPFv2 NBMA network
+ type: bool
+ point_to_multipoint:
+ description: Specify OSPFv2 point-to-multipoint network
+ type: bool
+ point_to_point:
+ description: Specify OSPFv2 point-to-point network
+ type: bool
+ nsf:
+ description: Non-stop forwarding
+ type: dict
+ suboptions:
+ cisco:
+ description: Cisco Non-stop forwarding
+ type: dict
+ suboptions:
+ enforce_global:
+ description: Cancel NSF restart when non-NSF-aware neighbors detected
+ for the whole OSPFv2 process
+ type: bool
+ set:
+ description: Enable Cisco NSF
+ type: bool
+ flush_delay_time:
+ description: Maximum time allowed for external route learning
+ type: int
+ ietf:
+ description: IETF graceful restart
+ type: dict
+ suboptions:
+ helper_disable:
+ description: Disable router's helper support level
+ type: bool
+ set:
+ description: Only enable ietf option
+ type: bool
+ interval:
+ description: Minimum interval between NSF restarts (<90-3600> seconds)
+ type: int
+ lifetime:
+ description: Maximum route lifetime following restart (<90-1800> seconds)
+ type: int
+ nsr:
+ description: Enable NSR for all VRFs in this process. 'False' option to
+ disable NSR for all VRFs in this process
+ type: bool
+ packet_size:
+ description: Size of OSPFv2 packets to use. min=576 max=MTU bytes
+ type: int
+ passive:
+ description: Enable/Disable passive
+ type: str
+ choices:
+ - enable
+ - disable
+ prefix_suppression:
+ description: Suppress advertisement of the prefixes
+ type: dict
+ suboptions:
+ set:
+ description: Set the suppression option
+ type: bool
+ secondary_address:
+ description: Enable/Disable secondary address suppression
+ type: bool
+ priority:
+ description: Router priority
+ type: int
+ process_id:
+ description: The OSPFv2 Process ID
+ type: str
+ required: true
+ protocol_shutdown:
+ description: Protocol specific configuration
+ type: dict
+ suboptions:
+ host_mode:
+ description: Only traffic destined for this box allowed(cisco-support)
+ type: bool
+ on_reload:
+ description: Shutdown post reload only
+ type: bool
+ set:
+ description: Shutdown the OSPFv2 Protocol
+ type: bool
+ limit:
+ description: High watermark for incoming priority events
+ type: dict
+ suboptions:
+ high:
+ description: Hello events are dropped when incoming event queue
+ exceeds this value
+ type: int
+ low:
+ description: DBD/LS Update/Req packets are dropped when incoming
+ event queue exceeds this value
+ type: int
+ medium:
+ description: LSA ACKs are dropped when incoming event queue exceeds
+ this value
+ type: int
+ redistribute:
+ description: Redistribute information from another routing Protocol
+ type: dict
+ suboptions:
+ route_type:
+ description: Route type to redistribute
+ type: str
+ choices: [application, bgp, connected, dagr, eigrp, isis, mobile,
+ ospf, rip, static, subscriber]
+ id:
+ description: OnePK application name for application routes (or) AS
+ number for bgp and eigrp (or) instance name for isis and ospf
+ type: str
+ level:
+ description: ISIS levels
+ choices: [1, 2, 12]
+ type: int
+ lsa_type_summary:
+ description: LSA type 3 for redistributed routes
+ type: bool
+ match:
+ description: Redistribution of routes. For OSPFv2 - external/internal/nssa-external
+ 1/2. For EIGRP - external/internal
+ type: str
+ metric:
+ description: Metric for redistributed routes
+ type: int
+ metric_type:
+ description: OSPFv2 exterior metric type for redistributed routes
+ type: int
+ choices: [1, 2]
+ route_policy:
+ description: Apply route-policy to redistribution
+ type: dict
+ suboptions:
+ name:
+ description: Name of the policy
+ type: str
+ parameters:
+ description: Specify parameter values for the policy
+ type: list
+ elements: str
+ nssa_only:
+ description: Redistribute to NSSA areas only
+ type: bool
+ preserve_med:
+ description: Preserve med of BGP routes
+ type: bool
+ tag:
+ description: Set tag for routes redistributed into OSPFv2
+ type: int
+ retransmit_interval:
+ description: Delay between LSA retransmissions
+ type: int
+ router_id:
+ description: OSPFv2 router-id in IPv4 address format (A.B.C.D)
+ type: str
+ security_ttl:
+ description: Enable security
+ type: dict
+ suboptions:
+ set:
+ description: Enable ttl security
+ type: bool
+ hops:
+ description: Maximum number of IP hops allowed <1-254>
+ type: int
+ summary_in:
+ description: Enable/Disable advertisement of external prefixes as inter-area
+ type: str
+ choices: [enable, disable]
+ summary_prefix:
+ description: Configure IP address summaries
+ type: list
+ elements: dict
+ suboptions:
+ prefix:
+ description: IP summary address/mask (A.B.C.D/prefix)
+ type: str
+ required: true
+ not_advertise:
+ description: Suppress routes that match the specified prefix/mask
+ pair
+ type: bool
+ tag:
+ description: Set tag
+ type: int
+ timers:
+ description: Configure timer related constants
+ type: dict
+ suboptions:
+ graceful_shutdown:
+ description: Timers for graceful shutdown(cisco-support)
+ type: dict
+ suboptions:
+ initial_delay:
+ description: Delay before starting graceful shutdown
+ type: int
+ retain_routes:
+ description: Time to keep routes active after graceful shutdown
+ type: int
+ lsa:
+ description: OSPFv2 global LSA timers
+ type: dict
+ suboptions:
+ group_pacing:
+ description: OSPFv2 LSA group pacing timer. Interval between group
+ of LSA being refreshed or maxaged
+ type: int
+ min_arrival:
+ description: OSPFv2 MinLSArrival timer. The minimum interval in
+ millisec between accepting the same LSA
+ type: int
+ refresh:
+ description: OSPFv2 LSA refresh interval. How often self-originated
+ LSAs should be refreshed, in seconds
+ type: int
+ throttle:
+ description: OSPFv2 throttle timers
+ type: dict
+ suboptions:
+ lsa_all:
+ description: LSA throttle timers for all types of OSPFv2 LSAs
+ type: dict
+ suboptions:
+ initial_delay:
+ description: Delay to generate first occurance of LSA in milliseconds
+ type: int
+ min_delay:
+ description: Minimum delay between originating the same LSA
+ in milliseconds
+ type: int
+ max_delay:
+ description: Maximum delay between originating the same LSA
+ in milliseconds
+ type: int
+ spf:
+ description: OSPFv2 SPF throttle timers
+ type: dict
+ suboptions:
+ change_delay:
+ description: Delay between receiving a change to SPF calculation
+ in milliseconds
+ type: int
+ second_delay:
+ description: Delay between first and second SPF calculation
+ in milliseconds
+ type: int
+ max_wait:
+ description: Maximum wait time in milliseconds for SPF calculations
+ type: int
+ fast_reroute:
+ description: Fast-reroute throttle timer. Delay between end of
+ SPF and start of the fast-reroute computation in milliseconds
+ type: int
+ pacing_flood:
+ description: OSPFv2 flood pacing timer. Interval in msec to pace flooding
+ on all interfaces
+ type: int
+ transmit_delay:
+ description: Estimated time needed to send link-state update packet
+ type: int
+ weight:
+ description: Interface weight
+ type: int
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config router ospf).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state the configuration should be left in.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - deleted
+ - parsed
+ - gathered
+ - rendered
+ - overridden
+ default: merged
+
+"""
+
+EXAMPLES = """
+# Using merged
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# Thu Jun 11 15:54:44.569 UTC
+# % No such configuration item(s)
+#
+
+- name: Merge provided OSPFv2 configuration with the existing configuration
+ cisco.iosxr.iosxr_ospfv2:
+ config:
+ processes:
+ - process_id: '27'
+ areas:
+ - area_id: '10'
+ hello_interval: 2
+ authentication:
+ keychain: ansi11393
+ - process_id: '26'
+ adjacency_stagger:
+ max_adjacency: 20
+ min_adjacency: 10
+ - process_id: '10'
+ authentication:
+ keychain: ansible_test1102
+ areas:
+ - area_id: '11'
+ default_cost: 5
+ cost: 11
+ - area_id: 22
+ default_cost: 6
+ - process_id: '30'
+ areas:
+ - area_id: 11
+ default_cost: 5
+ - area_id: 22
+ default_cost: 6
+
+ cost: 2
+ default_metric: 10
+ transmit_delay: 2
+ hello_interval: 1
+ dead_interval: 2
+ retransmit_interval: 2
+ weight: 2
+ packet_size: 577
+ priority: 1
+ router_id: 2.2.2.2
+ demand_circuit: enable
+ passive: disable
+ summary_in: enable
+ flood_reduction: disable
+ mtu_ignore: enable
+ external_out: disable
+ state: merged
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {}
+#
+# "commands": [
+# "router ospf 30",
+# "cost 2",
+# "weight 2",
+# "passive disable",
+# "priority 1",
+# "flood-reduction disable",
+# "default-metric 10",
+# "router-id 2.2.2.2",
+# "demand-circuit enable",
+# "packet-size 577",
+# "transmit-delay 2",
+# "summary-in enable",
+# "external-out disable",
+# "dead-interval 2",
+# "hello-interval 1",
+# "retransmit-interval 2",
+# "mtu-ignore enable",
+# "area 11 default-cost 5",
+# "area 22 default-cost 6",
+# "router ospf 26",
+# "adjacency stagger 10 20",
+# "authentication message-digest keychain ansible1101pass",
+# "router ospf 27",
+# "area 10 authentication keychain ansi11393",
+# "area 10 hello-interval 2",
+# "router ospf 10",
+# "authentication keychain ansible_test1102",
+# "area 11 default-cost 5",
+# "area 11 cost 11",
+# "area 22 default-cost 6"
+# ]
+#
+# "after": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "authentication": {
+# "keychain": "ansible_test1102"
+# },
+# "process_id": "10"
+# },
+# {
+# "adjacency_stagger": {
+# "max_adjacency": 20,
+# "min_adjacency": 10
+# },
+# "authentication": {
+# "message_digest": {
+# "keychain": "ansible1101pass"
+# }
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": "enable",
+# "external_out": "disable",
+# "flood_reduction": "disable",
+# "hello_interval": 1,
+# "mtu_ignore": "enable",
+# "packet_size": 577,
+# "passive": "disable",
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "summary_in": "enable",
+# "transmit_delay": 2,
+# "weight": 2
+# }
+# ]
+# }
+#
+#
+# ------------
+# After state
+# ------------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# Thu Jun 11 16:06:44.406 UTC
+# router ospf 10
+# authentication keychain ansible_test1102
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# authentication keychain ansi11393
+# hello-interval 2
+# !
+# !
+# router ospf 30
+# router-id 2.2.2.2
+# summary-in enable
+# external-out disable
+# cost 2
+# packet-size 577
+# weight 2
+# passive disable
+# priority 1
+# mtu-ignore enable
+# flood-reduction disable
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit enable
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+#
+
+
+# Using replaced
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# Thu Jun 11 16:06:44.406 UTC
+# router ospf 10
+# authentication keychain ansible_test1102
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# authentication keychain ansi11393
+# hello-interval 2
+# !
+# !
+# router ospf 30
+# router-id 2.2.2.2
+# summary-in enable
+# external-out disable
+# cost 2
+# packet-size 577
+# weight 2
+# passive disable
+# priority 1
+# mtu-ignore enable
+# flood-reduction disable
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit enable
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+#
+
+- name: Replace OSPFv2 routes configurations from the device
+ cisco.iosxr.iosxr_ospfv2:
+ config:
+ processes:
+ - process_id: 27
+ areas:
+ - area_id: 10
+ hello_interval: 2
+ - area_id: 20
+ cost: 2
+ default_cost: 2
+ authentication:
+ keychain: ansi11393
+ - process_id: 26
+ adjacency_stagger:
+ min_adjacency: 10
+ max_adjacency: 20
+ state: replaced
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "authentication": {
+# "keychain": "ansible_test1102"
+# },
+# "process_id": "10"
+# },
+# {
+# "adjacency_stagger": {
+# "max_adjacency": 20,
+# "min_adjacency": 10
+# },
+# "authentication": {
+# "message_digest": {
+# "keychain": "ansible1101pass"
+# }
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": "enable",
+# "external_out": "disable",
+# "flood_reduction": "disable",
+# "hello_interval": 1,
+# "mtu_ignore": "enable",
+# "packet_size": 577,
+# "passive": "disable",
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "summary_in": "enable",
+# "transmit_delay": 2,
+# "weight": 2
+# }
+# ]
+# }
+#
+# "commands": [
+# "router ospf 27",
+# "no area 10 authentication keychain ansi11393",
+# "area 20 authentication keychain ansi11393",
+# "area 20 default-cost 2",
+# "area 20 cost 2"
+# ]
+#
+# "after": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "authentication": {
+# "keychain": "ansible_test1102"
+# },
+# "process_id": "10"
+# },
+# {
+# "adjacency_stagger": {
+# "max_adjacency": 20,
+# "min_adjacency": 10
+# },
+# "authentication": {
+# "message_digest": {
+# "keychain": "ansible1101pass"
+# }
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# },
+# {
+# "area_id": "20",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "cost": 2,
+# "default_cost": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": "enable",
+# "external_out": "disable",
+# "flood_reduction": "disable",
+# "hello_interval": 1,
+# "mtu_ignore": "enable",
+# "packet_size": 577,
+# "passive": "disable",
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "summary_in": "enable",
+# "transmit_delay": 2,
+# "weight": 2
+# }
+# ]
+# }
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/RP0/CPU0:anton(config)#do show running-config router ospf
+# Thu Jun 11 16:40:31.038 UTC
+# router ospf 10
+# authentication keychain ansible_test1102
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# cost 2
+# authentication keychain ansi11393
+# default-cost 2
+# !
+# !
+# router ospf 30
+# router-id 2.2.2.2
+# summary-in enable
+# external-out disable
+# cost 2
+# packet-size 577
+# weight 2
+# passive disable
+# priority 1
+# mtu-ignore enable
+# flood-reduction disable
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit enable
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+#
+
+
+# Using overridden
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# Thu Jun 11 16:06:44.406 UTC
+# router ospf 10
+# authentication keychain ansible_test1102
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# authentication keychain ansi11393
+# hello-interval 2
+# !
+# !
+# router ospf 30
+# router-id 2.2.2.2
+# summary-in enable
+# external-out disable
+# cost 2
+# packet-size 577
+# weight 2
+# passive disable
+# priority 1
+# mtu-ignore enable
+# flood-reduction disable
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit enable
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+#
+
+- name: Override existing OSPFv2 configurations from the device
+ cisco.iosxr.iosxr_ospfv2:
+ config:
+ processes:
+ - process_id: 27
+ areas:
+ - area_id: 10
+ hello_interval: 2
+ authentication:
+ keychain: ansi11393
+ - area_id: 20
+ cost: 2
+ default_cost: 2
+ authentication:
+ keychain: ansi11393
+ - process_id: 26
+ adjacency_stagger:
+ min_adjacency: 10
+ max_adjacency: 20
+ state: overridden
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "authentication": {
+# "keychain": "ansible_test1102"
+# },
+# "process_id": "10"
+# },
+# {
+# "adjacency_stagger": {
+# "max_adjacency": 20,
+# "min_adjacency": 10
+# },
+# "authentication": {
+# "message_digest": {
+# "keychain": "ansible1101pass"
+# }
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": "enable",
+# "external_out": "disable",
+# "flood_reduction": "disable",
+# "hello_interval": 1,
+# "mtu_ignore": "enable",
+# "packet_size": 577,
+# "passive": "disable",
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "summary_in": "enable",
+# "transmit_delay": 2,
+# "weight": 2
+# }
+# ]
+# }
+#
+# "commands": [
+# "router ospf 10",
+# "no authentication keychain ansible_test1102",
+# "no area 11 default-cost 5",
+# "no area 11 cost 11",
+# "no area 22 default-cost 6",
+# "router ospf 30",
+# "no cost 2",
+# "no weight 2",
+# "no passive disable",
+# "no priority 1",
+# "no flood-reduction disable",
+# "no default-metric 10",
+# "no router-id 2.2.2.2",
+# "no demand-circuit enable",
+# "no packet-size 577",
+# "no transmit-delay 2",
+# "no summary-in enable",
+# "no external-out disable",
+# "no dead-interval 2",
+# "no hello-interval 1",
+# "no retransmit-interval 2",
+# "no mtu-ignore enable",
+# "no area 11 default-cost 5",
+# "no area 22 default-cost 6",
+# "router ospf 27",
+# "area 20 authentication keychain ansi11393",
+# "area 20 default-cost 2",
+# "area 20 cost 2"
+# ]
+#
+# "after": {
+# "processes": [
+# {
+# "process_id": "10"
+# },
+# {
+# "adjacency_stagger": {
+# "max_adjacency": 20,
+# "min_adjacency": 10
+# },
+# "authentication": {
+# "message_digest": {
+# "keychain": "ansible1101pass"
+# }
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "hello_interval": 2
+# },
+# {
+# "area_id": "20",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "cost": 2,
+# "default_cost": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "process_id": "30"
+# }
+# ]
+# }
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# Thu Jun 11 16:50:36.332 UTC
+# router ospf 10
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# authentication keychain ansi11393
+# hello-interval 2
+# !
+# area 20
+# cost 2
+# authentication keychain ansi11393
+# default-cost 2
+# !
+# !
+# router ospf 30
+# !
+#
+
+
+# Using deleted
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# Thu Jun 11 16:06:44.406 UTC
+# router ospf 10
+# authentication keychain ansible_test1102
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# authentication keychain ansi11393
+# hello-interval 2
+# !
+# !
+# router ospf 30
+# router-id 2.2.2.2
+# summary-in enable
+# external-out disable
+# cost 2
+# packet-size 577
+# weight 2
+# passive disable
+# priority 1
+# mtu-ignore enable
+# flood-reduction disable
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit enable
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+#
+
+- name: Deleted existing OSPFv2 configurations from the device
+ cisco.iosxr.iosxr_ospfv2:
+ config:
+ processes:
+ - process_id: '10'
+ - process_id: '26'
+ - process_id: '27'
+ - process_id: '30'
+ state: deleted
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "authentication": {
+# "keychain": "ansible_test1102"
+# },
+# "process_id": "10"
+# },
+# {
+# "adjacency_stagger": {
+# "max_adjacency": 20,
+# "min_adjacency": 10
+# },
+# "authentication": {
+# "message_digest": {
+# "keychain": "ansible1101pass"
+# }
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": "enable",
+# "external_out": "disable",
+# "flood_reduction": "disable",
+# "hello_interval": 1,
+# "mtu_ignore": "enable",
+# "packet_size": 577,
+# "passive": "disable",
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "summary_in": "enable",
+# "transmit_delay": 2,
+# "weight": 2
+# }
+# ]
+# },
+#
+# "commands": [
+# "router ospf 10",
+# "no authentication keychain ansible_test1102",
+# "no area 11 default-cost 5",
+# "no area 11 cost 11",
+# "no area 22 default-cost 6",
+# "router ospf 26",
+# "no adjacency stagger 10 20",
+# "no authentication message-digest keychain ansible1101pass",
+# "router ospf 27",
+# "no area 10 authentication keychain ansi11393",
+# "no area 10 hello-interval 2",
+# "router ospf 30",
+# "no cost 2",
+# "no weight 2",
+# "no passive disable",
+# "no priority 1",
+# "no flood-reduction disable",
+# "no default-metric 10",
+# "no router-id 2.2.2.2",
+# "no demand-circuit enable",
+# "no packet-size 577",
+# "no transmit-delay 2",
+# "no summary-in enable",
+# "no external-out disable",
+# "no dead-interval 2",
+# "no hello-interval 1",
+# "no retransmit-interval 2",
+# "no mtu-ignore enable",
+# "no area 11 default-cost 5",
+# "no area 22 default-cost 6"
+# ]
+#
+# "after": {
+# "processes": [
+# {
+# "process_id": "10"
+# },
+# {
+# "process_id": "26"
+# },
+# {
+# "process_id": "27"
+# },
+# {
+# "process_id": "30"
+# }
+# ]
+# }
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/RP0/CPU0:anton(config)#show running-config router ospf
+# Thu Jun 11 17:07:34.218 UTC
+# router ospf 10
+# !
+# router ospf 26
+# !
+# router ospf 27
+# !
+# router ospf 30
+# !
+
+
+# Using parsed
+# parsed.cfg
+# ------------
+# Thu Jun 11 17:28:51.918 UTC
+# router ospf 10
+# authentication keychain ansible_test1102
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# authentication keychain ansi11393
+# hello-interval 2
+# !
+# !
+# router ospf 30
+# router-id 2.2.2.2
+# summary-in enable
+# external-out disable
+# cost 2
+# packet-size 577
+# weight 2
+# passive disable
+# priority 1
+# mtu-ignore enable
+# flood-reduction disable
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit enable
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+- name: Parsed the device configuration to get output commands
+ cisco.iosxr.iosxr_ospfv2:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+#
+# "parsed": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "authentication": {
+# "keychain": "ansible_test1102"
+# },
+# "process_id": "10"
+# },
+# {
+# "adjacency_stagger": {
+# "max_adjacency": 20,
+# "min_adjacency": 10
+# },
+# "authentication": {
+# "message_digest": {
+# "keychain": "ansible1101pass"
+# }
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": "enable",
+# "external_out": "disable",
+# "flood_reduction": "disable",
+# "hello_interval": 1,
+# "mtu_ignore": "enable",
+# "packet_size": 577,
+# "passive": "disable",
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "summary_in": "enable",
+# "transmit_delay": 2,
+# "weight": 2
+# }
+# ]
+# }
+
+
+
+# Using rendered
+#
+#
+- name: Render the commands for provided configuration
+ cisco.iosxr.iosxr_ospfv2:
+ config:
+ processes:
+ - process_id: 27
+ areas:
+ - area_id: 10
+ hello_interval: 2
+ authentication:
+ keychain: ansi11393
+ - process_id: 26
+ adjacency_stagger:
+ min_adjacency: 10
+ max_adjacency: 20
+ - process_id: 10
+ authentication:
+ keychain: ansible_test1102
+ areas:
+ - area_id: 11
+ default_cost: 5
+ cost: 11
+ - area_id: 22
+ default_cost: 6
+ - process_id: 30
+ areas:
+ - area_id: 11
+ default_cost: 5
+ - area_id: 22
+ default_cost: 6
+
+ cost: 2
+ default_metric: 10
+ transmit_delay: 2
+ hello_interval: 1
+ dead_interval: 2
+ retransmit_interval: 2
+ weight: 2
+ packet_size: 577
+ priority: 1
+ router_id: 2.2.2.2
+ demand_circuit: enable
+ passive: disable
+ summary_in: enable
+ flood_reduction: disable
+ mtu_ignore: enable
+ external_out: disable
+ state: rendered
+
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+#
+# "rendered": [
+# "router ospf 27",
+# "area 10 authentication keychain ansi11393",
+# "area 10 hello-interval 2",
+# "router ospf 26",
+# "adjacency stagger 10 20",
+# "authentication message-digest keychain ansible1101pass",
+# "router ospf 10",
+# "authentication keychain ansible_test1102",
+# "area 11 default-cost 5",
+# "area 11 cost 11",
+# "area 22 default-cost 6",
+# "router ospf 30",
+# "cost 2",
+# "weight 2",
+# "passive disable",
+# "priority 1",
+# "flood-reduction disable",
+# "default-metric 10",
+# "router-id 2.2.2.2",
+# "demand-circuit enable",
+# "packet-size 577",
+# "transmit-delay 2",
+# "summary-in enable",
+# "external-out disable",
+# "dead-interval 2",
+# "hello-interval 1",
+# "retransmit-interval 2",
+# "mtu-ignore enable",
+# "area 11 default-cost 5",
+# "area 22 default-cost 6"
+# ]
+
+
+# Using gathered
+#
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# Thu Jun 11 16:06:44.406 UTC
+# router ospf 10
+# authentication keychain ansible_test1102
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# authentication keychain ansi11393
+# hello-interval 2
+# !
+# !
+# router ospf 30
+# router-id 2.2.2.2
+# summary-in enable
+# external-out disable
+# cost 2
+# packet-size 577
+# weight 2
+# passive disable
+# priority 1
+# mtu-ignore enable
+# flood-reduction disable
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit enable
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+#
+- name: Gather ospfv2 routes configuration
+ cisco.iosxr.iosxr_ospfv2:
+ state: gathered
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+# "gathered": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "authentication": {
+# "keychain": "ansible_test1102"
+# },
+# "process_id": "10"
+# },
+# {
+# "adjacency_stagger": {
+# "max_adjacency": 20,
+# "min_adjacency": 10
+# },
+# "authentication": {
+# "message_digest": {
+# "keychain": "ansible1101pass"
+# }
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "authentication": {
+# "keychain": "ansi11393"
+# },
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": "enable",
+# "external_out": "disable",
+# "flood_reduction": "disable",
+# "hello_interval": 1,
+# "mtu_ignore": "enable",
+# "packet_size": 577,
+# "passive": "disable",
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "summary_in": "enable",
+# "transmit_delay": 2,
+# "weight": 2
+# }
+# ]
+# }
+#
+# After state:
+# -------------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# Thu Jun 11 16:06:44.406 UTC
+# router ospf 10
+# authentication keychain ansible_test1102
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospf 26
+# authentication message-digest keychain ansible1101pass
+# adjacency stagger 10 20
+# !
+# router ospf 27
+# area 10
+# authentication keychain ansi11393
+# hello-interval 2
+# !
+# !
+# router ospf 30
+# router-id 2.2.2.2
+# summary-in enable
+# external-out disable
+# cost 2
+# packet-size 577
+# weight 2
+# passive disable
+# priority 1
+# mtu-ignore enable
+# flood-reduction disable
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit enable
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+#
+#
+
+"""
+RETURN = """
+before:
+ description: The configuration prior to the model invocation.
+ returned: always
+ type: dict
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The resulting configuration model invocation.
+ returned: when changed
+ type: dict
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample:
+ - "router ospf 30"
+ - "authentication message-digest keychain 'ansible1101pass'"
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.ospfv2.ospfv2 import (
+ Ospfv2Args,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.ospfv2.ospfv2 import (
+ Ospfv2,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "rendered", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+ mutually_exclusive = [("config", "running_config")]
+ module = AnsibleModule(
+ argument_spec=Ospfv2Args.argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ mutually_exclusive=mutually_exclusive,
+ )
+ result = Ospfv2(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospfv3.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospfv3.py
new file mode 100644
index 00000000..c4a52e55
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ospfv3.py
@@ -0,0 +1,2784 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2020 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_ospfv3
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+module: iosxr_ospfv3
+version_added: 1.1.0
+short_description: Resource module to configure OSPFv3.
+description:
+ - This module manages global ospfv3 configuration on devices running Cisco IOS-XR
+author: Rohit Thakur (@rohitthakur2590)
+notes:
+ - This module works with connection C(network_cli). See L(the IOS-XR Platform Options,../network/user_guide/platform_iosxr.html)
+options:
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config router ospfv3).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ config:
+ description: A list of ospfv3 process configuration
+ type: dict
+ suboptions:
+ processes:
+ description: A list of ospfv3 instances configuration
+ type: list
+ elements: dict
+ suboptions:
+ process_id:
+ description: The OSPFv3 Process ID
+ type: str
+ required: true
+ address_family_unicast:
+ description: Enable unicast topology for ipv4 address family
+ type: bool
+ authentication:
+ description: Enable authentication
+ type: dict
+ suboptions:
+ disable:
+ description: Do not authenticate OSPFv3 packets
+ type: bool
+ default: false
+ ipsec:
+ description: Specify IPSec AH authentication attributes
+ type: dict
+ suboptions:
+ spi:
+ description: Specify the Security Parameter Index value
+ type: int
+ algorithim_type:
+ description: Specify the type of algorithim
+ type: str
+ choices: ["md5", "sha1"]
+ key:
+ description: Specify key
+ type: str
+ clear_key:
+ description: Specify key in cleartext form
+ type: str
+ password_key:
+ description: Specify key in encrypted form
+ type: str
+ auto_cost:
+ description: Calculate ospfv3 interface cost according to bandwidth
+ type: dict
+ suboptions:
+ reference_bandwidth:
+ description: Specify reference bandwidth in megabits per sec
+ type: int
+ disable:
+ description: Assign ospfv3 cost based on interface type
+ type: bool
+ bfd:
+ description: Configure BFD parameters
+ type: dict
+ suboptions:
+ fast_detect:
+ description: Configure fast detection
+ type: dict
+ suboptions:
+ set:
+ description: Enable fast detection only
+ type: bool
+ strict_mode:
+ description: Hold down neighbor session until BFD session is up
+ type: bool
+ minimum_interval:
+ description: Hello interval in milli-seconds
+ type: int
+ multiplier:
+ description: Detect multiplier
+ type: int
+ areas:
+ description: Configure ospfv3 areas' properties
+ type: list
+ elements: dict
+ suboptions:
+ area_id:
+ description: Area ID as IP address or integer
+ type: str
+ required: True
+ authentication:
+ description: Enable authentication
+ type: dict
+ suboptions:
+ disable:
+ description: Do not authenticate OSPFv3 packets
+ type: bool
+ default: false
+ ipsec:
+ description: Specify IPSec AH authentication attributes
+ type: dict
+ suboptions:
+ spi:
+ description: Specify the Security Parameter Index value
+ type: int
+ algorithim_type:
+ description: Specify the type of algorithim
+ type: str
+ choices: ["md5", "sha1"]
+ key:
+ description: Specify key
+ type: str
+ clear_key:
+ description: Specify key in cleartext form
+ type: str
+ password_key:
+ description: Specify key in encrypted form
+ type: str
+ bfd:
+ description: Configure BFD parameters
+ type: dict
+ suboptions:
+ fast_detect:
+ description: Configure fast detection
+ type: dict
+ suboptions:
+ set:
+ description: Enable fast detection only
+ type: bool
+ strict_mode:
+ description: Hold down neighbor session until BFD session is up
+ type: bool
+ minimum_interval:
+ description: Hello interval in milli-seconds
+ type: int
+ multiplier:
+ description: Detect multiplier
+ type: int
+ cost:
+ description: Interface cost
+ type: int
+ database_filter:
+ description: Filter LSAs during synchronization and flooding
+ type: dict
+ suboptions:
+ all_outgoing_lsa:
+ description: Filter all outgoing LSA
+ type: bool
+ dead_interval:
+ description: Interval after which a neighbor is declared dead
+ type: int
+ default_cost:
+ description: Set the summary default-cost of a NSSA/stub area. Stub's advertised external route metric
+ type: int
+ demand_circuit:
+ description: Enable/Disable ospfv3 demand circuit
+ type: bool
+ distrinbute_rib_prefix_list_name:
+ description: Filter LSAs during synchronization and flooding
+ type: str
+ fast_reroute:
+ description: Specify IP Fast Reroute
+ type: dict
+ suboptions:
+ disabled:
+ description: Disable IP fast reroute
+ type: bool
+ per_link:
+ description: Specify per-prefix computation
+ type: dict
+ suboptions:
+ information_type:
+ description: Specify per-link LFA exclusion or FRR LFA candidate information
+ type: str
+ choices: ["exclude", "lfa_candidate"]
+ use_candidate_only:
+ description: Enable/Disable backup selection from candidate-list only
+ type: bool
+ interface:
+ description: Specify Per-link LFA exclusion information
+ type: dict
+ suboptions:
+ bvi:
+ description: Specify Bridge-Group Virtual Interface
+ type: list
+ elements: int
+ bundle_ether:
+ description: Specify Aggregated Ethernet interface(s)
+ type: list
+ elements: int
+ pos_int:
+ description: Specify Aggregated pos interface(s)
+ type: list
+ elements: int
+ fast_ethernet:
+ description: Specify FastEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fiftygige:
+ description: Specify FiftyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fortygige:
+ description: Specify FortyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fourhundredgige:
+ description: Specify FourHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ gigabitethernet:
+ description: Specify GigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ hundredgige:
+ description: Specify HundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ mgmteth:
+ description: Specify MgmtEth/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ multilink:
+ description: Specify Multilink network interface(s)
+ type: list
+ elements: str
+ pw_ether:
+ description: Specify PWHE Ethernet Interface
+ type: list
+ elements: int
+ pw_iw:
+ description: Specify PWHE VC11 IP Interworking Interface
+ type: list
+ elements: int
+ srp:
+ description: Specify SRP interface(s)
+ type: list
+ elements: str
+ serial:
+ description: Specify Serial network interface(s)
+ type: list
+ elements: str
+ tengige:
+ description: Specify TenGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ twentyfivegige:
+ description: Specify TwentyFiveGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ twohundredgige:
+ description: Specify TwoHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ nve:
+ description: Specify Network Virtualization Endpoint Interface(s)
+ type: list
+ elements: int
+ tunnel_ip:
+ description: Specify GRE/IPinIP Tunnel Interface(s)
+ type: list
+ elements: int
+ tunnel_ipsec:
+ description: Specify IPSec Tunnel interface(s)
+ type: list
+ elements: int
+ tunnel_mte:
+ description: Specify MPLS Traffic Engineering P2MP Tunnel interface(s)
+ type: list
+ elements: int
+ tunnel_mpls:
+ description: MPLS Transport Protocol Tunnel interface
+ type: int
+ per_prefix:
+ description: Specify per-prefix computation
+ type: dict
+ suboptions:
+ information_type:
+ description: Specify per_prefix LFA exclusion or FRR LFA candidate information
+ type: str
+ choices: ["exclude", "lfa_candidate"]
+ use_candidate_only:
+ description: Enable/Disable backup selection from candidate-list only
+ type: bool
+ interface:
+ description: Specify Per-link LFA exclusion information
+ type: dict
+ suboptions:
+ bvi:
+ description: Specify Bridge-Group Virtual Interface
+ type: list
+ elements: int
+ bundle_ether:
+ description: Specify Aggregated Ethernet interface(s)
+ type: list
+ elements: int
+ pos_int:
+ description: Specify Aggregated pos interface(s)
+ type: list
+ elements: int
+ fast_ethernet:
+ description: Specify FastEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fiftygige:
+ description: Specify FiftyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fortygige:
+ description: Specify FortyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fourhundredgige:
+ description: Specify FourHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ gigabitethernet:
+ description: Specify GigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ hundredgige:
+ description: Specify HundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ mgmteth:
+ description: Specify MgmtEth/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ multilink:
+ description: Specify Multilink network interface(s)
+ type: list
+ elements: str
+ pw_ether:
+ description: Specify PWHE Ethernet Interface
+ type: list
+ elements: int
+ pw_iw:
+ description: Specify PWHE VC11 IP Interworking Interface
+ type: list
+ elements: int
+ srp:
+ description: Specify SRP interface(s)
+ type: list
+ elements: str
+ serial:
+ description: Specify Serial network interface(s)
+ type: list
+ elements: str
+ tengige:
+ description: Specify TenGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ twentyfivegige:
+ description: Specify TwentyFiveGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ twohundredgige:
+ description: Specify TwoHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ nve:
+ description: Specify Network Virtualization Endpoint Interface(s)
+ type: list
+ elements: int
+ tunnel_ip:
+ description: Specify GRE/IPinIP Tunnel Interface(s)
+ type: list
+ elements: int
+ tunnel_ipsec:
+ description: Specify IPSec Tunnel interface(s)
+ type: list
+ elements: int
+ tunnel_mte:
+ description: Specify MPLS Traffic Engineering P2MP Tunnel interface(s)
+ type: list
+ elements: int
+ tunnel_mpls:
+ description: MPLS Transport Protocol Tunnel interface
+ type: int
+ flood_reduction:
+ description: Enable/Disable flood reduction
+ type: bool
+ hello_interval:
+ description: Specify Time between HELLO packets
+ type: int
+ instance_id:
+ description: Specify instance ID
+ type: int
+ mtu_ignore:
+ description: Enable/Disable ignoring of MTU in DBD packets
+ type: bool
+ mpls_ldp_sync:
+ description: Enable/Disable MPLS LDP Sync
+ type: bool
+ network:
+ description: Specify Network type
+ type: str
+ choices: ["broadcast", "non-broadcast", "point-to-multipoint", "point-to-point"]
+ nssa:
+ description: NSSA settings for the area
+ type: dict
+ suboptions:
+ set:
+ description: Configure area as NSSA
+ type: bool
+ default_information_originate:
+ description: Originate default Type 7 LSA
+ type: dict
+ suboptions:
+ set:
+ description: Set nssa to default information originate
+ type: bool
+ metric:
+ description: ospfv3 default metric
+ type: int
+ metric_type:
+ description: Metric type for default routes
+ type: int
+ no_redistribution:
+ description: Do not send redistributed LSAs into NSSA area
+ type: bool
+ no_summary:
+ description: Do not send summary LSAs into NSSA area
+ type: bool
+ translate:
+ description: Translate LSA
+ type: dict
+ suboptions:
+ type7:
+ description: Translate from Type 7 to Type 5
+ type: dict
+ suboptions:
+ always:
+ description: Always translate LSAs
+ type: bool
+ required: true
+ packet_size:
+ description: Specify limit size of OSPFv3 packets
+ type: int
+ passive:
+ description: Enable/Disable routing updates on an interface
+ type: bool
+ prefix_suppression:
+ description: Hide all transit addresses on this interface
+ type: bool
+ priority:
+ description: Specify Router priority
+ type: int
+ ranges:
+ description: Summarize routes matching address/mask (border routers only)
+ type: list
+ elements: dict
+ suboptions:
+ address:
+ description: IP in Prefix format (X:X::X/length)
+ type: str
+ required: True
+ cost:
+ description: Specify user specified metric for this range
+ type: int
+ advertise:
+ description: Advertise this range (default)
+ type: bool
+ not_advertise:
+ description: DoNotAdvertise this range
+ type: bool
+ retransmit_interval:
+ description: Specify Delay between LSA retransmissions
+ type: int
+ stub:
+ description: Settings for configuring the area as a stub
+ type: dict
+ suboptions:
+ set:
+ description: Configure the area as a stub
+ type: bool
+ no_summary:
+ description: Do not send summary LSA into stub area
+ type: bool
+ transmit_delay:
+ description: Specify estimated time needed to send link-state update packet
+ type: int
+ virtual_link:
+ description: Define a virtual link
+ type: list
+ elements: dict
+ suboptions:
+ id:
+ description: Router-ID of virtual link neighbor (A.B.C.D)
+ type: str
+ required: True
+ authentication:
+ description: Enable authentication
+ type: dict
+ suboptions:
+ disable:
+ description: Do not authenticate OSPFv3 packets
+ type: bool
+ default: false
+ ipsec:
+ description: Specify IPSec AH authentication attributes
+ type: dict
+ suboptions:
+ spi:
+ description: Specify the Security Parameter Index value
+ type: int
+ algorithim_type:
+ description: Specify the type of algorithim
+ type: str
+ choices: ["md5", "sha1"]
+ key:
+ description: Specify key
+ type: str
+ clear_key:
+ description: Specify key in cleartext form
+ type: str
+ password_key:
+ description: Specify key in encrypted form
+ type: str
+ dead_interval:
+ description: Interval after which a neighbor is declared dead
+ type: int
+ hello_interval:
+ description: Time between HELLO packets
+ type: int
+ retransmit_interval:
+ description: Delay between LSA retransmissions
+ type: int
+ transmit_delay:
+ description: Link state transmit delay
+ type: int
+ encryption:
+ description: Encrypt and authenticate OSPFv3 packets
+ type: dict
+ suboptions:
+ disable:
+ description: Do not encrypt OSPFv3 packets
+ type: bool
+ default: false
+ ipsec:
+ description: Specify IPSec ESP encryption and authentication
+ type: dict
+ suboptions:
+ spi:
+ description: Specify the Security Parameter Index value
+ type: int
+ esp:
+ description: Specify encryption parameters
+ type: dict
+ suboptions:
+ triple_des:
+ description: This specify the triple DES algorithim
+ type: dict
+ suboptions:
+ key:
+ description: Cleartext 3DES key
+ type: str
+ clear_key:
+ description: Specify 3DES key in cleartext form
+ type: str
+ password_key:
+ description: Specify 3DES key in encrypted form
+ type: str
+ aes:
+ description: This specify the aes algorithim
+ type: dict
+ suboptions:
+ algorithim_type:
+ description: Specify the bit encryption for aes algorithim
+ type: str
+ choices: ["192", "256"]
+ key:
+ description: Cleartext AES key
+ type: str
+ clear_key:
+ description: Specify AES key in cleartext form
+ type: str
+ password_key:
+ description: Specify AES key in encrypted form
+ type: str
+ des:
+ description: This specify the des algorithim
+ type: dict
+ suboptions:
+ key:
+ description: Cleartext AES key
+ type: str
+ clear_key:
+ description: Specify AES key in cleartext form
+ type: str
+ password_key:
+ description: Specify AES key in encrypted form
+ type: str
+ null_encryption:
+ description: Specify null encryption attributes
+ type: dict
+ suboptions:
+ authentication:
+ description: Specify authentication parameters
+ type: dict
+ suboptions:
+ algorithim_type:
+ description: Specify the type of algorithim
+ type: str
+ choices: ["md5", "sha1"]
+ key:
+ description: Specify key
+ type: str
+ clear_key:
+ description: Specify key in cleartext form
+ type: str
+ password_key:
+ description: Specify key in encrypted form
+ type: str
+ encryption:
+ description: Encrypt and authenticate OSPFv3 packets
+ type: dict
+ suboptions:
+ disable:
+ description: Do not encrypt OSPFv3 packets
+ type: bool
+ default: false
+ ipsec:
+ description: Specify IPSec ESP encryption and authentication
+ type: dict
+ suboptions:
+ spi:
+ description: Specify the Security Parameter Index value
+ type: int
+ esp:
+ description: Specify encryption parameters
+ type: dict
+ suboptions:
+ triple_des:
+ description: This specify the triple DES algorithim
+ type: dict
+ suboptions:
+ key:
+ description: Cleartext 3DES key
+ type: str
+ clear_key:
+ description: Specify 3DES key in cleartext form
+ type: str
+ password_key:
+ description: Specify 3DES key in encrypted form
+ type: str
+ aes:
+ description: This specify the aes algorithim
+ type: dict
+ suboptions:
+ algorithim_type:
+ description: Specify the bit encryption for aes algorithim
+ type: str
+ choices: ["192", "256"]
+ key:
+ description: Cleartext AES key
+ type: str
+ clear_key:
+ description: Specify AES key in cleartext form
+ type: str
+ password_key:
+ description: Specify AES key in encrypted form
+ type: str
+ des:
+ description: This specify the des algorithim
+ type: dict
+ suboptions:
+ key:
+ description: Cleartext AES key
+ type: str
+ clear_key:
+ description: Specify AES key in cleartext form
+ type: str
+ password_key:
+ description: Specify AES key in encrypted form
+ type: str
+ null_encryption:
+ description: Specify null encryption attributes
+ type: dict
+ suboptions:
+ authentication:
+ description: Specify authentication parameters
+ type: dict
+ suboptions:
+ algorithim_type:
+ description: Specify the type of algorithim
+ type: str
+ choices: ["md5", "sha1"]
+ key:
+ description: Specify key
+ type: str
+ clear_key:
+ description: Specify key in cleartext form
+ type: str
+ password_key:
+ description: Specify key in encrypted form
+ type: str
+ capability:
+ description: Enable specific OSPFv3 feature
+ type: dict
+ suboptions:
+ type7:
+ description: Specify type7 nssa capability
+ type: dict
+ suboptions:
+ prefer:
+ description: Prefer type7 externals over type5
+ type: bool
+ translate:
+ description: Translate type7 to type5
+ type: bool
+ cost:
+ description: Specify Interface cost
+ type: int
+ database_filter:
+ description: Filter LSAs during synchronization and flooding
+ type: dict
+ suboptions:
+ all_outgoing_lsa:
+ description: Filter all outgoing LSA
+ type: bool
+ dead_interval:
+ description: Interval after which a neighbor is declared dead
+ type: int
+ default_information_originate:
+ description: Control distribution of default information
+ type: dict
+ suboptions:
+ always:
+ description: Always advertise default route
+ type: bool
+ metric:
+ description: ospfv3 default metric
+ type: int
+ metric_type:
+ description: ospfv3 metric type for default routes
+ type: int
+ route_policy:
+ description: Apply route-policy to default-information origination
+ type: str
+ tag:
+ description: Set tag for default route
+ type: int
+ set:
+ description: Enable distribution of default route
+ type: bool
+ default_metric:
+ description: Set metric of redistributed routes
+ type: int
+ demand_circuit:
+ description: Enable/Disable ospfv3 demand circuit
+ type: bool
+ distance:
+ description: Define an administrative distance
+ type: dict
+ suboptions:
+ admin_distance:
+ description: Administrative distance
+ type: int
+ ospfv3_distance:
+ description: ospfv3 administrative distance
+ type: dict
+ suboptions:
+ external:
+ description: Distance for external routes
+ type: int
+ inter_area:
+ description: Distance for inter-area routes
+ type: int
+ intra_area:
+ description: Distance for intra-area routes
+ type: int
+ distribute_list:
+ description: Filter prefixes to/from RIB
+ type: dict
+ suboptions:
+ prefix_list:
+ description: Filter prefixes based on an IPv6 prefix-list
+ type: list
+ elements: str
+ suboptions:
+ name:
+ description: Specify Prefix-list name
+ type: str
+ in:
+ description: Filter prefixes installed to RIB
+ type: bool
+ out:
+ description: Filter prefixes redistributed from RIB
+ type: bool
+ encryption:
+ description: Encrypt and authenticate OSPFv3 packets
+ type: dict
+ suboptions:
+ disable:
+ description: Do not encrypt OSPFv3 packets
+ type: bool
+ default: false
+ ipsec:
+ description: Specify IPSec ESP encryption and authentication
+ type: dict
+ suboptions:
+ spi:
+ description: Specify the Security Parameter Index value
+ type: int
+ esp:
+ description: Specify encryption parameters
+ type: dict
+ suboptions:
+ triple_des:
+ description: This specify the triple DES algorithim
+ type: dict
+ suboptions:
+ key:
+ description: Cleartext 3DES key
+ type: str
+ clear_key:
+ description: Specify 3DES key in cleartext form
+ type: str
+ password_key:
+ description: Specify 3DES key in encrypted form
+ type: str
+ aes:
+ description: This specify the aes algorithim
+ type: dict
+ suboptions:
+ algorithim_type:
+ description: Specify the bit encryption for aes algorithim
+ type: str
+ choices: ["192", "256"]
+ key:
+ description: Cleartext AES key
+ type: str
+ clear_key:
+ description: Specify AES key in cleartext form
+ type: str
+ password_key:
+ description: Specify AES key in encrypted form
+ type: str
+ des:
+ description: This specify the des algorithim
+ type: dict
+ suboptions:
+ key:
+ description: Cleartext AES key
+ type: str
+ clear_key:
+ description: Specify AES key in cleartext form
+ type: str
+ password_key:
+ description: Specify AES key in encrypted form
+ type: str
+ null_encryption:
+ description: Specify null encryption attributes
+ type: dict
+ suboptions:
+ authentication:
+ description: Specify authentication parameters
+ type: dict
+ suboptions:
+ algorithim_type:
+ description: Specify the type of algorithim
+ type: str
+ choices: ["md5", "sha1"]
+ key:
+ description: Specify key
+ type: str
+ clear_key:
+ description: Specify key in cleartext form
+ type: str
+ password_key:
+ description: Specify key in encrypted form
+ type: str
+ fast_reroute:
+ description: Specify IP Fast Reroute
+ type: dict
+ suboptions:
+ disabled:
+ description: Disable IP fast reroute
+ type: bool
+ per_link:
+ description: Specify per-prefix computation
+ type: dict
+ suboptions:
+ information_type:
+ description: Specify per-link LFA exclusion or FRR LFA candidate information
+ type: str
+ choices: ["exclude", "lfa_candidate"]
+ use_candidate_only:
+ description: Enable/Disable backup selection from candidate-list only
+ type: bool
+ interface:
+ description: Specify Per-link LFA exclusion information
+ type: dict
+ suboptions:
+ bvi:
+ description: Specify Bridge-Group Virtual Interface
+ type: list
+ elements: int
+ bundle_ether:
+ description: Specify Aggregated Ethernet interface(s)
+ type: list
+ elements: int
+ pos_int:
+ description: Specify Aggregated pos interface(s)
+ type: list
+ elements: int
+ fast_ethernet:
+ description: Specify FastEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fiftygige:
+ description: Specify FiftyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fortygige:
+ description: Specify FortyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fourhundredgige:
+ description: Specify FourHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ gigabitethernet:
+ description: Specify GigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ hundredgige:
+ description: Specify HundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ mgmteth:
+ description: Specify MgmtEth/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ multilink:
+ description: Specify Multilink network interface(s)
+ type: list
+ elements: str
+ pw_ether:
+ description: Specify PWHE Ethernet Interface
+ type: list
+ elements: int
+ pw_iw:
+ description: Specify PWHE VC11 IP Interworking Interface
+ type: list
+ elements: int
+ srp:
+ description: Specify SRP interface(s)
+ type: list
+ elements: str
+ serial:
+ description: Specify Serial network interface(s)
+ type: list
+ elements: str
+ tengige:
+ description: Specify TenGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ twentyfivegige:
+ description: Specify TwentyFiveGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ twohundredgige:
+ description: Specify TwoHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ nve:
+ description: Specify Network Virtualization Endpoint Interface(s)
+ type: list
+ elements: int
+ tunnel_ip:
+ description: Specify GRE/IPinIP Tunnel Interface(s)
+ type: list
+ elements: int
+ tunnel_ipsec:
+ description: Specify IPSec Tunnel interface(s)
+ type: list
+ elements: int
+ tunnel_mte:
+ description: Specify MPLS Traffic Engineering P2MP Tunnel interface(s)
+ type: list
+ elements: int
+ tunnel_mpls:
+ description: MPLS Transport Protocol Tunnel interface
+ type: int
+ per_prefix:
+ description: Specify per-prefix computation
+ type: dict
+ suboptions:
+ information_type:
+ description: Specify per_prefix LFA exclusion or FRR LFA candidate information
+ type: str
+ choices: ["exclude", "lfa_candidate"]
+ use_candidate_only:
+ description: Enable/Disable backup selection from candidate-list only
+ type: bool
+ interface:
+ description: Specify Per-link LFA exclusion information
+ type: dict
+ suboptions:
+ bvi:
+ description: Specify Bridge-Group Virtual Interface
+ type: list
+ elements: int
+ bundle_ether:
+ description: Specify Aggregated Ethernet interface(s)
+ type: list
+ elements: int
+ post_int:
+ description: Specify Aggregated pos interface(s)
+ type: list
+ elements: int
+ fast_ethernet:
+ description: Specify FastEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fiftygige:
+ description: Specify FiftyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fortygige:
+ description: Specify FortyGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ fourhundredgige:
+ description: Specify FourHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ gigabitethernet:
+ description: Specify GigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ hundredgige:
+ description: Specify HundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ mgmteth:
+ description: Specify MgmtEth/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ multilink:
+ description: Specify Multilink network interface(s)
+ type: list
+ elements: str
+ pw_ether:
+ description: Specify PWHE Ethernet Interface
+ type: list
+ elements: int
+ pw_iw:
+ description: Specify PWHE VC11 IP Interworking Interface
+ type: list
+ elements: int
+ srp:
+ description: Specify SRP interface(s)
+ type: list
+ elements: str
+ serial:
+ description: Specify Serial network interface(s)
+ type: list
+ elements: str
+ tengige:
+ description: Specify TenGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ twentyfivegige:
+ description: Specify TwentyFiveGigabitEthernet/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ twohundredgige:
+ description: Specify TwoHundredGigE/IEEE 802.3 interface(s)
+ type: list
+ elements: str
+ nve:
+ description: Specify Network Virtualization Endpoint Interface(s)
+ type: list
+ elements: int
+ tunnel_ip:
+ description: Specify GRE/IPinIP Tunnel Interface(s)
+ type: list
+ elements: int
+ tunnel_ipsec:
+ description: Specify IPSec Tunnel interface(s)
+ type: list
+ elements: int
+ tunnel_mte:
+ description: Specify MPLS Traffic Engineering P2MP Tunnel interface(s)
+ type: list
+ elements: int
+ tunnel_mpls:
+ description: MPLS Transport Protocol Tunnel interface
+ type: int
+ flood_reduction:
+ description: Enable/Disable flood reduction
+ type: bool
+ graceful_restart:
+ description: Enable Graceful-Restart
+ type: dict
+ suboptions:
+ set:
+ description: Set graceful restart
+ type: bool
+ helper_disable:
+ description: Disable router's helper support level
+ type: bool
+ min_interval:
+ description: Minimum interval between Graceful Restarts
+ type: int
+ max_interval:
+ description: Maximum route lifetime following restart
+ type: int
+ hello_interval:
+ description: Specify Time between HELLO packets
+ type: int
+ ignore_mospf_type6_lsa:
+ description: Ignore MOSPF Type 6 LSA
+ type: bool
+ instance_id:
+ description: Specify instance ID
+ type: int
+ log_adjacency_changes:
+ description: Log adjacency state changes
+ type: dict
+ suboptions:
+ set:
+ description: Set log adjacency
+ type: bool
+ disable:
+ description: Disable log adjacency changes
+ type: bool
+ detail:
+ description: Log all state changes
+ type: bool
+ maximum:
+ description: Set OSPFv3 limits
+ type: dict
+ suboptions:
+ interfaces:
+ description: Specify limit for number of interfaces
+ type: int
+ paths:
+ description: Specify limit for number of paths
+ type: int
+ redistributed_prefixes:
+ description: Specify limit for number of redistributed prefixes
+ type: int
+ mpls_ldp_sync:
+ description: Enable/Disable MPLS LDP Sync
+ type: bool
+ mtu_ignore:
+ description: Enable/Disable ignoring of MTU in DBD packets
+ type: bool
+ network:
+ description: Specify Network type
+ type: str
+ choices: ["broadcast", "non-broadcast", "point-to-multipoint", "point-to-point"]
+ nsr:
+ description: Enable/Disable NSR for all VRFs in this process
+ type: bool
+ packet_size:
+ description: Specify limit size of OSPFv3 packets
+ type: int
+ passive:
+ description: Enable/Disable routing updates on an interface
+ type: bool
+ prefix_suppression:
+ description: Hide all transit addresses on this interface
+ type: bool
+ priority:
+ description: Specify Router priority
+ type: int
+ protocol_shutdown:
+ description: Gracefully shutdown the OSPFv3 protocol
+ type: bool
+ redistribute:
+ description: Redistribute information from another routing Protocol
+ type: dict
+ suboptions:
+ application:
+ description: Specify application routes
+ type: list
+ elements: dict
+ suboptions:
+ id:
+ description: OnePK Application name
+ type: str
+ required: true
+ set:
+ description: Set application route
+ type: bool
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ bgp:
+ description: Specify bgp routes
+ type: list
+ elements: dict
+ suboptions:
+ id:
+ description: BGP process name
+ type: int
+ required: true
+ set:
+ description: Set bgp route number
+ type: bool
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ preserved_med:
+ description: Specify preserve med of BGP routes
+ type: str
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ connected:
+ description: Specify connected routes
+ type: dict
+ suboptions:
+ set:
+ description: Set connected route
+ type: bool
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ eigrp:
+ description: Specify eigrp routes
+ type: list
+ elements: dict
+ suboptions:
+ id:
+ description: EIGRP process name
+ type: int
+ required: true
+ set:
+ description: Set bgp route number
+ type: bool
+ match:
+ description: Redistribution of EIGRP routes
+ type: str
+ choices: ["external", "internal"]
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ isis:
+ description: Specify IS-IS routes
+ type: list
+ elements: dict
+ suboptions:
+ id:
+ description: IS-IS name
+ type: str
+ required: true
+ set:
+ description: Set IS-IS route number
+ type: bool
+ level:
+ description: Specify IS-IS level routes
+ type: str
+ choices: ["level-1", "level-1-2", "level-2"]
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ mobile:
+ description: Specify mobile routes
+ type: dict
+ suboptions:
+ set:
+ description: Set mobile route number
+ type: bool
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ ospfv3:
+ description: Specify ospfv3 routes
+ type: list
+ elements: dict
+ suboptions:
+ id:
+ description: OSPFv3 process name
+ type: str
+ required: true
+ set:
+ description: Set ospfv3 route number
+ type: bool
+ match:
+ description: Redistribution of OSPFv3 routes
+ type: dict
+ suboptions:
+ external:
+ description: Redistribute OSPFv3 external routes
+ type: int
+ choices: ["1", "2"]
+ nssa_external:
+ description: Redistribute NSSA OSPFv3 external routes
+ type: int
+ choices: ["1", "2"]
+ internal:
+ description: Redistribute OSPFv3 internal routes
+ type: bool
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ static:
+ description: Specify static routes
+ type: dict
+ suboptions:
+ set:
+ description: Set static route
+ type: bool
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ subscriber:
+ description: Specify subscriber routes
+ type: dict
+ suboptions:
+ set:
+ description: Set static route
+ type: bool
+ metric:
+ description: Specify metric for redistributed routes
+ type: int
+ metric_type:
+ description: Specify OSPFv3 exterior metric type for redistributed routes
+ type: int
+ route_policy:
+ description: Apply route policy to redistribution
+ type: str
+ tag:
+ description: Set tag for routes redistributed into OSPFv3
+ type: int
+ retransmit_interval:
+ description: Delay between LSA retransmissions
+ type: int
+ router_id:
+ description: ospfv3 router-id in IPv4 address format (A.B.C.D)
+ type: str
+ spf_prefix_priority:
+ description: Specify SPF configuration
+ type: dict
+ suboptions:
+ disable:
+ description: Disable SPF prefix priority
+ type: bool
+ route_policy:
+ description: Specify the route-policy to prioritize route install
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Specify name of the policy
+ type: str
+ value:
+ description: Specify parameter values for the policy ()
+ type: str
+ stub_router:
+ description: Enter stub router configuration submode
+ type: dict
+ suboptions:
+ router_lsa:
+ description: Modify self originated router LSAs
+ type: dict
+ suboptions:
+ advertise_with:
+ description: Advertise LSAs with specified type
+ type: str
+ choices: ["max-metric", "r-bit", "v6-bit"]
+ always:
+ description: Force ospfv3 stub router mode unconditionally
+ type: bool
+ external_lsa:
+ description: Override External LSA metric in stub router mode
+ type: dict
+ suboptions:
+ set:
+ description: Set external lsa
+ type: bool
+ metric:
+ description: Metric to use while in stub router mode
+ type: int
+ include_stub:
+ description: Set maximum metric for stub links in stub router mode
+ type: bool
+ on_proc_migration:
+ description: Enter stub router mode on ospfv3 process migration
+ type: int
+ on_proc_restart:
+ description: Enter stub router mode on ospfv3 process restart
+ type: int
+ on_startup:
+ description: Enter stub router mode on startup
+ type: dict
+ suboptions:
+ time:
+ description: Time in seconds to stay in stub router mode
+ type: int
+ wait_for_bgp:
+ description: Exit stub router mode when BGP converges
+ type: bool
+ on_switchover:
+ description: Enter stub router mode on RP switchover
+ type: int
+ summary_lsa:
+ description: Override Summary LSA metric in stub router mode
+ type: dict
+ suboptions:
+ set:
+ description: Enable summary LSA
+ type: bool
+ metric:
+ description: Metric to use while in stub router mode
+ type: int
+ summary_prefix:
+ description: Configure IP address summaries
+ type: list
+ elements: dict
+ suboptions:
+ prefix:
+ description: IP summary address/mask (A.B.C.D/prefix)
+ type: str
+ required: True
+ not_advertise:
+ description: Suppress routes that match the specified prefix/mask pair
+ type: bool
+ tag:
+ description: Set tag
+ type: int
+ timers:
+ description: Adjust routing timers
+ type: dict
+ suboptions:
+ lsa_arrival:
+ description: Specify LSA arrival timers
+ type: int
+ pacing:
+ description: Specify pacing timers
+ type: dict
+ suboptions:
+ flood:
+ description: Flood pacing timer
+ type: int
+ lsa_group:
+ description: LSA group pacing timer
+ type: int
+ retransmission:
+ description: LSA group pacing timer
+ type: int
+ throttle:
+ description: Adjust throttle timers
+ type: dict
+ suboptions:
+ lsa:
+ description: Specify LSA throttle timers
+ type: dict
+ suboptions:
+ all_lsa_initial:
+ description: Delay to generate first occurrence of LSA in milliseconds
+ type: int
+ all_lsa_minimum:
+ description: Minimum delay between originating the same LSA in milliseconds
+ type: int
+ spf:
+ description: Specify SPF throttle timers
+ type: dict
+ suboptions:
+ spf_initial:
+ description: Delay to generate first occurrence of SPF in ms
+ type: int
+ spf_minimum:
+ description: Minimum delay between originating the same SPF in ms
+ type: int
+ trace:
+ description: Specify OSPF tracing options
+ type: dict
+ suboptions:
+ size:
+ description: Delete existing buffer and create one with N entries
+ type: str
+ value:
+ description: Specify trace entry
+ type: int
+ transmit_delay:
+ description: Estimated time needed to send link-state update packet
+ type: int
+ state:
+ description:
+ - The state the configuration should be left in
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - gathered
+ - rendered
+ - parsed
+ default: merged
+"""
+EXAMPLES = """
+# Using merged
+
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospfv3
+# Thu Jun 11 15:54:44.569 UTC
+# % No such configuration item(s)
+#
+
+- name: Merge provided OSPFv3 configuration with the existing configuration
+ cisco.iosxr.iosxr_ospfv3:
+ config:
+ processes:
+ - process_id: 27
+ areas:
+ - area_id: 10
+ hello_interval: 2
+ - process_id: 26
+ authentication:
+ disable: true
+ - process_id: 10
+ areas:
+ - area_id: 11
+ default_cost: 5
+ cost: 11
+ - area_id: 22
+ default_cost: 6
+ - process_id: 30
+ areas:
+ - area_id: 11
+ default_cost: 5
+ - area_id: 22
+ default_cost: 6
+ cost: 2
+ default_metric: 10
+ transmit_delay: 2
+ hello_interval: 1
+ dead_interval: 2
+ retransmit_interval: 2
+ packet_size: 577
+ priority: 1
+ router_id: '2.2.2.2'
+ demand_circuit: true
+ mtu_ignore: true
+ state: merged
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {}
+#
+# "commands": [
+# "router ospfv3 10",
+# "area 11 default-cost 5",
+# "area 11 cost 11",
+# "area 22 default-cost 6",
+# "router ospfv3 26",
+# "authentication disable",
+# "router ospfv3 27",
+# "area 10 hello-interval 2",
+# "router ospfv3 30",
+# "cost 2",
+# "priority 1",
+# "default-metric 10",
+# "router-id 2.2.2.2",
+# "demand-circuit",
+# "packet-size 577",
+# "transmit-delay 2",
+# "dead-interval 2",
+# "hello-interval 1",
+# "retransmit-interval 2",
+# "mtu-ignore",
+# "area 11 default-cost 5",
+# "area 22 default-cost 6"
+# ]
+#
+# "after": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "process_id": "10"
+# },
+# {
+# "authentication": {
+# "disable": true
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": true,
+# "hello_interval": 1,
+# "mtu_ignore": true,
+# "packet_size": 577,
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "transmit_delay": 2
+# }
+# ]
+# }
+#
+#
+# ------------
+# After state
+# ------------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospfv3
+# router ospfv3 10
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# !
+# area 30
+# !
+# !
+# router ospfv3 30
+# cost 2
+# priority 1
+# mtu-ignore
+# packet-size 577
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit
+# hello-interval 1
+# transmit-delay 2
+# router-id 2.2.2.2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# router ospfv3 10
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# !
+# area 30
+# !
+# !
+# router ospfv3 30
+# cost 2
+# priority 1
+# mtu-ignore
+# packet-size 577
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit
+# hello-interval 1
+# transmit-delay 2
+# router-id 2.2.2.2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+
+
+
+# Using replaced
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# router ospfv3 10
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# !
+# area 30
+# !
+# !
+# router ospfv3 30
+# cost 2
+# priority 1
+# mtu-ignore
+# packet-size 577
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit
+# hello-interval 1
+# transmit-delay 2
+# router-id 2.2.2.2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# router ospfv3 10
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# !
+# area 30
+# !
+# !
+# router ospfv3 30
+# cost 2
+# priority 1
+# mtu-ignore
+# packet-size 577
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit
+# hello-interval 1
+# transmit-delay 2
+# router-id 2.2.2.2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+
+- name: Replace OSPFv3 routes configurations from the device
+ cisco.iosxr.iosxr_ospfv3:
+ config:
+ processes:
+ - process_id: 27
+ areas:
+ - area_id: 10
+ hello_interval: 2
+ - area_id: 20
+ cost: 2
+ default_cost: 2
+ - process_id: 26
+ authentication:
+ disable: true
+ state: replaced
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "process_id": "10"
+# },
+# {
+# "authentication": {
+# "disable": true
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": true,
+# "hello_interval": 1,
+# "mtu_ignore": true,
+# "packet_size": 577,
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "transmit_delay": 2
+# }
+# ]
+# }
+#
+# "commands": [
+# "router ospfv3 27",
+# "area 20 default-cost 2",
+# "area 20 cost 2"
+# ]
+#
+# "after": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "process_id": "10"
+# },
+# {
+# "authentication": {
+# "disable": true
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# },
+# {
+# "area_id": "20",
+# "cost": 2,
+# "default_cost": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": true,
+# "hello_interval": 1,
+# "mtu_ignore": true,
+# "packet_size": 577,
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "transmit_delay": 2
+# }
+# ]
+# }
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/RP0/CPU0:anton(config)#do show running-config router ospfv3
+# router ospfv3 10
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# cost 2
+# default-cost 2
+# !
+# area 30
+# !
+# !
+# router ospfv3 30
+# cost 2
+# priority 1
+# mtu-ignore
+# packet-size 577
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit
+# hello-interval 1
+# transmit-delay 2
+# router-id 2.2.2.2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+
+
+- name: Override existing OSPFv3 configurations from the device
+ cisco.iosxr.iosxr_ospfv3:
+ config:
+ processes:
+ - process_id: 27
+ areas:
+ - area_id: 10
+ hello_interval: 2
+ authentication:
+ disable: true
+ - area_id: 20
+ cost: 2
+ default_cost: 2
+ authentication:
+ disable: true
+ - process_id: 26
+ areas:
+ - area_id: 10
+ hello_interval: 2
+ authentication:
+ disable: true
+ state: overridden
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "process_id": "10"
+# },
+# {
+# "authentication": {
+# "disable": true
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# },
+# {
+# "area_id": "20",
+# "cost": 2,
+# "default_cost": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": true,
+# "hello_interval": 1,
+# "mtu_ignore": true,
+# "packet_size": 577,
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "transmit_delay": 2
+# }
+# ]
+# }
+#
+# "commands": [
+# "router ospfv3 10",
+# "no area 11 default-cost 5",
+# "no area 11 cost 11",
+# "no area 22 default-cost 6",
+# "router ospfv3 30",
+# "no cost 2",
+# "no priority 1",
+# "no default-metric 10",
+# "no router-id 2.2.2.2",
+# "no demand-circuit",
+# "no packet-size 577",
+# "no transmit-delay 2",
+# "no dead-interval 2",
+# "no hello-interval 1",
+# "no retransmit-interval 2",
+# "no mtu-ignore",
+# "no area 11 default-cost 5",
+# "no area 22 default-cost 6",
+# "router ospfv3 26",
+# "area 10 hello-interval 4"
+# ]
+#
+# "after": {
+# "processes": [
+# {
+# "process_id": "10"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 4
+# }
+# ],
+# "authentication": {
+# "disable": true
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# },
+# {
+# "area_id": "20",
+# "cost": 2,
+# "default_cost": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "process_id": "30"
+# }
+# ]
+# }
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospfv3
+# router ospfv3 10
+# area 11
+# !
+# area 22
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# area 10
+# hello-interval 4
+# !
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# cost 2
+# default-cost 2
+# !
+# area 30
+# !
+# !
+# router ospfv3 30
+# area 11
+# !
+# area 22
+# !
+# !
+
+
+
+# Using deleted
+#
+# ------------
+# Before state
+# ------------
+#
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospfv3
+# router ospfv3 10
+# area 11
+# !
+# area 22
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# area 10
+# hello-interval 4
+# !
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# cost 2
+# default-cost 2
+# !
+# area 30
+# !
+# !
+# router ospfv3 30
+# area 11
+# !
+# area 22
+# !
+# !
+
+- name: Deleted existing OSPFv3 configurations from the device
+ cisco.iosxr.iosxr_ospfv3:
+ config:
+ processes:
+ - process_id: '10'
+ - process_id: '26'
+ - process_id: '27'
+ - process_id: '30'
+ state: deleted
+
+#
+#
+# ------------------------
+# Module Execution Result
+# ------------------------
+#
+# "before": {
+# "processes": [
+# {
+# "process_id": "10"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 4
+# }
+# ],
+# "authentication": {
+# "disable": true
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# },
+# {
+# "area_id": "20",
+# "cost": 2,
+# "default_cost": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "process_id": "30"
+# }
+# ]
+# },
+#
+# "commands": [
+# "router ospfv3 26",
+# "no authentication disable",
+# "no area 10 hello-interval 4",
+# "router ospfv3 27",
+# "no area 10 hello-interval 2",
+# "no area 20 default-cost 2",
+# "no area 20 cost 2"
+# ]
+#
+# "after": {
+# "processes": [
+# {
+# "process_id": "10"
+# },
+# {
+# "process_id": "26"
+# },
+# {
+# "process_id": "27"
+# },
+# {
+# "process_id": "30"
+# }
+# ]
+# }
+#
+#
+# -----------
+# After state
+# -----------
+#
+# RP/0/RP0/CPU0:anton(config)#show running-config router ospfv3
+# router ospfv3 10
+# !
+# router ospfv3 26
+# !
+# router ospfv3 27
+# !
+# router ospfv3 30
+# !
+
+
+# Using parsed
+# parsed.cfg
+# ------------
+# router ospfv3 10
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# !
+# router ospfv3 30
+# router-id 2.2.2.2
+# cost 2
+# packet-size 577
+# priority 1
+# mtu-ignore
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit
+# hello-interval 1
+# transmit-delay 2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+- name: Parsed the device configuration to get output commands
+ cisco.iosxr.iosxr_ospfv3:
+ running_config: "{{ lookup('file', './parsed.cfg') }}"
+ state: parsed
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+#
+# "parsed": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "process_id": "10"
+# },
+# {
+# "authentication": {
+# "disable": true
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": true,
+# "hello_interval": 1,
+# "mtu_ignore": true,
+# "packet_size": 577,
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "transmit_delay": 2
+# }
+# ]
+# }
+#
+# Using rendered
+#
+#
+- name: Render the commands for provided configuration
+ cisco.iosxr.iosxr_ospfv3:
+ config:
+ processes:
+ - process_id: 27
+ areas:
+ - area_id: 10
+ hello_interval: 2
+ - process_id: 26
+ authentication:
+ disable: true
+ - process_id: 10
+ areas:
+ - area_id: 11
+ default_cost: 5
+ cost: 11
+ - area_id: 22
+ default_cost: 6
+ - process_id: 30
+ areas:
+ - area_id: 11
+ default_cost: 5
+ - area_id: 22
+ default_cost: 6
+ cost: 2
+ default_metric: 10
+ transmit_delay: 2
+ hello_interval: 1
+ dead_interval: 2
+ retransmit_interval: 2
+ packet_size: 577
+ priority: 1
+ router_id: '2.2.2.2'
+ demand_circuit: true
+ mtu_ignore: true
+ state: rendered
+
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+#
+# "rendered": [
+# "router ospfv3 27",
+# "area 10 hello-interval 2",
+# "router ospfv3 26",
+# "authentication disable",
+# "router ospfv3 10",
+# "area 11 default-cost 5",
+# "area 11 cost 11",
+# "area 22 default-cost 6",
+# "router ospfv3 30",
+# "cost 2",
+# "priority 1",
+# "default-metric 10",
+# "router-id 2.2.2.2",
+# "demand-circuit",
+# "packet-size 577",
+# "transmit-delay 2",
+# "dead-interval 2",
+# "hello-interval 1",
+# "retransmit-interval 2",
+# "mtu-ignore",
+# "area 11 default-cost 5",
+# "area 22 default-cost 6"
+# ]
+
+
+# Using gathered
+#
+# Before state:
+# -------------
+#
+# RP/0/RP0/CPU0:anton#show running-config router ospf
+# router ospfv3 10
+# area 11
+# cost 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+# router ospfv3 26
+# authentication disable
+# area 10
+# !
+# !
+# router ospfv3 27
+# area 10
+# hello-interval 2
+# !
+# area 20
+# !
+# area 30
+# !
+# !
+# router ospfv3 30
+# cost 2
+# priority 1
+# mtu-ignore
+# packet-size 577
+# dead-interval 2
+# retransmit-interval 2
+# demand-circuit
+# hello-interval 1
+# transmit-delay 2
+# router-id 2.2.2.2
+# default-metric 10
+# area 11
+# default-cost 5
+# !
+# area 22
+# default-cost 6
+# !
+# !
+
+- name: Gather ospfv3 routes configuration
+ cisco.iosxr.iosxr_ospfv3:
+ state: gathered
+#
+#
+# -------------------------
+# Module Execution Result
+# -------------------------
+#
+# "gathered": {
+# "processes": [
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "cost": 11,
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "process_id": "10"
+# },
+# {
+# "authentication": {
+# "disable": true
+# },
+# "process_id": "26"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "10",
+# "hello_interval": 2
+# }
+# ],
+# "process_id": "27"
+# },
+# {
+# "areas": [
+# {
+# "area_id": "11",
+# "default_cost": 5
+# },
+# {
+# "area_id": "22",
+# "default_cost": 6
+# }
+# ],
+# "cost": 2,
+# "dead_interval": 2,
+# "default_metric": 10,
+# "demand_circuit": true,
+# "hello_interval": 1,
+# "mtu_ignore": true,
+# "packet_size": 577,
+# "priority": 1,
+# "process_id": "30",
+# "retransmit_interval": 2,
+# "router_id": "2.2.2.2",
+# "transmit_delay": 2
+# }
+# ]
+# }
+#
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.ospfv3.ospfv3 import (
+ Ospfv3Args,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.ospfv3.ospfv3 import (
+ Ospfv3,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ module = AnsibleModule(
+ argument_spec=Ospfv3Args.argument_spec,
+ mutually_exclusive=[["config", "running_config"]],
+ required_if=[
+ ["state", "merged", ["config"]],
+ ["state", "replaced", ["config"]],
+ ["state", "overridden", ["config"]],
+ ["state", "rendered", ["config"]],
+ ["state", "parsed", ["running_config"]],
+ ],
+ supports_check_mode=True,
+ )
+
+ result = Ospfv3(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ping.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ping.py
new file mode 100644
index 00000000..9861cc09
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_ping.py
@@ -0,0 +1,176 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2022 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+"""
+The module file for iosxr_ping
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+module: iosxr_ping
+short_description: Tests reachability using ping from IOSXR switch.
+description:
+- Tests reachability using ping from switch to a remote destination.
+- For a general purpose network module, see the L(net_ping,https://docs.ansible.com/ansible/latest/collections/ansible/netcommon/net_ping_module.html)
+ module.
+- For Windows targets, use the L(win_ping,https://docs.ansible.com/ansible/latest/collections/ansible/windows/win_ping_module.html)
+ module instead.
+- For targets running Python, use the L(ping,https://docs.ansible.com/ansible/latest/collections/ansible/builtin/ping_module.html)
+ module instead.
+notes:
+- Tested against IOSXR 7.2.2.
+- This module works with connection C(network_cli).
+- For a general purpose network module, see the L(net_ping,https://docs.ansible.com/ansible/latest/collections/ansible/netcommon/net_ping_module.html)
+ module.
+- For Windows targets, use the L(win_ping,https://docs.ansible.com/ansible/latest/collections/ansible/windows/win_ping_module.html)
+ module instead.
+- For targets running Python, use the L(ping,https://docs.ansible.com/ansible/latest/collections/ansible/builtin/ping_module.html) module instead.
+
+author: Sagar Paul (@KB-perByte)
+options:
+ count:
+ description:
+ - Repeat count the number of packets to send.
+ type: int
+ afi:
+ description:
+ - Define echo type ipv4 or ipv6.
+ choices:
+ - ipv4
+ - ipv6
+ default: ipv4
+ type: str
+ dest:
+ description:
+ - The IP Address or hostname (resolvable by switch) of the remote node.
+ required: true
+ type: str
+ df_bit:
+ description:
+ - Set the DF bit in IP-header.
+ default: false
+ type: bool
+ sweep:
+ description:
+ - Sweep ping.
+ default: false
+ type: bool
+ validate:
+ description:
+ - Validate return packet.
+ default: false
+ type: bool
+ source:
+ description:
+ - Source address or source interface.
+ type: str
+ size:
+ description:
+ - Datagram size the size of packets to send.
+ type: int
+ state:
+ description:
+ - Determines if the expected result is success or fail.
+ choices:
+ - absent
+ - present
+ default: present
+ type: str
+ vrf:
+ description:
+ - The VRF to use for forwarding.
+ type: str
+"""
+
+EXAMPLES = """
+- name: Test reachability to 198.51.100.251 using default vrf
+ cisco.iosxr.iosxr_ping:
+ dest: 198.51.100.251
+
+- name: Test reachability to 198.51.100.252 using prod vrf
+ cisco.iosxr.iosxr_ping:
+ dest: 198.51.100.252
+ vrf: prod
+ afi: ipv4
+
+- name: Test unreachability to 198.51.100.253 using default vrf
+ cisco.iosxr.iosxr_ping:
+ dest: 198.51.100.253
+ state: absent
+
+- name: Test reachability to 198.51.100.250 using prod vrf and setting count and source
+ cisco.iosxr.iosxr_ping:
+ dest: 198.51.100.250
+ source: loopback0
+ vrf: prod
+ count: 20
+
+- name: Test reachability to 198.51.100.249 using df-bit and size
+ cisco.iosxr.iosxr_ping:
+ dest: 198.51.100.249
+ df_bit: true
+ size: 1400
+
+- name: Test reachability to ipv6 address
+ cisco.iosxr.iosxr_ping:
+ dest: 2001:db8:ffff:ffff:ffff:ffff:ffff:ffff
+ afi: ipv6
+"""
+
+RETURN = """
+commands:
+ description: Show the command sent.
+ returned: always
+ type: list
+ sample: ["ping vrf prod 198.51.100.251 count 20 source loopback0"]
+packet_loss:
+ description: Percentage of packets lost.
+ returned: always
+ type: str
+ sample: "0%"
+packets_rx:
+ description: Packets successfully received.
+ returned: always
+ type: int
+ sample: 20
+packets_tx:
+ description: Packets successfully transmitted.
+ returned: always
+ type: int
+ sample: 20
+rtt:
+ description: Show RTT stats.
+ returned: always
+ type: dict
+ sample: {"avg": 2, "max": 8, "min": 1}
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.ping.ping import (
+ PingArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.ping.ping import Ping
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ module = AnsibleModule(argument_spec=PingArgs.argument_spec)
+
+ result = Ping(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_prefix_lists.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_prefix_lists.py
new file mode 100644
index 00000000..1fccc852
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_prefix_lists.py
@@ -0,0 +1,1115 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2022 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+"""
+The module file for iosxr_prefix_lists
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+module: iosxr_prefix_lists
+short_description: Resource module to configure prefix lists.
+description:
+- This module manages prefix-lists configuration on devices running Cisco IOSXR.
+version_added: 2.3.0
+notes:
+- Tested against IOSXR 7.0.2.
+- This module works with connection C(network_cli).
+author: Ashwini Mhatre (@amhatre)
+options:
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the Iosxr device by
+ executing the command B(show running-config prefix-list).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ config:
+ description: A list of prefix-lists configuration.
+ type: list
+ elements: dict
+ suboptions:
+ afi:
+ description:
+ - The Address Family Identifier (AFI) for the prefix-lists.
+ type: str
+ choices: ["ipv4", "ipv6"]
+ prefix_lists:
+ description: List of prefix-list configurations.
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Name of the prefix-list.
+ type: str
+ entries:
+ description: List of configurations for the specified prefix-list
+ type: list
+ elements: dict
+ suboptions:
+ sequence:
+ description: Sequence Number.
+ type: int
+ action:
+ description: Prefix-List permit or deny.
+ type: str
+ choices: ["permit", "deny", "remark"]
+ description:
+ description: Description of the prefix list. only applicable for action "remark".
+ type: str
+ prefix:
+ description: IP or IPv6 prefix in A.B.C.D/LEN or A:B::C:D/LEN format. only applicable for action "permit" and "deny"
+ type: str
+ eq:
+ description: Exact prefix length to be matched.
+ type: int
+ ge:
+ description: Minimum prefix length to be matched.
+ type: int
+ le:
+ description: Maximum prefix length to be matched.
+ type: int
+ state:
+ description:
+ - The state the configuration should be left in.
+ - Refer to examples for more details.
+ - With state I(replaced), for the listed prefix-lists,
+ sequences that are in running-config but not in the task are negated.
+ - With state I(overridden), all prefix-lists that are in running-config but
+ not in the task are negated.
+ - Please refer to examples for more details.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - parsed
+ - gathered
+ - rendered
+ default: merged
+"""
+
+EXAMPLES = """
+# Using merged
+# Before state
+#RP/0/0/CPU0:10#show running-config
+#Thu Feb 4 09:38:36.245 UTC
+#% No such configuration item(s)
+#RP/0/0/CPU0:10#
+#
+- name: Merge the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_prefix_lists:
+ state: merged
+ config:
+ - afi: ipv6
+ prefix_lists:
+ - name: pl_1
+ entries:
+ - prefix: 2001:db8:1234::/48
+ action: deny
+ sequence: 1
+ - name: pl_2
+ entries:
+ - sequence: 2
+ action: remark
+ description: TEST_PL_2_REMARK
+ - afi: ipv4
+ prefix_lists:
+ - name: pl1
+ entries:
+ - sequence: 3
+ action: remark
+ description: TEST_PL1_2_REMARK
+ - sequence: 4
+ action: permit
+ prefix: 10.0.0.0/24
+ - name: pl2
+ entries:
+ - sequence: 5
+ action: remark
+ description: TEST_PL2_REMARK
+ - name: pl3
+ entries:
+ - sequence: 6
+ action: permit
+ prefix: 35.0.0.0/8
+ eq: 0
+
+#
+# After state:
+#
+#RP/0/0/CPU0:10#show running-config
+# ipv6 prefix-list pl_1
+# 1 deny 2001:db8:1234::/48
+# !
+# ipv6 prefix-list pl_2
+# 2 remark TEST_PL_2_REMARK
+# !
+# ipv4 prefix-list pl1
+# 3 remark TEST_PL1_2_REMARK
+# 4 permit 10.0.0.0/24
+# !
+# ipv4 prefix-list pl2
+# 5 remark TEST_PL2_REMARK
+# !
+# ipv4 prefix-list pl3
+# 6 permit 35.0.0.0/8 eq 0
+# !
+
+#Module execution
+#
+# "after": [
+# {
+# "afi": "ipv6",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "deny",
+# "prefix": "2001:db8:1234::/48",
+# "sequence": 1
+# }
+# ],
+# "name": "pl_1"
+# },
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL_2_REMARK",
+# "sequence": 2
+# }
+# ],
+# "name": "pl_2"
+# }
+# ]
+# },
+# {
+# "afi": "ipv4",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL1_2_REMARK",
+# "sequence": 3
+# },
+# {
+# "action": "permit",
+# "prefix": "10.0.0.0/24",
+# "sequence": 4
+# }
+# ],
+# "name": "pl1"
+# },
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL2_REMARK",
+# "sequence": 5
+# }
+# ],
+# "name": "pl2"
+# },
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "prefix": "35.0.0.0/8",
+# "sequence": 6,
+# "eq": 0
+# }
+# ],
+# "name": "pl3"
+# },
+# ]
+# }
+# ],
+# "before": [],
+# "changed": true,
+# "commands": [
+# "ipv6 prefix-list pl_1 1 deny 2001:db8:1234::/48",
+# "ipv6 prefix-list pl_2 2 remark TEST_PL_2_REMARK",
+# "ipv4 prefix-list pl1 3 remark TEST_PL1_2_REMARK",
+# "ipv4 prefix-list pl1 4 permit 10.0.0.0/24",
+# "ipv4 prefix-list pl2 5 remark TEST_PL2_REMARK"
+# "ipv4 prefix-list pl3 6 permit 35.0.0.0/8 eq 0"
+# ]
+#-----------------------------------------------------------------------
+# Using replaced:
+# --------------
+# Before state
+#RP/0/0/CPU0:10#show running-config
+#
+# ipv6 prefix-list pl_1
+# 1 deny 2001:db8:1234::/48
+# !
+# ipv6 prefix-list pl_2
+# 2 remark TEST_PL_2_REMARK
+# !
+# ipv4 prefix-list pl1
+# 3 remark TEST_PL1_2_REMARK
+# 4 permit 10.0.0.0/24
+# !
+# ipv4 prefix-list pl2
+# 5 remark TEST_PL2_REMARK
+# !
+#
+#
+- name: Replace device configurations of listed prefix lists with provided configurations
+ register: result
+ cisco.iosxr.iosxr_prefix_lists: &id001
+ config:
+ - afi: ipv4
+ prefix_lists:
+ - name: pl1
+ entries:
+ - sequence: 3
+ action: permit
+ prefix: 10.0.0.0/24
+ - afi: ipv6
+ prefix_lists:
+ - name: pl_1
+ entries:
+ - prefix: 2001:db8:1234::/48
+ action: permit
+ sequence: 1
+ - name: pl_2
+ entries:
+ - sequence: 2
+ action: remark
+ description: TEST_PL1_2
+ state: replaced
+# After state:
+#RP/0/0/CPU0:10#show running-config
+#
+# ipv6 prefix-list pl_1
+# 1 deny 2001:db8:1234::/48
+# !
+# ipv6 prefix-list pl_2
+# 2 remark TEST_PL1_2
+# !
+# ipv4 prefix-list pl1
+# 3 permit 10.0.0.0/24
+# !
+# ipv4 prefix-list pl2
+# 5 remark TEST_PL2_REMARK
+#
+# Module Execution:
+#
+# "after": [
+# {
+# "afi": "ipv6",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "deny",
+# "prefix": "2001:db8:1234::/48",
+# "sequence": 1
+# }
+# ],
+# "name": "pl_1"
+# },
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL1_2",
+# "sequence": 2
+# }
+# ],
+# "name": "pl_2"
+# }
+# ]
+# },
+# {
+# "afi": "ipv4",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "prefix": "10.0.0.0/24",
+# "sequence": 3
+# }
+# ],
+# "name": "pl1"
+# },
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL2_REMARK",
+# "sequence": 5
+# }
+# ],
+# "name": "pl2"
+# }
+# ]
+# }
+# ],
+# "before": [
+# {
+# "afi": "ipv6",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "deny",
+# "prefix": "2001:db8:1234::/48",
+# "sequence": 1
+# }
+# ],
+# "name": "pl_1"
+# },
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL_2_REMARK",
+# "sequence": 2
+# }
+# ],
+# "name": "pl_2"
+# }
+# ]
+# },
+# {
+# "afi": "ipv4",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL1_2_REMARK",
+# "sequence": 3
+# },
+# {
+# "action": "permit",
+# "prefix": "10.0.0.0/24",
+# "sequence": 4
+# }
+# ],
+# "name": "pl1"
+# },
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL2_REMARK",
+# "sequence": 5
+# }
+# ],
+# "name": "pl2"
+# }
+# ]
+# }
+# ],
+# "changed": true,
+# "commands": [
+# "no ipv4 prefix-list pl1 3 remark TEST_PL1_2_REMARK",
+# "no ipv4 prefix-list pl1 4 permit 10.0.0.0/24",
+# "ipv4 prefix-list pl1 3 permit 10.0.0.0/24",
+# "ipv6 prefix-list pl_2 2 remark TEST_PL1_2"
+# ],
+# "invocation": {
+# "module_args": {
+# "config": [
+# {
+# "afi": "ipv4",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "description": null,
+# "prefix": "10.0.0.0/24",
+# "sequence": 3
+# }
+# ],
+# "name": "pl1"
+# }
+# ]
+# },
+# {
+# "afi": "ipv6",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "description": null,
+# "prefix": "2001:db8:1234::/48",
+# "sequence": 1
+# }
+# ],
+# "name": "pl_1"
+# },
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL1_2",
+# "prefix": null,
+# "sequence": 2
+# }
+# ],
+# "name": "pl_2"
+# }
+# ]
+# }
+# ],
+# "running_config": null,
+# "state": "replaced"
+# }
+# }
+# }
+#------------------------------------------------------------------
+# Using deleted:
+# -------------
+# Before state:
+#RP/0/0/CPU0:10#show running-config
+#
+# ipv6 prefix-list pl_1
+# 1 deny 2001:db8:1234::/48
+# !
+# ipv6 prefix-list pl_2
+# 2 remark TEST_PL_2_REMARK
+# !
+# ipv4 prefix-list pl1
+# 3 remark TEST_PL1_2_REMARK
+# 4 permit 10.0.0.0/24
+# !
+# ipv4 prefix-list pl2
+# 5 remark TEST_PL2_REMARK
+# ipv4 prefix-list pl3
+# 6 permit 35.0.0.0/8 eq 0
+
+- name: Delete all prefix-lists from the device
+ cisco.iosxr.iosxr_prefix_lists:
+ state: deleted
+
+# After state:
+#RP/0/0/CPU0:10#show running-config
+#
+#
+# Module Execution:
+#
+# "after": [],
+# "before": [
+# {
+# "afi": "ipv6",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "deny",
+# "prefix": "2001:db8:1234::/48",
+# "sequence": 1
+# }
+# ],
+# "name": "pl_1"
+# },
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL1_2",
+# "sequence": 2
+# }
+# ],
+# "name": "pl_2"
+# }
+# ]
+# },
+# {
+# "afi": "ipv4",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "prefix": "10.0.0.0/24",
+# "sequence": 3
+# }
+# ],
+# "name": "pl1"
+# },
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL2_REMARK",
+# "sequence": 5
+# }
+# ],
+# "name": "pl2"
+# },
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "prefix": " 35.0.0.0/8",
+# "sequence": 6,
+# "eq": 0
+# }
+# ],
+# "name": "pl3"
+# },
+# ]
+# }
+# ],
+# "changed": true,
+# "commands": [
+# "no ipv6 prefix-list pl_1",
+# "no ipv6 prefix-list pl_2",
+# "no ipv4 prefix-list pl1",
+# "no ipv4 prefix-list pl2"
+# "no ipv4 prefix-list pl3"
+# ],
+# "invocation": {
+# "module_args": {
+# "config": null,
+# "running_config": null,
+# "state": "deleted"
+# }
+# }
+# }
+#---------------------------------------------------------------------------------
+#
+# using gathered:
+# --------------
+# Before state:
+#RP/0/0/CPU0:10#show running-config
+#
+# ipv6 prefix-list pl_1
+# 1 deny 2001:db8:1234::/48
+# !
+# ipv6 prefix-list pl_2
+# 2 remark TEST_PL_2_REMARK
+# !
+# ipv4 prefix-list pl1
+# 3 remark TEST_PL1_2_REMARK
+# 4 permit 10.0.0.0/24
+# !
+# ipv4 prefix-list pl2
+# 5 remark TEST_PL2_REMARK
+#!
+# ipv4 prefix-list pl3
+# 6 permit 35.0.0.0/8 eq 0
+#!
+- name: Gather ACL interfaces facts using gathered state
+ cisco.iosxr.iosxr_prefix_lists:
+ state: gathered
+#
+# Module Execution:
+#
+# "gathered": [
+# {
+# "afi": "ipv6",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "deny",
+# "prefix": "2001:db8:1234::/48",
+# "sequence": 1
+# }
+# ],
+# "name": "pl_1"
+# },
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL_2_REMARK",
+# "sequence": 2
+# }
+# ],
+# "name": "pl_2"
+# }
+# ]
+# },
+# {
+# "afi": "ipv4",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL1_2_REMARK",
+# "sequence": 3
+# },
+# {
+# "action": "permit",
+# "prefix": "10.0.0.0/24",
+# "sequence": 4
+# }
+# ],
+# "name": "pl1"
+# },
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL2_REMARK",
+# "sequence": 5
+# }
+# ],
+# "name": "pl2"
+# },
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "prefix": "35.0.0.0/8",
+# "sequence": 6,
+# "eq": 0
+# }
+# ],
+# "name": "pl3"
+# },
+# ]
+# }
+# ],
+# "changed": false,
+#--------------------------------------------------------------------------
+# Using parsed:
+# --------------
+#
+# parsed.cfg
+#------------------------------
+# ipv6 prefix-list pl_1
+# 1 deny 2001:db8:1234::/48
+# !
+# ipv6 prefix-list pl_2
+# 2 remark TEST_PL_2_REMARK
+# !
+# ipv4 prefix-list pl1
+# 3 remark TEST_PL1_2_REMARK
+# 4 permit 10.0.0.0/24
+# !
+# ipv4 prefix-list pl2
+# 5 remark TEST_PL2_REMARK
+#!
+# ipv4 prefix-list pl3
+# 6 permit 35.0.0.0/8 eq 0
+#
+#
+- name: Parse externally provided Prefix_lists config to agnostic model
+ cisco.iosxr.iosxr_prefix_lists:
+ running_config: "{{ lookup('file', './fixtures/parsed.cfg') }}"
+ state: parsed
+#
+# Module execution:
+#"parsed": [
+# {
+# "afi": "ipv6",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "deny",
+# "prefix": "2001:db8:1234::/48",
+# "sequence": 1
+# }
+# ],
+# "name": "pl_1"
+# },
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL_2_REMARK",
+# "sequence": 2
+# }
+# ],
+# "name": "pl_2"
+# }
+# ]
+# },
+# {
+# "afi": "ipv4",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL1_2_REMARK",
+# "sequence": 3
+# },
+# {
+# "action": "permit",
+# "prefix": "10.0.0.0/24",
+# "sequence": 4
+# }
+# ],
+# "name": "pl1"
+# },
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL2_REMARK",
+# "sequence": 5
+# }
+# ],
+# "name": "pl2"
+# },
+# {
+# "entries": [
+# {
+# "action": "permit",
+# "prefix": "35.0.0.0/8",
+# "sequence": 6,
+# "eq": 0
+# }
+# ],
+# "name": "pl3"
+# },
+# ]
+# }
+# ]
+#
+#----------------------------------------------------------------------------
+# Using rendered:
+# --------------
+#
+- name: Render platform specific commands from task input using rendered state
+ register: result
+ cisco.iosxr.iosxr_prefix_lists:
+ config:
+ - afi: ipv6
+ prefix_lists:
+ - name: pl_1
+ entries:
+ - prefix: 2001:db8:1234::/48
+ action: deny
+ sequence: 1
+ - name: pl_2
+ entries:
+ - sequence: 2
+ action: remark
+ description: TEST_PL_2_REMARK
+ - afi: ipv4
+ prefix_lists:
+ - name: pl1
+ entries:
+ - sequence: 3
+ action: remark
+ description: TEST_PL1_2_REMARK
+ - sequence: 4
+ action: permit
+ prefix: 10.0.0.0/24
+ - name: pl2
+ entries:
+ - sequence: 5
+ action: remark
+ description: TEST_PL2_REMARK
+ - sequence: 6
+ action: permit
+ prefix: 35.0.0.0/8
+ eq: 0
+
+ state: rendered
+# After state:
+# Module Execution:
+# "rendered": [
+# "ipv6 prefix-list pl_1 1 deny 2001:db8:1234::/48",
+# "ipv6 prefix-list pl_2 2 remark TEST_PL_2_REMARK",
+# "ipv4 prefix-list pl1 3 remark TEST_PL1_2_REMARK",
+# "ipv4 prefix-list pl1 4 permit 10.0.0.0/24",
+# "ipv4 prefix-list pl2 5 remark TEST_PL2_REMARK",
+# "ipv4 prefix-list pl2 6 permit 35.0.0.0/8 eq 0"
+# ]
+#
+#---------------------------------------------------------------------------------
+# Using overridden:
+# --------------
+# Before state:
+#RP/0/0/CPU0:10#show running-config
+#
+# ipv6 prefix-list pl_1
+# 1 deny 2001:db8:1234::/48
+# !
+# ipv6 prefix-list pl_2
+# 2 remark TEST_PL_2_REMARK
+# !
+# ipv4 prefix-list pl1
+# 3 remark TEST_PL1_2_REMARK
+# 4 permit 10.0.0.0/24
+# !
+# ipv4 prefix-list pl2
+# 5 remark TEST_PL2_REMARK
+#
+- name: Overridde all Prefix_lists configuration with provided configuration
+ cisco.iosxr.iosxr_prefix_lists:
+ config:
+ - afi: ipv4
+ prefix_lists:
+ - name: pl3
+ entries:
+ - sequence: 3
+ action: remark
+ description: TEST_PL1_3_REMARK
+ - sequence: 4
+ action: permit
+ prefix: 10.0.0.0/24
+ - sequence: 6
+ action: permit
+ prefix: 35.0.0.0/8
+ eq: 0
+ state: overridden
+
+# After state:
+#RP/0/0/CPU0:10#show running-config
+#
+#ipv4 prefix-list pl3
+# 3 remark TEST_PL1_3_REMARK
+# 4 permit 10.0.0.0/24
+# 6 permit 35.0.0.0/8 eq 0
+# !
+#!
+# # Module Execution:
+# "after": [
+# {
+# "afi": "ipv4",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL1_3_REMARK",
+# "sequence": 3
+# },
+# {
+# "action": "permit",
+# "prefix": "10.0.0.0/24",
+# "sequence": 4
+# },
+# {
+# "action": "permit",
+# "prefix": "35.0.0.0/8",
+# "sequence": 6,
+# "eq": 0
+# }
+# ],
+# "name": "pl3"
+# }
+# ]
+# }
+# ],
+# "before": [
+# {
+# "afi": "ipv6",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "deny",
+# "prefix": "2001:db8:1234::/48",
+# "sequence": 1
+# }
+# ],
+# "name": "pl_1"
+# },
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL_2_REMARK",
+# "sequence": 2
+# }
+# ],
+# "name": "pl_2"
+# }
+# ]
+# },
+# {
+# "afi": "ipv4",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL1_2_REMARK",
+# "sequence": 3
+# },
+# {
+# "action": "permit",
+# "prefix": "10.0.0.0/24",
+# "sequence": 4
+# }
+# ],
+# "name": "pl1"
+# },
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL2_REMARK",
+# "sequence": 5
+# }
+# ],
+# "name": "pl2"
+# }
+# ]
+# }
+# ],
+# "changed": true,
+# "commands": [
+# "no ipv6 prefix-list pl_1",
+# "no ipv6 prefix-list pl_2",
+# "no ipv4 prefix-list pl1",
+# "no ipv4 prefix-list pl2",
+# "ipv4 prefix-list pl3 3 remark TEST_PL1_3_REMARK",
+# "ipv4 prefix-list pl3 4 permit 10.0.0.0/24",
+# "ipv4 prefix-list pl3 6 permit 35.0.0.0/8 eq 0"
+# ],
+# "invocation": {
+# "module_args": {
+# "config": [
+# {
+# "afi": "ipv4",
+# "prefix_lists": [
+# {
+# "entries": [
+# {
+# "action": "remark",
+# "description": "TEST_PL1_3_REMARK",
+# "prefix": null,
+# "sequence": 3,
+# "ge": null,
+# "le": null,
+# "eq": null
+# },
+# {
+# "action": "permit",
+# "description": null,
+# "prefix": "10.0.0.0/24",
+# "sequence": 4,
+# "ge": null,
+# "le": null,
+# "eq": null
+# },
+# {
+# "action": "permit",
+# "description": null,
+# "prefix": "35.0.0.0/8",
+# "sequence": 6,
+# "ge": null,
+# "le": null,
+# "eq": 0
+# }
+# ],
+# "name": "pl3"
+# }
+# ]
+# }
+# ],
+# "running_config": null,
+# "state": "overridden"
+# }
+# }
+# }
+#
+"""
+
+RETURN = """
+before:
+ description: The configuration prior to the module execution.
+ returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged)
+ type: dict
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+after:
+ description: The resulting configuration after module execution.
+ returned: when changed
+ type: dict
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged)
+ type: list
+ sample:
+ - "ipv6 prefix-list pl_1 1 deny 2001:db8:1234::/48"
+ - "ipv6 prefix-list pl_2 2 remark TEST_PL_2_REMARK"
+ - "ipv4 prefix-list pl1 3 remark TEST_PL1_2_REMARK"
+ - "ipv4 prefix-list pl1 4 permit 10.0.0.0/24"
+ - "ipv4 prefix-list pl2 5 remark TEST_PL2_REMARK"
+rendered:
+ description: The provided configuration in the task rendered in device-native format (offline).
+ returned: when I(state) is C(rendered)
+ type: list
+ sample:
+ - "ipv6 prefix-list pl_1 1 deny 2001:db8:1234::/48"
+ - "ipv6 prefix-list pl_2 2 remark TEST_PL_2_REMARK"
+ - "ipv4 prefix-list pl1 3 remark TEST_PL1_2_REMARK"
+ - "ipv4 prefix-list pl1 4 permit 10.0.0.0/24"
+ - "ipv4 prefix-list pl2 5 remark TEST_PL2_REMARK"
+gathered:
+ description: Facts about the network resource gathered from the remote device as structured data.
+ returned: when I(state) is C(gathered)
+ type: list
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+parsed:
+ description: The device native config provided in I(running_config) option parsed into structured data as per module argspec.
+ returned: when I(state) is C(parsed)
+ type: list
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.prefix_lists.prefix_lists import (
+ Prefix_listsArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.prefix_lists.prefix_lists import (
+ Prefix_lists,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ module = AnsibleModule(
+ argument_spec=Prefix_listsArgs.argument_spec,
+ mutually_exclusive=[["config", "running_config"]],
+ required_if=[
+ ["state", "merged", ["config"]],
+ ["state", "replaced", ["config"]],
+ ["state", "overridden", ["config"]],
+ ["state", "rendered", ["config"]],
+ ["state", "parsed", ["running_config"]],
+ ],
+ supports_check_mode=True,
+ )
+
+ result = Prefix_lists(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_snmp_server.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_snmp_server.py
new file mode 100644
index 00000000..43d7016d
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_snmp_server.py
@@ -0,0 +1,2328 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2022 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+"""
+The module file for iosxr_snmp_server
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+---
+module: iosxr_snmp_server
+short_description: Resource module to configure snmp server.
+description: This module configures and manages the attributes of snmp-server on Cisco
+ IOSXR platforms.
+version_added: 2.6.0
+author: Ashwini Mhatre (@amhatre)
+notes:
+- Tested against Cisco Iosxr 7.0.2
+- This module works with connection C(network_cli).
+options:
+ config:
+ description: SNMP server configuration.
+ type: dict
+ suboptions:
+ chassis_id:
+ description: SNMP chassis identifier.
+ type: str
+ communities:
+ description: Enable SNMP; set community string and access privileges.
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Community name.
+ type: str
+ acl_v4:
+ description: Ipv4 access list.
+ type: str
+ acl_v6:
+ description: IPv6 access list name.
+ type: str
+ ro:
+ description: Only reads are permitted.
+ type: bool
+ rw:
+ description: Read-write access.
+ type: bool
+ sdrowner:
+ type: bool
+ description: SDR Owner permissions for MIB Objects.
+ systemowner:
+ type: bool
+ description: System Owner permissions for MIB objects.
+ v4_acl:
+ description: V4 Access-list name.
+ type: str
+ community_maps:
+ description: Community Mapping as per RFC-2576.
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description: Community name
+ type: str
+ context:
+ description: Context Name for the community mapping.
+ type: str
+ security_name:
+ description: Security Name for the community mapping.
+ type: str
+ target_list:
+ description: list of targets valid with this community.
+ type: str
+ correlator:
+ description: Configure properties of the event correlator
+ type: dict
+ suboptions:
+ buffer_size:
+ type: int
+ description: Configure size of the correlator buffer.
+ rules:
+ type: list
+ elements: dict
+ description: Configure a specified correlation rule.
+ suboptions:
+ rule_name:
+ type: str
+ description: name of rule.
+ timeout:
+ type: int
+ description: Specify timeout.
+ rule_sets:
+ type: list
+ elements: dict
+ description: Configure a specified correlation ruleset.
+ suboptions:
+ name:
+ type: str
+ description: Name of the ruleset
+ contact:
+ description: Person to contact about the syste,.
+ type: str
+ context:
+ description: Create/Delete a context apart from default
+ type: list
+ elements: str
+ drop:
+ type: dict
+ description: Silently drop SNMP packets
+ suboptions:
+ unknown_user:
+ description: Silently drop unknown v3 user packets
+ type: bool
+ report_IPv4:
+ description: Config to drop snmpv3 error reports matching Ipv4 ACL.
+ type: str
+ report_IPv6:
+ description: Config to drop snmpv3 error reports matching Ipv4 ACL.
+ type: str
+ engineid:
+ description: SNMPv3 engine ID configuration.
+ type: dict
+ suboptions:
+ local:
+ description: Local SNMP agent
+ type: str
+ groups:
+ description: SNMP USM group
+ type: list
+ elements: dict
+ suboptions:
+ group:
+ description: SNMP group for the user
+ type: str
+ version:
+ description: snmp security group version
+ type: str
+ choices: ['v1', 'v3', 'v2c']
+ context:
+ description: Specify a context to associate with the group
+ type: str
+ notify:
+ description: View to restrict notifications
+ type: str
+ read:
+ description: View to restrict read access
+ type: str
+ write:
+ description: View to restrict write access
+ type: str
+ acl_v4:
+ description: Ipv4 Type of Access-list
+ type: str
+ aliases:
+ - Ipv4_acl
+ acl_v6:
+ description: Ipv6 Type of Access-list
+ type: str
+ aliases:
+ - Ipv6_acl
+ v4_acl:
+ description: V4 Access-list name
+ type: str
+ hosts: &hosts
+ description: Notification destinations
+ type: list
+ elements: dict
+ suboptions:
+ host:
+ description: Hostname or IP address of SNMP notification host.
+ type: str
+ community:
+ description: community string.
+ type: str
+ udp_port:
+ description: UDP destination port for notification messages.
+ type: int
+ informs:
+ description: Use SNMP inform messages.
+ type: bool
+ traps:
+ description: Use SNMP trap messages
+ type: bool
+ version:
+ description: Notification message SNMP version.
+ type: str
+ choices: ['1', '2c', '3']
+ ifindex:
+ description: Enable ifindex persistence
+ type: bool
+ ifmib:
+ type: dict
+ description: IF-MIB configuration commands.
+ suboptions:
+ ifalias_long:
+ type: bool
+ description: Modify parameters for ifAlias object.
+ internal_cache_max_duration:
+ type: int
+ description: IFMIB internal lookahead cache.
+ ipsubscriber:
+ type: bool
+ description: Enable ipsubscriber interfaces in IFMIB.
+ stats:
+ type: bool
+ description: Modify IF-MIB statistics parameters.
+ inform:
+ description: Configure SNMP Informs options
+ suboptions:
+ pending:
+ description: Set number of unacked informs to hold
+ type: int
+ retries:
+ description: Set retry count for informs
+ type: int
+ timeout:
+ description: Set timeout for informs
+ type: int
+ type: dict
+ interfaces:
+ type: list
+ elements: dict
+ description: Enter the SNMP interface configuration commands.
+ suboptions:
+ name:
+ type: str
+ description: Name of interface.
+ notification_linkupdown_disable:
+ type: bool
+ description: Disable linkUp and linkDown notification.
+ index_persistent:
+ type: bool
+ description: Configure ifIndex attributes Persistency across system reloads.
+ ipv4: &ip
+ description: Mark the dscp/precedence bit for ipv4 packets.
+ type: dict
+ suboptions:
+ dscp:
+ description: Set IP DSCP (DiffServ CodePoint).Please refer vendor document for valid entries.
+ type: str
+ precedence:
+ description: Set precedence Please refer vendor document for valid entries.
+ type: str
+ ipv6: *ip
+ location:
+ description: The sysLocation string.
+ type: str
+ logging_threshold_oid_processing:
+ type: int
+ description: Configure threshold to start logging slow OID requests processing.
+ logging_threshold_pdu_processing:
+ type: int
+ description: Configure threshold to start logging slow PDU requests processing.
+ mib_bulkstat_max_procmem_size:
+ type: int
+ description: per process memory limit in kilo bytes
+ mib_object_lists:
+ description: mib object lists
+ type: list
+ elements: str
+ mib_schema:
+ type: list
+ elements: dict
+ description: mib schema
+ suboptions:
+ name:
+ type: str
+ description: mib schema name.
+ object_list:
+ type: str
+ description: Name of an object List.
+ poll_interval:
+ type: int
+ description: Periodicity for polling of objects in this schema in Min.
+ mib_bulkstat_transfer_ids:
+ description: mib bulkstat transfer ids.
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ type: str
+ description: mib transfer-id name.
+ buffer_size:
+ type: int
+ description: Bulkstat data file maximum size.
+ enable:
+ type: bool
+ description: Start Data Collection for this Configuration
+ format_schemaASCI:
+ type: bool
+ description: format
+ retain:
+ type: int
+ description: Retention period in Min.
+ retry:
+ type: int
+ description: Number of Retries.
+ schema:
+ type: str
+ description: Schema that contains objects to be collected.
+ transfer_interval:
+ type: int
+ description: transfer-interval
+ mroutemib_send_all_vrf:
+ type: bool
+ description: Configurations related to IPMROUTE-MIB(cisco-support).
+ notification_log_mib:
+ description: notification log mib.
+ type: dict
+ suboptions:
+ GlobalSize:
+ type: int
+ description: GlobalSize, max number of notifications that can be logged in all logs.
+ default:
+ type: bool
+ description: To create a default log
+ disable:
+ type: bool
+ description: disable, to disable the logging in default log.
+ size:
+ description: size, The max number of notifications that this log (default) can hold.
+ type: int
+ oid_poll_stats:
+ type: bool
+ description: Enable OID poll stats oper CLI
+ overload_control:
+ type: dict
+ description: Set overload-control params for handling incoming messages in critical processing mode.
+ suboptions:
+ overload_drop_time:
+ type: int
+ description: Overload drop time (in seconds) for incoming queue (default 1 sec).
+ overload_throttle_rate:
+ type: int
+ description: Overload throttle rate for incoming queue (default 500 msec)
+ packetsize:
+ type: int
+ description: Largest SNMP packet size.
+ queue_length:
+ type: int
+ description: Queue length (default 100).
+ targets:
+ type: list
+ elements: dict
+ description: targets
+ suboptions:
+ name:
+ type: str
+ description: Name of the target list.
+ host:
+ type: str
+ description: Specify host name.
+ vrf:
+ type: str
+ description: Specify VRF name.
+ throttle_time:
+ type: int
+ description: Set throttle time for handling incoming messages.
+ timeouts:
+ type: dict
+ description: SNMP timeouts
+ suboptions:
+ duplicate:
+ description: Duplicate request feature timeout
+ type: int
+ inQdrop:
+ type: int
+ description: incoming queue drop feature.
+ pdu_stats:
+ type: int
+ description: SNMP pdu statistics end to end.
+ subagent:
+ type: int
+ description: Sub-Agent Request timeout.
+ threshold:
+ type: int
+ description: threshold incoming queue drop feature.
+ trap:
+ type: dict
+ description: MIB trap configurations.
+ suboptions:
+ authentication_vrf_disable:
+ type: bool
+ description: Disable authentication traps for packets on a vrf.
+ link_ietf:
+ type: bool
+ description: Link up/down trap configuratio.
+ throttle_time:
+ type: int
+ description: Set throttle time for handling more traps.
+ trap_source:
+ description: Assign an interface for the source address of all traps
+ type: str
+ trap_timeout:
+ description: Set timeout for TRAP message retransmissions
+ type: int
+ traps:
+ description: Enable traps to all configured recipients.
+ type: dict
+ suboptions:
+ addrpool:
+ type: dict
+ description: Enable SNMP Address Pool traps.
+ suboptions:
+ low:
+ type: bool
+ description: Enable SNMP Address Pool Low Threshold trap.
+ high:
+ type: bool
+ description: Enable SNMP Address Pool High Threshold trap.
+ bfd:
+ type: bool
+ description: Enable BFD traps.
+ bgp:
+ description: Enable Bgp traps.
+ type: dict
+ suboptions:
+ cbgp2:
+ type: bool
+ description: Enable CISCO-BGP4-MIB v2 traps.
+ updown:
+ type: bool
+ description: Enable CISCO-BGP4-MIB v2 up/down traps.
+ bulkstat_collection:
+ type: bool
+ description: Enable Data-Collection-MIB Collection notifications.
+ bulkstat_transfer:
+ type: bool
+ description: Enable Data-Collection-MIB Trnasfer notifications.
+ bridgemib:
+ type: bool
+ description: Enable SNMP Trap for Bridge MIB.
+ copy_complete:
+ type: bool
+ description: Enable CISCO-CONFIG-COPY-MIB ccCopyCompletion traps.
+ cisco_entity_ext:
+ type: bool
+ description: Enable SNMP entity traps
+ config:
+ type: bool
+ description: Enable SNMP config traps.
+ diameter:
+ type: dict
+ description: Enable SNMP diameter traps.
+ suboptions:
+ peerdown:
+ type: bool
+ description: Enable peer connection down notification.
+ peerup:
+ type: bool
+ description: Enable peer connection up notification.
+ permanentfail:
+ type: bool
+ description: Enable permanent failure notification.
+ protocolerror:
+ type: bool
+ description: Enable protocol error notifications
+ transientfail:
+ type: bool
+ description: Enable transient failure notification.
+ entity:
+ type: bool
+ description: Enable SNMP entity traps.
+ entity_redundancy:
+ type: dict
+ description: Enable SNMP CISCO-ENTITY-REDUNDANCY-MIB traps.
+ suboptions:
+ all:
+ type: bool
+ description: Enable all CISCO-ENTITY-REDUNDANCY-MIB traps
+ status:
+ type: bool
+ description: Enable status change traps
+ switchover:
+ type: bool
+ description: Enable switchover traps.
+ entity_state:
+ type: dict
+ description: Enable SNMP entity-state traps.
+ suboptions:
+ operstatus:
+ type: bool
+ description: Enable entity oper status enable notification.
+ switchover:
+ description: Enable entity state switchover notifications
+ type: bool
+ flash:
+ type: dict
+ description: Enable flash-mib traps.
+ suboptions:
+ insertion:
+ type: bool
+ description: Enable ciscoFlashDeviceInsertedNotif.
+ removal:
+ type: bool
+ description: Enable ciscoFlashDeviceRemovedNotif.
+ fru_ctrl:
+ type: bool
+ description: Enable SNMP entity FRU control traps.
+ hsrp:
+ type: bool
+ description: Enable SNMP hsrp traps.
+ ipsla:
+ type: bool
+ description: Enable SNMP hipsla traps.
+ ipsec:
+ type: dict
+ description: Enable SNMP IPSec traps.
+ suboptions:
+ start:
+ type: bool
+ description: Enable SNMP IPsec Tunnel Start trap.
+ stop:
+ type: bool
+ description: Enable SNMP IPsec Tunnel Stop trap.
+ isakmp:
+ type: dict
+ description: Enable SNMP isakmp traps.
+ suboptions:
+ start:
+ type: bool
+ description: Enable SNMP isakmp Tunnel Start trap.
+ stop:
+ type: bool
+ description: Enable SNMP isakmp Tunnel Stop trap.
+
+ isis:
+ description: Enable isis traps. If set to enabled , all the traps are set.
+ type: dict
+ suboptions:
+ adjacency_change:
+ description: adjacency-change
+ type: bool
+ all:
+ type: bool
+ description: anable all is-is traps.
+ area_mismatch:
+ description: area-mismatch
+ type: bool
+ attempt_to_exceed_max_sequence:
+ description: attempt-to-exceed-max-sequence
+ type: bool
+ authentication_failure:
+ description: authentication-failure.
+ type: bool
+ authentication_type_failure:
+ description: authentication-type-failure.
+ type: bool
+ corrupted_lsp_detected:
+ description: isisCorruptedLSPDetected
+ type: bool
+ database_overload:
+ description: database-overload
+ type: bool
+ id_len_mismatch:
+ type: bool
+ description: isisIDLenMismatch
+ lsp_error_detected:
+ type: bool
+ description: lsp-error-detected.
+ lsp_too_large_to_propagate:
+ type: bool
+ description: lsp-too-large-to-propagate
+ manual_address_drops:
+ type: bool
+ description: manual_address_drops
+ max_area_addresses_mismatch:
+ type: bool
+ description: max_area_addresses_mismatch
+ orig_lsp_buff_size_mismatch:
+ type: bool
+ description: orig-lsp-buff-size-mismatch
+ version_skew:
+ type: bool
+ description: version-skew
+ own_lsp_purge:
+ description: own-lsp-purge
+ type: bool
+ rejected_adjacency:
+ description: rejected-adjacency
+ type: bool
+ protocols_supported_mismatch:
+ description: protocols-supported-mismatch
+ type: bool
+ sequence_number_skip:
+ description: sequence-number-skip.
+ type: bool
+ l2tun:
+ type: dict
+ description: Enable L2TUN traps.
+ suboptions:
+ pseudowire_status:
+ type: bool
+ description: Enable L2TUN pseudowire status traps.
+ sessions:
+ type: bool
+ description: Enable L2TUN sessions traps.
+ tunnel_down:
+ type: bool
+ description: Enable L2TUN tunnel DOWN traps.
+ tunnel_up:
+ type: bool
+ description: Enable L2TUN tunnel UP traps.
+ l2vpn:
+ type: dict
+ description: Enable L2VPN traps.
+ suboptions:
+ all:
+ type: bool
+ description: Enable L2VPN ALL traps.
+ cisco:
+ type: bool
+ description: Enable L2VPN CISCO traps.
+ vc_down:
+ type: bool
+ description: Enable L2VPN VC DOWN traps.
+ vc_up:
+ type: bool
+ description: Enable L2VPN VC UP traps.
+ msdp_peer_state_change:
+ type: bool
+ description: Enable SNMP MSDP traps
+ ntp:
+ type: bool
+ description: Enable SNMP Cisco Ntp traps.
+ ospf:
+ description: Enable Ospf traps. If set to enabled , all the traps are set.
+ type: dict
+ suboptions:
+ errors:
+ description: error
+ type: dict
+ suboptions:
+ bad_packet:
+ type: bool
+ description: bad-packet
+ authentication_failure:
+ type: bool
+ description: authentication-failure.
+ config_error:
+ type: bool
+ description: config-error
+ virt_bad_packet:
+ type: bool
+ description: virt-bad-packet
+ virt_authentication_failure:
+ type: bool
+ description: virt-authentication-failure
+ virt_config_error:
+ type: bool
+ description: virt_config_error
+ lsa:
+ description: lsa
+ type: dict
+ suboptions:
+ lsa_maxage:
+ type: bool
+ description: lsa-maxage
+ lsa_originate:
+ type: bool
+ description: lsa-originate
+ retransmit:
+ description: retransmit
+ type: dict
+ suboptions:
+ packets:
+ type: bool
+ description: packets
+ virt_packets:
+ type: bool
+ description: virt-packets
+ state_change:
+ description: state-change.
+ type: dict
+ suboptions:
+ if_state_change:
+ type: bool
+ description: if-state-change
+ neighbor_state_change:
+ type: bool
+ description: neighbor-state-change
+ virtif_state_change:
+ type: bool
+ description: virtif-state-change
+ virtneighbor_state_change:
+ type: bool
+ description: virtneighbor-state-change
+ ospfv3:
+ description: Enable Ospfv3 traps. If set to enabled , all the traps are set.
+ type: dict
+ suboptions:
+ errors:
+ description: error
+ type: dict
+ suboptions:
+ bad_packet:
+ type: bool
+ description: bad-packet
+ config_error:
+ type: bool
+ description: config-error
+ virt_bad_packet:
+ type: bool
+ description: virt-bad-packet
+ virt_config_error:
+ type: bool
+ description: virt_config_error
+ state_change:
+ description: state-change.
+ type: dict
+ suboptions:
+ if_state_change:
+ type: bool
+ description: if-state-change
+ neighbor_state_change:
+ type: bool
+ description: neighbor-state-change
+ virtif_state_change:
+ type: bool
+ description: virtif-state-change
+ virtneighbor_state_change:
+ type: bool
+ description: virtneighbor-state-change
+ nssa_state_change:
+ type: bool
+ description: nssa-state-change
+ restart_status_change:
+ type: bool
+ description: restart-status-change
+ restart_helper_status_change:
+ type: bool
+ description: restart-helper-status-change
+ restart_virtual_helper_status_change:
+ type: bool
+ description: restart-virtual-helper-status-change
+ power:
+ type: bool
+ description: Enable SNMP entity power traps.
+ rf:
+ type: bool
+ description: Enable SNMP RF-MIB traps.
+ pim:
+ description: Enable Pim traps. If set to enabled , all the traps are set.
+ type: dict
+ suboptions:
+ interface_state_change :
+ description: interface-state-change .
+ type: bool
+ invalid_message_received :
+ description: invalid-message-received
+ type: bool
+ neighbor_change:
+ description: neighbor-change.
+ type: bool
+ rp_mapping_change:
+ description: rp-mapping-change.
+ type: bool
+ rsvp:
+ description: Enable rsvp traps. If set to enabled , all the traps are set.
+ type: dict
+ suboptions:
+ all:
+ description: enable all traps.
+ type: bool
+ lost_flow:
+ description: lost-flow
+ type: bool
+ new_flow:
+ description: new-flow
+ type: bool
+ selective_vrf_download_role_change:
+ type: bool
+ description: Enable selective VRF download traps.
+ sensor:
+ type: bool
+ description: Enable SNMP entity sensor traps
+ snmp:
+ description: Enable snmp traps. If set to enabled , all the traps are set.
+ type: dict
+ suboptions:
+ authentication:
+ description: authentication
+ type: bool
+ linkdown:
+ description: link-down
+ type: bool
+ linkup:
+ description: link-up
+ type: bool
+ warmstart:
+ description: warmstart.
+ type: bool
+ coldstart:
+ description: coldstart.
+ type: bool
+ vrrp_events:
+ description: vrrp
+ type: bool
+ syslog:
+ type: bool
+ description: syslog
+ subscriber:
+ type: dict
+ description: Subscriber notification commands.
+ suboptions:
+ session_agg_access_interface:
+ type: bool
+ description: Subscriber notification at access interface level
+ session_agg_node:
+ type: bool
+ description: Subscriber notification at node level
+ system:
+ type: bool
+ description: Enable SNMP SYSTEMMIB-MIB traps.
+ vpls:
+ type: dict
+ description: Enable VPLS traps
+ suboptions:
+ all:
+ type: bool
+ description: Enable all VPLS traps.
+ full_clear:
+ type: bool
+ description: Enable VPLS Full Clear traps.
+ full_raise:
+ type: bool
+ description: Enable VPLS Full Raise traps.
+ status:
+ type: bool
+ description: Enable VPLS Status traps
+ users:
+ description: SNMP user configuration.
+ type: list
+ elements: dict
+ suboptions:
+ user:
+ description: SNMP user name
+ type: str
+ group:
+ description: SNMP group for the user.
+ type: str
+ acl_v4:
+ description: Ipv4 Type of Access-list
+ type: str
+ aliases:
+ - Ipv4_acl
+ acl_v6:
+ description: Ipv6 Type of Access-list
+ type: str
+ aliases:
+ - Ipv6_acl
+ SDROwner:
+ description: SDR Owner permissions for MIB Objects.
+ type: bool
+ SystemOwner:
+ description: System Owner permissions for MIB objects.
+ type: bool
+ v4_acl:
+ type: str
+ description: V4 Access-list name
+ version:
+ description: snmp security version
+ type: str
+ choices: ['v1', 'v2c', 'v3']
+ vrfs:
+ description: Specify the VRF in which the source address is used
+ type: list
+ elements: dict
+ suboptions:
+ vrf:
+ description: vrf name.
+ type: str
+ context:
+ description: Configure the source interface for SNMP notifications
+ type: list
+ elements: str
+ hosts: *hosts
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOSXR device by
+ executing the command B(show running-config snmp-server).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ state:
+ description:
+ - The state the configuration should be left in.
+ - The states I(replaced) and I(overridden) have identical
+ behaviour for this module.
+ - Please refer to examples for more details.
+ type: str
+ choices: [deleted, merged, overridden, replaced, gathered, rendered, parsed]
+ default: merged
+"""
+
+EXAMPLES = """
+# Using state: merged
+# Before state:
+# -------------
+# RP/0/RP0/CPU0:test2#show running-config snmp-server
+# --------------------- EMPTY -----------------
+# Merged play:
+# ------------
+- name: Merge the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_snmp_server:
+ config:
+ vrfs:
+ - hosts:
+ - community: test1
+ host: 1.1.1.1
+ traps: true
+ vrf: vrf1
+ users:
+ - Ipv4_acl: test1
+ Ipv6_acl: test2
+ group: test2
+ user: u1
+ version: v1
+ timeouts:
+ duplicate: 0
+ inQdrop: 0
+ trap:
+ throttle_time: 12
+ targets:
+ - host: 1.1.1.2
+ name: test
+
+ ifmib:
+ internal_cache_max_duration: 4
+ inform:
+ retries: 7
+ chassis_id: test2
+ packetsize: 490
+ queue_length: 2
+ throttle_time: 60
+ trap_source: GigabitEthernet0/0/0/2
+ trap_timeout: 3
+ context:
+ - c1
+ - c2
+ contact: t1
+ correlator:
+ buffer_size: 1024
+ communities:
+ - name: test2
+ ro: true
+ sdrowner: true
+ acl_v4: test
+ acl_v6: test1
+ community_maps:
+ - name: cm1
+ context: c1
+ target_list: t1
+ security_name: s1
+ drop:
+ report_IPv4: test1
+ unknown_user: true
+ ipv6:
+ precedence: routine
+ ipv4:
+ dscp: af11
+ location: test1
+ logging_threshold_oid_processing: 1
+ logging_threshold_pdu_processing: 1
+ mib_bulkstat_max_procmem_size: 101
+ mroutemib_send_all_vrf: true
+ overload_control:
+ overload_drop_time: 4
+ overload_throttle_rate: 6
+ notification_log_mib:
+ GlobalSize: 5
+ size: 5
+ traps:
+ hsrp: true
+ ipsla: true
+ ipsec:
+ start: true
+ stop: true
+ bridgemib: true
+ bulkstat_collection: true
+ cisco_entity_ext: true
+ config: true
+ copy_complete: true
+ addrpool:
+ high: true
+ low: true
+ bfd: true
+ bgp:
+ cbgp2: true
+ l2tun:
+ sessions: true
+ tunnel_down: true
+ tunnel_up: true
+ l2vpn:
+ all: true
+ vc_down: true
+ vc_up: true
+ msdp_peer_state_change: true
+#
+# Commands Fired:
+# ------------
+# "commands": [
+# "snmp-server chassis-id test2",
+# "snmp-server correlator buffer-size 1024",
+# "snmp-server contact t1",
+# "snmp-server ipv4 dscp af11",
+# "snmp-server ipv6 precedence routine",
+# "snmp-server location test1",
+# "snmp-server logging threshold oid-processing 1",
+# "snmp-server logging threshold pdu-processing 1",
+# "snmp-server mib bulkstat max-procmem-size 101",
+# "snmp-server mroutemib send-all-vrf",
+# "snmp-server overload-control 4 6",
+# "snmp-server packetsize 490",
+# "snmp-server queue-length 2",
+# "snmp-server throttle-time 60",
+# "snmp-server trap-source GigabitEthernet0/0/0/2",
+# "snmp-server trap-timeout 3",
+# "snmp-server drop report acl IPv4 test1",
+# "snmp-server drop unknown-user",
+# "snmp-server ifmib internal cache max-duration 4",
+# "snmp-server inform retries 7",
+# "snmp-server notification-log-mib size 5",
+# "snmp-server notification-log-mib GlobalSize 5",
+# "snmp-server trap throttle-time 12",
+# "snmp-server timeouts inQdrop 0",
+# "snmp-server timeouts duplicate 0",
+# "snmp-server traps addrpool low",
+# "snmp-server traps addrpool high",
+# "snmp-server traps bfd",
+# "snmp-server traps bgp cbgp2",
+# "snmp-server traps bulkstat collection",
+# "snmp-server traps bridgemib",
+# "snmp-server traps copy-complete",
+# "snmp-server traps cisco-entity-ext",
+# "snmp-server traps config",
+# "snmp-server traps hsrp",
+# "snmp-server traps ipsla",
+# "snmp-server traps ipsec tunnel start",
+# "snmp-server traps ipsec tunnel stop",
+# "snmp-server traps l2tun sessions",
+# "snmp-server traps l2tun tunnel-up",
+# "snmp-server traps l2tun tunnel-down",
+# "snmp-server traps l2vpn all",
+# "snmp-server traps l2vpn vc-up",
+# "snmp-server traps l2vpn vc-down",
+# "snmp-server traps msdp peer-state-change",
+# "snmp-server community test2 RO SDROwner IPv4 test IPv6 test1",
+# "snmp-server community-map cm1 context c1 security-name s1 target-list t1",
+# "snmp-server context c1",
+# "snmp-server context c2",
+# "snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2",
+# "snmp-server target list test2 vrf vrf2",
+# "snmp-server target list test host 1.1.1.2",
+# "snmp-server vrf vrf1",
+# "host 1.1.1.1 traps test1"
+#
+# ],
+# After state:
+# ------------
+# RP/0/RP0/CPU0:test2#show running-config snmp-server
+# Mon Nov 29 12:49:29.521 UTC
+# snmp-server vrf vrf1
+# host 1.1.1.1 traps test1
+# !
+# snmp-server drop report acl IPv4 test1
+# snmp-server drop unknown-user
+# snmp-server ipv4 dscp af11
+# snmp-server ipv6 precedence routine
+# snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2
+# snmp-server community test2 RO SDROwner IPv4 test IPv6 test1
+# snmp-server queue-length 2
+# snmp-server trap-timeout 3
+# snmp-server trap throttle-time 12
+# snmp-server traps bfd
+# snmp-server traps bgp cbgp2
+# snmp-server traps copy-complete
+# snmp-server traps hsrp
+# snmp-server traps ipsla
+# snmp-server traps msdp peer-state-change
+# snmp-server traps ipsec tunnel stop
+# snmp-server traps ipsec tunnel start
+# snmp-server traps config
+# snmp-server traps l2tun sessions
+# snmp-server traps l2tun tunnel-up
+# snmp-server traps l2tun tunnel-down
+# snmp-server traps bulkstat collection
+# snmp-server traps l2vpn all
+# snmp-server traps l2vpn vc-up
+# snmp-server traps l2vpn vc-down
+# snmp-server traps bridgemib
+# snmp-server traps addrpool low
+# snmp-server traps addrpool high
+# snmp-server traps cisco-entity-ext
+# snmp-server chassis-id test2
+# snmp-server contact t1
+# snmp-server location test1
+# snmp-server target list test host 1.1.1.2
+# snmp-server target list test2 vrf vrf2
+# snmp-server context c1
+# snmp-server context c2
+# snmp-server logging threshold oid-processing 1
+# snmp-server logging threshold pdu-processing 1
+# snmp-server mib bulkstat max-procmem-size 101
+# snmp-server timeouts duplicate 0
+# snmp-server timeouts inQdrop 0
+# snmp-server packetsize 490
+# snmp-server correlator buffer-size 1024
+# snmp-server trap-source GigabitEthernet0/0/0/2
+# snmp-server throttle-time 60
+# snmp-server community-map cm1 context c1 security-name s1 target-list t1
+# snmp-server inform retries 7
+# snmp-server overload-control 4 6
+# snmp-server ifmib internal cache max-duration 4
+# snmp-server mroutemib send-all-vrf
+# snmp-server notification-log-mib size 5
+# snmp-server notification-log-mib GlobalSize 5
+#
+#
+# Using state: deleted
+# Before state:
+# -------------
+# RP/0/RP0/CPU0:test2#show running-config snmp-server
+# Mon Nov 29 12:49:29.521 UTC
+# snmp-server vrf vrf1
+# host 1.1.1.1 traps test1
+# !
+# snmp-server drop report acl IPv4 test1
+# snmp-server drop unknown-user
+# snmp-server ipv4 dscp af11
+# snmp-server ipv6 precedence routine
+# snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2
+# snmp-server community test2 RO SDROwner IPv4 test IPv6 test1
+# snmp-server queue-length 2
+# snmp-server trap-timeout 3
+# snmp-server trap throttle-time 12
+# snmp-server traps bfd
+# snmp-server traps bgp cbgp2
+# snmp-server traps copy-complete
+# snmp-server traps hsrp
+# snmp-server traps ipsla
+# snmp-server traps msdp peer-state-change
+# snmp-server traps ipsec tunnel stop
+# snmp-server traps ipsec tunnel start
+# snmp-server traps config
+# snmp-server traps l2tun sessions
+# snmp-server traps l2tun tunnel-up
+# snmp-server traps l2tun tunnel-down
+# snmp-server traps bulkstat collection
+# snmp-server traps l2vpn all
+# snmp-server traps l2vpn vc-up
+# snmp-server traps l2vpn vc-down
+# snmp-server traps bridgemib
+# snmp-server traps addrpool low
+# snmp-server traps addrpool high
+# snmp-server traps cisco-entity-ext
+# snmp-server chassis-id test2
+# snmp-server contact t1
+# snmp-server location test1
+# snmp-server target list test host 1.1.1.2
+# snmp-server target list test2 vrf vrf2
+# snmp-server context c1
+# snmp-server context c2
+# snmp-server logging threshold oid-processing 1
+# snmp-server logging threshold pdu-processing 1
+# snmp-server mib bulkstat max-procmem-size 101
+# snmp-server timeouts duplicate 0
+# snmp-server timeouts inQdrop 0
+# snmp-server packetsize 490
+# snmp-server correlator buffer-size 1024
+# snmp-server trap-source GigabitEthernet0/0/0/2
+# snmp-server throttle-time 60
+# snmp-server community-map cm1 context c1 security-name s1 target-list t1
+# snmp-server inform retries 7
+# snmp-server overload-control 4 6
+# snmp-server ifmib internal cache max-duration 4
+# snmp-server mroutemib send-all-vrf
+# snmp-server notification-log-mib size 5
+# snmp-server notification-log-mib GlobalSize 5
+# Deleted play:
+# -------------
+- name: Remove all existing configuration
+ cisco.iosxr.iosxr_snmp_server:
+ state: deleted
+# Commands Fired:
+# ---------------
+# "commands": [
+# "no snmp-server chassis-id test2",
+# "no snmp-server correlator buffer-size 1024",
+# "no snmp-server contact t1",
+# "no snmp-server ipv4 dscp af11",
+# "no snmp-server ipv6 precedence routine",
+# "no snmp-server location test1",
+# "no snmp-server logging threshold oid-processing 1",
+# "no snmp-server logging threshold pdu-processing 1",
+# "no snmp-server mib bulkstat max-procmem-size 101",
+# "no snmp-server mroutemib send-all-vrf",
+# "no snmp-server overload-control 4 6",
+# "no snmp-server packetsize 490",
+# "no snmp-server queue-length 2",
+# "no snmp-server throttle-time 60",
+# "no snmp-server trap-source GigabitEthernet0/0/0/2",
+# "no snmp-server trap-timeout 3",
+# "no snmp-server drop report acl IPv4 test1",
+# "no snmp-server drop unknown-user",
+# "no snmp-server ifmib internal cache max-duration 4",
+# "no snmp-server inform retries 7",
+# "no snmp-server notification-log-mib size 5",
+# "no snmp-server notification-log-mib GlobalSize 5",
+# "no snmp-server trap throttle-time 12",
+# "no snmp-server timeouts inQdrop 0",
+# "no snmp-server timeouts duplicate 0",
+# "no snmp-server traps addrpool low",
+# "no snmp-server traps addrpool high",
+# "no snmp-server traps bfd",
+# "no snmp-server traps bgp cbgp2",
+# "no snmp-server traps bulkstat collection",
+# "no snmp-server traps bridgemib",
+# "no snmp-server traps copy-complete",
+# "no snmp-server traps cisco-entity-ext",
+# "no snmp-server traps config",
+# "no snmp-server traps hsrp",
+# "no snmp-server traps ipsla",
+# "no snmp-server traps ipsec tunnel start",
+# "no snmp-server traps ipsec tunnel stop",
+# "no snmp-server traps l2tun sessions",
+# "no snmp-server traps l2tun tunnel-up",
+# "no snmp-server traps l2tun tunnel-down",
+# "no snmp-server traps l2vpn all",
+# "no snmp-server traps l2vpn vc-up",
+# "no snmp-server traps l2vpn vc-down",
+# "no snmp-server traps msdp peer-state-change",
+# "no snmp-server community test2 RO SDROwner IPv4 test IPv6 test1",
+# "no snmp-server community-map cm1 context c1 security-name s1 target-list t1",
+# "no snmp-server context c1",
+# "no snmp-server context c2",
+# "no snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2",
+# "no snmp-server target list test host 1.1.1.2",
+# "no snmp-server target list test2 vrf vrf2",
+# "no snmp-server vrf vrf1"
+# ],
+# After state:
+# ------------
+# RP/0/0/CPU0:10#show running-config ntp
+# --------------------- EMPTY -----------------
+# Using state: overridden
+# Before state:
+# -------------
+# RP/0/0/CPU0:10#show running-config snmp-server
+# snmp-server vrf vrf1
+# host 1.1.1.1 traps test1
+# !
+# snmp-server drop report acl IPv4 test1
+# snmp-server drop unknown-user
+# snmp-server ipv4 dscp af11
+# snmp-server ipv6 precedence routine
+# snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2
+# snmp-server community test2 RO SDROwner IPv4 test IPv6 test1
+# snmp-server queue-length 2
+# snmp-server trap-timeout 3
+# snmp-server trap throttle-time 12
+# snmp-server traps bfd
+# snmp-server traps bgp cbgp2
+# snmp-server traps copy-complete
+# snmp-server traps hsrp
+# snmp-server traps ipsla
+# snmp-server traps msdp peer-state-change
+# snmp-server traps ipsec tunnel stop
+# snmp-server traps ipsec tunnel start
+# snmp-server traps config
+# snmp-server traps l2tun sessions
+# snmp-server traps l2tun tunnel-up
+# snmp-server traps l2tun tunnel-down
+# snmp-server traps bulkstat collection
+# snmp-server traps l2vpn all
+# snmp-server traps l2vpn vc-up
+# snmp-server traps l2vpn vc-down
+# snmp-server traps bridgemib
+# snmp-server traps addrpool low
+# snmp-server traps addrpool high
+# snmp-server traps cisco-entity-ext
+# snmp-server chassis-id test2
+# snmp-server contact t1
+# snmp-server location test1
+# snmp-server target list test host 1.1.1.2
+# snmp-server target list test2 vrf vrf2
+# snmp-server context c1
+# snmp-server context c2
+# snmp-server logging threshold oid-processing 1
+# snmp-server logging threshold pdu-processing 1
+# snmp-server mib bulkstat max-procmem-size 101
+# snmp-server timeouts duplicate 0
+# snmp-server timeouts inQdrop 0
+# snmp-server packetsize 490
+# snmp-server correlator buffer-size 1024
+# snmp-server trap-source GigabitEthernet0/0/0/2
+# snmp-server throttle-time 60
+# snmp-server community-map cm1 context c1 security-name s1 target-list t1
+# snmp-server inform retries 7
+# snmp-server overload-control 4 6
+# snmp-server ifmib internal cache max-duration 4
+# snmp-server mroutemib send-all-vrf
+# snmp-server notification-log-mib size 5
+# snmp-server notification-log-mib GlobalSize 5
+# Overridden play:
+# ----------------
+- name: Override Snmp-server configuration with provided configuration
+ cisco.iosxr.iosxr_snmp_server:
+ config:
+ timeouts:
+ duplicate: 0
+ inQdrop: 0
+ trap:
+ throttle_time: 13
+ targets:
+ - host: 1.1.1.2
+ name: test
+
+ ifmib:
+ internal_cache_max_duration: 5
+ inform:
+ retries: 7
+ chassis_id: test
+ packetsize: 491
+ queue_length: 2
+ throttle_time: 60
+ trap_source: GigabitEthernet0/0/0/2
+ trap_timeout: 3
+ context:
+ - c1
+ - c2
+ contact: t1
+ correlator:
+ buffer_size: 1025
+ communities:
+ - name: test1
+ ro: true
+ sdrowner: true
+ acl_v4: test
+ acl_v6: test1
+ community_maps:
+ - name: cm2
+ context: c1
+ target_list: t1
+ security_name: s1
+ drop:
+ report_IPv4: test2
+ unknown_user: true
+ ipv6:
+ precedence: routine
+ ipv4:
+ dscp: af11
+ location: test1
+ logging_threshold_oid_processing: 2
+ logging_threshold_pdu_processing: 2
+ mib_bulkstat_max_procmem_size: 101
+ mroutemib_send_all_vrf: true
+ overload_control:
+ overload_drop_time: 4
+ overload_throttle_rate: 6
+ notification_log_mib:
+ GlobalSize: 5
+ size: 5
+ traps:
+ hsrp: true
+ ipsla: true
+ ipsec:
+ start: true
+ stop: true
+ bridgemib: true
+ bulkstat_collection: true
+ cisco_entity_ext: true
+ config: true
+ copy_complete: true
+ l2vpn:
+ all: true
+ vc_down: true
+ vc_up: true
+ msdp_peer_state_change: true
+ state: overridden
+# Commands Fired:
+# ---------------
+# "commands": [
+# "no snmp-server traps addrpool low",
+# "no snmp-server traps addrpool high",
+# "no snmp-server traps bfd",
+# "no snmp-server traps bgp cbgp2",
+# "no snmp-server traps l2tun sessions",
+# "no snmp-server traps l2tun tunnel-up",
+# "no snmp-server traps l2tun tunnel-down",
+# "no snmp-server community test2 RO SDROwner IPv4 test IPv6 test1",
+# "no snmp-server community-map cm1 context c1 security-name s1 target-list t1",
+# "no snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2",
+# "no snmp-server vrf vrf1",
+# "snmp-server chassis-id test",
+# "snmp-server correlator buffer-size 1025",
+# "snmp-server logging threshold oid-processing 2",
+# "snmp-server logging threshold pdu-processing 2",
+# "snmp-server packetsize 491",
+# "snmp-server drop report acl IPv4 test2",
+# "snmp-server ifmib internal cache max-duration 5",
+# "snmp-server trap throttle-time 13",
+# "snmp-server community test1 RO SDROwner IPv4 test IPv6 test1",
+# "snmp-server community-map cm2 context c1 security-name s1 target-list t1"
+# ],
+# After state:
+# ------------
+# RP/0/RP0/CPU0:test2#show running-config snmp-server
+# Mon Nov 29 12:57:34.182 UTC
+# snmp-server drop report acl IPv4 test2
+# snmp-server drop unknown-user
+# snmp-server ipv4 dscp af11
+# snmp-server ipv6 precedence routine
+# snmp-server community test1 RO SDROwner IPv4 test IPv6 test1
+# snmp-server queue-length 2
+# snmp-server trap-timeout 3
+# snmp-server trap throttle-time 13
+# snmp-server traps copy-complete
+# snmp-server traps hsrp
+# snmp-server traps ipsla
+# snmp-server traps msdp peer-state-change
+# snmp-server traps ipsec tunnel stop
+# snmp-server traps ipsec tunnel start
+# snmp-server traps config
+# snmp-server traps bulkstat collection
+# snmp-server traps l2vpn all
+# snmp-server traps l2vpn vc-up
+# snmp-server traps l2vpn vc-down
+# snmp-server traps bridgemib
+# snmp-server traps cisco-entity-ext
+# snmp-server chassis-id test
+# snmp-server contact t1
+# snmp-server location test1
+# snmp-server target list test host 1.1.1.2
+# snmp-server target list test2 vrf vrf2
+# snmp-server context c1
+# snmp-server context c2
+# snmp-server logging threshold oid-processing 2
+# snmp-server logging threshold pdu-processing 2
+# snmp-server mib bulkstat max-procmem-size 101
+# snmp-server timeouts duplicate 0
+# snmp-server timeouts inQdrop 0
+# snmp-server packetsize 491
+# snmp-server correlator buffer-size 1025
+# snmp-server trap-source GigabitEthernet0/0/0/2
+# snmp-server throttle-time 60
+# snmp-server community-map cm2 context c1 security-name s1 target-list t1
+# snmp-server inform retries 7
+# snmp-server overload-control 4 6
+# snmp-server ifmib internal cache max-duration 5
+# snmp-server mroutemib send-all-vrf
+# snmp-server notification-log-mib size 5
+# snmp-server notification-log-mib GlobalSize 5
+#
+# Using state: replaced
+# Before state:
+# -------------
+# RP/0/0/CPU0:10#show running-config snmp-server
+# snmp-server vrf vrf1
+# host 1.1.1.1 traps test1
+# !
+# snmp-server drop report acl IPv4 test1
+# snmp-server drop unknown-user
+# snmp-server ipv4 dscp af11
+# snmp-server ipv6 precedence routine
+# snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2
+# snmp-server community test2 RO SDROwner IPv4 test IPv6 test1
+# snmp-server queue-length 2
+# snmp-server trap-timeout 3
+# snmp-server trap throttle-time 12
+# snmp-server traps bfd
+# snmp-server traps bgp cbgp2
+# snmp-server traps copy-complete
+# snmp-server traps hsrp
+# snmp-server traps ipsla
+# snmp-server traps msdp peer-state-change
+# snmp-server traps ipsec tunnel stop
+# snmp-server traps ipsec tunnel start
+# snmp-server traps config
+# snmp-server traps l2tun sessions
+# snmp-server traps l2tun tunnel-up
+# snmp-server traps l2tun tunnel-down
+# snmp-server traps bulkstat collection
+# snmp-server traps l2vpn all
+# snmp-server traps l2vpn vc-up
+# snmp-server traps l2vpn vc-down
+# snmp-server traps bridgemib
+# snmp-server traps addrpool low
+# snmp-server traps addrpool high
+# snmp-server traps cisco-entity-ext
+# snmp-server chassis-id test2
+# snmp-server contact t1
+# snmp-server location test1
+# snmp-server target list test host 1.1.1.2
+# snmp-server target list test2 vrf vrf2
+# snmp-server context c1
+# snmp-server context c2
+# snmp-server logging threshold oid-processing 1
+# snmp-server logging threshold pdu-processing 1
+# snmp-server mib bulkstat max-procmem-size 101
+# snmp-server timeouts duplicate 0
+# snmp-server timeouts inQdrop 0
+# snmp-server packetsize 490
+# snmp-server correlator buffer-size 1024
+# snmp-server trap-source GigabitEthernet0/0/0/2
+# snmp-server throttle-time 60
+# snmp-server community-map cm1 context c1 security-name s1 target-list t1
+# snmp-server inform retries 7
+# snmp-server overload-control 4 6
+# snmp-server ifmib internal cache max-duration 4
+# snmp-server mroutemib send-all-vrf
+# snmp-server notification-log-mib size 5
+# snmp-server notification-log-mib GlobalSize 5
+#
+#
+# Replaced play:
+# ----------------
+- name: Replace Snmp-server configuration with provided configuration
+ cisco.iosxr.iosxr_snmp_server:
+ state: replaced
+ config:
+ timeouts:
+ duplicate: 0
+ inQdrop: 0
+ trap:
+ throttle_time: 13
+ targets:
+ - host: 1.1.1.2
+ name: test
+
+ ifmib:
+ internal_cache_max_duration: 5
+ inform:
+ retries: 7
+ chassis_id: test
+ packetsize: 491
+ queue_length: 2
+ throttle_time: 60
+ trap_source: GigabitEthernet0/0/0/2
+ trap_timeout: 3
+ context:
+ - c1
+ - c2
+ contact: t1
+ correlator:
+ buffer_size: 1025
+ communities:
+ - name: test1
+ ro: true
+ sdrowner: true
+ acl_v4: test
+ acl_v6: test1
+ community_maps:
+ - name: cm2
+ context: c1
+ target_list: t1
+ security_name: s1
+ drop:
+ report_IPv4: test2
+ unknown_user: true
+ ipv6:
+ precedence: routine
+ ipv4:
+ dscp: af11
+ location: test1
+ logging_threshold_oid_processing: 2
+ logging_threshold_pdu_processing: 2
+ mib_bulkstat_max_procmem_size: 101
+ mroutemib_send_all_vrf: true
+ overload_control:
+ overload_drop_time: 4
+ overload_throttle_rate: 6
+ notification_log_mib:
+ GlobalSize: 5
+ size: 5
+ traps:
+ hsrp: true
+ ipsla: true
+ ipsec:
+ start: true
+ stop: true
+ bridgemib: true
+ bulkstat_collection: true
+ cisco_entity_ext: true
+ config: true
+ copy_complete: true
+ l2vpn:
+ all: true
+ vc_down: true
+ vc_up: true
+ msdp_peer_state_change: true
+#
+# Commands Fired:
+# ---------------
+# "commands": [
+# "no snmp-server traps addrpool low",
+# "no snmp-server traps addrpool high",
+# "no snmp-server traps bfd",
+# "no snmp-server traps bgp cbgp2",
+# "no snmp-server traps l2tun sessions",
+# "no snmp-server traps l2tun tunnel-up",
+# "no snmp-server traps l2tun tunnel-down",
+# "no snmp-server community test2 RO SDROwner IPv4 test IPv6 test1",
+# "no snmp-server community-map cm1 context c1 security-name s1 target-list t1",
+# "no snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2",
+# "no snmp-server vrf vrf1",
+# "snmp-server chassis-id test",
+# "snmp-server correlator buffer-size 1025",
+# "snmp-server logging threshold oid-processing 2",
+# "snmp-server logging threshold pdu-processing 2",
+# "snmp-server packetsize 491",
+# "snmp-server drop report acl IPv4 test2",
+# "snmp-server ifmib internal cache max-duration 5",
+# "snmp-server trap throttle-time 13",
+# "snmp-server community test1 RO SDROwner IPv4 test IPv6 test1",
+# "snmp-server community-map cm2 context c1 security-name s1 target-list t1"
+# ],
+# After state:
+# ------------
+# RP/0/RP0/CPU0:ios#show running-config snmp-server
+# Mon Sep 13 10:38:22.690 UTC
+# RP/0/0/CPU0:10#show running-config snmp-server
+# snmp-server vrf vrf1
+# host 1.1.1.1 traps test1
+# !
+# snmp-server drop report acl IPv4 test1
+# snmp-server drop unknown-user
+# snmp-server ipv4 dscp af11
+# snmp-server ipv6 precedence routine
+# snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2
+# snmp-server community test2 RO SDROwner IPv4 test IPv6 test1
+# snmp-server queue-length 2
+# snmp-server trap-timeout 3
+# snmp-server trap throttle-time 12
+# snmp-server traps bfd
+# snmp-server traps bgp cbgp2
+# snmp-server traps copy-complete
+# snmp-server traps hsrp
+# snmp-server traps ipsla
+# snmp-server traps msdp peer-state-change
+# snmp-server traps ipsec tunnel stop
+# snmp-server traps ipsec tunnel start
+# snmp-server traps config
+# snmp-server traps l2tun sessions
+# snmp-server traps l2tun tunnel-up
+# snmp-server traps l2tun tunnel-down
+# snmp-server traps bulkstat collection
+# snmp-server traps l2vpn all
+# snmp-server traps l2vpn vc-up
+# snmp-server traps l2vpn vc-down
+# snmp-server traps bridgemib
+# snmp-server traps addrpool low
+# snmp-server traps addrpool high
+# snmp-server traps cisco-entity-ext
+# snmp-server chassis-id test2
+# snmp-server contact t1
+# snmp-server location test1
+# snmp-server target list test host 1.1.1.2
+# snmp-server target list test2 vrf vrf2
+# snmp-server context c1
+# snmp-server context c2
+# snmp-server logging threshold oid-processing 1
+# snmp-server logging threshold pdu-processing 1
+# snmp-server mib bulkstat max-procmem-size 101
+# snmp-server timeouts duplicate 0
+# snmp-server timeouts inQdrop 0
+# snmp-server packetsize 490
+# snmp-server correlator buffer-size 1024
+# snmp-server trap-source GigabitEthernet0/0/0/2
+# snmp-server throttle-time 60
+# snmp-server community-map cm1 context c1 security-name s1 target-list t1
+# snmp-server inform retries 7
+# snmp-server overload-control 4 6
+# snmp-server ifmib internal cache max-duration 4
+# snmp-server mroutemib send-all-vrf
+# snmp-server notification-log-mib size 5
+# snmp-server notification-log-mib GlobalSize 5
+#
+#
+# Using state: gathered
+# Before state:
+# -------------
+# RP/0/RP0/CPU0:test2#show running-config snmp-server
+# Mon Nov 29 12:49:29.521 UTC
+# snmp-server vrf vrf1
+# host 1.1.1.1 traps test1
+# !
+# snmp-server drop report acl IPv4 test1
+# snmp-server drop unknown-user
+# snmp-server ipv4 dscp af11
+# snmp-server ipv6 precedence routine
+# snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2
+# snmp-server community test2 RO SDROwner IPv4 test IPv6 test1
+# snmp-server queue-length 2
+# snmp-server trap-timeout 3
+# snmp-server trap throttle-time 12
+# snmp-server traps bfd
+# snmp-server traps bgp cbgp2
+# snmp-server traps copy-complete
+# snmp-server traps hsrp
+# snmp-server traps ipsla
+# snmp-server traps msdp peer-state-change
+# snmp-server traps ipsec tunnel stop
+# snmp-server traps ipsec tunnel start
+# snmp-server traps config
+# snmp-server traps l2tun sessions
+# snmp-server traps l2tun tunnel-up
+# snmp-server traps l2tun tunnel-down
+# snmp-server traps bulkstat collection
+# snmp-server traps l2vpn all
+# snmp-server traps l2vpn vc-up
+# snmp-server traps l2vpn vc-down
+# snmp-server traps bridgemib
+# snmp-server traps addrpool low
+# snmp-server traps addrpool high
+# snmp-server traps cisco-entity-ext
+# snmp-server chassis-id test2
+# snmp-server contact t1
+# snmp-server location test1
+# snmp-server target list test host 1.1.1.2
+# snmp-server target list test2 vrf vrf2
+# snmp-server context c1
+# snmp-server context c2
+# snmp-server logging threshold oid-processing 1
+# snmp-server logging threshold pdu-processing 1
+# snmp-server mib bulkstat max-procmem-size 101
+# snmp-server timeouts duplicate 0
+# snmp-server timeouts inQdrop 0
+# snmp-server packetsize 490
+# snmp-server correlator buffer-size 1024
+# snmp-server trap-source GigabitEthernet0/0/0/2
+# snmp-server throttle-time 60
+# snmp-server community-map cm1 context c1 security-name s1 target-list t1
+# snmp-server inform retries 7
+# snmp-server overload-control 4 6
+# snmp-server ifmib internal cache max-duration 4
+# snmp-server mroutemib send-all-vrf
+# snmp-server notification-log-mib size 5
+# snmp-server notification-log-mib GlobalSize 5
+# Gathered play:
+# --------------
+- name: Gather listed snmp server
+ cisco.iosxr.iosxr_snmp_server:
+ state: gathered
+# Module Execution Result:
+# ------------------------
+# "gathered": {
+# "chassis_id": "test2",
+# "communities": [
+# {
+# "acl_v4": "test",
+# "acl_v6": "test1",
+# "name": "test2",
+# "ro": true,
+# "sdrowner": true
+# }
+# ],
+# "community_maps": [
+# {
+# "context": "c1",
+# "name": "cm1",
+# "security_name": "s1",
+# "target_list": "t1"
+# }
+# ],
+# "contact": "t1",
+# "context": [
+# "c1",
+# "c2"
+# ],
+# "correlator": {
+# "buffer_size": 1024
+# },
+# "drop": {
+# "report_IPv4": "test1",
+# "unknown_user": true
+# },
+# "ifmib": {
+# "internal_cache_max_duration": 4
+# },
+# "inform": {
+# "retries": 7
+# },
+# "ipv4": {
+# "dscp": "af11"
+# },
+# "ipv6": {
+# "precedence": "routine"
+# },
+# "location": "test1",
+# "logging_threshold_oid_processing": 1,
+# "logging_threshold_pdu_processing": 1,
+# "mib_bulkstat_max_procmem_size": 101,
+# "mroutemib_send_all_vrf": true,
+# "notification_log_mib": {
+# "GlobalSize": 5,
+# "size": 5
+# },
+# "overload_control": {
+# "overload_drop_time": 4,
+# "overload_throttle_rate": 6
+# },
+# "packetsize": 490,
+# "queue_length": 2,
+# "targets": [
+# {
+# "host": "1.1.1.2",
+# "name": "test"
+# },
+# {
+# "name": "test2",
+# "vrf": "vrf2"
+# }
+# ],
+# "throttle_time": 60,
+# "timeouts": {
+# "duplicate": 0,
+# "inQdrop": 0
+# },
+# "trap": {
+# "throttle_time": 12
+# },
+# "trap_source": "GigabitEthernet0/0/0/2",
+# "trap_timeout": 3,
+# "traps": {
+# "addrpool": {
+# "high": true,
+# "low": true
+# },
+# "bfd": true,
+# "bgp": {
+# "cbgp2": true
+# },
+# "bridgemib": true,
+# "bulkstat_collection": true,
+# "cisco_entity_ext": true,
+# "config": true,
+# "copy_complete": true,
+# "hsrp": true,
+# "ipsec": {
+# "start": true,
+# "stop": true
+# },
+# "ipsla": true,
+# "l2tun": {
+# "sessions": true,
+# "tunnel_down": true,
+# "tunnel_up": true
+# },
+# "l2vpn": {
+# "all": true,
+# "vc_down": true,
+# "vc_up": true
+# },
+# "msdp_peer_state_change": true
+# },
+# "users": [
+# {
+# "Ipv4_acl": "test1",
+# "Ipv6_acl": "test2",
+# "group": "test2",
+# "user": "u1",
+# "version": "v1"
+# }
+# ],
+# "vrfs": [
+# {
+# "hosts": [
+# {
+# "community": "test1",
+# "host": "1.1.1.1",
+# "traps": true
+# }
+# ],
+# "vrf": "vrf1"
+# }
+# ]
+# }
+#
+#
+# Using state: rendered
+# Rendered play:
+# --------------
+- name: Render platform specific configuration lines with state rendered (without connecting to the device)
+ cisco.iosxr.iosxr_snmp_server:
+ state: rendered
+ config:
+ vrfs:
+ - hosts:
+ - community: test1
+ host: 1.1.1.1
+ traps: true
+ vrf: vrf1
+ users:
+ - Ipv4_acl: test1
+ Ipv6_acl: test2
+ group: test2
+ user: u1
+ version: v1
+ timeouts:
+ duplicate: 0
+ inQdrop: 0
+ trap:
+ throttle_time: 12
+ targets:
+ - host: 1.1.1.2
+ name: test
+
+ ifmib:
+ internal_cache_max_duration: 4
+ inform:
+ retries: 7
+ chassis_id: test2
+ packetsize: 490
+ queue_length: 2
+ throttle_time: 60
+ trap_source: GigabitEthernet0/0/0/2
+ trap_timeout: 3
+ context:
+ - c1
+ - c2
+ contact: t1
+ correlator:
+ buffer_size: 1024
+ communities:
+ - name: test2
+ ro: true
+ sdrowner: true
+ acl_v4: test
+ acl_v6: test1
+ community_maps:
+ - name: cm1
+ context: c1
+ target_list: t1
+ security_name: s1
+ drop:
+ report_IPv4: test1
+ unknown_user: true
+ ipv6:
+ precedence: routine
+ ipv4:
+ dscp: af11
+ location: test1
+ logging_threshold_oid_processing: 1
+ logging_threshold_pdu_processing: 1
+ mib_bulkstat_max_procmem_size: 101
+ mroutemib_send_all_vrf: true
+ overload_control:
+ overload_drop_time: 4
+ overload_throttle_rate: 6
+ notification_log_mib:
+ GlobalSize: 5
+ size: 5
+ traps:
+ hsrp: true
+ ipsla: true
+ ipsec:
+ start: true
+ stop: true
+ bridgemib: true
+ bulkstat_collection: true
+ cisco_entity_ext: true
+ config: true
+ copy_complete: true
+ addrpool:
+ high: true
+ low: true
+ bfd: true
+ bgp:
+ cbgp2: true
+ l2tun:
+ sessions: true
+ tunnel_down: true
+ tunnel_up: true
+ l2vpn:
+ all: true
+ vc_down: true
+ vc_up: true
+ msdp_peer_state_change: true
+ register: result
+# Module Execution Result:
+# ------------------------
+# "rendered": [
+# "snmp-server chassis-id test2",
+# "snmp-server correlator buffer-size 1024",
+# "snmp-server contact t1",
+# "snmp-server ipv4 dscp af11",
+# "snmp-server ipv6 precedence routine",
+# "snmp-server location test1",
+# "snmp-server logging threshold oid-processing 1",
+# "snmp-server logging threshold pdu-processing 1",
+# "snmp-server mib bulkstat max-procmem-size 101",
+# "snmp-server mroutemib send-all-vrf",
+# "snmp-server overload-control 4 6",
+# "snmp-server packetsize 490",
+# "snmp-server queue-length 2",
+# "snmp-server throttle-time 60",
+# "snmp-server trap-source GigabitEthernet0/0/0/2",
+# "snmp-server trap-timeout 3",
+# "snmp-server drop report acl IPv4 test1",
+# "snmp-server drop unknown-user",
+# "snmp-server ifmib internal cache max-duration 4",
+# "snmp-server inform retries 7",
+# "snmp-server notification-log-mib size 5",
+# "snmp-server notification-log-mib GlobalSize 5",
+# "snmp-server trap throttle-time 12",
+# "snmp-server timeouts inQdrop 0",
+# "snmp-server timeouts duplicate 0",
+# "snmp-server traps addrpool low",
+# "snmp-server traps addrpool high",
+# "snmp-server traps bfd",
+# "snmp-server traps bgp cbgp2",
+# "snmp-server traps bulkstat collection",
+# "snmp-server traps bridgemib",
+# "snmp-server traps copy-complete",
+# "snmp-server traps cisco-entity-ext",
+# "snmp-server traps config",
+# "snmp-server traps hsrp",
+# "snmp-server traps ipsla",
+# "snmp-server traps ipsec tunnel start",
+# "snmp-server traps ipsec tunnel stop",
+# "snmp-server traps l2tun sessions",
+# "snmp-server traps l2tun tunnel-up",
+# "snmp-server traps l2tun tunnel-down",
+# "snmp-server traps l2vpn all",
+# "snmp-server traps l2vpn vc-up",
+# "snmp-server traps l2vpn vc-down",
+# "snmp-server traps msdp peer-state-change",
+# "snmp-server community test2 RO SDROwner IPv4 test IPv6 test1",
+# "snmp-server community-map cm1 context c1 security-name s1 target-list t1",
+# "snmp-server context c1",
+# "snmp-server context c2",
+# "snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2",
+# "snmp-server target list test2 vrf vrf2",
+# "snmp-server target list test host 1.1.1.2",
+# "snmp-server vrf vrf1",
+# "host 1.1.1.1 traps test1"
+# ],
+# Using state: parsed
+# File: parsed.cfg
+# ----------------
+# snmp-server vrf vrf1
+# host 1.1.1.1 traps test1
+# !
+# snmp-server drop report acl IPv4 test1
+# snmp-server drop unknown-user
+# snmp-server ipv4 dscp af11
+# snmp-server ipv6 precedence routine
+# snmp-server user u1 test2 v1 IPv4 test1 IPv6 test2
+# snmp-server community test2 RO SDROwner IPv4 test IPv6 test1
+# snmp-server queue-length 2
+# snmp-server trap-timeout 3
+# snmp-server trap throttle-time 12
+# snmp-server traps bfd
+# snmp-server traps bgp cbgp2
+# snmp-server traps copy-complete
+# snmp-server traps hsrp
+# snmp-server traps ipsla
+# snmp-server traps msdp peer-state-change
+# snmp-server traps ipsec tunnel stop
+# snmp-server traps ipsec tunnel start
+# snmp-server traps config
+# snmp-server traps l2tun sessions
+# snmp-server traps l2tun tunnel-up
+# snmp-server traps l2tun tunnel-down
+# snmp-server traps bulkstat collection
+# snmp-server traps l2vpn all
+# snmp-server traps l2vpn vc-up
+# snmp-server traps l2vpn vc-down
+# snmp-server traps bridgemib
+# snmp-server traps addrpool low
+# snmp-server traps addrpool high
+# snmp-server traps cisco-entity-ext
+# snmp-server chassis-id test2
+# snmp-server contact t1
+# snmp-server location test1
+# snmp-server target list test host 1.1.1.2
+# snmp-server target list test2 vrf vrf2
+# snmp-server context c1
+# snmp-server context c2
+# snmp-server logging threshold oid-processing 1
+# snmp-server logging threshold pdu-processing 1
+# snmp-server mib bulkstat max-procmem-size 101
+# snmp-server timeouts duplicate 0
+# snmp-server timeouts inQdrop 0
+# snmp-server packetsize 490
+# snmp-server correlator buffer-size 1024
+# snmp-server trap-source GigabitEthernet0/0/0/2
+# snmp-server throttle-time 60
+# snmp-server community-map cm1 context c1 security-name s1 target-list t1
+# snmp-server inform retries 7
+# snmp-server overload-control 4 6
+# snmp-server ifmib internal cache max-duration 4
+# snmp-server mroutemib send-all-vrf
+# snmp-server notification-log-mib size 5
+# snmp-server notification-log-mib GlobalSize 5
+# ------------
+- name: Parse the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_snmp_server:
+ running_config: "{{ lookup('file', 'parsed.cfg') }}"
+ state: parsed
+# Module Execution Result:
+# ------------------------
+# "parsed":{
+# "chassis_id": "test2",
+# "communities": [
+# {
+# "acl_v4": "test",
+# "acl_v6": "test1",
+# "name": "test2",
+# "ro": true,
+# "sdrowner": true
+# }
+# ],
+# "community_maps": [
+# {
+# "context": "c1",
+# "name": "cm1",
+# "security_name": "s1",
+# "target_list": "t1"
+# }
+# ],
+# "contact": "t1",
+# "context": [
+# "c1",
+# "c2"
+# ],
+# "correlator": {
+# "buffer_size": 1024
+# },
+# "drop": {
+# "report_IPv4": "test1",
+# "unknown_user": true
+# },
+# "ifmib": {
+# "internal_cache_max_duration": 4
+# },
+# "inform": {
+# "retries": 7
+# },
+# "ipv4": {
+# "dscp": "af11"
+# },
+# "ipv6": {
+# "precedence": "routine"
+# },
+# "location": "test1",
+# "logging_threshold_oid_processing": 1,
+# "logging_threshold_pdu_processing": 1,
+# "mib_bulkstat_max_procmem_size": 101,
+# "mroutemib_send_all_vrf": true,
+# "notification_log_mib": {
+# "GlobalSize": 5,
+# "size": 5
+# },
+# "overload_control": {
+# "overload_drop_time": 4,
+# "overload_throttle_rate": 6
+# },
+# "packetsize": 490,
+# "queue_length": 2,
+# "targets": [
+# {
+# "host": "1.1.1.2",
+# "name": "test"
+# },
+# {
+# "name": "test2",
+# "vrf": "vrf2"
+# }
+# ],
+# "throttle_time": 60,
+# "timeouts": {
+# "duplicate": 0,
+# "inQdrop": 0
+# },
+# "trap": {
+# "throttle_time": 12
+# },
+# "trap_source": "GigabitEthernet0/0/0/2",
+# "trap_timeout": 3,
+# "traps": {
+# "addrpool": {
+# "high": true,
+# "low": true
+# },
+# "bfd": true,
+# "bgp": {
+# "cbgp2": true
+# },
+# "bridgemib": true,
+# "bulkstat_collection": true,
+# "cisco_entity_ext": true,
+# "config": true,
+# "copy_complete": true,
+# "hsrp": true,
+# "ipsec": {
+# "start": true,
+# "stop": true
+# },
+# "ipsla": true,
+# "l2tun": {
+# "sessions": true,
+# "tunnel_down": true,
+# "tunnel_up": true
+# },
+# "l2vpn": {
+# "all": true,
+# "vc_down": true,
+# "vc_up": true
+# },
+# "msdp_peer_state_change": true
+# },
+# "users": [
+# {
+# "Ipv4_acl": "test1",
+# "Ipv6_acl": "test2",
+# "group": "test2",
+# "user": "u1",
+# "version": "v1"
+# }
+# ],
+# "vrfs": [
+# {
+# "hosts": [
+# {
+# "community": "test1",
+# "host": "1.1.1.1",
+# "traps": true
+# }
+# ],
+# "vrf": "vrf1"
+# }
+# ]
+# }
+"""
+
+RETURN = """
+before:
+ description: The configuration prior to the module execution.
+ returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged)
+ type: dict
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+after:
+ description: The resulting configuration after module execution.
+ returned: when changed
+ type: dict
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: when I(state) is C(merged), C(replaced), C(overridden), C(deleted) or C(purged)
+ type: list
+ sample:
+ - sample command 1
+ - sample command 2
+ - sample command 3
+rendered:
+ description: The provided configuration in the task rendered in device-native format (offline).
+ returned: when I(state) is C(rendered)
+ type: list
+ sample:
+ - sample command 1
+ - sample command 2
+ - sample command 3
+gathered:
+ description: Facts about the network resource gathered from the remote device as structured data.
+ returned: when I(state) is C(gathered)
+ type: list
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+parsed:
+ description: The device native config provided in I(running_config) option parsed into structured data as per module argspec.
+ returned: when I(state) is C(parsed)
+ type: list
+ sample: >
+ This output will always be in the same format as the
+ module argspec.
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.snmp_server.snmp_server import (
+ Snmp_serverArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.snmp_server.snmp_server import (
+ Snmp_server,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ module = AnsibleModule(
+ argument_spec=Snmp_serverArgs.argument_spec,
+ mutually_exclusive=[["config", "running_config"]],
+ required_if=[
+ ["state", "merged", ["config"]],
+ ["state", "replaced", ["config"]],
+ ["state", "overridden", ["config"]],
+ ["state", "rendered", ["config"]],
+ ["state", "parsed", ["running_config"]],
+ ],
+ supports_check_mode=True,
+ )
+
+ result = Snmp_server(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_static_routes.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_static_routes.py
new file mode 100644
index 00000000..665eb013
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_static_routes.py
@@ -0,0 +1,856 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# Copyright 2019 Red Hat
+# GNU General Public License v3.0+
+# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#############################################
+# WARNING #
+#############################################
+#
+# This file is auto generated by the resource
+# module builder playbook.
+#
+# Do not edit this file manually.
+#
+# Changes to this file will be over written
+# by the resource module builder.
+#
+# Changes should be made in the model used to
+# generate this file or in the resource module
+# builder template.
+#
+#############################################
+
+"""
+The module file for iosxr_static_routes
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_static_routes
+short_description: Resource module to configure static routes.
+description:
+- This module manages static routes on devices running Cisco IOS-XR.
+version_added: 1.0.0
+author: Nilashish Chakraborty (@NilashishC)
+options:
+ running_config:
+ description:
+ - This option is used only with state I(parsed).
+ - The value of this option should be the output received from the IOS-XR device
+ by executing the command B(show running-config router static).
+ - The state I(parsed) reads the configuration from C(running_config) option and
+ transforms it into Ansible structured data as per the resource module's argspec
+ and the value is then returned in the I(parsed) key within the result.
+ type: str
+ config:
+ description: A dictionary of static route options.
+ type: list
+ elements: dict
+ suboptions:
+ vrf:
+ description:
+ - The VRF to which the static route(s) belong.
+ type: str
+ address_families:
+ description: A dictionary specifying the address family to which the static
+ route(s) belong.
+ type: list
+ elements: dict
+ suboptions:
+ afi:
+ description:
+ - Specifies the top level address family indicator.
+ type: str
+ choices:
+ - ipv4
+ - ipv6
+ required: true
+ safi:
+ description:
+ - Specifies the subsequent address family indicator.
+ type: str
+ choices:
+ - unicast
+ - multicast
+ required: true
+ routes:
+ description: A dictionary that specifies the static route configurations.
+ elements: dict
+ type: list
+ suboptions:
+ dest:
+ description:
+ - An IPv4 or IPv6 address in CIDR notation that specifies the destination
+ network for the static route.
+ type: str
+ required: true
+ next_hops:
+ description:
+ - Next hops to the specified destination.
+ type: list
+ elements: dict
+ suboptions:
+ forward_router_address:
+ description:
+ - The IP address of the next hop that can be used to reach the
+ destination network.
+ type: str
+ interface:
+ description:
+ - The interface to use to reach the destination.
+ type: str
+ dest_vrf:
+ description:
+ - The destination VRF.
+ type: str
+ admin_distance:
+ description:
+ - The administrative distance for this static route.
+ - Refer to vendor documentation for valid values.
+ type: int
+ metric:
+ description:
+ - Specifes the metric for this static route.
+ - Refer to vendor documentation for valid values.
+ type: int
+ description:
+ description:
+ - Specifies the description for this static route.
+ type: str
+ vrflabel:
+ description:
+ - Specifies the VRF label for this static route.
+ - Refer to vendor documentation for valid values.
+ type: int
+ tag:
+ description:
+ - Specifies a numeric tag for this static route.
+ - Refer to vendor documentation for valid values.
+ type: int
+ track:
+ description:
+ - Specifies the object to be tracked.
+ - This enables object tracking for static routes.
+ type: str
+ tunnel_id:
+ description:
+ - Specifies a tunnel id for the route.
+ - Refer to vendor documentation for valid values.
+ type: int
+ state:
+ description:
+ - The state the configuration should be left in.
+ type: str
+ choices:
+ - merged
+ - replaced
+ - overridden
+ - deleted
+ - gathered
+ - rendered
+ - parsed
+ default: merged
+
+"""
+EXAMPLES = """
+
+# Using merged
+
+# Before state
+# -------------
+# RP/0/RP0/CPU0:ios#show running-config router static
+# Sat Feb 22 07:46:30.089 UTC
+# % No such configuration item(s)
+#
+- name: Merge the provided configuration with the existing running configuration
+ cisco.iosxr.iosxr_static_routes:
+ config:
+ - address_families:
+ - afi: ipv4
+ safi: unicast
+ routes:
+ - dest: 192.0.2.16/28
+ next_hops:
+ - forward_router_address: 192.0.2.10
+ interface: FastEthernet0/0/0/1
+ description: LAB
+ metric: 120
+ tag: 10
+
+ - interface: FastEthernet0/0/0/5
+ track: ip_sla_1
+
+ - dest: 192.0.2.32/28
+ next_hops:
+ - forward_router_address: 192.0.2.11
+ admin_distance: 100
+
+ - afi: ipv6
+ safi: unicast
+ routes:
+ - dest: 2001:db8:1000::/36
+ next_hops:
+ - interface: FastEthernet0/0/0/7
+ description: DC
+
+ - interface: FastEthernet0/0/0/8
+ forward_router_address: 2001:db8:2000:2::1
+
+ - vrf: DEV_SITE
+ address_families:
+ - afi: ipv4
+ safi: unicast
+ routes:
+ - dest: 192.0.2.48/28
+ next_hops:
+ - forward_router_address: 192.0.2.12
+ description: DEV
+ dest_vrf: test_1
+
+ - dest: 192.0.2.80/28
+ next_hops:
+ - interface: FastEthernet0/0/0/2
+ forward_router_address: 192.0.2.14
+ dest_vrf: test_1
+ track: ip_sla_2
+ vrflabel: 124
+ state: merged
+
+# After state
+# -------------
+# RP/0/RP0/CPU0:ios#show running-config router static
+# Sat Feb 22 07:49:11.754 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV
+# 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+# !
+# !
+# !
+
+# Using merged to update existing static routes
+
+# Before state
+# -------------
+# RP/0/RP0/CPU0:ios#show running-config router static
+# Sat Feb 22 07:49:11.754 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV
+# 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+# !
+# !
+# !
+
+- name: Update existing static routes configuration using merged
+ cisco.iosxr.iosxr_static_routes:
+ config:
+ - vrf: DEV_SITE
+ address_families:
+ - afi: ipv4
+ safi: unicast
+ routes:
+ - dest: 192.0.2.48/28
+ next_hops:
+ - forward_router_address: 192.0.2.12
+ vrflabel: 2301
+ dest_vrf: test_1
+
+ - dest: 192.0.2.80/28
+ next_hops:
+ - interface: FastEthernet0/0/0/2
+ forward_router_address: 192.0.2.14
+ dest_vrf: test_1
+ description: rt_test_1
+ state: merged
+
+# After state
+# -------------
+# RP/0/RP0/CPU0:ios#show running-config router static
+# Sat Feb 22 07:49:11.754 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV vrflabel 2301
+# 192.0.2.80/28 vrf test_1 192.0.2.14 FastEthernet0/0/0/2 description rt_test_1 track ip_sla_2 vrflabel 124
+# !
+# !
+# !
+
+# Using replaced to replace all next hop entries for a single destination network
+
+# Before state
+# --------------
+
+# RP/0/RP0/CPU0:ios#sh running-config router static
+# Sat Feb 22 07:59:08.669 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV
+# 192.0.2.48/28 GigabitEthernet0/0/0/1 192.0.3.24 vrflabel 2302
+# 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+# !
+# !
+# !
+
+- name: Replace device configurations of static routes with provided configurations
+ cisco.iosxr.iosxr_static_routes:
+ config:
+ - vrf: DEV_SITE
+ address_families:
+ - afi: ipv4
+ safi: unicast
+ routes:
+ - dest: 192.0.2.48/28
+ next_hops:
+ - forward_router_address: 192.0.2.15
+ interface: FastEthernet0/0/0/3
+ description: DEV_NEW
+ dest_vrf: dev_test_2
+ state: replaced
+
+# After state
+# ------------
+# RP/0/RP0/CPU0:ios#sh running-config router static
+# Sat Feb 22 08:04:07.085 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf dev_test_2 FastEthernet0/0/0/3 192.0.2.15 description DEV_NEW
+# 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+# !
+# !
+# !
+
+# Using overridden to override all static route entries on the device
+
+# Before state
+# -------------
+# RP/0/RP0/CPU0:ios#sh running-config router static
+# Sat Feb 22 07:59:08.669 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV
+# 192.0.2.48/28 GigabitEthernet0/0/0/1 192.0.3.24 vrflabel 2302
+# 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+# !
+# !
+# !
+
+- name: Overridde all static routes configuration with provided configuration
+ cisco.iosxr.iosxr_static_routes:
+ config:
+ - vrf: DEV_NEW
+ address_families:
+ - afi: ipv4
+ safi: unicast
+ routes:
+ - dest: 192.0.2.48/28
+ next_hops:
+ - forward_router_address: 192.0.2.15
+ interface: FastEthernet0/0/0/3
+ description: DEV1
+ - afi: ipv6
+ safi: unicast
+ routes:
+ - dest: 2001:db8:3000::/36
+ next_hops:
+ - interface: FastEthernet0/0/0/4
+ forward_router_address: 2001:db8:2000:2::2
+ description: PROD1
+ track: ip_sla_1
+ state: overridden
+
+# After state
+# -------------
+# RP/0/RP0/CPU0:ios#sh running-config router static
+# Sat Feb 22 08:07:41.516 UTC
+# router static
+# vrf DEV_NEW
+# address-family ipv4 unicast
+# 192.0.2.48/28 FastEthernet0/0/0/3 192.0.2.15 description DEV1
+# !
+# address-family ipv6 unicast
+# 2001:db8:3000::/36 FastEthernet0/0/0/4 2001:db8:2000:2::2 description PROD1 track ip_sla_1
+# !
+# !
+# !
+
+# Using deleted to delete all destination network entries under a single AFI
+
+# Before state
+# -------------
+# RP/0/RP0/CPU0:ios#sh running-config router static
+# Sat Feb 22 07:59:08.669 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV
+# 192.0.2.48/28 GigabitEthernet0/0/0/1 192.0.3.24 vrflabel 2302
+# 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+# !
+# !
+# !
+
+- name: Delete all destination network entries under a single AFI
+ cisco.iosxr.iosxr_static_routes:
+ config:
+ - vrf: DEV_SITE
+ address_families:
+ - afi: ipv4
+ safi: unicast
+ state: deleted
+
+# After state
+# ------------
+
+# RP/0/RP0/CPU0:ios#sh running-config router static
+# Sat Feb 22 08:16:41.464 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# !
+# !
+
+# Using deleted to remove all static route entries from the device
+
+# Before state
+# -------------
+# RP/0/RP0/CPU0:ios#sh running-config router static
+# Sat Feb 22 07:59:08.669 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV
+# 192.0.2.48/28 GigabitEthernet0/0/0/1 192.0.3.24 vrflabel 2302
+# 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+# !
+# !
+# !
+
+- name: Delete static routes configuration
+ cisco.iosxr.iosxr_static_routes:
+ state: deleted
+
+# After state
+# ------------
+# RP/0/RP0/CPU0:ios#sh running-config router static
+# Sat Feb 22 08:50:43.038 UTC
+# % No such configuration item(s)
+
+# Using gathered to gather static route facts from the device
+
+- name: Gather static routes facts from the device using iosxr_static_routes module
+ cisco.iosxr.iosxr_static_routes:
+ state: gathered
+
+# Task output (redacted)
+# -----------------------
+# "gathered": [
+# {
+# "address_families": [
+# {
+# "afi": "ipv4",
+# "routes": [
+# {
+# "dest": "192.0.2.16/28",
+# "next_hops": [
+# {
+# "description": "LAB",
+# "forward_router_address": "192.0.2.10",
+# "interface": "FastEthernet0/0/0/1",
+# "metric": 120,
+# "tag": 10
+# },
+# {
+# "interface": "FastEthernet0/0/0/5",
+# "track": "ip_sla_1"
+# }
+# ]
+# },
+# {
+# "dest": "192.0.2.32/28",
+# "next_hops": [
+# {
+# "admin_distance": 100,
+# "forward_router_address": "192.0.2.11"
+# }
+# ]
+# }
+# ],
+# "safi": "unicast"
+# },
+# {
+# "afi": "ipv6",
+# "routes": [
+# {
+# "dest": "2001:db8:1000::/36",
+# "next_hops": [
+# {
+# "description": "DC",
+# "interface": "FastEthernet0/0/0/7"
+# },
+# {
+# "forward_router_address": "2001:db8:2000:2::1",
+# "interface": "FastEthernet0/0/0/8"
+# }
+# ]
+# }
+# ],
+# "safi": "unicast"
+# }
+# ]
+# },
+# {
+# "address_families": [
+# {
+# "afi": "ipv4",
+# "routes": [
+# {
+# "dest": "192.0.2.48/28",
+# "next_hops": [
+# {
+# "description": "DEV",
+# "dest_vrf": "test_1",
+# "forward_router_address": "192.0.2.12"
+# },
+# {
+# "forward_router_address": "192.0.3.24",
+# "interface": "GigabitEthernet0/0/0/1",
+# "vrflabel": 2302
+# }
+# ]
+# },
+# {
+# "dest": "192.0.2.80/28",
+# "next_hops": [
+# {
+# "dest_vrf": "test_1",
+# "forward_router_address": "192.0.2.14",
+# "interface": "FastEthernet0/0/0/2",
+# "track": "ip_sla_2",
+# "vrflabel": 124
+# }
+# ]
+# }
+# ],
+# "safi": "unicast"
+# }
+# ],
+# "vrf": "DEV_SITE"
+# }
+# ]
+
+# Using rendered
+
+- name: Render platform specific commands (without connecting to the device)
+ cisco.iosxr.iosxr_static_routes:
+ config:
+ - vrf: DEV_SITE
+ address_families:
+ - afi: ipv4
+ safi: unicast
+ routes:
+ - dest: 192.0.2.48/28
+ next_hops:
+ - forward_router_address: 192.0.2.12
+ description: DEV
+ dest_vrf: test_1
+
+ - dest: 192.0.2.80/28
+ next_hops:
+ - interface: FastEthernet0/0/0/2
+ forward_router_address: 192.0.2.14
+ dest_vrf: test_1
+ track: ip_sla_2
+ vrflabel: 124
+
+# Task Output (redacted)
+# -----------------------
+# "rendered": [
+# "router static"s,
+# "vrf DEV_SITE",
+# "address-family ipv4 unicast",
+# "192.0.2.48/28 vrf test_1 192.0.2.12 description DEV",
+# "192.0.2.80/28 vrf test_1 192.0.2.14 FastEthernet0/0/0/2 track ip_sla_2 vrflabel 124"
+
+# Using parsed
+
+# parsed.cfg
+# ------------
+# Fri Nov 29 21:10:41.896 UTC
+# router static
+# address-family ipv4 unicast
+# 192.0.2.16/28 FastEthernet0/0/0/1 192.0.2.10 tag 10 description LAB metric 120
+# 192.0.2.16/28 FastEthernet0/0/0/5 track ip_sla_1
+# 192.0.2.32/28 192.0.2.11 100
+# !
+# address-family ipv6 unicast
+# 2001:db8:1000::/36 FastEthernet0/0/0/7 description DC
+# 2001:db8:1000::/36 FastEthernet0/0/0/8 2001:db8:2000:2::1
+# !
+# vrf DEV_SITE
+# address-family ipv4 unicast
+# 192.0.2.48/28 vrf test_1 192.0.2.12 description DEV
+# 192.0.2.80/28 vrf test_1 FastEthernet0/0/0/2 192.0.2.14 vrflabel 124 track ip_sla_2
+# !
+# !
+# !
+
+- name: Use parsed state to convert externally supplied device specific static routes
+ commands to structured format
+ cisco.iosxr.iosxr_static_routes:
+ running_config: "{{ lookup('file', '../../fixtures/parsed.cfg') }}"
+ state: parsed
+
+# Task output (redacted)
+# -----------------------
+# "parsed": [
+# {
+# "address_families": [
+# {
+# "afi": "ipv4",
+# "routes": [
+# {
+# "dest": "192.0.2.16/28",
+# "next_hops": [
+# {
+# "description": "LAB",
+# "forward_router_address": "192.0.2.10",
+# "interface": "FastEthernet0/0/0/1",
+# "metric": 120,
+# "tag": 10
+# },
+# {
+# "interface": "FastEthernet0/0/0/5",
+# "track": "ip_sla_1"
+# }
+# ]
+# },
+# {
+# "dest": "192.0.2.32/28",
+# "next_hops": [
+# {
+# "admin_distance": 100,
+# "forward_router_address": "192.0.2.11"
+# }
+# ]
+# }
+# ],
+# "safi": "unicast"
+# },
+# {
+# "afi": "ipv6",
+# "routes": [
+# {
+# "dest": "2001:db8:1000::/36",
+# "next_hops": [
+# {
+# "description": "DC",
+# "interface": "FastEthernet0/0/0/7"
+# },
+# {
+# "forward_router_address": "2001:db8:2000:2::1",
+# "interface": "FastEthernet0/0/0/8"
+# }
+# ]
+# }
+# ],
+# "safi": "unicast"
+# }
+# ]
+# },
+# {
+# "address_families": [
+# {
+# "afi": "ipv4",
+# "routes": [
+# {
+# "dest": "192.0.2.48/28",
+# "next_hops": [
+# {
+# "description": "DEV",
+# "dest_vrf": "test_1",
+# "forward_router_address": "192.0.2.12"
+# }
+# ]
+# },
+# {
+# "dest": "192.0.2.80/28",
+# "next_hops": [
+# {
+# "dest_vrf": "test_1",
+# "forward_router_address": "192.0.2.14",
+# "interface": "FastEthernet0/0/0/2",
+# "track": "ip_sla_2",
+# "vrflabel": 124
+# }
+# ]
+# }
+# ],
+# "safi": "unicast"
+# }
+# ],
+# "vrf": "DEV_SITE"
+# }
+# ]
+# }
+"""
+RETURN = """
+before:
+ description: The configuration prior to the model invocation.
+ returned: always
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+after:
+ description: The resulting configuration model invocation.
+ returned: when changed
+ type: list
+ sample: >
+ The configuration returned will always be in the same format
+ of the parameters above.
+commands:
+ description: The set of commands pushed to the remote device.
+ returned: always
+ type: list
+ sample:
+ - router static
+ - vrf dev_site
+ - address-family ipv4 unicast
+ - 192.0.2.48/28 192.0.2.12 FastEthernet0/0/0/1 track ip_sla_10 description dev1
+ - address-family ipv6 unicast
+ - no 2001:db8:1000::/36
+ - 2001:db8:3000::/36 2001:db8:2000:2::2 FastEthernet0/0/0/4 track ip_sla_11 description prod1
+"""
+
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.argspec.static_routes.static_routes import (
+ Static_routesArgs,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.config.static_routes.static_routes import (
+ Static_routes,
+)
+
+
+def main():
+ """
+ Main entry point for module execution
+
+ :returns: the result form module invocation
+ """
+ required_if = [
+ ("state", "merged", ("config",)),
+ ("state", "replaced", ("config",)),
+ ("state", "overridden", ("config",)),
+ ("state", "parsed", ("running_config",)),
+ ]
+ mutually_exclusive = [("config", "running_config")]
+
+ module = AnsibleModule(
+ argument_spec=Static_routesArgs.argument_spec,
+ required_if=required_if,
+ mutually_exclusive=mutually_exclusive,
+ supports_check_mode=True,
+ )
+
+ result = Static_routes(module).execute_module()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_system.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_system.py
new file mode 100644
index 00000000..0d0d60ad
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_system.py
@@ -0,0 +1,748 @@
+#!/usr/bin/python
+#
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_system
+author:
+- Peter Sprygada (@privateip)
+- Kedar Kekan (@kedarX)
+short_description: Module to manage the system attributes.
+description:
+- This module provides declarative management of node system attributes on Cisco IOS
+ XR devices. It provides an option to configure host system parameters or remove
+ those parameters from the device active configuration.
+version_added: 1.0.0
+requirements:
+- ncclient >= 0.5.3 when using netconf
+- lxml >= 4.1.1 when using netconf
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+notes:
+- This module works with connection C(network_cli) and C(netconf). See L(the IOS-XR
+ Platform Options,../network/user_guide/platform_iosxr.html).
+- name-servers I(state=absent) operation with C(netconf) transport is a success, but
+ with rpc-error. This is due to XR platform issue. Recommended to use I(ignore_errors)
+ option with the task as a workaround.
+options:
+ hostname:
+ description:
+ - Configure the device hostname parameter. This option takes an ASCII string value.
+ type: str
+ vrf:
+ description:
+ - VRF name for domain services
+ type: str
+ default: "default"
+ domain_name:
+ description:
+ - Configure the IP domain name on the remote device to the provided value. Value
+ should be in the dotted name form and will be appended to the C(hostname) to
+ create a fully-qualified domain name.
+ type: str
+ domain_search:
+ description:
+ - Provides the list of domain suffixes to append to the hostname for the purpose
+ of doing name resolution. This argument accepts a list of names and will be
+ reconciled with the current active configuration on the running node.
+ type: list
+ elements: str
+ lookup_source:
+ description:
+ - The C(lookup_source) argument provides one or more source interfaces to use
+ for performing DNS lookups. The interface provided in C(lookup_source) must
+ be a valid interface configured on the device.
+ type: str
+ lookup_enabled:
+ description:
+ - Provides administrative control for enabling or disabling DNS lookups. When
+ this argument is set to True, lookups are performed and when it is set to False,
+ lookups are not performed.
+ type: bool
+ default: true
+ name_servers:
+ description:
+ - The C(name_serves) argument accepts a list of DNS name servers by way of either
+ FQDN or IP address to use to perform name resolution lookups. This argument
+ accepts wither a list of DNS servers See examples.
+ type: list
+ elements: str
+ state:
+ description:
+ - State of the configuration values in the device's current active configuration. When
+ set to I(present), the values should be configured in the device active configuration
+ and when set to I(absent) the values should not be in the device active configuration
+ default: present
+ choices:
+ - present
+ - absent
+ type: str
+"""
+
+EXAMPLES = """
+- name: configure hostname and domain-name (default vrf=default)
+ cisco.iosxr.iosxr_system:
+ hostname: iosxr01
+ domain_name: test.example.com
+ domain_search:
+ - ansible.com
+ - redhat.com
+ - cisco.com
+- name: remove configuration
+ cisco.iosxr.iosxr_system:
+ hostname: iosxr01
+ domain_name: test.example.com
+ domain_search:
+ - ansible.com
+ - redhat.com
+ - cisco.com
+ state: absent
+- name: configure hostname and domain-name with vrf
+ cisco.iosxr.iosxr_system:
+ hostname: iosxr01
+ vrf: nondefault
+ domain_name: test.example.com
+ domain_search:
+ - ansible.com
+ - redhat.com
+ - cisco.com
+- name: configure DNS lookup sources
+ cisco.iosxr.iosxr_system:
+ lookup_source: MgmtEth0/0/CPU0/0
+ lookup_enabled: true
+- name: configure name servers
+ cisco.iosxr.iosxr_system:
+ name_servers:
+ - 8.8.8.8
+ - 8.8.4.4
+"""
+
+RETURN = """
+commands:
+ description: The list of configuration mode commands to send to the device
+ returned: always
+ type: list
+ sample:
+ - hostname iosxr01
+ - ip domain-name test.example.com
+xml:
+ description: NetConf rpc xml sent to device with transport C(netconf)
+ returned: always (empty list when no xml rpc to send)
+ type: list
+ sample:
+ - '<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <ip-domain xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-ip-domain-cfg">
+ <vrfs>
+ <vrf>
+ <vrf-name>default</vrf-name>
+ <lists>
+ <list xc:operation="merge">
+ <order>0</order>
+ <list-name>redhat.com</list-name>
+ </list>
+ </lists>
+ </vrf>
+ </vrfs>
+ </ip-domain>
+ </config>'
+"""
+
+import collections
+import re
+
+from ansible.module_utils.basic import AnsibleModule
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ build_xml,
+ etree_find,
+ etree_findall,
+ get_config,
+ is_cliconf,
+ is_netconf,
+ load_config,
+)
+
+
+def diff_list(want, have):
+ adds = set(want).difference(have)
+ removes = set(have).difference(want)
+ return (adds, removes)
+
+
+class ConfigBase(object):
+ def __init__(self, module):
+ self._module = module
+ self._result = {"changed": False, "warnings": []}
+ self._want = dict()
+ self._have = dict()
+
+ def map_params_to_obj(self):
+ self._want.update(
+ {
+ "hostname": self._module.params["hostname"],
+ "vrf": self._module.params["vrf"],
+ "domain_name": self._module.params["domain_name"],
+ "domain_search": self._module.params["domain_search"],
+ "lookup_source": self._module.params["lookup_source"],
+ "lookup_enabled": self._module.params["lookup_enabled"],
+ "name_servers": self._module.params["name_servers"],
+ },
+ )
+
+
+class CliConfiguration(ConfigBase):
+ def __init__(self, module):
+ super(CliConfiguration, self).__init__(module)
+
+ def map_obj_to_commands(self):
+ commands = list()
+ state = self._module.params["state"]
+
+ def needs_update(x):
+ return self._want.get(x) and (self._want.get(x) != self._have.get(x))
+
+ if state == "absent":
+ if self._have["hostname"] != "ios":
+ commands.append("no hostname")
+ if self._have["domain_name"]:
+ commands.append("no domain name")
+ if self._have["lookup_source"]:
+ commands.append(
+ "no domain lookup source-interface {0!s}".format(self._have["lookup_source"]),
+ )
+ if not self._have["lookup_enabled"]:
+ commands.append("no domain lookup disable")
+ for item in self._have["name_servers"]:
+ commands.append("no domain name-server {0!s}".format(item))
+ for item in self._have["domain_search"]:
+ commands.append("no domain list {0!s}".format(item))
+
+ elif state == "present":
+ if needs_update("hostname"):
+ commands.append("hostname {0!s}".format(self._want["hostname"]))
+
+ if needs_update("domain_name"):
+ commands.append("domain name {0!s}".format(self._want["domain_name"]))
+
+ if needs_update("lookup_source"):
+ commands.append(
+ "domain lookup source-interface {0!s}".format(self._want["lookup_source"]),
+ )
+
+ cmd = None
+ if not self._want["lookup_enabled"] and self._have["lookup_enabled"]:
+ cmd = "domain lookup disable"
+ elif self._want["lookup_enabled"] and not self._have["lookup_enabled"]:
+ cmd = "no domain lookup disable"
+ if cmd is not None:
+ commands.append(cmd)
+
+ if self._want["name_servers"] is not None:
+ adds, removes = diff_list(self._want["name_servers"], self._have["name_servers"])
+ for item in adds:
+ commands.append("domain name-server {0!s}".format(item))
+ for item in removes:
+ commands.append("no domain name-server {0!s}".format(item))
+
+ if self._want["domain_search"] is not None:
+ adds, removes = diff_list(self._want["domain_search"], self._have["domain_search"])
+ for item in adds:
+ commands.append("domain list {0!s}".format(item))
+ for item in removes:
+ commands.append("no domain list {0!s}".format(item))
+
+ self._result["commands"] = []
+ if commands:
+ commit = not self._module.check_mode
+ diff = load_config(self._module, commands, commit=commit)
+ if diff:
+ self._result["diff"] = dict(prepared=diff)
+
+ self._result["commands"] = commands
+ self._result["changed"] = True
+
+ def parse_hostname(self, config):
+ match = re.search(r"^hostname (\S+)", config, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_domain_name(self, config):
+ match = re.search(r"^domain name (\S+)", config, re.M)
+ if match:
+ return match.group(1)
+
+ def parse_lookup_source(self, config):
+ match = re.search(r"^domain lookup source-interface (\S+)", config, re.M)
+ if match:
+ return match.group(1)
+
+ def map_config_to_obj(self):
+ config = get_config(self._module)
+ self._have.update(
+ {
+ "hostname": self.parse_hostname(config),
+ "domain_name": self.parse_domain_name(config),
+ "domain_search": re.findall(r"^domain list (\S+)", config, re.M),
+ "lookup_source": self.parse_lookup_source(config),
+ "lookup_enabled": "domain lookup disable" not in config,
+ "name_servers": re.findall(r"^domain name-server (\S+)", config, re.M),
+ },
+ )
+
+ def run(self):
+ self.map_params_to_obj()
+ self.map_config_to_obj()
+ self.map_obj_to_commands()
+
+ return self._result
+
+
+class NCConfiguration(ConfigBase):
+ def __init__(self, module):
+ super(NCConfiguration, self).__init__(module)
+ self._system_meta = collections.OrderedDict()
+ self._system_domain_meta = collections.OrderedDict()
+ self._system_server_meta = collections.OrderedDict()
+ self._hostname_meta = collections.OrderedDict()
+ self._lookup_source_meta = collections.OrderedDict()
+ self._lookup_meta = collections.OrderedDict()
+
+ def map_obj_to_xml_rpc(self):
+ self._system_meta.update(
+ [
+ ("vrfs", {"xpath": "ip-domain/vrfs", "tag": True, "operation": "edit"}),
+ ("vrf", {"xpath": "ip-domain/vrfs/vrf", "tag": True, "operation": "edit"}),
+ ("a:vrf", {"xpath": "ip-domain/vrfs/vrf/vrf-name", "operation": "edit"}),
+ (
+ "a:domain_name",
+ {
+ "xpath": "ip-domain/vrfs/vrf/name",
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ ],
+ )
+
+ self._system_domain_meta.update(
+ [
+ ("vrfs", {"xpath": "ip-domain/vrfs", "tag": True, "operation": "edit"}),
+ ("vrf", {"xpath": "ip-domain/vrfs/vrf", "tag": True, "operation": "edit"}),
+ ("a:vrf", {"xpath": "ip-domain/vrfs/vrf/vrf-name", "operation": "edit"}),
+ ("lists", {"xpath": "ip-domain/vrfs/vrf/lists", "tag": True, "operation": "edit"}),
+ (
+ "list",
+ {
+ "xpath": "ip-domain/vrfs/vrf/lists/list",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ ("a:order", {"xpath": "ip-domain/vrfs/vrf/lists/list/order", "operation": "edit"}),
+ (
+ "a:domain_search",
+ {"xpath": "ip-domain/vrfs/vrf/lists/list/list-name", "operation": "edit"},
+ ),
+ ],
+ )
+
+ self._system_server_meta.update(
+ [
+ ("vrfs", {"xpath": "ip-domain/vrfs", "tag": True, "operation": "edit"}),
+ ("vrf", {"xpath": "ip-domain/vrfs/vrf", "tag": True, "operation": "edit"}),
+ ("a:vrf", {"xpath": "ip-domain/vrfs/vrf/vrf-name", "operation": "edit"}),
+ (
+ "servers",
+ {"xpath": "ip-domain/vrfs/vrf/servers", "tag": True, "operation": "edit"},
+ ),
+ (
+ "server",
+ {
+ "xpath": "ip-domain/vrfs/vrf/servers/server",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ (
+ "a:order",
+ {"xpath": "ip-domain/vrfs/vrf/servers/server/order", "operation": "edit"},
+ ),
+ (
+ "a:name_servers",
+ {
+ "xpath": "ip-domain/vrfs/vrf/servers/server/server-address",
+ "operation": "edit",
+ },
+ ),
+ ],
+ )
+
+ self._hostname_meta.update(
+ [
+ (
+ "a:hostname",
+ {"xpath": "host-names/host-name", "operation": "edit", "attrib": "operation"},
+ ),
+ ],
+ )
+
+ self._lookup_source_meta.update(
+ [
+ ("vrfs", {"xpath": "ip-domain/vrfs", "tag": True, "operation": "edit"}),
+ ("vrf", {"xpath": "ip-domain/vrfs/vrf", "tag": True, "operation": "edit"}),
+ ("a:vrf", {"xpath": "ip-domain/vrfs/vrf/vrf-name", "operation": "edit"}),
+ (
+ "a:lookup_source",
+ {
+ "xpath": "ip-domain/vrfs/vrf/source-interface",
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ ],
+ )
+
+ self._lookup_meta.update(
+ [
+ ("vrfs", {"xpath": "ip-domain/vrfs", "tag": True, "operation": "edit"}),
+ ("vrf", {"xpath": "ip-domain/vrfs/vrf", "tag": True, "operation": "edit"}),
+ ("a:vrf", {"xpath": "ip-domain/vrfs/vrf/vrf-name", "operation": "edit"}),
+ (
+ "lookup",
+ {
+ "xpath": "ip-domain/vrfs/vrf/lookup",
+ "tag": True,
+ "operation": "edit",
+ "attrib": "operation",
+ },
+ ),
+ ],
+ )
+
+ state = self._module.params["state"]
+ _get_filter = build_xml("ip-domain", opcode="filter")
+ running = get_config(self._module, source="running", config_filter=_get_filter)
+ _get_filter = build_xml("host-names", opcode="filter")
+ hostname_runn = get_config(self._module, source="running", config_filter=_get_filter)
+
+ hostname_ele = etree_find(hostname_runn, "host-name")
+ hostname = hostname_ele.text if hostname_ele is not None else None
+
+ vrf_ele = etree_findall(running, "vrf")
+ vrf_map = {}
+ for vrf in vrf_ele:
+ name_server_list = list()
+ domain_list = list()
+ vrf_name_ele = etree_find(vrf, "vrf-name")
+ vrf_name = vrf_name_ele.text if vrf_name_ele is not None else None
+
+ domain_name_ele = etree_find(vrf, "name")
+ domain_name = domain_name_ele.text if domain_name_ele is not None else None
+
+ domain_ele = etree_findall(vrf, "list-name")
+ for domain in domain_ele:
+ domain_list.append(domain.text)
+
+ server_ele = etree_findall(vrf, "server-address")
+ for server in server_ele:
+ name_server_list.append(server.text)
+
+ lookup_source_ele = etree_find(vrf, "source-interface")
+ lookup_source = lookup_source_ele.text if lookup_source_ele is not None else None
+
+ lookup_enabled = False if etree_find(vrf, "lookup") is not None else True
+
+ vrf_map[vrf_name] = {
+ "domain_name": domain_name,
+ "domain_search": domain_list,
+ "name_servers": name_server_list,
+ "lookup_source": lookup_source,
+ "lookup_enabled": lookup_enabled,
+ }
+
+ opcode = None
+ hostname_param = {}
+ lookup_param = {}
+ system_param = {}
+ sys_server_params = list()
+ sys_domain_params = list()
+ add_domain_params = list()
+ del_domain_params = list()
+ add_server_params = list()
+ del_server_params = list()
+ lookup_source_params = {}
+
+ try:
+ sys_node = vrf_map[self._want["vrf"]]
+ except KeyError:
+ sys_node = {
+ "domain_name": None,
+ "domain_search": [],
+ "name_servers": [],
+ "lookup_source": None,
+ "lookup_enabled": True,
+ }
+
+ if state == "absent":
+ opcode = "delete"
+
+ def needs_update(x):
+ return self._want[x] is not None and self._want[x] == sys_node[x]
+
+ if needs_update("domain_name"):
+ system_param = {"vrf": self._want["vrf"], "domain_name": self._want["domain_name"]}
+
+ if needs_update("hostname"):
+ hostname_param = {"hostname": hostname}
+
+ if not self._want["lookup_enabled"] and not sys_node["lookup_enabled"]:
+ lookup_param["vrf"] = self._want["vrf"]
+
+ if needs_update("lookup_source"):
+ lookup_source_params["vrf"] = self._want["vrf"]
+ lookup_source_params["lookup_source"] = self._want["lookup_source"]
+
+ if self._want["domain_search"]:
+ domain_param = {}
+ domain_param["domain_name"] = self._want["domain_name"]
+ domain_param["vrf"] = self._want["vrf"]
+ domain_param["order"] = "0"
+ for domain in self._want["domain_search"]:
+ if domain in sys_node["domain_search"]:
+ domain_param["domain_search"] = domain
+ sys_domain_params.append(domain_param.copy())
+
+ if self._want["name_servers"]:
+ server_param = {}
+ server_param["vrf"] = self._want["vrf"]
+ server_param["order"] = "0"
+ for server in self._want["name_servers"]:
+ if server in sys_node["name_servers"]:
+ server_param["name_servers"] = server
+ sys_server_params.append(server_param.copy())
+
+ elif state == "present":
+ opcode = "merge"
+
+ def needs_update(x):
+ return self._want[x] is not None and (
+ sys_node[x] is None
+ or (sys_node[x] is not None and self._want[x] != sys_node[x])
+ )
+
+ if needs_update("domain_name"):
+ system_param = {"vrf": self._want["vrf"], "domain_name": self._want["domain_name"]}
+
+ if self._want["hostname"] is not None and self._want["hostname"] != hostname:
+ hostname_param = {"hostname": self._want["hostname"]}
+
+ if not self._want["lookup_enabled"] and sys_node["lookup_enabled"]:
+ lookup_param["vrf"] = self._want["vrf"]
+
+ if needs_update("lookup_source"):
+ lookup_source_params["vrf"] = self._want["vrf"]
+ lookup_source_params["lookup_source"] = self._want["lookup_source"]
+
+ if self._want["domain_search"]:
+ domain_adds, domain_removes = diff_list(
+ self._want["domain_search"],
+ sys_node["domain_search"],
+ )
+ domain_param = {}
+ domain_param["domain_name"] = self._want["domain_name"]
+ domain_param["vrf"] = self._want["vrf"]
+ domain_param["order"] = "0"
+ for domain in domain_adds:
+ if domain not in sys_node["domain_search"]:
+ domain_param["domain_search"] = domain
+ add_domain_params.append(domain_param.copy())
+ for domain in domain_removes:
+ if domain in sys_node["domain_search"]:
+ domain_param["domain_search"] = domain
+ del_domain_params.append(domain_param.copy())
+
+ if self._want["name_servers"]:
+ server_adds, server_removes = diff_list(
+ self._want["name_servers"],
+ sys_node["name_servers"],
+ )
+ server_param = {}
+ server_param["vrf"] = self._want["vrf"]
+ server_param["order"] = "0"
+ for domain in server_adds:
+ if domain not in sys_node["name_servers"]:
+ server_param["name_servers"] = domain
+ add_server_params.append(server_param.copy())
+ for domain in server_removes:
+ if domain in sys_node["name_servers"]:
+ server_param["name_servers"] = domain
+ del_server_params.append(server_param.copy())
+
+ self._result["xml"] = []
+ _edit_filter_list = list()
+ if opcode:
+ if hostname_param:
+ _edit_filter_list.append(
+ build_xml(
+ "host-names",
+ xmap=self._hostname_meta,
+ params=hostname_param,
+ opcode=opcode,
+ ),
+ )
+
+ if system_param:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._system_meta,
+ params=system_param,
+ opcode=opcode,
+ ),
+ )
+
+ if lookup_source_params:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._lookup_source_meta,
+ params=lookup_source_params,
+ opcode=opcode,
+ ),
+ )
+ if lookup_param:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._lookup_meta,
+ params=lookup_param,
+ opcode=opcode,
+ ),
+ )
+
+ if opcode == "delete":
+ if sys_domain_params:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._system_domain_meta,
+ params=sys_domain_params,
+ opcode=opcode,
+ ),
+ )
+ if sys_server_params:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._system_server_meta,
+ params=sys_server_params,
+ opcode=opcode,
+ ),
+ )
+ if self._want["vrf"] != "default":
+ self._result["warnings"] = [
+ "name-servers delete operation with non-default vrf is a success, "
+ "but with rpc-error. Recommended to use 'ignore_errors' option with the task as a workaround",
+ ]
+ elif opcode == "merge":
+ if add_domain_params:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._system_domain_meta,
+ params=add_domain_params,
+ opcode=opcode,
+ ),
+ )
+ if del_domain_params:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._system_domain_meta,
+ params=del_domain_params,
+ opcode="delete",
+ ),
+ )
+
+ if add_server_params:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._system_server_meta,
+ params=add_server_params,
+ opcode=opcode,
+ ),
+ )
+ if del_server_params:
+ _edit_filter_list.append(
+ build_xml(
+ "ip-domain",
+ xmap=self._system_server_meta,
+ params=del_server_params,
+ opcode="delete",
+ ),
+ )
+
+ diff = None
+ if _edit_filter_list:
+ commit = not self._module.check_mode
+ diff = load_config(
+ self._module,
+ _edit_filter_list,
+ commit=commit,
+ running=running,
+ nc_get_filter=_get_filter,
+ )
+
+ if diff:
+ if self._module._diff:
+ self._result["diff"] = dict(prepared=diff)
+
+ self._result["xml"] = _edit_filter_list
+ self._result["changed"] = True
+
+ def run(self):
+ self.map_params_to_obj()
+ self.map_obj_to_xml_rpc()
+
+ return self._result
+
+
+def main():
+ """Main entry point for Ansible module execution"""
+ argument_spec = dict(
+ hostname=dict(type="str"),
+ vrf=dict(type="str", default="default"),
+ domain_name=dict(type="str"),
+ domain_search=dict(type="list", elements="str"),
+ name_servers=dict(type="list", elements="str"),
+ lookup_source=dict(type="str"),
+ lookup_enabled=dict(type="bool", default=True),
+ state=dict(choices=["present", "absent"], default="present"),
+ )
+
+ module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
+
+ config_object = None
+ if is_cliconf(module):
+ # Commenting the below cliconf deprecation support call for Ansible 2.9 as it'll be continued to be supported
+ config_object = CliConfiguration(module)
+ elif is_netconf(module):
+ config_object = NCConfiguration(module)
+
+ result = None
+ if config_object:
+ result = config_object.run()
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/modules/iosxr_user.py b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_user.py
new file mode 100644
index 00000000..6aefaa72
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/modules/iosxr_user.py
@@ -0,0 +1,905 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# (c) 2017, Ansible by Red Hat, inc
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: iosxr_user
+author:
+- Trishna Guha (@trishnaguha)
+- Sebastiaan van Doesselaar (@sebasdoes)
+- Kedar Kekan (@kedarX)
+short_description: Module to manage the aggregates of local users.
+description:
+- This module provides declarative management of the local usernames configured on
+ network devices. It allows playbooks to manage either individual usernames or the
+ aggregate of usernames in the current running config. It also supports purging usernames
+ from the configuration that are not explicitly defined.
+version_added: 1.0.0
+extends_documentation_fragment:
+- cisco.iosxr.iosxr
+notes:
+- This module works with connection C(network_cli) and C(netconf). See L(the IOS-XR
+ Platform Options,../network/user_guide/platform_iosxr.html).
+options:
+ aggregate:
+ description:
+ - The set of username objects to be configured on the remote Cisco IOS XR device.
+ The list entries can either be the username or a hash of username and properties.
+ This argument is mutually exclusive with the C(name) argument.
+ aliases:
+ - users
+ - collection
+ type: list
+ elements: dict
+ suboptions:
+ name:
+ description:
+ - The username to be configured on the Cisco IOS XR device. This argument accepts
+ a string value and is mutually exclusive with the C(aggregate) argument. Please
+ note that this option is not same as C(provider username).
+ type: str
+ required: true
+ configured_password:
+ description:
+ - The password to be configured on the Cisco IOS XR device. The password needs
+ to be provided in clear text. Password is encrypted on the device when used
+ with I(cli) and by Ansible when used with I(netconf) using the same MD5 hash
+ technique with salt size of 3. Please note that this option is not same as C(provider
+ password).
+ type: str
+ update_password:
+ description:
+ - Since passwords are encrypted in the device running config, this argument will
+ instruct the module when to change the password. When set to C(always), the
+ password will always be updated in the device and when set to C(on_create) the
+ password will be updated only if the username is created.
+ type: str
+ choices:
+ - on_create
+ - always
+ group:
+ description:
+ - Configures the group for the username in the device running configuration. The
+ argument accepts a string value defining the group name. This argument does
+ not check if the group has been configured on the device.
+ type: str
+ aliases:
+ - role
+ groups:
+ description:
+ - Configures the groups for the username in the device running configuration.
+ The argument accepts a list of group names. This argument does not check if
+ the group has been configured on the device. It is similar to the aggregate
+ command for usernames, but lets you configure multiple groups for the user(s).
+ type: list
+ elements: str
+ admin:
+ description:
+ - Enters into administration configuration mode for making config changes to the
+ device.
+ - Applicable only when using network_cli transport
+ type: bool
+ state:
+ description:
+ - Configures the state of the username definition as it relates to the device
+ operational configuration. When set to I(present), the username(s) should be
+ configured in the device active configuration and when set to I(absent) the
+ username(s) should not be in the device active configuration
+ type: str
+ choices:
+ - present
+ - absent
+ public_key:
+ description:
+ - Configures the contents of the public keyfile to upload to the IOS-XR node.
+ This enables users to login using the accompanying private key. IOS-XR only
+ accepts base64 decoded files, so this will be decoded and uploaded to the node.
+ Do note that this requires an OpenSSL public key file, PuTTy generated files
+ will not work! Mutually exclusive with public_key_contents. If used with multiple
+ users in aggregates, then the same key file is used for all users.
+ type: str
+ public_key_contents:
+ description:
+ - Configures the contents of the public keyfile to upload to the IOS-XR node.
+ This enables users to login using the accompanying private key. IOS-XR only
+ accepts base64 decoded files, so this will be decoded and uploaded to the node.
+ Do note that this requires an OpenSSL public key file, PuTTy generated files
+ will not work! Mutually exclusive with public_key.If used with multiple users
+ in aggregates, then the same key file is used for all users.
+ type: str
+ name:
+ description:
+ - The username to be configured on the Cisco IOS XR device. This argument accepts
+ a string value and is mutually exclusive with the C(aggregate) argument. Please
+ note that this option is not same as C(provider username).
+ type: str
+ configured_password:
+ description:
+ - The password to be configured on the Cisco IOS XR device. The password needs
+ to be provided in clear text. Password is encrypted on the device when used
+ with I(cli) and by Ansible when used with I(netconf) using the same MD5 hash
+ technique with salt size of 3. Please note that this option is not same as C(provider
+ password).
+ type: str
+ update_password:
+ description:
+ - Since passwords are encrypted in the device running config, this argument will
+ instruct the module when to change the password. When set to C(always), the
+ password will always be updated in the device and when set to C(on_create) the
+ password will be updated only if the username is created.
+ type: str
+ default: always
+ choices:
+ - on_create
+ - always
+ group:
+ description:
+ - Configures the group for the username in the device running configuration. The
+ argument accepts a string value defining the group name. This argument does
+ not check if the group has been configured on the device.
+ type: str
+ aliases:
+ - role
+ groups:
+ description:
+ - Configures the groups for the username in the device running configuration.
+ The argument accepts a list of group names. This argument does not check if
+ the group has been configured on the device. It is similar to the aggregate
+ command for usernames, but lets you configure multiple groups for the user(s).
+ type: list
+ elements: str
+ purge:
+ description:
+ - Instructs the module to consider the resource definition absolute. It will remove
+ any previously configured usernames on the device with the exception of the
+ `admin` user and the current defined set of users.
+ type: bool
+ default: false
+ admin:
+ description:
+ - Enters into administration configuration mode for making config changes to the
+ device.
+ - Applicable only when using network_cli transport
+ type: bool
+ default: false
+ state:
+ description:
+ - Configures the state of the username definition as it relates to the device
+ operational configuration. When set to I(present), the username(s) should be
+ configured in the device active configuration and when set to I(absent) the
+ username(s) should not be in the device active configuration
+ type: str
+ default: present
+ choices:
+ - present
+ - absent
+ public_key:
+ description:
+ - Configures the contents of the public keyfile to upload to the IOS-XR node.
+ This enables users to login using the accompanying private key. IOS-XR only
+ accepts base64 decoded files, so this will be decoded and uploaded to the node.
+ Do note that this requires an OpenSSL public key file, PuTTy generated files
+ will not work! Mutually exclusive with public_key_contents. If used with multiple
+ users in aggregates, then the same key file is used for all users.
+ type: str
+ public_key_contents:
+ description:
+ - Configures the contents of the public keyfile to upload to the IOS-XR node.
+ This enables users to login using the accompanying private key. IOS-XR only
+ accepts base64 decoded files, so this will be decoded and uploaded to the node.
+ Do note that this requires an OpenSSL public key file, PuTTy generated files
+ will not work! Mutually exclusive with public_key.If used with multiple users
+ in aggregates, then the same key file is used for all users.
+ type: str
+
+requirements:
+- ncclient >= 0.5.3 when using netconf
+- lxml >= 4.1.1 when using netconf
+- base64 when using I(public_key_contents) or I(public_key)
+"""
+
+EXAMPLES = """
+- name: create a new user
+ cisco.iosxr.iosxr_user:
+ name: ansible
+ configured_password: mypassword
+ state: present
+- name: create a new user in admin configuration mode
+ cisco.iosxr.iosxr_user:
+ name: ansible
+ configured_password: mypassword
+ admin: true
+ state: present
+- name: remove all users except admin
+ cisco.iosxr.iosxr_user:
+ purge: true
+- name: set multiple users to group sys-admin
+ cisco.iosxr.iosxr_user:
+ aggregate:
+ - name: netop
+ - name: netend
+ group: sysadmin
+ state: present
+- name: set multiple users to multiple groups
+ cisco.iosxr.iosxr_user:
+ aggregate:
+ - name: netop
+ - name: netend
+ groups:
+ - sysadmin
+ - root-system
+ state: present
+- name: Change Password for User netop
+ cisco.iosxr.iosxr_user:
+ name: netop
+ configured_password: '{{ new_password }}'
+ update_password: always
+ state: present
+- name: Add private key authentication for user netop
+ cisco.iosxr.iosxr_user:
+ name: netop
+ state: present
+ public_key_contents: "{{ lookup('file', '/home/netop/.ssh/id_rsa.pub' }}"
+"""
+
+RETURN = """
+commands:
+ description: The list of configuration mode commands to send to the device
+ returned: always
+ type: list
+ sample:
+ - username ansible secret password group sysadmin
+ - username admin secret admin
+xml:
+ description: NetConf rpc xml sent to device with transport C(netconf)
+ returned: always (empty list when no xml rpc to send)
+ type: list
+ sample:
+ - '<config xmlns:xc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">
+ <aaa xmlns=\"http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-lib-cfg\">
+ <usernames xmlns=\"http://cisco.com/ns/yang/Cisco-IOS-XR-aaa-locald-cfg\">
+ <username xc:operation=\"merge\">
+ <name>test7</name>
+ <usergroup-under-usernames>
+ <usergroup-under-username>
+ <name>sysadmin</name>
+ </usergroup-under-username>
+ </usergroup-under-usernames>
+ <secret>$1$ZsXC$zZ50wqhDC543ZWQkkAHLW0</secret>
+ </username>
+ </usernames>
+ </aaa>
+ </config>'
+"""
+
+import collections
+import os
+
+from copy import deepcopy
+from functools import partial
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import (
+ remove_default_spec,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ build_xml,
+ copy_file,
+ etree_findall,
+ get_capabilities,
+ get_config,
+ get_connection,
+ is_cliconf,
+ is_netconf,
+ load_config,
+)
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.utils.utils import Version
+
+
+try:
+ from base64 import b64decode
+
+ HAS_B64 = True
+except ImportError:
+ HAS_B64 = False
+
+
+class PublicKeyManager(object):
+ def __init__(self, module, result):
+ self._module = module
+ self._result = result
+
+ def convert_key_to_base64(self):
+ """IOS-XR only accepts base64 decoded files, this converts the public key to a temp file."""
+ if self._module.params["aggregate"]:
+ name = "aggregate"
+ else:
+ name = self._module.params["name"]
+
+ if self._module.params["public_key_contents"]:
+ key = self._module.params["public_key_contents"]
+ elif self._module.params["public_key"]:
+ readfile = open(self._module.params["public_key"], "r")
+ key = readfile.read()
+ splitfile = key.split()[1]
+
+ base64key = b64decode(splitfile)
+ base64file = open("/tmp/publickey_%s.b64" % (name), "wb")
+ base64file.write(base64key)
+ base64file.close()
+
+ return "/tmp/publickey_%s.b64" % (name)
+
+ def copy_key_to_node(self, base64keyfile):
+ """Copy key to IOS-XR node. We use SFTP because older IOS-XR versions don't handle SCP very well."""
+
+ if self._module.params["aggregate"]:
+ name = "aggregate"
+ else:
+ name = self._module.params["name"]
+
+ src = base64keyfile
+ dst = "/harddisk:/publickey_%s.b64" % (name)
+
+ copy_file(self._module, src, dst)
+
+ def addremovekey(self, command):
+ """Add or remove key based on command"""
+ admin = self._module.params.get("admin")
+
+ conn = get_connection(self._module)
+ if admin:
+ conn.send_command("admin")
+ out = conn.send_command(command, prompt="yes/no", answer="yes")
+ if admin:
+ conn.send_command("exit")
+
+ return out
+
+ def run(self):
+
+ if self._module.params["state"] == "present":
+ if not self._module.check_mode:
+ key = self.convert_key_to_base64()
+ self.copy_key_to_node(key)
+
+ if self._module.params["aggregate"]:
+ for user in self._module.params["aggregate"]:
+ cmdtodo = (
+ "crypto key import authentication rsa username %s harddisk:/publickey_aggregate.b64"
+ % (user)
+ )
+ self.addremovekey(cmdtodo)
+ else:
+ cmdtodo = (
+ "crypto key import authentication rsa username %s harddisk:/publickey_%s.b64"
+ % (self._module.params["name"], self._module.params["name"])
+ )
+ self.addremovekey(cmdtodo)
+ elif self._module.params["state"] == "absent":
+ if not self._module.check_mode:
+ if self._module.params["aggregate"]:
+ for user in self._module.params["aggregate"]:
+ cmdtodo = "crypto key zeroize authentication rsa username %s" % (user)
+ self.addremovekey(cmdtodo)
+ else:
+ cmdtodo = "crypto key zeroize authentication rsa username %s" % (
+ self._module.params["name"]
+ )
+ self.addremovekey(cmdtodo)
+ elif self._module.params["purge"] is True:
+ if not self._module.check_mode:
+ cmdtodo = "crypto key zeroize authentication rsa all"
+ self.addremovekey(cmdtodo)
+
+ return self._result
+
+
+def search_obj_in_list(name, lst):
+ for o in lst:
+ if o["name"] == name:
+ return o
+
+ return None
+
+
+class ConfigBase(object):
+ def __init__(self, module, result, flag=None):
+ self._module = module
+ self._result = result
+ self._want = list()
+ self._have = list()
+
+ def get_param_value(self, key, item):
+ # if key doesn't exist in the item, get it from module.params
+ if not item.get(key):
+ value = self._module.params[key]
+
+ # if key does exist, do a type check on it to validate it
+ else:
+ value_type = self._module.argument_spec[key].get("type", "str")
+ type_checker = self._module._CHECK_ARGUMENT_TYPES_DISPATCHER[value_type]
+ type_checker(item[key])
+ value = item[key]
+
+ # validate the param value (if validator func exists)
+ validator = globals().get("validate_%s" % key)
+ if all((value, validator)):
+ validator(value, self._module)
+
+ return value
+
+ def map_params_to_obj(self):
+ users = self._module.params["aggregate"]
+
+ aggregate = list()
+ if not users:
+ if not self._module.params["name"] and self._module.params["purge"]:
+ pass
+ elif not self._module.params["name"]:
+ self._module.fail_json(msg="username is required")
+ else:
+ aggregate = [{"name": self._module.params["name"]}]
+ else:
+ for item in users:
+ if not isinstance(item, dict):
+ aggregate.append({"name": item})
+ elif "name" not in item:
+ self._module.fail_json(msg="name is required")
+ else:
+ aggregate.append(item)
+
+ for item in aggregate:
+ get_value = partial(self.get_param_value, item=item)
+ item["configured_password"] = get_value("configured_password")
+ item["group"] = get_value("group")
+ item["groups"] = get_value("groups")
+ item["state"] = get_value("state")
+ self._want.append(item)
+
+
+class CliConfiguration(ConfigBase):
+ def __init__(self, module, result):
+ super(CliConfiguration, self).__init__(module, result)
+
+ def map_config_to_obj(self):
+ data = get_config(self._module, config_filter="username")
+
+ if "No such configuration item" in data:
+ return
+
+ users = data.strip().rstrip("!").split("!")
+
+ for user in users:
+ user_config = user.strip().splitlines()
+
+ name = user_config[0].strip().split()[1]
+ group = None
+
+ if len(user_config) > 1:
+ group_or_secret = user_config[1].strip().split()
+ if group_or_secret[0] == "group":
+ group = group_or_secret[1]
+
+ obj = {"name": name, "state": "present", "configured_password": None, "group": group}
+ self._have.append(obj)
+
+ def map_obj_to_commands(self):
+ commands = list()
+
+ for w in self._want:
+ name = w["name"]
+ state = w["state"]
+
+ obj_in_have = search_obj_in_list(name, self._have)
+
+ if state == "absent" and obj_in_have:
+ commands.append("no username " + name)
+ elif state == "present" and not obj_in_have:
+ user_cmd = "username " + name
+ commands.append(user_cmd)
+
+ if w["configured_password"]:
+ commands.append(user_cmd + " secret " + w["configured_password"])
+ if w["group"]:
+ commands.append(user_cmd + " group " + w["group"])
+ elif w["groups"]:
+ for group in w["groups"]:
+ commands.append(user_cmd + " group " + group)
+
+ elif state == "present" and obj_in_have:
+ user_cmd = "username " + name
+
+ if self._module.params["update_password"] == "always" and w["configured_password"]:
+ commands.append(user_cmd + " secret " + w["configured_password"])
+ if w["group"] and w["group"] != obj_in_have["group"]:
+ commands.append(user_cmd + " group " + w["group"])
+ elif w["groups"]:
+ for group in w["groups"]:
+ commands.append(user_cmd + " group " + group)
+
+ if self._module.params["purge"]:
+ want_users = [x["name"] for x in self._want]
+ have_users = [x["name"] for x in self._have]
+ for item in set(have_users).difference(set(want_users)):
+ if item != "admin":
+ commands.append("no username %s" % item)
+
+ if "no username admin" in commands:
+ self._module.fail_json(msg="cannot delete the `admin` account")
+
+ self._result["commands"] = []
+ if commands:
+ commit = not self._module.check_mode
+ admin = self._module.params["admin"]
+ diff = load_config(self._module, commands, commit=commit, admin=admin)
+ if diff:
+ self._result["diff"] = dict(prepared=diff)
+
+ self._result["commands"] = commands
+ self._result["changed"] = True
+
+ def run(self):
+ self.map_params_to_obj()
+ self.map_config_to_obj()
+ self.map_obj_to_commands()
+
+ return self._result
+
+
+class NCConfiguration(ConfigBase):
+ def __init__(self, module, result):
+ super(NCConfiguration, self).__init__(module, result)
+ self._locald_meta = collections.OrderedDict()
+ self._locald_group_meta = collections.OrderedDict()
+
+ def generate_md5_hash(self, arg):
+ """
+ Generate MD5 hash with randomly generated salt size of 3.
+ :param arg:
+ :return passwd:
+ """
+ cmd = "openssl passwd -salt `openssl rand -base64 3` -1 "
+ return os.popen(cmd + arg).readlines()[0].strip()
+
+ def map_obj_to_xml_rpc(self, os_version):
+ if os_version and Version(os_version) > Version("7.0"):
+ self._locald_meta.update(
+ [
+ ("aaa_locald", {"xpath": "aaa/usernames", "tag": True, "ns": True}),
+ (
+ "username",
+ {"xpath": "aaa/usernames/username", "tag": True, "attrib": "operation"},
+ ),
+ ("a:name", {"xpath": "aaa/usernames/username/name"}),
+ ("a:ordering_index", {"xpath": "aaa/usernames/username/ordering-index"}),
+ (
+ "secret",
+ {
+ "xpath": "aaa/usernames/username/secret",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ ("a:type", {"xpath": "aaa/usernames/username/secret/type", "value": "type5"}),
+ (
+ "a:configured_password",
+ {"xpath": "aaa/usernames/username/secret/secret5", "operation": "edit"},
+ ),
+ ],
+ )
+ self._locald_group_meta.update(
+ [
+ ("aaa_locald", {"xpath": "aaa/usernames", "tag": True, "ns": True}),
+ (
+ "username",
+ {"xpath": "aaa/usernames/username", "tag": True, "attrib": "operation"},
+ ),
+ ("a:name", {"xpath": "aaa/usernames/username/name"}),
+ ("a:ordering_index", {"xpath": "aaa/usernames/username/ordering-index"}),
+ (
+ "usergroups",
+ {
+ "xpath": "aaa/usernames/username/usergroup-under-usernames",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "usergroup",
+ {
+ "xpath": "aaa/usernames/username/usergroup-under-usernames/usergroup-under-username",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:group",
+ {
+ "xpath": "aaa/usernames/username/usergroup-under-usernames/usergroup-under-username/name",
+ "operation": "edit",
+ },
+ ),
+ ],
+ )
+ else:
+ self._locald_meta.update(
+ [
+ ("aaa_locald", {"xpath": "aaa/usernames", "tag": True, "ns": True}),
+ (
+ "username",
+ {"xpath": "aaa/usernames/username", "tag": True, "attrib": "operation"},
+ ),
+ ("a:name", {"xpath": "aaa/usernames/username/name"}),
+ (
+ "a:configured_password",
+ {"xpath": "aaa/usernames/username/secret", "operation": "edit"},
+ ),
+ ],
+ )
+ self._locald_group_meta.update(
+ [
+ ("aaa_locald", {"xpath": "aaa/usernames", "tag": True, "ns": True}),
+ (
+ "username",
+ {"xpath": "aaa/usernames/username", "tag": True, "attrib": "operation"},
+ ),
+ ("a:name", {"xpath": "aaa/usernames/username/name"}),
+ (
+ "usergroups",
+ {
+ "xpath": "aaa/usernames/username/usergroup-under-usernames",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "usergroup",
+ {
+ "xpath": "aaa/usernames/username/usergroup-under-usernames/usergroup-under-username",
+ "tag": True,
+ "operation": "edit",
+ },
+ ),
+ (
+ "a:group",
+ {
+ "xpath": "aaa/usernames/username/usergroup-under-usernames/usergroup-under-username/name",
+ "operation": "edit",
+ },
+ ),
+ ],
+ )
+
+ state = self._module.params["state"]
+ _get_filter = build_xml("aaa", opcode="filter")
+ running = get_config(self._module, source="running", config_filter=_get_filter)
+
+ elements = etree_findall(running, "username")
+ users = list()
+ for element in elements:
+ name_list = etree_findall(element, "name")
+ users.append(name_list[0].text)
+ list_size = len(name_list)
+ if list_size == 1:
+ self._have.append({"name": name_list[0].text, "group": None, "groups": None})
+ elif list_size == 2:
+ self._have.append(
+ {"name": name_list[0].text, "group": name_list[1].text, "groups": None},
+ )
+ elif list_size > 2:
+ name_iter = iter(name_list)
+ next(name_iter)
+ tmp_list = list()
+ for name in name_iter:
+ tmp_list.append(name.text)
+
+ self._have.append({"name": name_list[0].text, "group": None, "groups": tmp_list})
+ if os_version and Version(os_version) > Version("7.0"):
+ ordering_index = etree_findall(element, "ordering-index")
+ if len(self._have) > 0:
+ self._have[-1].update(ordering_index=ordering_index[0].text)
+
+ locald_params = list()
+ locald_group_params = list()
+ opcode = None
+ ordering_index_list = [
+ int(user.get("ordering_index")) for user in self._have if user.get("ordering_index")
+ ]
+
+ if state == "absent":
+ opcode = "delete"
+ for want_item in self._want:
+ if want_item["name"] in users:
+ obj_in_have = search_obj_in_list(want_item["name"], self._have)
+ if os_version and Version(os_version) > Version("7.0"):
+ want_item["ordering_index"] = obj_in_have["ordering_index"]
+ want_item["configured_password"] = None
+ locald_params.append(want_item)
+ elif state == "present":
+ opcode = "merge"
+ for want_item in self._want:
+ obj_in_have = search_obj_in_list(want_item["name"], self._have)
+ if want_item["name"] not in users:
+ if os_version and Version(os_version) > Version("7.0"):
+ want_item["configured_password"] = self.generate_md5_hash(
+ want_item["configured_password"],
+ )
+ new_ordering_index = ordering_index_list[-1] + 1
+ want_item["ordering_index"] = str(new_ordering_index)
+ ordering_index_list.append(new_ordering_index)
+ want_item["type"] = "type5"
+ want_item["configured_password"] = self.generate_md5_hash(
+ want_item["configured_password"],
+ )
+ locald_params.append(want_item)
+ if want_item["group"] is not None:
+ locald_group_params.append(want_item)
+ if want_item["groups"] is not None:
+ for group in want_item["groups"]:
+ want_item["group"] = group
+ locald_group_params.append(want_item.copy())
+ else:
+ if os_version and Version(os_version) > Version("7.0"):
+ if obj_in_have:
+ # Add iosxr 7.0 > specific parameters
+ want_item["type"] = "type5"
+ want_item["ordering_index"] = obj_in_have["ordering_index"]
+ if (
+ self._module.params["update_password"] == "always"
+ and want_item["configured_password"] is not None
+ ):
+
+ want_item["configured_password"] = self.generate_md5_hash(
+ want_item["configured_password"],
+ )
+ locald_params.append(want_item)
+ else:
+ want_item["configured_password"] = None
+
+ if (
+ want_item["group"] is not None
+ and want_item["group"] != obj_in_have["group"]
+ ):
+ locald_group_params.append(want_item)
+ elif want_item["groups"] is not None:
+ for group in want_item["groups"]:
+ want_item["group"] = group
+ locald_group_params.append(want_item.copy())
+
+ purge_params = list()
+ if self._module.params["purge"]:
+ want_users = [x["name"] for x in self._want]
+ have_users = [x["name"] for x in self._have]
+ for item in set(have_users).difference(set(want_users)):
+ if item != "admin":
+ purge_params.append({"name": item})
+
+ self._result["xml"] = []
+ _edit_filter_list = list()
+ if opcode is not None:
+ if locald_params:
+ _edit_filter_list.append(
+ build_xml("aaa", xmap=self._locald_meta, params=locald_params, opcode=opcode),
+ )
+
+ if locald_group_params:
+ _edit_filter_list.append(
+ build_xml(
+ "aaa",
+ xmap=self._locald_group_meta,
+ params=locald_group_params,
+ opcode=opcode,
+ ),
+ )
+
+ if purge_params:
+ _edit_filter_list.append(
+ build_xml("aaa", xmap=self._locald_meta, params=purge_params, opcode="delete"),
+ )
+ diff = None
+ if _edit_filter_list:
+ commit = not self._module.check_mode
+ diff = load_config(
+ self._module,
+ _edit_filter_list,
+ commit=commit,
+ running=running,
+ nc_get_filter=_get_filter,
+ )
+
+ if diff:
+ if self._module._diff:
+ self._result["diff"] = dict(prepared=diff)
+
+ self._result["xml"] = _edit_filter_list
+ self._result["changed"] = True
+
+ def run(self):
+ os_version = get_capabilities(self._module).get("device_info").get("network_os_version")
+ self.map_params_to_obj()
+ self.map_obj_to_xml_rpc(os_version)
+
+ return self._result
+
+
+def main():
+ """main entry point for module execution"""
+ element_spec = dict(
+ name=dict(type="str"),
+ configured_password=dict(type="str", no_log=True),
+ update_password=dict(type="str", default="always", choices=["on_create", "always"]),
+ admin=dict(type="bool", default=False),
+ public_key=dict(type="str"),
+ public_key_contents=dict(type="str"),
+ group=dict(type="str", aliases=["role"]),
+ groups=dict(type="list", elements="str"),
+ state=dict(type="str", default="present", choices=["present", "absent"]),
+ )
+ aggregate_spec = deepcopy(element_spec)
+ aggregate_spec["name"] = dict(required=True)
+
+ # remove default in aggregate spec, to handle common arguments
+ remove_default_spec(aggregate_spec)
+
+ mutually_exclusive = [
+ ("name", "aggregate"),
+ ("public_key", "public_key_contents"),
+ ("group", "groups"),
+ ]
+
+ argument_spec = dict(
+ aggregate=dict(
+ type="list",
+ elements="dict",
+ options=aggregate_spec,
+ aliases=["users", "collection"],
+ ),
+ purge=dict(type="bool", default=False),
+ )
+
+ argument_spec.update(element_spec)
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ mutually_exclusive=mutually_exclusive,
+ supports_check_mode=True,
+ )
+
+ if module.params["public_key_contents"] or module.params["public_key"]:
+ if not HAS_B64:
+ module.fail_json(
+ msg="library base64 is required but does not appear to be "
+ "installed. It can be installed using `pip install base64`",
+ )
+
+ result = {"changed": False, "warnings": []}
+
+ config_object = None
+ if is_cliconf(module):
+ # Commenting the below cliconf deprecation support call for Ansible 2.9 as it'll be continued to be supported
+ config_object = CliConfiguration(module, result)
+ elif is_netconf(module):
+ config_object = NCConfiguration(module, result)
+
+ if config_object:
+ result = config_object.run()
+
+ if module.params["public_key_contents"] or module.params["public_key"]:
+ pubkey_object = PublicKeyManager(module, result)
+ result = pubkey_object.run()
+
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/cisco/iosxr/plugins/netconf/__init__.py b/ansible_collections/cisco/iosxr/plugins/netconf/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/netconf/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/netconf/iosxr.py b/ansible_collections/cisco/iosxr/plugins/netconf/iosxr.py
new file mode 100644
index 00000000..e0b1bac8
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/netconf/iosxr.py
@@ -0,0 +1,378 @@
+#
+# (c) 2017 Red Hat Inc.
+# (c) 2017 Kedar Kekan (kkekan@redhat.com)
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+author: Ansible Networking Team (@ansible-network)
+name: iosxr
+short_description: Use iosxr netconf plugin to run netconf commands on Cisco IOSXR
+ platform
+description:
+- This iosxr plugin provides low level abstraction apis for sending and receiving
+ netconf commands from Cisco iosxr network devices.
+version_added: 1.0.0
+options:
+ ncclient_device_handler:
+ type: str
+ default: iosxr
+ description:
+ - Specifies the ncclient device handler name for Cisco iosxr network os. To identify
+ the ncclient device handler name refer ncclient library documentation.
+"""
+
+import collections
+import json
+import re
+
+from ansible.errors import AnsibleConnectionFailure
+from ansible.module_utils._text import to_native, to_text
+from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.netconf import (
+ remove_namespaces,
+)
+from ansible_collections.ansible.netcommon.plugins.plugin_utils.netconf_base import (
+ NetconfBase,
+ ensure_ncclient,
+)
+
+from ansible_collections.cisco.iosxr.plugins.module_utils.network.iosxr.iosxr import (
+ build_xml,
+ etree_find,
+)
+
+
+try:
+ from ncclient import manager
+ from ncclient.operations import RPCError
+ from ncclient.transport.errors import SSHUnknownHostError
+ from ncclient.xml_ import to_xml
+
+ HAS_NCCLIENT = True
+except (
+ ImportError,
+ AttributeError,
+): # paramiko and gssapi are incompatible and raise AttributeError not ImportError
+ HAS_NCCLIENT = False
+
+
+class Netconf(NetconfBase):
+ def get_device_info(self):
+ device_info = {}
+ device_info["network_os"] = "iosxr"
+ install_meta = collections.OrderedDict()
+ install_meta.update(
+ [
+ ("prepare", {"xpath": "install/prepare", "tag": True}),
+ (
+ "prepared-boot-image",
+ {
+ "xpath": "install/prepare/prepared-boot-image",
+ "tag": True,
+ },
+ ),
+ ("version", {"xpath": "install/version", "tag": True}),
+ ("label", {"xpath": "install/version/label", "tag": True}),
+ (
+ "hardware-info",
+ {"xpath": "install/version/hardware-info", "tag": True},
+ ),
+ ("package", {"xpath": "install/version/package", "tag": True}),
+ ],
+ )
+ install_filter = build_xml(
+ "install",
+ install_meta,
+ opcode="filter",
+ namespace="install",
+ )
+ try:
+ reply = self.get(install_filter)
+ resp = remove_namespaces(
+ re.sub(r'<\?xml version="1.0" encoding="UTF-8"\?>', "", reply),
+ )
+ ele_package_name = etree_find(resp.strip(), "name")
+ if ele_package_name is not None:
+ device_info["network_os_package"] = ele_package_name.text
+ ele_label = etree_find(resp.strip(), "label")
+ if ele_label is not None:
+ device_info["network_os_version"] = ele_label.text
+
+ model_search_strs = [
+ r"^[Cc]isco (.+) \(\) processor",
+ r"^[Cc]isco (.+) \(revision",
+ r"^[Cc]isco (\S+ \S+).+bytes of .*memory",
+ ]
+ ele_hardware_info = etree_find(resp.strip(), "hardware-info")
+ if ele_hardware_info is not None:
+ for item in model_search_strs:
+ match = re.search(item, ele_hardware_info.text, re.M)
+ if match:
+ device_info["network_os_model"] = match.group(1)
+ break
+ except Exception as exc:
+ error_msg = to_text(exc, errors="surrogate_or_strict").strip()
+ if "bad-namespace" in error_msg:
+ device_info = self.get_device_info_old_version()
+ else:
+ self._connection.queue_message(
+ "vvvv",
+ "Fail to retrieve device info %s" % exc,
+ )
+ try:
+ hostname_filter = build_xml(
+ "host-names",
+ opcode="filter",
+ namespace="host-names",
+ )
+ reply = self.get(hostname_filter)
+ resp = remove_namespaces(
+ re.sub(r'<\?xml version="1.0" encoding="UTF-8"\?>', "", reply),
+ )
+ hostname_ele = etree_find(resp.strip(), "host-name")
+ device_info["network_os_hostname"] = (
+ hostname_ele.text if hostname_ele is not None else None
+ )
+ except Exception as exc:
+ self._connection.queue_message(
+ "vvvv",
+ "Fail to retrieve device info %s" % exc,
+ )
+ return device_info
+
+ def get_capabilities(self):
+ result = dict()
+ result["rpc"] = self.get_base_rpc()
+ result["network_api"] = "netconf"
+ result["device_info"] = self.get_device_info()
+ result["server_capabilities"] = list(self.m.server_capabilities)
+ result["client_capabilities"] = list(self.m.client_capabilities)
+ result["session_id"] = self.m.session_id
+ result["device_operations"] = self.get_device_operations(
+ result["server_capabilities"],
+ )
+ return json.dumps(result)
+
+ @staticmethod
+ @ensure_ncclient
+ def guess_network_os(obj):
+ """
+ Guess the remote network os name
+ :param obj: Netconf connection class object
+ :return: Network OS name
+ """
+ try:
+ m = manager.connect(
+ host=obj._play_context.remote_addr,
+ port=obj._play_context.port or 830,
+ username=obj._play_context.remote_user,
+ password=obj._play_context.password,
+ key_filename=obj.key_filename,
+ hostkey_verify=obj.get_option("host_key_checking"),
+ look_for_keys=obj.get_option("look_for_keys"),
+ allow_agent=obj._play_context.allow_agent,
+ timeout=obj.get_option("persistent_connect_timeout"),
+ # We need to pass in the path to the ssh_config file when guessing
+ # the network_os so that a jumphost is correctly used if defined
+ ssh_config=obj._ssh_config,
+ )
+ except SSHUnknownHostError as exc:
+ raise AnsibleConnectionFailure(to_native(exc))
+
+ guessed_os = None
+ for c in m.server_capabilities:
+ if re.search("IOS-XR", c):
+ guessed_os = "iosxr"
+ break
+
+ m.close_session()
+ return guessed_os
+
+ # TODO: change .xml to .data_xml, when ncclient supports data_xml on all platforms
+ def get(self, filter=None, remove_ns=False):
+ if isinstance(filter, list):
+ filter = tuple(filter)
+ try:
+ resp = self.m.get(filter=filter)
+ if remove_ns:
+ response = remove_namespaces(resp)
+ else:
+ response = resp.data_xml if hasattr(resp, "data_xml") else resp.xml
+ return response
+ except RPCError as exc:
+ raise Exception(to_xml(exc.xml))
+
+ def get_config(self, source=None, filter=None, remove_ns=False):
+ if isinstance(filter, list):
+ filter = tuple(filter)
+ try:
+ resp = self.m.get_config(source=source, filter=filter)
+ if remove_ns:
+ response = remove_namespaces(resp)
+ else:
+ response = resp.data_xml if hasattr(resp, "data_xml") else resp.xml
+ return response
+ except RPCError as exc:
+ raise Exception(to_xml(exc.xml))
+
+ def edit_config(
+ self,
+ config=None,
+ format="xml",
+ target="candidate",
+ default_operation=None,
+ test_option=None,
+ error_option=None,
+ remove_ns=False,
+ ):
+ if config is None:
+ raise ValueError("config value must be provided")
+ try:
+ resp = self.m.edit_config(
+ config,
+ format=format,
+ target=target,
+ default_operation=default_operation,
+ test_option=test_option,
+ error_option=error_option,
+ )
+ if remove_ns:
+ response = remove_namespaces(resp)
+ else:
+ response = resp.data_xml if hasattr(resp, "data_xml") else resp.xml
+ return response
+ except RPCError as exc:
+ raise Exception(to_xml(exc.xml))
+
+ def commit(
+ self,
+ confirmed=False,
+ timeout=None,
+ persist=None,
+ remove_ns=False,
+ ):
+ timeout = to_text(timeout, errors="surrogate_or_strict")
+ try:
+ resp = self.m.commit(
+ confirmed=confirmed,
+ timeout=timeout,
+ persist=persist,
+ )
+ if remove_ns:
+ response = remove_namespaces(resp)
+ else:
+ response = resp.data_xml if hasattr(resp, "data_xml") else resp.xml
+ return response
+ except RPCError as exc:
+ raise Exception(to_xml(exc.xml))
+
+ def validate(self, source="candidate", remove_ns=False):
+ try:
+ resp = self.m.validate(source=source)
+ if remove_ns:
+ response = remove_namespaces(resp)
+ else:
+ response = resp.data_xml if hasattr(resp, "data_xml") else resp.xml
+ return response
+ except RPCError as exc:
+ raise Exception(to_xml(exc.xml))
+
+ def discard_changes(self, remove_ns=False):
+ try:
+ resp = self.m.discard_changes()
+ if remove_ns:
+ response = remove_namespaces(resp)
+ else:
+ response = resp.data_xml if hasattr(resp, "data_xml") else resp.xml
+ return response
+ except RPCError as exc:
+ raise Exception(to_xml(exc.xml))
+
+ def get_device_info_old_version(self):
+ device_info = {}
+ device_info["network_os"] = "iosxr"
+ install_meta = collections.OrderedDict()
+ install_meta.update(
+ [
+ (
+ "boot-variables",
+ {"xpath": "install/boot-variables", "tag": True},
+ ),
+ (
+ "boot-variable",
+ {
+ "xpath": "install/boot-variables/boot-variable",
+ "tag": True,
+ "lead": True,
+ },
+ ),
+ ("software", {"xpath": "install/software", "tag": True}),
+ (
+ "alias-devices",
+ {"xpath": "install/software/alias-devices", "tag": True},
+ ),
+ (
+ "alias-device",
+ {
+ "xpath": "install/software/alias-devices/alias-device",
+ "tag": True,
+ },
+ ),
+ (
+ "m:device-name",
+ {
+ "xpath": "install/software/alias-devices/alias-device/device-name",
+ "value": "disk0:",
+ },
+ ),
+ ],
+ )
+
+ install_filter = build_xml(
+ "install",
+ install_meta,
+ opcode="filter",
+ namespace="install_old",
+ )
+ try:
+ reply = self.get(install_filter)
+ resp = remove_namespaces(
+ re.sub(r'<\?xml version="1.0" encoding="UTF-8"\?>', "", reply),
+ )
+ ele_boot_variable = etree_find(resp, "boot-variable/boot-variable")
+ if ele_boot_variable is not None:
+ device_info["network_os_image"] = re.split(
+ "[:|,]",
+ ele_boot_variable.text,
+ )[1]
+ ele_package_name = etree_find(reply, "package-name")
+ if ele_package_name is not None:
+ device_info["network_os_package"] = ele_package_name.text
+ device_info["network_os_version"] = re.split(
+ "-",
+ ele_package_name.text,
+ )[-1]
+ except Exception as exc:
+ self._connection.queue_message(
+ "vvvv",
+ "Fail to retrieve device info %s" % exc,
+ )
+ return device_info
diff --git a/ansible_collections/cisco/iosxr/plugins/sub_plugins/grpc/__init__.py b/ansible_collections/cisco/iosxr/plugins/sub_plugins/grpc/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/sub_plugins/grpc/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/sub_plugins/grpc/iosxr.py b/ansible_collections/cisco/iosxr/plugins/sub_plugins/grpc/iosxr.py
new file mode 100644
index 00000000..0bcfd0e7
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/sub_plugins/grpc/iosxr.py
@@ -0,0 +1,200 @@
+# (c) 2019 Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+---
+author: Ansible Networking Team
+grpc : iosxr
+short_description: gRPC Plugin for IOS XR devices
+description:
+ - This gRPC plugin provides methods to connect and talk to Cisco IOS XR
+ devices over gRPC protocol.
+version_added: ""
+"""
+import json
+import os
+import sys
+
+from ansible_collections.ansible.netcommon.plugins.sub_plugins.grpc.base import (
+ GrpcBase,
+ ensure_connect,
+)
+
+
+class Grpc(GrpcBase):
+ def __init__(self, connection):
+ super(Grpc, self).__init__(connection)
+ module_name = "ems_grpc_pb2"
+ module_path = os.path.join(
+ os.path.dirname(os.path.realpath(__file__)),
+ "pb/ems_grpc_pb2.py",
+ )
+ if sys.version_info[0] == 3 and sys.version_info[1] >= 5:
+ import importlib.util
+
+ spec = importlib.util.spec_from_file_location(module_name, module_path)
+ self._ems_grpc_pb2 = importlib.util.module_from_spec(spec)
+ spec.loader.exec_module(self._ems_grpc_pb2)
+ elif sys.version_info[0] == 3 and sys.version_info[1] < 5:
+ import importlib.machinery
+
+ loader = importlib.machinery.SourceFileLoader(module_name, module_path)
+ self._ems_grpc_pb2 = loader.load_module()
+ elif sys.version_info[0] == 2:
+ import imp
+
+ self._ems_grpc_pb2 = imp.load_source(module_name, module_path)
+
+ def get_config(self, section=None):
+ stub = self._ems_grpc_pb2.beta_create_gRPCConfigOper_stub(
+ self._connection._channel,
+ )
+ message = self._ems_grpc_pb2.ConfigGetArgs(yangpathjson=section)
+ responses = stub.GetConfig(
+ message,
+ self._connection._timeout,
+ metadata=self._connection._login_credentials,
+ )
+ output = {"response": "", "error": ""}
+ for response in responses:
+ output["response"] += response.yangjson
+ output["error"] += response.errors
+ return output
+
+ def get(self, section=None):
+ stub = self._ems_grpc_pb2.beta_create_gRPCConfigOper_stub(
+ self._connection._channel,
+ )
+ message = self._ems_grpc_pb2.GetOperArgs(yangpathjson=section)
+ responses = stub.GetOper(
+ message,
+ self._connection._timeout,
+ metadata=self._connection._login_credentials,
+ )
+ output = {"response": "", "error": ""}
+ for response in responses:
+ output["response"] += response.yangjson
+ output["error"] += response.errors
+ return output
+
+ @ensure_connect
+ def merge_config(self, path):
+ """Merge grpc call equivalent of PATCH RESTconf call
+ :param data: JSON
+ :type data: str
+ :return: Return the response object
+ :rtype: Response object
+ """
+ path = json.dumps(path)
+ stub = self._ems_grpc_pb2.beta_create_gRPCConfigOper_stub(
+ self._connection._channel,
+ )
+ message = self._ems_grpc_pb2.ConfigArgs(yangjson=path)
+ response = stub.MergeConfig(
+ message,
+ self._connection._timeout,
+ metadata=self._connection._login_credentials,
+ )
+ if response:
+ return response.errors
+ else:
+ return None
+
+ @ensure_connect
+ def replace_config(self, path):
+ """Replace grpc call equivalent of PATCH RESTconf call
+ :param data: JSON
+ :type data: str
+ :return: Return the response object
+ :rtype: Response object
+ """
+ path = json.dumps(path)
+ stub = self._ems_grpc_pb2.beta_create_gRPCConfigOper_stub(
+ self._connection._channel,
+ )
+ message = self._ems_grpc_pb2.ConfigArgs(yangjson=path)
+ response = stub.ReplaceConfig(
+ message,
+ self._connection._timeout,
+ metadata=self._connection._login_credentials,
+ )
+ if response:
+ return response.errors
+ else:
+ return None
+
+ @ensure_connect
+ def delete_config(self, path):
+ """Delete grpc call equivalent of PATCH RESTconf call
+ :param data: JSON
+ :type data: str
+ :return: Return the response object
+ :rtype: Response object
+ """
+ path = json.dumps(path)
+ stub = self._ems_grpc_pb2.beta_create_gRPCConfigOper_stub(
+ self._connection._channel,
+ )
+ message = self._ems_grpc_pb2.ConfigArgs(yangjson=path)
+ response = stub.DeleteConfig(
+ message,
+ self._connection._timeout,
+ metadata=self._connection._login_credentials,
+ )
+ if response:
+ return response.errors
+ else:
+ return None
+
+ @ensure_connect
+ def run_cli(self, command=None, display=None):
+ if command is None:
+ raise ValueError("command value must be provided")
+
+ output = {"response": "", "error": ""}
+ stub = self._ems_grpc_pb2.beta_create_gRPCExec_stub(
+ self._connection._channel,
+ )
+
+ message = self._ems_grpc_pb2.ShowCmdArgs(cli=command)
+ if display == "text":
+ responses = stub.ShowCmdTextOutput(
+ message,
+ self._connection._timeout,
+ metadata=self._connection._login_credentials,
+ )
+ for response in responses:
+ output["response"] += response.output
+ output["error"] += response.errors
+ else:
+ responses = stub.ShowCmdJSONOutput(
+ message,
+ self._connection._timeout,
+ metadata=self._connection._login_credentials,
+ )
+ for response in responses:
+ output["response"] += response.jsonoutput
+ output["error"] += response.errors
+ return output
+
+ @property
+ def server_capabilities(self):
+ capability = dict()
+ capability["display"] = ["json", "text"]
+ capability["data_type"] = ["config", "oper"]
+ capability["supports_commit"] = True
+ capability["supports_cli_command"] = True
+ return capability
+
+ @ensure_connect
+ def get_capabilities(self):
+ result = dict()
+ result["rpc"] = self.__rpc__ + ["commit", "discard_changes"]
+ result["network_api"] = "ansible.netcommon.grpc"
+ result["server_capabilities"] = self.server_capabilities
+ return result
diff --git a/ansible_collections/cisco/iosxr/plugins/sub_plugins/grpc/pb/__init__.py b/ansible_collections/cisco/iosxr/plugins/sub_plugins/grpc/pb/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/sub_plugins/grpc/pb/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py b/ansible_collections/cisco/iosxr/plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py
new file mode 100644
index 00000000..e16c305b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/sub_plugins/grpc/pb/ems_grpc_pb2.py
@@ -0,0 +1,2350 @@
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: ems_grpc.proto
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+import sys
+
+
+_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode("latin1"))
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pb2 # noqa: F401
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import enum_type_wrapper
+
+
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+ name="ems_grpc.proto",
+ package="IOSXRExtensibleManagabilityService",
+ syntax="proto3",
+ serialized_pb=_b(
+ '\n\x0e\x65ms_grpc.proto\x12"IOSXRExtensibleManagabilityService"4\n\rConfigGetArgs\x12\r\n\x05ReqId\x18\x01 \x01(\x03\x12\x14\n\x0cyangpathjson\x18\x02 \x01(\t"D\n\x0e\x43onfigGetReply\x12\x10\n\x08ResReqId\x18\x01 \x01(\x03\x12\x10\n\x08yangjson\x18\x02 \x01(\t\x12\x0e\n\x06\x65rrors\x18\x03 \x01(\t"2\n\x0bGetOperArgs\x12\r\n\x05ReqId\x18\x01 \x01(\x03\x12\x14\n\x0cyangpathjson\x18\x02 \x01(\t"B\n\x0cGetOperReply\x12\x10\n\x08ResReqId\x18\x01 \x01(\x03\x12\x10\n\x08yangjson\x18\x02 \x01(\t\x12\x0e\n\x06\x65rrors\x18\x03 \x01(\t"-\n\nConfigArgs\x12\r\n\x05ReqId\x18\x01 \x01(\x03\x12\x10\n\x08yangjson\x18\x02 \x01(\t"/\n\x0b\x43onfigReply\x12\x10\n\x08ResReqId\x18\x01 \x01(\x03\x12\x0e\n\x06\x65rrors\x18\x02 \x01(\t"+\n\rCliConfigArgs\x12\r\n\x05ReqId\x18\x01 \x01(\x03\x12\x0b\n\x03\x63li\x18\x02 \x01(\t"2\n\x0e\x43liConfigReply\x12\x10\n\x08ResReqId\x18\x01 \x01(\x03\x12\x0e\n\x06\x65rrors\x18\x02 \x01(\t"A\n\x11\x43ommitReplaceArgs\x12\r\n\x05ReqId\x18\x01 \x01(\x03\x12\x0b\n\x03\x63li\x18\x02 \x01(\t\x12\x10\n\x08yangjson\x18\x03 \x01(\t"6\n\x12\x43ommitReplaceReply\x12\x10\n\x08ResReqId\x18\x01 \x01(\x03\x12\x0e\n\x06\x65rrors\x18\x02 \x01(\t"+\n\tCommitMsg\x12\r\n\x05label\x18\x01 \x01(\t\x12\x0f\n\x07\x63omment\x18\x02 \x01(\t"W\n\nCommitArgs\x12:\n\x03msg\x18\x01 \x01(\x0b\x32-.IOSXRExtensibleManagabilityService.CommitMsg\x12\r\n\x05ReqId\x18\x02 \x01(\x03"q\n\x0b\x43ommitReply\x12@\n\x06result\x18\x01 \x01(\x0e\x32\x30.IOSXRExtensibleManagabilityService.CommitResult\x12\x10\n\x08ResReqId\x18\x02 \x01(\x03\x12\x0e\n\x06\x65rrors\x18\x03 \x01(\t"#\n\x12\x44iscardChangesArgs\x12\r\n\x05ReqId\x18\x01 \x01(\x03"7\n\x13\x44iscardChangesReply\x12\x10\n\x08ResReqId\x18\x01 \x01(\x03\x12\x0e\n\x06\x65rrors\x18\x02 \x01(\t")\n\x0bShowCmdArgs\x12\r\n\x05ReqId\x18\x01 \x01(\x03\x12\x0b\n\x03\x63li\x18\x02 \x01(\t"D\n\x10ShowCmdTextReply\x12\x10\n\x08ResReqId\x18\x01 \x01(\x03\x12\x0e\n\x06output\x18\x02 \x01(\t\x12\x0e\n\x06\x65rrors\x18\x03 \x01(\t"H\n\x10ShowCmdJSONReply\x12\x10\n\x08ResReqId\x18\x01 \x01(\x03\x12\x12\n\njsonoutput\x18\x02 \x01(\t\x12\x0e\n\x06\x65rrors\x18\x03 \x01(\t"A\n\x0e\x43reateSubsArgs\x12\r\n\x05ReqId\x18\x01 \x01(\x03\x12\x0e\n\x06\x65ncode\x18\x02 \x01(\x03\x12\x10\n\x08subidstr\x18\x03 \x01(\t"A\n\x0f\x43reateSubsReply\x12\x10\n\x08ResReqId\x18\x01 \x01(\x03\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12\x0e\n\x06\x65rrors\x18\x03 \x01(\t*3\n\x0c\x43ommitResult\x12\n\n\x06\x43HANGE\x10\x00\x12\r\n\tNO_CHANGE\x10\x01\x12\x08\n\x04\x46\x41IL\x10\x02\x32\xc6\t\n\x0egRPCConfigOper\x12v\n\tGetConfig\x12\x31.IOSXRExtensibleManagabilityService.ConfigGetArgs\x1a\x32.IOSXRExtensibleManagabilityService.ConfigGetReply"\x00\x30\x01\x12p\n\x0bMergeConfig\x12..IOSXRExtensibleManagabilityService.ConfigArgs\x1a/.IOSXRExtensibleManagabilityService.ConfigReply"\x00\x12q\n\x0c\x44\x65leteConfig\x12..IOSXRExtensibleManagabilityService.ConfigArgs\x1a/.IOSXRExtensibleManagabilityService.ConfigReply"\x00\x12r\n\rReplaceConfig\x12..IOSXRExtensibleManagabilityService.ConfigArgs\x1a/.IOSXRExtensibleManagabilityService.ConfigReply"\x00\x12t\n\tCliConfig\x12\x31.IOSXRExtensibleManagabilityService.CliConfigArgs\x1a\x32.IOSXRExtensibleManagabilityService.CliConfigReply"\x00\x12\x80\x01\n\rCommitReplace\x12\x35.IOSXRExtensibleManagabilityService.CommitReplaceArgs\x1a\x36.IOSXRExtensibleManagabilityService.CommitReplaceReply"\x00\x12q\n\x0c\x43ommitConfig\x12..IOSXRExtensibleManagabilityService.CommitArgs\x1a/.IOSXRExtensibleManagabilityService.CommitReply"\x00\x12\x89\x01\n\x14\x43onfigDiscardChanges\x12\x36.IOSXRExtensibleManagabilityService.DiscardChangesArgs\x1a\x37.IOSXRExtensibleManagabilityService.DiscardChangesReply"\x00\x12p\n\x07GetOper\x12/.IOSXRExtensibleManagabilityService.GetOperArgs\x1a\x30.IOSXRExtensibleManagabilityService.GetOperReply"\x00\x30\x01\x12y\n\nCreateSubs\x12\x32.IOSXRExtensibleManagabilityService.CreateSubsArgs\x1a\x33.IOSXRExtensibleManagabilityService.CreateSubsReply"\x00\x30\x01\x32\x8a\x02\n\x08gRPCExec\x12~\n\x11ShowCmdTextOutput\x12/.IOSXRExtensibleManagabilityService.ShowCmdArgs\x1a\x34.IOSXRExtensibleManagabilityService.ShowCmdTextReply"\x00\x30\x01\x12~\n\x11ShowCmdJSONOutput\x12/.IOSXRExtensibleManagabilityService.ShowCmdArgs\x1a\x34.IOSXRExtensibleManagabilityService.ShowCmdJSONReply"\x00\x30\x01\x62\x06proto3', # noqa: E501
+ ),
+)
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+_COMMITRESULT = _descriptor.EnumDescriptor(
+ name="CommitResult",
+ full_name="IOSXRExtensibleManagabilityService.CommitResult",
+ filename=None,
+ file=DESCRIPTOR,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name="CHANGE",
+ index=0,
+ number=0,
+ options=None,
+ type=None,
+ ),
+ _descriptor.EnumValueDescriptor(
+ name="NO_CHANGE",
+ index=1,
+ number=1,
+ options=None,
+ type=None,
+ ),
+ _descriptor.EnumValueDescriptor(
+ name="FAIL",
+ index=2,
+ number=2,
+ options=None,
+ type=None,
+ ),
+ ],
+ containing_type=None,
+ options=None,
+ serialized_start=1278,
+ serialized_end=1329,
+)
+_sym_db.RegisterEnumDescriptor(_COMMITRESULT)
+
+CommitResult = enum_type_wrapper.EnumTypeWrapper(_COMMITRESULT)
+CHANGE = 0
+NO_CHANGE = 1
+FAIL = 2
+
+
+_CONFIGGETARGS = _descriptor.Descriptor(
+ name="ConfigGetArgs",
+ full_name="IOSXRExtensibleManagabilityService.ConfigGetArgs",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ReqId",
+ full_name="IOSXRExtensibleManagabilityService.ConfigGetArgs.ReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="yangpathjson",
+ full_name="IOSXRExtensibleManagabilityService.ConfigGetArgs.yangpathjson",
+ index=1,
+ number=2,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=54,
+ serialized_end=106,
+)
+
+
+_CONFIGGETREPLY = _descriptor.Descriptor(
+ name="ConfigGetReply",
+ full_name="IOSXRExtensibleManagabilityService.ConfigGetReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ResReqId",
+ full_name="IOSXRExtensibleManagabilityService.ConfigGetReply.ResReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="yangjson",
+ full_name="IOSXRExtensibleManagabilityService.ConfigGetReply.yangjson",
+ index=1,
+ number=2,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="errors",
+ full_name="IOSXRExtensibleManagabilityService.ConfigGetReply.errors",
+ index=2,
+ number=3,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=108,
+ serialized_end=176,
+)
+
+
+_GETOPERARGS = _descriptor.Descriptor(
+ name="GetOperArgs",
+ full_name="IOSXRExtensibleManagabilityService.GetOperArgs",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ReqId",
+ full_name="IOSXRExtensibleManagabilityService.GetOperArgs.ReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="yangpathjson",
+ full_name="IOSXRExtensibleManagabilityService.GetOperArgs.yangpathjson",
+ index=1,
+ number=2,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=178,
+ serialized_end=228,
+)
+
+
+_GETOPERREPLY = _descriptor.Descriptor(
+ name="GetOperReply",
+ full_name="IOSXRExtensibleManagabilityService.GetOperReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ResReqId",
+ full_name="IOSXRExtensibleManagabilityService.GetOperReply.ResReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="yangjson",
+ full_name="IOSXRExtensibleManagabilityService.GetOperReply.yangjson",
+ index=1,
+ number=2,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="errors",
+ full_name="IOSXRExtensibleManagabilityService.GetOperReply.errors",
+ index=2,
+ number=3,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=230,
+ serialized_end=296,
+)
+
+
+_CONFIGARGS = _descriptor.Descriptor(
+ name="ConfigArgs",
+ full_name="IOSXRExtensibleManagabilityService.ConfigArgs",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ReqId",
+ full_name="IOSXRExtensibleManagabilityService.ConfigArgs.ReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="yangjson",
+ full_name="IOSXRExtensibleManagabilityService.ConfigArgs.yangjson",
+ index=1,
+ number=2,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=298,
+ serialized_end=343,
+)
+
+
+_CONFIGREPLY = _descriptor.Descriptor(
+ name="ConfigReply",
+ full_name="IOSXRExtensibleManagabilityService.ConfigReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ResReqId",
+ full_name="IOSXRExtensibleManagabilityService.ConfigReply.ResReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="errors",
+ full_name="IOSXRExtensibleManagabilityService.ConfigReply.errors",
+ index=1,
+ number=2,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=345,
+ serialized_end=392,
+)
+
+
+_CLICONFIGARGS = _descriptor.Descriptor(
+ name="CliConfigArgs",
+ full_name="IOSXRExtensibleManagabilityService.CliConfigArgs",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ReqId",
+ full_name="IOSXRExtensibleManagabilityService.CliConfigArgs.ReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="cli",
+ full_name="IOSXRExtensibleManagabilityService.CliConfigArgs.cli",
+ index=1,
+ number=2,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=394,
+ serialized_end=437,
+)
+
+
+_CLICONFIGREPLY = _descriptor.Descriptor(
+ name="CliConfigReply",
+ full_name="IOSXRExtensibleManagabilityService.CliConfigReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ResReqId",
+ full_name="IOSXRExtensibleManagabilityService.CliConfigReply.ResReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="errors",
+ full_name="IOSXRExtensibleManagabilityService.CliConfigReply.errors",
+ index=1,
+ number=2,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=439,
+ serialized_end=489,
+)
+
+
+_COMMITREPLACEARGS = _descriptor.Descriptor(
+ name="CommitReplaceArgs",
+ full_name="IOSXRExtensibleManagabilityService.CommitReplaceArgs",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ReqId",
+ full_name="IOSXRExtensibleManagabilityService.CommitReplaceArgs.ReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="cli",
+ full_name="IOSXRExtensibleManagabilityService.CommitReplaceArgs.cli",
+ index=1,
+ number=2,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="yangjson",
+ full_name="IOSXRExtensibleManagabilityService.CommitReplaceArgs.yangjson",
+ index=2,
+ number=3,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=491,
+ serialized_end=556,
+)
+
+
+_COMMITREPLACEREPLY = _descriptor.Descriptor(
+ name="CommitReplaceReply",
+ full_name="IOSXRExtensibleManagabilityService.CommitReplaceReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ResReqId",
+ full_name="IOSXRExtensibleManagabilityService.CommitReplaceReply.ResReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="errors",
+ full_name="IOSXRExtensibleManagabilityService.CommitReplaceReply.errors",
+ index=1,
+ number=2,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=558,
+ serialized_end=612,
+)
+
+
+_COMMITMSG = _descriptor.Descriptor(
+ name="CommitMsg",
+ full_name="IOSXRExtensibleManagabilityService.CommitMsg",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="label",
+ full_name="IOSXRExtensibleManagabilityService.CommitMsg.label",
+ index=0,
+ number=1,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="comment",
+ full_name="IOSXRExtensibleManagabilityService.CommitMsg.comment",
+ index=1,
+ number=2,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=614,
+ serialized_end=657,
+)
+
+
+_COMMITARGS = _descriptor.Descriptor(
+ name="CommitArgs",
+ full_name="IOSXRExtensibleManagabilityService.CommitArgs",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="msg",
+ full_name="IOSXRExtensibleManagabilityService.CommitArgs.msg",
+ index=0,
+ number=1,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="ReqId",
+ full_name="IOSXRExtensibleManagabilityService.CommitArgs.ReqId",
+ index=1,
+ number=2,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=659,
+ serialized_end=746,
+)
+
+
+_COMMITREPLY = _descriptor.Descriptor(
+ name="CommitReply",
+ full_name="IOSXRExtensibleManagabilityService.CommitReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="result",
+ full_name="IOSXRExtensibleManagabilityService.CommitReply.result",
+ index=0,
+ number=1,
+ type=14,
+ cpp_type=8,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="ResReqId",
+ full_name="IOSXRExtensibleManagabilityService.CommitReply.ResReqId",
+ index=1,
+ number=2,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="errors",
+ full_name="IOSXRExtensibleManagabilityService.CommitReply.errors",
+ index=2,
+ number=3,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=748,
+ serialized_end=861,
+)
+
+
+_DISCARDCHANGESARGS = _descriptor.Descriptor(
+ name="DiscardChangesArgs",
+ full_name="IOSXRExtensibleManagabilityService.DiscardChangesArgs",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ReqId",
+ full_name="IOSXRExtensibleManagabilityService.DiscardChangesArgs.ReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=863,
+ serialized_end=898,
+)
+
+
+_DISCARDCHANGESREPLY = _descriptor.Descriptor(
+ name="DiscardChangesReply",
+ full_name="IOSXRExtensibleManagabilityService.DiscardChangesReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ResReqId",
+ full_name="IOSXRExtensibleManagabilityService.DiscardChangesReply.ResReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="errors",
+ full_name="IOSXRExtensibleManagabilityService.DiscardChangesReply.errors",
+ index=1,
+ number=2,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=900,
+ serialized_end=955,
+)
+
+
+_SHOWCMDARGS = _descriptor.Descriptor(
+ name="ShowCmdArgs",
+ full_name="IOSXRExtensibleManagabilityService.ShowCmdArgs",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ReqId",
+ full_name="IOSXRExtensibleManagabilityService.ShowCmdArgs.ReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="cli",
+ full_name="IOSXRExtensibleManagabilityService.ShowCmdArgs.cli",
+ index=1,
+ number=2,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=957,
+ serialized_end=998,
+)
+
+
+_SHOWCMDTEXTREPLY = _descriptor.Descriptor(
+ name="ShowCmdTextReply",
+ full_name="IOSXRExtensibleManagabilityService.ShowCmdTextReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ResReqId",
+ full_name="IOSXRExtensibleManagabilityService.ShowCmdTextReply.ResReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="output",
+ full_name="IOSXRExtensibleManagabilityService.ShowCmdTextReply.output",
+ index=1,
+ number=2,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="errors",
+ full_name="IOSXRExtensibleManagabilityService.ShowCmdTextReply.errors",
+ index=2,
+ number=3,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=1000,
+ serialized_end=1068,
+)
+
+
+_SHOWCMDJSONREPLY = _descriptor.Descriptor(
+ name="ShowCmdJSONReply",
+ full_name="IOSXRExtensibleManagabilityService.ShowCmdJSONReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ResReqId",
+ full_name="IOSXRExtensibleManagabilityService.ShowCmdJSONReply.ResReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="jsonoutput",
+ full_name="IOSXRExtensibleManagabilityService.ShowCmdJSONReply.jsonoutput",
+ index=1,
+ number=2,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="errors",
+ full_name="IOSXRExtensibleManagabilityService.ShowCmdJSONReply.errors",
+ index=2,
+ number=3,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=1070,
+ serialized_end=1142,
+)
+
+
+_CREATESUBSARGS = _descriptor.Descriptor(
+ name="CreateSubsArgs",
+ full_name="IOSXRExtensibleManagabilityService.CreateSubsArgs",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ReqId",
+ full_name="IOSXRExtensibleManagabilityService.CreateSubsArgs.ReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="encode",
+ full_name="IOSXRExtensibleManagabilityService.CreateSubsArgs.encode",
+ index=1,
+ number=2,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="subidstr",
+ full_name="IOSXRExtensibleManagabilityService.CreateSubsArgs.subidstr",
+ index=2,
+ number=3,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=1144,
+ serialized_end=1209,
+)
+
+
+_CREATESUBSREPLY = _descriptor.Descriptor(
+ name="CreateSubsReply",
+ full_name="IOSXRExtensibleManagabilityService.CreateSubsReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="ResReqId",
+ full_name="IOSXRExtensibleManagabilityService.CreateSubsReply.ResReqId",
+ index=0,
+ number=1,
+ type=3,
+ cpp_type=2,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="data",
+ full_name="IOSXRExtensibleManagabilityService.CreateSubsReply.data",
+ index=1,
+ number=2,
+ type=12,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b(""),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ _descriptor.FieldDescriptor(
+ name="errors",
+ full_name="IOSXRExtensibleManagabilityService.CreateSubsReply.errors",
+ index=2,
+ number=3,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=_b("").decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ options=None,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ options=None,
+ is_extendable=False,
+ syntax="proto3",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=1211,
+ serialized_end=1276,
+)
+
+_COMMITARGS.fields_by_name["msg"].message_type = _COMMITMSG
+_COMMITREPLY.fields_by_name["result"].enum_type = _COMMITRESULT
+DESCRIPTOR.message_types_by_name["ConfigGetArgs"] = _CONFIGGETARGS
+DESCRIPTOR.message_types_by_name["ConfigGetReply"] = _CONFIGGETREPLY
+DESCRIPTOR.message_types_by_name["GetOperArgs"] = _GETOPERARGS
+DESCRIPTOR.message_types_by_name["GetOperReply"] = _GETOPERREPLY
+DESCRIPTOR.message_types_by_name["ConfigArgs"] = _CONFIGARGS
+DESCRIPTOR.message_types_by_name["ConfigReply"] = _CONFIGREPLY
+DESCRIPTOR.message_types_by_name["CliConfigArgs"] = _CLICONFIGARGS
+DESCRIPTOR.message_types_by_name["CliConfigReply"] = _CLICONFIGREPLY
+DESCRIPTOR.message_types_by_name["CommitReplaceArgs"] = _COMMITREPLACEARGS
+DESCRIPTOR.message_types_by_name["CommitReplaceReply"] = _COMMITREPLACEREPLY
+DESCRIPTOR.message_types_by_name["CommitMsg"] = _COMMITMSG
+DESCRIPTOR.message_types_by_name["CommitArgs"] = _COMMITARGS
+DESCRIPTOR.message_types_by_name["CommitReply"] = _COMMITREPLY
+DESCRIPTOR.message_types_by_name["DiscardChangesArgs"] = _DISCARDCHANGESARGS
+DESCRIPTOR.message_types_by_name["DiscardChangesReply"] = _DISCARDCHANGESREPLY
+DESCRIPTOR.message_types_by_name["ShowCmdArgs"] = _SHOWCMDARGS
+DESCRIPTOR.message_types_by_name["ShowCmdTextReply"] = _SHOWCMDTEXTREPLY
+DESCRIPTOR.message_types_by_name["ShowCmdJSONReply"] = _SHOWCMDJSONREPLY
+DESCRIPTOR.message_types_by_name["CreateSubsArgs"] = _CREATESUBSARGS
+DESCRIPTOR.message_types_by_name["CreateSubsReply"] = _CREATESUBSREPLY
+DESCRIPTOR.enum_types_by_name["CommitResult"] = _COMMITRESULT
+
+ConfigGetArgs = _reflection.GeneratedProtocolMessageType(
+ "ConfigGetArgs",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_CONFIGGETARGS,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.ConfigGetArgs)
+ ),
+)
+_sym_db.RegisterMessage(ConfigGetArgs)
+
+ConfigGetReply = _reflection.GeneratedProtocolMessageType(
+ "ConfigGetReply",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_CONFIGGETREPLY,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.ConfigGetReply)
+ ),
+)
+_sym_db.RegisterMessage(ConfigGetReply)
+
+GetOperArgs = _reflection.GeneratedProtocolMessageType(
+ "GetOperArgs",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_GETOPERARGS,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.GetOperArgs)
+ ),
+)
+_sym_db.RegisterMessage(GetOperArgs)
+
+GetOperReply = _reflection.GeneratedProtocolMessageType(
+ "GetOperReply",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_GETOPERREPLY,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.GetOperReply)
+ ),
+)
+_sym_db.RegisterMessage(GetOperReply)
+
+ConfigArgs = _reflection.GeneratedProtocolMessageType(
+ "ConfigArgs",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_CONFIGARGS,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.ConfigArgs)
+ ),
+)
+_sym_db.RegisterMessage(ConfigArgs)
+
+ConfigReply = _reflection.GeneratedProtocolMessageType(
+ "ConfigReply",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_CONFIGREPLY,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.ConfigReply)
+ ),
+)
+_sym_db.RegisterMessage(ConfigReply)
+
+CliConfigArgs = _reflection.GeneratedProtocolMessageType(
+ "CliConfigArgs",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_CLICONFIGARGS,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.CliConfigArgs)
+ ),
+)
+_sym_db.RegisterMessage(CliConfigArgs)
+
+CliConfigReply = _reflection.GeneratedProtocolMessageType(
+ "CliConfigReply",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_CLICONFIGREPLY,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.CliConfigReply)
+ ),
+)
+_sym_db.RegisterMessage(CliConfigReply)
+
+CommitReplaceArgs = _reflection.GeneratedProtocolMessageType(
+ "CommitReplaceArgs",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_COMMITREPLACEARGS,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.CommitReplaceArgs)
+ ),
+)
+_sym_db.RegisterMessage(CommitReplaceArgs)
+
+CommitReplaceReply = _reflection.GeneratedProtocolMessageType(
+ "CommitReplaceReply",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_COMMITREPLACEREPLY,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.CommitReplaceReply)
+ ),
+)
+_sym_db.RegisterMessage(CommitReplaceReply)
+
+CommitMsg = _reflection.GeneratedProtocolMessageType(
+ "CommitMsg",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_COMMITMSG,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.CommitMsg)
+ ),
+)
+_sym_db.RegisterMessage(CommitMsg)
+
+CommitArgs = _reflection.GeneratedProtocolMessageType(
+ "CommitArgs",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_COMMITARGS,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.CommitArgs)
+ ),
+)
+_sym_db.RegisterMessage(CommitArgs)
+
+CommitReply = _reflection.GeneratedProtocolMessageType(
+ "CommitReply",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_COMMITREPLY,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.CommitReply)
+ ),
+)
+_sym_db.RegisterMessage(CommitReply)
+
+DiscardChangesArgs = _reflection.GeneratedProtocolMessageType(
+ "DiscardChangesArgs",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_DISCARDCHANGESARGS,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.DiscardChangesArgs)
+ ),
+)
+_sym_db.RegisterMessage(DiscardChangesArgs)
+
+DiscardChangesReply = _reflection.GeneratedProtocolMessageType(
+ "DiscardChangesReply",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_DISCARDCHANGESREPLY,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.DiscardChangesReply)
+ ),
+)
+_sym_db.RegisterMessage(DiscardChangesReply)
+
+ShowCmdArgs = _reflection.GeneratedProtocolMessageType(
+ "ShowCmdArgs",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_SHOWCMDARGS,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.ShowCmdArgs)
+ ),
+)
+_sym_db.RegisterMessage(ShowCmdArgs)
+
+ShowCmdTextReply = _reflection.GeneratedProtocolMessageType(
+ "ShowCmdTextReply",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_SHOWCMDTEXTREPLY,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.ShowCmdTextReply)
+ ),
+)
+_sym_db.RegisterMessage(ShowCmdTextReply)
+
+ShowCmdJSONReply = _reflection.GeneratedProtocolMessageType(
+ "ShowCmdJSONReply",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_SHOWCMDJSONREPLY,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.ShowCmdJSONReply)
+ ),
+)
+_sym_db.RegisterMessage(ShowCmdJSONReply)
+
+CreateSubsArgs = _reflection.GeneratedProtocolMessageType(
+ "CreateSubsArgs",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_CREATESUBSARGS,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.CreateSubsArgs)
+ ),
+)
+_sym_db.RegisterMessage(CreateSubsArgs)
+
+CreateSubsReply = _reflection.GeneratedProtocolMessageType(
+ "CreateSubsReply",
+ (_message.Message,),
+ dict(
+ DESCRIPTOR=_CREATESUBSREPLY,
+ __module__="ems_grpc_pb2",
+ # @@protoc_insertion_point(class_scope:IOSXRExtensibleManagabilityService.CreateSubsReply)
+ ),
+)
+_sym_db.RegisterMessage(CreateSubsReply)
+
+
+import grpc
+
+from grpc.beta import implementations as beta_implementations
+from grpc.beta import interfaces as beta_interfaces
+from grpc.framework.common import cardinality
+from grpc.framework.interfaces.face import utilities as face_utilities
+
+
+class gRPCConfigOperStub(object):
+ def __init__(self, channel):
+ """Constructor.
+
+ Args:
+ channel: A grpc.Channel.
+ """
+ self.GetConfig = channel.unary_stream(
+ "/IOSXRExtensibleManagabilityService.gRPCConfigOper/GetConfig",
+ request_serializer=ConfigGetArgs.SerializeToString,
+ response_deserializer=ConfigGetReply.FromString,
+ )
+ self.MergeConfig = channel.unary_unary(
+ "/IOSXRExtensibleManagabilityService.gRPCConfigOper/MergeConfig",
+ request_serializer=ConfigArgs.SerializeToString,
+ response_deserializer=ConfigReply.FromString,
+ )
+ self.DeleteConfig = channel.unary_unary(
+ "/IOSXRExtensibleManagabilityService.gRPCConfigOper/DeleteConfig",
+ request_serializer=ConfigArgs.SerializeToString,
+ response_deserializer=ConfigReply.FromString,
+ )
+ self.ReplaceConfig = channel.unary_unary(
+ "/IOSXRExtensibleManagabilityService.gRPCConfigOper/ReplaceConfig",
+ request_serializer=ConfigArgs.SerializeToString,
+ response_deserializer=ConfigReply.FromString,
+ )
+ self.CliConfig = channel.unary_unary(
+ "/IOSXRExtensibleManagabilityService.gRPCConfigOper/CliConfig",
+ request_serializer=CliConfigArgs.SerializeToString,
+ response_deserializer=CliConfigReply.FromString,
+ )
+ self.CommitReplace = channel.unary_unary(
+ "/IOSXRExtensibleManagabilityService.gRPCConfigOper/CommitReplace",
+ request_serializer=CommitReplaceArgs.SerializeToString,
+ response_deserializer=CommitReplaceReply.FromString,
+ )
+ self.CommitConfig = channel.unary_unary(
+ "/IOSXRExtensibleManagabilityService.gRPCConfigOper/CommitConfig",
+ request_serializer=CommitArgs.SerializeToString,
+ response_deserializer=CommitReply.FromString,
+ )
+ self.ConfigDiscardChanges = channel.unary_unary(
+ "/IOSXRExtensibleManagabilityService.gRPCConfigOper/ConfigDiscardChanges",
+ request_serializer=DiscardChangesArgs.SerializeToString,
+ response_deserializer=DiscardChangesReply.FromString,
+ )
+ self.GetOper = channel.unary_stream(
+ "/IOSXRExtensibleManagabilityService.gRPCConfigOper/GetOper",
+ request_serializer=GetOperArgs.SerializeToString,
+ response_deserializer=GetOperReply.FromString,
+ )
+ self.CreateSubs = channel.unary_stream(
+ "/IOSXRExtensibleManagabilityService.gRPCConfigOper/CreateSubs",
+ request_serializer=CreateSubsArgs.SerializeToString,
+ response_deserializer=CreateSubsReply.FromString,
+ )
+
+
+class gRPCConfigOperServicer(object):
+ def GetConfig(self, request, context):
+ """Configuration related commands"""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details("Method not implemented!")
+ raise NotImplementedError("Method not implemented!")
+
+ def MergeConfig(self, request, context):
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details("Method not implemented!")
+ raise NotImplementedError("Method not implemented!")
+
+ def DeleteConfig(self, request, context):
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details("Method not implemented!")
+ raise NotImplementedError("Method not implemented!")
+
+ def ReplaceConfig(self, request, context):
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details("Method not implemented!")
+ raise NotImplementedError("Method not implemented!")
+
+ def CliConfig(self, request, context):
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details("Method not implemented!")
+ raise NotImplementedError("Method not implemented!")
+
+ def CommitReplace(self, request, context):
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details("Method not implemented!")
+ raise NotImplementedError("Method not implemented!")
+
+ def CommitConfig(self, request, context):
+ """Do we need implicit or explicit commit"""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details("Method not implemented!")
+ raise NotImplementedError("Method not implemented!")
+
+ def ConfigDiscardChanges(self, request, context):
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details("Method not implemented!")
+ raise NotImplementedError("Method not implemented!")
+
+ def GetOper(self, request, context):
+ """Get only returns oper data"""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details("Method not implemented!")
+ raise NotImplementedError("Method not implemented!")
+
+ def CreateSubs(self, request, context):
+ """Get Telemetry Data"""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details("Method not implemented!")
+ raise NotImplementedError("Method not implemented!")
+
+
+def add_gRPCConfigOperServicer_to_server(servicer, server):
+ rpc_method_handlers = {
+ "GetConfig": grpc.unary_stream_rpc_method_handler(
+ servicer.GetConfig,
+ request_deserializer=ConfigGetArgs.FromString,
+ response_serializer=ConfigGetReply.SerializeToString,
+ ),
+ "MergeConfig": grpc.unary_unary_rpc_method_handler(
+ servicer.MergeConfig,
+ request_deserializer=ConfigArgs.FromString,
+ response_serializer=ConfigReply.SerializeToString,
+ ),
+ "DeleteConfig": grpc.unary_unary_rpc_method_handler(
+ servicer.DeleteConfig,
+ request_deserializer=ConfigArgs.FromString,
+ response_serializer=ConfigReply.SerializeToString,
+ ),
+ "ReplaceConfig": grpc.unary_unary_rpc_method_handler(
+ servicer.ReplaceConfig,
+ request_deserializer=ConfigArgs.FromString,
+ response_serializer=ConfigReply.SerializeToString,
+ ),
+ "CliConfig": grpc.unary_unary_rpc_method_handler(
+ servicer.CliConfig,
+ request_deserializer=CliConfigArgs.FromString,
+ response_serializer=CliConfigReply.SerializeToString,
+ ),
+ "CommitReplace": grpc.unary_unary_rpc_method_handler(
+ servicer.CommitReplace,
+ request_deserializer=CommitReplaceArgs.FromString,
+ response_serializer=CommitReplaceReply.SerializeToString,
+ ),
+ "CommitConfig": grpc.unary_unary_rpc_method_handler(
+ servicer.CommitConfig,
+ request_deserializer=CommitArgs.FromString,
+ response_serializer=CommitReply.SerializeToString,
+ ),
+ "ConfigDiscardChanges": grpc.unary_unary_rpc_method_handler(
+ servicer.ConfigDiscardChanges,
+ request_deserializer=DiscardChangesArgs.FromString,
+ response_serializer=DiscardChangesReply.SerializeToString,
+ ),
+ "GetOper": grpc.unary_stream_rpc_method_handler(
+ servicer.GetOper,
+ request_deserializer=GetOperArgs.FromString,
+ response_serializer=GetOperReply.SerializeToString,
+ ),
+ "CreateSubs": grpc.unary_stream_rpc_method_handler(
+ servicer.CreateSubs,
+ request_deserializer=CreateSubsArgs.FromString,
+ response_serializer=CreateSubsReply.SerializeToString,
+ ),
+ }
+ generic_handler = grpc.method_handlers_generic_handler(
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ rpc_method_handlers,
+ )
+ server.add_generic_rpc_handlers((generic_handler,))
+
+
+class BetagRPCConfigOperServicer(object):
+ def GetConfig(self, request, context):
+ """Configuration related commands"""
+ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
+
+ def MergeConfig(self, request, context):
+ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
+
+ def DeleteConfig(self, request, context):
+ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
+
+ def ReplaceConfig(self, request, context):
+ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
+
+ def CliConfig(self, request, context):
+ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
+
+ def CommitReplace(self, request, context):
+ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
+
+ def CommitConfig(self, request, context):
+ """Do we need implicit or explicit commit"""
+ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
+
+ def ConfigDiscardChanges(self, request, context):
+ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
+
+ def GetOper(self, request, context):
+ """Get only returns oper data"""
+ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
+
+ def CreateSubs(self, request, context):
+ """Get Telemetry Data"""
+ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
+
+
+class BetagRPCConfigOperStub(object):
+ def GetConfig(
+ self,
+ request,
+ timeout,
+ metadata=None,
+ with_call=False,
+ protocol_options=None,
+ ):
+ """Configuration related commands"""
+ raise NotImplementedError()
+
+ def MergeConfig(
+ self,
+ request,
+ timeout,
+ metadata=None,
+ with_call=False,
+ protocol_options=None,
+ ):
+ raise NotImplementedError()
+
+ MergeConfig.future = None
+
+ def DeleteConfig(
+ self,
+ request,
+ timeout,
+ metadata=None,
+ with_call=False,
+ protocol_options=None,
+ ):
+ raise NotImplementedError()
+
+ DeleteConfig.future = None
+
+ def ReplaceConfig(
+ self,
+ request,
+ timeout,
+ metadata=None,
+ with_call=False,
+ protocol_options=None,
+ ):
+ raise NotImplementedError()
+
+ ReplaceConfig.future = None
+
+ def CliConfig(
+ self,
+ request,
+ timeout,
+ metadata=None,
+ with_call=False,
+ protocol_options=None,
+ ):
+ raise NotImplementedError()
+
+ CliConfig.future = None
+
+ def CommitReplace(
+ self,
+ request,
+ timeout,
+ metadata=None,
+ with_call=False,
+ protocol_options=None,
+ ):
+ raise NotImplementedError()
+
+ CommitReplace.future = None
+
+ def CommitConfig(
+ self,
+ request,
+ timeout,
+ metadata=None,
+ with_call=False,
+ protocol_options=None,
+ ):
+ """Do we need implicit or explicit commit"""
+ raise NotImplementedError()
+
+ CommitConfig.future = None
+
+ def ConfigDiscardChanges(
+ self,
+ request,
+ timeout,
+ metadata=None,
+ with_call=False,
+ protocol_options=None,
+ ):
+ raise NotImplementedError()
+
+ ConfigDiscardChanges.future = None
+
+ def GetOper(
+ self,
+ request,
+ timeout,
+ metadata=None,
+ with_call=False,
+ protocol_options=None,
+ ):
+ """Get only returns oper data"""
+ raise NotImplementedError()
+
+ def CreateSubs(
+ self,
+ request,
+ timeout,
+ metadata=None,
+ with_call=False,
+ protocol_options=None,
+ ):
+ """Get Telemetry Data"""
+ raise NotImplementedError()
+
+
+def beta_create_gRPCConfigOper_server(
+ servicer,
+ pool=None,
+ pool_size=None,
+ default_timeout=None,
+ maximum_timeout=None,
+):
+ request_deserializers = {
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CliConfig",
+ ): CliConfigArgs.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CommitConfig",
+ ): CommitArgs.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CommitReplace",
+ ): CommitReplaceArgs.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "ConfigDiscardChanges",
+ ): DiscardChangesArgs.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CreateSubs",
+ ): CreateSubsArgs.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "DeleteConfig",
+ ): ConfigArgs.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "GetConfig",
+ ): ConfigGetArgs.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "GetOper",
+ ): GetOperArgs.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "MergeConfig",
+ ): ConfigArgs.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "ReplaceConfig",
+ ): ConfigArgs.FromString,
+ }
+ response_serializers = {
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CliConfig",
+ ): CliConfigReply.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CommitConfig",
+ ): CommitReply.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CommitReplace",
+ ): CommitReplaceReply.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "ConfigDiscardChanges",
+ ): DiscardChangesReply.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CreateSubs",
+ ): CreateSubsReply.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "DeleteConfig",
+ ): ConfigReply.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "GetConfig",
+ ): ConfigGetReply.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "GetOper",
+ ): GetOperReply.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "MergeConfig",
+ ): ConfigReply.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "ReplaceConfig",
+ ): ConfigReply.SerializeToString,
+ }
+ method_implementations = {
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CliConfig",
+ ): face_utilities.unary_unary_inline(servicer.CliConfig),
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CommitConfig",
+ ): face_utilities.unary_unary_inline(servicer.CommitConfig),
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CommitReplace",
+ ): face_utilities.unary_unary_inline(servicer.CommitReplace),
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "ConfigDiscardChanges",
+ ): face_utilities.unary_unary_inline(servicer.ConfigDiscardChanges),
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CreateSubs",
+ ): face_utilities.unary_stream_inline(servicer.CreateSubs),
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "DeleteConfig",
+ ): face_utilities.unary_unary_inline(servicer.DeleteConfig),
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "GetConfig",
+ ): face_utilities.unary_stream_inline(servicer.GetConfig),
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "GetOper",
+ ): face_utilities.unary_stream_inline(servicer.GetOper),
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "MergeConfig",
+ ): face_utilities.unary_unary_inline(servicer.MergeConfig),
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "ReplaceConfig",
+ ): face_utilities.unary_unary_inline(servicer.ReplaceConfig),
+ }
+ server_options = beta_implementations.server_options(
+ request_deserializers=request_deserializers,
+ response_serializers=response_serializers,
+ thread_pool=pool,
+ thread_pool_size=pool_size,
+ default_timeout=default_timeout,
+ maximum_timeout=maximum_timeout,
+ )
+ return beta_implementations.server(
+ method_implementations,
+ options=server_options,
+ )
+
+
+def beta_create_gRPCConfigOper_stub(
+ channel,
+ host=None,
+ metadata_transformer=None,
+ pool=None,
+ pool_size=None,
+):
+ request_serializers = {
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CliConfig",
+ ): CliConfigArgs.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CommitConfig",
+ ): CommitArgs.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CommitReplace",
+ ): CommitReplaceArgs.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "ConfigDiscardChanges",
+ ): DiscardChangesArgs.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CreateSubs",
+ ): CreateSubsArgs.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "DeleteConfig",
+ ): ConfigArgs.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "GetConfig",
+ ): ConfigGetArgs.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "GetOper",
+ ): GetOperArgs.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "MergeConfig",
+ ): ConfigArgs.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "ReplaceConfig",
+ ): ConfigArgs.SerializeToString,
+ }
+ response_deserializers = {
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CliConfig",
+ ): CliConfigReply.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CommitConfig",
+ ): CommitReply.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CommitReplace",
+ ): CommitReplaceReply.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "ConfigDiscardChanges",
+ ): DiscardChangesReply.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "CreateSubs",
+ ): CreateSubsReply.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "DeleteConfig",
+ ): ConfigReply.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "GetConfig",
+ ): ConfigGetReply.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "GetOper",
+ ): GetOperReply.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "MergeConfig",
+ ): ConfigReply.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ "ReplaceConfig",
+ ): ConfigReply.FromString,
+ }
+ cardinalities = {
+ "CliConfig": cardinality.Cardinality.UNARY_UNARY,
+ "CommitConfig": cardinality.Cardinality.UNARY_UNARY,
+ "CommitReplace": cardinality.Cardinality.UNARY_UNARY,
+ "ConfigDiscardChanges": cardinality.Cardinality.UNARY_UNARY,
+ "CreateSubs": cardinality.Cardinality.UNARY_STREAM,
+ "DeleteConfig": cardinality.Cardinality.UNARY_UNARY,
+ "GetConfig": cardinality.Cardinality.UNARY_STREAM,
+ "GetOper": cardinality.Cardinality.UNARY_STREAM,
+ "MergeConfig": cardinality.Cardinality.UNARY_UNARY,
+ "ReplaceConfig": cardinality.Cardinality.UNARY_UNARY,
+ }
+ stub_options = beta_implementations.stub_options(
+ host=host,
+ metadata_transformer=metadata_transformer,
+ request_serializers=request_serializers,
+ response_deserializers=response_deserializers,
+ thread_pool=pool,
+ thread_pool_size=pool_size,
+ )
+ return beta_implementations.dynamic_stub(
+ channel,
+ "IOSXRExtensibleManagabilityService.gRPCConfigOper",
+ cardinalities,
+ options=stub_options,
+ )
+
+
+class gRPCExecStub(object):
+ """
+ Should we seperate Exec from Config/Oper?
+
+
+ """
+
+ def __init__(self, channel):
+ """Constructor.
+
+ Args:
+ channel: A grpc.Channel.
+ """
+ self.ShowCmdTextOutput = channel.unary_stream(
+ "/IOSXRExtensibleManagabilityService.gRPCExec/ShowCmdTextOutput",
+ request_serializer=ShowCmdArgs.SerializeToString,
+ response_deserializer=ShowCmdTextReply.FromString,
+ )
+ self.ShowCmdJSONOutput = channel.unary_stream(
+ "/IOSXRExtensibleManagabilityService.gRPCExec/ShowCmdJSONOutput",
+ request_serializer=ShowCmdArgs.SerializeToString,
+ response_deserializer=ShowCmdJSONReply.FromString,
+ )
+
+
+class gRPCExecServicer(object):
+ """
+ Should we seperate Exec from Config/Oper?
+
+
+ """
+
+ def ShowCmdTextOutput(self, request, context):
+ """Exec commands"""
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details("Method not implemented!")
+ raise NotImplementedError("Method not implemented!")
+
+ def ShowCmdJSONOutput(self, request, context):
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details("Method not implemented!")
+ raise NotImplementedError("Method not implemented!")
+
+
+def add_gRPCExecServicer_to_server(servicer, server):
+ rpc_method_handlers = {
+ "ShowCmdTextOutput": grpc.unary_stream_rpc_method_handler(
+ servicer.ShowCmdTextOutput,
+ request_deserializer=ShowCmdArgs.FromString,
+ response_serializer=ShowCmdTextReply.SerializeToString,
+ ),
+ "ShowCmdJSONOutput": grpc.unary_stream_rpc_method_handler(
+ servicer.ShowCmdJSONOutput,
+ request_deserializer=ShowCmdArgs.FromString,
+ response_serializer=ShowCmdJSONReply.SerializeToString,
+ ),
+ }
+ generic_handler = grpc.method_handlers_generic_handler(
+ "IOSXRExtensibleManagabilityService.gRPCExec",
+ rpc_method_handlers,
+ )
+ server.add_generic_rpc_handlers((generic_handler,))
+
+
+class BetagRPCExecServicer(object):
+ """
+ Should we seperate Exec from Config/Oper?
+
+
+ """
+
+ def ShowCmdTextOutput(self, request, context):
+ """Exec commands"""
+ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
+
+ def ShowCmdJSONOutput(self, request, context):
+ context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)
+
+
+class BetagRPCExecStub(object):
+ """
+ Should we seperate Exec from Config/Oper?
+
+
+ """
+
+ def ShowCmdTextOutput(
+ self,
+ request,
+ timeout,
+ metadata=None,
+ with_call=False,
+ protocol_options=None,
+ ):
+ """Exec commands"""
+ raise NotImplementedError()
+
+ def ShowCmdJSONOutput(
+ self,
+ request,
+ timeout,
+ metadata=None,
+ with_call=False,
+ protocol_options=None,
+ ):
+ raise NotImplementedError()
+
+
+def beta_create_gRPCExec_server(
+ servicer,
+ pool=None,
+ pool_size=None,
+ default_timeout=None,
+ maximum_timeout=None,
+):
+ request_deserializers = {
+ (
+ "IOSXRExtensibleManagabilityService.gRPCExec",
+ "ShowCmdJSONOutput",
+ ): ShowCmdArgs.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCExec",
+ "ShowCmdTextOutput",
+ ): ShowCmdArgs.FromString,
+ }
+ response_serializers = {
+ (
+ "IOSXRExtensibleManagabilityService.gRPCExec",
+ "ShowCmdJSONOutput",
+ ): ShowCmdJSONReply.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCExec",
+ "ShowCmdTextOutput",
+ ): ShowCmdTextReply.SerializeToString,
+ }
+ method_implementations = {
+ (
+ "IOSXRExtensibleManagabilityService.gRPCExec",
+ "ShowCmdJSONOutput",
+ ): face_utilities.unary_stream_inline(servicer.ShowCmdJSONOutput),
+ (
+ "IOSXRExtensibleManagabilityService.gRPCExec",
+ "ShowCmdTextOutput",
+ ): face_utilities.unary_stream_inline(servicer.ShowCmdTextOutput),
+ }
+ server_options = beta_implementations.server_options(
+ request_deserializers=request_deserializers,
+ response_serializers=response_serializers,
+ thread_pool=pool,
+ thread_pool_size=pool_size,
+ default_timeout=default_timeout,
+ maximum_timeout=maximum_timeout,
+ )
+ return beta_implementations.server(
+ method_implementations,
+ options=server_options,
+ )
+
+
+def beta_create_gRPCExec_stub(
+ channel,
+ host=None,
+ metadata_transformer=None,
+ pool=None,
+ pool_size=None,
+):
+ request_serializers = {
+ (
+ "IOSXRExtensibleManagabilityService.gRPCExec",
+ "ShowCmdJSONOutput",
+ ): ShowCmdArgs.SerializeToString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCExec",
+ "ShowCmdTextOutput",
+ ): ShowCmdArgs.SerializeToString,
+ }
+ response_deserializers = {
+ (
+ "IOSXRExtensibleManagabilityService.gRPCExec",
+ "ShowCmdJSONOutput",
+ ): ShowCmdJSONReply.FromString,
+ (
+ "IOSXRExtensibleManagabilityService.gRPCExec",
+ "ShowCmdTextOutput",
+ ): ShowCmdTextReply.FromString,
+ }
+ cardinalities = {
+ "ShowCmdJSONOutput": cardinality.Cardinality.UNARY_STREAM,
+ "ShowCmdTextOutput": cardinality.Cardinality.UNARY_STREAM,
+ }
+ stub_options = beta_implementations.stub_options(
+ host=host,
+ metadata_transformer=metadata_transformer,
+ request_serializers=request_serializers,
+ response_deserializers=response_deserializers,
+ thread_pool=pool,
+ thread_pool_size=pool_size,
+ )
+ return beta_implementations.dynamic_stub(
+ channel,
+ "IOSXRExtensibleManagabilityService.gRPCExec",
+ cardinalities,
+ options=stub_options,
+ )
+
+
+# @@protoc_insertion_point(module_scope)
diff --git a/ansible_collections/cisco/iosxr/plugins/terminal/__init__.py b/ansible_collections/cisco/iosxr/plugins/terminal/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/terminal/__init__.py
diff --git a/ansible_collections/cisco/iosxr/plugins/terminal/iosxr.py b/ansible_collections/cisco/iosxr/plugins/terminal/iosxr.py
new file mode 100644
index 00000000..5b60dcd9
--- /dev/null
+++ b/ansible_collections/cisco/iosxr/plugins/terminal/iosxr.py
@@ -0,0 +1,61 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+#
+from __future__ import absolute_import, division, print_function
+
+
+__metaclass__ = type
+
+import re
+
+from ansible.errors import AnsibleConnectionFailure
+from ansible_collections.ansible.netcommon.plugins.plugin_utils.terminal_base import TerminalBase
+
+
+class TerminalModule(TerminalBase):
+
+ terminal_stdout_re = [
+ re.compile(rb"[\r\n]*[\w+\-\.:\/\[\]]+(?:\([^\)]+\)){,3}(?:>|#) ?$"),
+ re.compile(rb"]]>]]>[\r\n]?"),
+ ]
+
+ terminal_stderr_re = [
+ re.compile(rb"% ?Error"),
+ re.compile(rb"% ?Bad secret"),
+ re.compile(rb"% ?This command is not authorized"),
+ re.compile(rb"invalid input", re.I),
+ re.compile(rb"(?:incomplete|ambiguous) command", re.I),
+ re.compile(rb"(?<!\()connection timed out(?!\))", re.I),
+ re.compile(rb"[^\r\n]+ not found", re.I),
+ re.compile(rb"'[^']' +returned error code: ?\d+"),
+ re.compile(rb"Failed to commit", re.I),
+ re.compile(rb"show configuration failed \[inheritance\]", re.I),
+ ]
+
+ terminal_config_prompt = re.compile(r"^.+\(config(-.*)?\)#$")
+
+ def on_open_shell(self):
+ try:
+ for cmd in (
+ b"terminal length 0",
+ b"terminal width 512",
+ b"terminal exec prompt no-timestamp",
+ ):
+ self._exec_cli_command(cmd)
+ except AnsibleConnectionFailure:
+ raise AnsibleConnectionFailure("unable to set terminal parameters")