summaryrefslogtreecommitdiff
path: root/lib/ansible/module_utils
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ansible/module_utils')
-rw-r--r--lib/ansible/module_utils/network/eos/argspec/acl_interfaces/acl_interfaces.py88
-rw-r--r--lib/ansible/module_utils/network/eos/argspec/acls/acls.py468
-rw-r--r--lib/ansible/module_utils/network/eos/argspec/facts/facts.py22
-rw-r--r--lib/ansible/module_utils/network/eos/argspec/interfaces/interfaces.py50
-rw-r--r--lib/ansible/module_utils/network/eos/argspec/l2_interfaces/l2_interfaces.py50
-rw-r--r--lib/ansible/module_utils/network/eos/argspec/l3_interfaces/l3_interfaces.py53
-rw-r--r--lib/ansible/module_utils/network/eos/argspec/lacp/lacp.py51
-rw-r--r--lib/ansible/module_utils/network/eos/argspec/lacp_interfaces/lacp_interfaces.py48
-rw-r--r--lib/ansible/module_utils/network/eos/argspec/lag_interfaces/lag_interfaces.py55
-rw-r--r--lib/ansible/module_utils/network/eos/argspec/lldp_global/lldp_global.py58
-rw-r--r--lib/ansible/module_utils/network/eos/argspec/lldp_interfaces/lldp_interfaces.py49
-rw-r--r--lib/ansible/module_utils/network/eos/argspec/static_routes/static_routes.py115
-rw-r--r--lib/ansible/module_utils/network/eos/argspec/vlans/vlans.py54
-rw-r--r--lib/ansible/module_utils/network/eos/config/acl_interfaces/acl_interfaces.py394
-rw-r--r--lib/ansible/module_utils/network/eos/config/acls/acls.py483
-rw-r--r--lib/ansible/module_utils/network/eos/config/interfaces/interfaces.py236
-rw-r--r--lib/ansible/module_utils/network/eos/config/l2_interfaces/l2_interfaces.py250
-rw-r--r--lib/ansible/module_utils/network/eos/config/l3_interfaces/l3_interfaces.py263
-rw-r--r--lib/ansible/module_utils/network/eos/config/lacp/lacp.py161
-rw-r--r--lib/ansible/module_utils/network/eos/config/lacp_interfaces/lacp_interfaces.py214
-rw-r--r--lib/ansible/module_utils/network/eos/config/lag_interfaces/lag_interfaces.py225
-rw-r--r--lib/ansible/module_utils/network/eos/config/lldp_global/lldp_global.py166
-rw-r--r--lib/ansible/module_utils/network/eos/config/lldp_interfaces/lldp_interfaces.py216
-rw-r--r--lib/ansible/module_utils/network/eos/config/static_routes/static_routes.py390
-rw-r--r--lib/ansible/module_utils/network/eos/config/vlans/vlans.py224
-rw-r--r--lib/ansible/module_utils/network/eos/eos.py630
-rw-r--r--lib/ansible/module_utils/network/eos/facts/acl_interfaces/acl_interfaces.py133
-rw-r--r--lib/ansible/module_utils/network/eos/facts/acls/acls.py300
-rw-r--r--lib/ansible/module_utils/network/eos/facts/facts.py72
-rw-r--r--lib/ansible/module_utils/network/eos/facts/interfaces/interfaces.py107
-rw-r--r--lib/ansible/module_utils/network/eos/facts/l2_interfaces/l2_interfaces.py108
-rw-r--r--lib/ansible/module_utils/network/eos/facts/l3_interfaces/l3_interfaces.py101
-rw-r--r--lib/ansible/module_utils/network/eos/facts/lacp/lacp.py89
-rw-r--r--lib/ansible/module_utils/network/eos/facts/lacp_interfaces/lacp_interfaces.py90
-rw-r--r--lib/ansible/module_utils/network/eos/facts/lag_interfaces/lag_interfaces.py103
-rw-r--r--lib/ansible/module_utils/network/eos/facts/legacy/base.py182
-rw-r--r--lib/ansible/module_utils/network/eos/facts/lldp_global/lldp_global.py86
-rw-r--r--lib/ansible/module_utils/network/eos/facts/lldp_interfaces/lldp_interfaces.py92
-rw-r--r--lib/ansible/module_utils/network/eos/facts/static_routes/static_routes.py202
-rw-r--r--lib/ansible/module_utils/network/eos/facts/vlans/vlans.py108
-rw-r--r--lib/ansible/module_utils/network/eos/providers/cli/config/bgp/address_family.py129
-rw-r--r--lib/ansible/module_utils/network/eos/providers/cli/config/bgp/neighbors.py173
-rw-r--r--lib/ansible/module_utils/network/eos/providers/cli/config/bgp/process.py163
-rw-r--r--lib/ansible/module_utils/network/eos/providers/module.py62
-rw-r--r--lib/ansible/module_utils/network/eos/providers/providers.py120
-rw-r--r--lib/ansible/module_utils/network/eos/utils/utils.py54
46 files changed, 0 insertions, 7487 deletions
diff --git a/lib/ansible/module_utils/network/eos/argspec/acl_interfaces/acl_interfaces.py b/lib/ansible/module_utils/network/eos/argspec/acl_interfaces/acl_interfaces.py
deleted file mode 100644
index 7e1409a7d9..0000000000
--- a/lib/ansible/module_utils/network/eos/argspec/acl_interfaces/acl_interfaces.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#
-# -*- 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 eos_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 eos_acl_interfaces module
- """
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'elements': 'dict',
- 'options': {
- 'access_groups': {
- 'elements': 'dict',
- 'options': {
- 'acls': {
- 'elements': 'dict',
- 'options': {
- 'direction': {
- 'required': True,
- 'choices': ['in', 'out'],
- 'type': 'str'
- },
- 'name': {
- 'required': True,
- 'type': 'str'
- }
- },
- 'type': 'list'
- },
- 'afi': {
- 'required': True,
- 'choices': ['ipv4', 'ipv6'],
- 'type': 'str'
- }
- },
- 'type': 'list'
- },
- 'name': {
- 'required': True,
- 'type': 'str'
- }
- },
- 'type': 'list'
- },
- 'running_config': {
- 'type': 'str'
- },
- 'state': {
- 'choices': [
- 'merged', 'replaced', 'overridden', 'deleted', 'gathered',
- 'parsed', 'rendered'
- ],
- 'default':
- 'merged',
- 'type':
- 'str'
- }
- } # pylint: disable=C0301
diff --git a/lib/ansible/module_utils/network/eos/argspec/acls/acls.py b/lib/ansible/module_utils/network/eos/argspec/acls/acls.py
deleted file mode 100644
index f998982404..0000000000
--- a/lib/ansible/module_utils/network/eos/argspec/acls/acls.py
+++ /dev/null
@@ -1,468 +0,0 @@
-#
-# -*- 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 eos_acls module
-"""
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-class AclsArgs(object): # pylint: disable=R0903
- """The arg spec for the eos_acls module
- """
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'elements': 'dict',
- 'options': {
- 'acls': {
- 'elements': 'dict',
- 'options': {
- 'aces': {
- 'elements': 'dict',
- 'options': {
- 'destination': {
- 'mutually_exclusive':
- [['address', 'subnet_address', 'any', 'host'],
- ['wildcard_bits', 'subnet_address', 'any', 'host']],
- 'options': {
- 'address': {
- 'type': 'str'
- },
- 'any': {
- 'type': 'bool'
- },
- 'host': {
- 'type': 'str'
- },
- 'port_protocol': {
- 'type': 'dict'
- },
- 'subnet_address': {
- 'type': 'str'
- },
- 'wildcard_bits': {
- 'type': 'str'
- }
- },
- 'required_together':
- [['address', 'wildcard_bits']],
- 'type':
- 'dict'
- },
- 'fragment_rules': {
- 'type': 'bool'
- },
- 'fragments': {
- 'type': 'bool'
- },
- 'grant': {
- 'choices': ['permit', 'deny'],
- 'type': 'str'
- },
- 'line': {
- 'type': 'str',
- 'aliases': ['ace']
- },
- 'hop_limit': {
- 'type': 'dict'
- },
- 'log': {
- 'type': 'bool'
- },
- 'protocol': {
- 'type': 'str'
- },
- 'protocol_options': {
- 'options': {
- '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'
- },
- 'message_code': {
- 'type': 'int'
- },
- 'message_num': {
- 'type': 'int'
- },
- 'message_type': {
- 'type': 'int'
- },
- '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'
- },
- 'icmpv6': {
- 'options': {
- 'address_unreachable': {
- 'type': 'bool'
- },
- 'beyond_scope': {
- 'type': 'bool'
- },
- 'echo_reply': {
- 'type': 'bool'
- },
- 'echo_request': {
- 'type': 'bool'
- },
- 'erroneous_header': {
- 'type': 'bool'
- },
- 'fragment_reassembly_exceeded':
- {
- 'type': 'bool'
- },
- 'hop_limit_exceeded': {
- 'type': 'bool'
- },
- 'neighbor_advertisement': {
- 'type': 'bool'
- },
- 'neighbor_solicitation': {
- 'type': 'bool'
- },
- 'no_admin': {
- 'type': 'bool'
- },
- 'no_route': {
- 'type': 'bool'
- },
- 'packet_too_big': {
- 'type': 'bool'
- },
- 'parameter_problem': {
- 'type': 'bool'
- },
- 'port_unreachable': {
- 'type': 'bool'
- },
- 'redirect_message': {
- 'type': 'bool'
- },
- 'reject_route': {
- 'type': 'bool'
- },
- 'router_advertisement': {
- 'type': 'bool'
- },
- 'router_solicitation': {
- 'type': 'bool'
- },
- 'source_address_failed': {
- 'type': 'bool'
- },
- 'source_routing_error': {
- 'type': 'bool'
- },
- 'time_exceeded': {
- 'type': 'bool'
- },
- 'unreachable': {
- 'type': 'bool'
- },
- 'unrecognized_ipv6_option': {
- 'type': 'bool'
- },
- 'unrecognized_next_header': {
- 'type': 'bool'
- }
- },
- 'type': 'dict'
- },
- 'ip': {
- 'options': {
- 'nexthop_group': {
- 'type': 'str'
- }
- },
- 'type': 'dict'
- },
- 'ipv6': {
- 'options': {
- 'nexthop_group': {
- 'type': 'str'
- }
- },
- 'type': 'dict'
- },
- 'tcp': {
- 'options': {
- 'flags': {
- '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'
- }
- },
- 'type': 'dict'
- },
- 'remark': {
- 'type': 'str'
- },
- 'sequence': {
- 'type': 'int'
- },
- 'source': {
- 'mutually_exclusive':
- [['address', 'subnet_address', 'any', 'host'],
- ['wildcard_bits', 'subnet_address', 'any', 'host']],
- 'options': {
- 'address': {
- 'type': 'str'
- },
- 'any': {
- 'type': 'bool'
- },
- 'host': {
- 'type': 'str'
- },
- 'port_protocol': {
- 'type': 'dict'
- },
- 'subnet_address': {
- 'type': 'str'
- },
- 'wildcard_bits': {
- 'type': 'str'
- }
- },
- 'required_together': [['address', 'wildcard_bits']],
- 'type': 'dict'
- },
- 'tracked': {
- 'type': 'bool'
- },
- 'ttl': {
- 'options': {
- 'eq': {
- 'type': 'int'
- },
- 'gt': {
- 'type': 'int'
- },
- 'lt': {
- 'type': 'int'
- },
- 'neq': {
- 'type': 'int'
- }
- },
- 'type': 'dict'
- },
- 'vlan': {
- 'type': 'str'
- }
- },
- 'type': 'list'
- },
- 'name': {
- 'required': True,
- 'type': 'str'
- },
- 'standard': {
- 'type': 'bool'
- }
- },
- 'type': 'list'
- },
- 'afi': {
- 'choices': ['ipv4', 'ipv6'],
- 'required': True,
- 'type': 'str'
- }
- },
- 'type': 'list'
- },
- 'running_config': {
- 'type': 'str'
- },
- 'state': {
- 'choices': [
- 'deleted', 'merged', 'overridden', 'replaced', 'gathered',
- 'rendered', 'parsed'
- ],
- 'default':
- 'merged',
- 'type':
- 'str'
- }
- } # pylint: disable=C0301
diff --git a/lib/ansible/module_utils/network/eos/argspec/facts/facts.py b/lib/ansible/module_utils/network/eos/argspec/facts/facts.py
deleted file mode 100644
index 79446b03be..0000000000
--- a/lib/ansible/module_utils/network/eos/argspec/facts/facts.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- 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 eos facts module.
-"""
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-class FactsArgs(object):
- """ The arg spec for the eos facts module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'gather_subset': dict(default=['!config'], type='list'),
- 'gather_network_resources': dict(type='list'),
- }
diff --git a/lib/ansible/module_utils/network/eos/argspec/interfaces/interfaces.py b/lib/ansible/module_utils/network/eos/argspec/interfaces/interfaces.py
deleted file mode 100644
index 880e5126e7..0000000000
--- a/lib/ansible/module_utils/network/eos/argspec/interfaces/interfaces.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# -*- 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 eos_interfaces module
-"""
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-class InterfacesArgs(object):
- """The arg spec for the eos_interfaces module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'options': {
- 'name': {'required': True, 'type': 'str'},
- 'description': {'required': False, 'type': 'str'},
- 'enabled': {'default': True, 'required': False, 'type': 'bool'},
- 'mtu': {'required': False, 'type': 'int'},
- 'speed': {'required': False, 'type': 'str'},
- 'duplex': {'required': False, 'type': 'str'}
- },
- 'type': 'list'},
- 'state': {'default': 'merged', 'choices': ['merged', 'replaced', 'overridden', 'deleted'], 'required': False, 'type': 'str'}
- }
diff --git a/lib/ansible/module_utils/network/eos/argspec/l2_interfaces/l2_interfaces.py b/lib/ansible/module_utils/network/eos/argspec/l2_interfaces/l2_interfaces.py
deleted file mode 100644
index e9b9a5be19..0000000000
--- a/lib/ansible/module_utils/network/eos/argspec/l2_interfaces/l2_interfaces.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# -*- 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 eos_l2_interfaces module
-"""
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-class L2_interfacesArgs(object):
- """The arg spec for the eos_l2_interfaces module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'elements': 'dict',
- 'options': {
- 'access': {'options': {'vlan': {'type': 'int'}},
- 'type': 'dict'},
- 'mode': {'type': 'str', 'choices': ['access', 'trunk']},
- 'name': {'required': True, 'type': 'str'},
- 'trunk': {'options': {'native_vlan': {'type': 'int'}, 'trunk_allowed_vlans': {'type': 'list'}},
- 'type': 'dict'}},
- 'type': 'list'},
- 'state': {'default': 'merged', 'choices': ['merged', 'replaced', 'overridden', 'deleted'], 'required': False, 'type': 'str'}
- }
diff --git a/lib/ansible/module_utils/network/eos/argspec/l3_interfaces/l3_interfaces.py b/lib/ansible/module_utils/network/eos/argspec/l3_interfaces/l3_interfaces.py
deleted file mode 100644
index 2708b47c42..0000000000
--- a/lib/ansible/module_utils/network/eos/argspec/l3_interfaces/l3_interfaces.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# -*- 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 eos_l3_interfaces module
-"""
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-class L3_interfacesArgs(object):
- """The arg spec for the eos_l3_interfaces module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'elements': 'dict',
- 'options': {
- 'name': {'required': True, 'type': 'str'},
- 'ipv4': {'elements': 'dict',
- 'options': {'address': {'type': 'str'}, 'secondary': {'type': 'bool'}},
- 'type': 'list'},
- 'ipv6': {'elements': 'dict',
- 'options': {'address': {'type': 'str'}},
- 'type': 'list'},
- },
- 'type': 'list'},
- 'state': {'default': 'merged', 'choices': ['merged', 'replaced', 'overridden', 'deleted'], 'type': 'str'}
- }
diff --git a/lib/ansible/module_utils/network/eos/argspec/lacp/lacp.py b/lib/ansible/module_utils/network/eos/argspec/lacp/lacp.py
deleted file mode 100644
index b0862a222e..0000000000
--- a/lib/ansible/module_utils/network/eos/argspec/lacp/lacp.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# -*- 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 eos_lacp module
-"""
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-class LacpArgs(object):
- """The arg spec for the eos_lacp module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'options': {
- 'system': {
- 'options': {
- 'priority': {'type': 'int'}
- },
- 'type': 'dict'
- }
- },
- 'type': 'dict'
- },
- 'state': {'choices': ['merged', 'replaced', 'deleted'], 'default': 'merged', 'type': 'str'}}
diff --git a/lib/ansible/module_utils/network/eos/argspec/lacp_interfaces/lacp_interfaces.py b/lib/ansible/module_utils/network/eos/argspec/lacp_interfaces/lacp_interfaces.py
deleted file mode 100644
index bbe20867f0..0000000000
--- a/lib/ansible/module_utils/network/eos/argspec/lacp_interfaces/lacp_interfaces.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# -*- 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 eos_lacp_interfaces module
-"""
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-class Lacp_interfacesArgs(object):
- """The arg spec for the eos_lacp_interfaces module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {'elements': 'dict',
- 'options': {'name': {'type': 'str'},
- 'port_priority': {'type': 'int'},
- 'rate': {'choices': ['fast', 'normal'], 'type': 'str'}},
- 'type': 'list'},
- 'state': {'choices': ['merged', 'replaced', 'overridden', 'deleted'],
- 'default': 'merged',
- 'type': 'str'}}
diff --git a/lib/ansible/module_utils/network/eos/argspec/lag_interfaces/lag_interfaces.py b/lib/ansible/module_utils/network/eos/argspec/lag_interfaces/lag_interfaces.py
deleted file mode 100644
index ff672ffb93..0000000000
--- a/lib/ansible/module_utils/network/eos/argspec/lag_interfaces/lag_interfaces.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# -*- 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 eos_lag_interfaces module
-"""
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-class Lag_interfacesArgs(object):
- """The arg spec for the eos_lag_interfaces module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'elements': 'dict',
- 'options': {
- 'name': {'required': True, 'type': 'str'},
- 'members': {
- 'elements': 'dict',
- 'options': {
- 'member': {'type': 'str'},
- 'mode': {'choices': ['active', 'on', 'passive'], 'type': 'str'},
- },
- 'type': 'list',
- },
- },
- 'type': 'list'},
- 'state': {'default': 'merged', 'choices': ['merged', 'replaced', 'overridden', 'deleted'], 'type': 'str'}
- }
diff --git a/lib/ansible/module_utils/network/eos/argspec/lldp_global/lldp_global.py b/lib/ansible/module_utils/network/eos/argspec/lldp_global/lldp_global.py
deleted file mode 100644
index 2dc3e0cf58..0000000000
--- a/lib/ansible/module_utils/network/eos/argspec/lldp_global/lldp_global.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#
-# -*- 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 eos_lldp_global module
-"""
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-class Lldp_globalArgs(object):
- """The arg spec for the eos_lldp_global module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'options': {
- 'holdtime': {'type': 'int'},
- 'reinit': {'type': 'int'},
- 'timer': {'type': 'int'},
- 'tlv_select': {
- 'options': {
- 'link_aggregation': {'type': 'bool'},
- 'management_address': {'type': 'bool'},
- 'max_frame_size': {'type': 'bool'},
- 'port_description': {'type': 'bool'},
- 'system_capabilities': {'type': 'bool'},
- 'system_description': {'type': 'bool'},
- 'system_name': {'type': 'bool'}},
- 'type': 'dict'}},
- 'type': 'dict'},
- 'state': {'choices': ['merged', 'replaced', 'deleted'], 'default': 'merged', 'type': 'str'}
- }
diff --git a/lib/ansible/module_utils/network/eos/argspec/lldp_interfaces/lldp_interfaces.py b/lib/ansible/module_utils/network/eos/argspec/lldp_interfaces/lldp_interfaces.py
deleted file mode 100644
index 2cdc866891..0000000000
--- a/lib/ansible/module_utils/network/eos/argspec/lldp_interfaces/lldp_interfaces.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-# -*- 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 eos_lldp_interfaces module
-"""
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-class Lldp_interfacesArgs(object):
- """The arg spec for the eos_lldp_interfaces module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'elements': 'dict',
- 'options': {'name': {'type': 'str'},
- 'receive': {'type': 'bool'},
- 'transmit': {'type': 'bool'}},
- 'type': 'list'},
- 'state': {'choices': ['merged', 'replaced', 'overridden', 'deleted'],
- 'default': 'merged',
- 'type': 'str'}}
diff --git a/lib/ansible/module_utils/network/eos/argspec/static_routes/static_routes.py b/lib/ansible/module_utils/network/eos/argspec/static_routes/static_routes.py
deleted file mode 100644
index f4b9277b1e..0000000000
--- a/lib/ansible/module_utils/network/eos/argspec/static_routes/static_routes.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#
-# -*- 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 eos_static_routes module
-"""
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-class Static_routesArgs(object):
- """The arg spec for the eos_static_routes module
- """
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'elements': 'dict',
- 'options': {
- 'address_families': {
- 'elements': 'dict',
- 'options': {
- 'afi': {
- 'choices': ['ipv4', 'ipv6'],
- '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'
- },
- 'forward_router_address': {
- 'type': 'str'
- },
- 'interface': {
- 'type': 'str'
- },
- 'nexthop_grp': {
- 'type': 'str'
- },
- 'mpls_label': {
- 'type': 'int'
- },
- 'tag': {
- 'type': 'int'
- },
- 'track': {
- 'type': 'str'
- },
- 'vrf': {
- 'type': 'str'
- }
- },
- 'type': 'list'
- }
- },
- 'type': 'list'
- }
- },
- 'type': 'list'
- },
- 'vrf': {
- 'type': 'str'
- }
- },
- 'type': 'list'
- },
- 'running_config': {
- 'type': 'str'
- },
- 'state': {
- 'choices': [
- 'deleted', 'merged', 'overridden', 'replaced', 'gathered',
- 'rendered', 'parsed'
- ],
- 'default':
- 'merged',
- 'type':
- 'str'
- }
- } # pylint: disable=C0301
diff --git a/lib/ansible/module_utils/network/eos/argspec/vlans/vlans.py b/lib/ansible/module_utils/network/eos/argspec/vlans/vlans.py
deleted file mode 100644
index ea2211ca3d..0000000000
--- a/lib/ansible/module_utils/network/eos/argspec/vlans/vlans.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# -*- 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 eos_vlans module
-"""
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-
-class VlansArgs(object):
- """The arg spec for the eos_vlans module
- """
-
- def __init__(self, **kwargs):
- pass
-
- argument_spec = {
- 'config': {
- 'elements': 'dict',
- 'options': {
- 'vlan_id': {'required': True, 'type': 'int'},
- 'name': {'type': 'str'},
- 'state': {'choices': ['active', 'suspend'], 'type': 'str'},
- },
- 'type': 'list',
- },
- 'state': {
- 'choices': ['merged', 'replaced', 'overridden', 'deleted'],
- 'default': 'merged',
- 'type': 'str',
- },
- }
diff --git a/lib/ansible/module_utils/network/eos/config/acl_interfaces/acl_interfaces.py b/lib/ansible/module_utils/network/eos/config/acl_interfaces/acl_interfaces.py
deleted file mode 100644
index c3eb56ace2..0000000000
--- a/lib/ansible/module_utils/network/eos/config/acl_interfaces/acl_interfaces.py
+++ /dev/null
@@ -1,394 +0,0 @@
-#
-# -*- 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 eos_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
-
-import itertools
-
-from ansible.module_utils.network.common.cfg.base import ConfigBase
-from ansible.module_utils.network.common.utils import to_list, search_obj_in_list
-from ansible.module_utils.network.eos.facts.facts import Facts
-
-
-class Acl_interfaces(ConfigBase):
- """
- The eos_acl_interfaces class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'acl_interfaces',
- ]
-
- def __init__(self, module):
- super(Acl_interfaces, self).__init__(module)
-
- def get_acl_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)
- acl_interfaces_facts = facts['ansible_network_resources'].get('acl_interfaces')
- if not acl_interfaces_facts:
- return []
- return acl_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()
- changed = False
-
- if self.state in self.ACTION_STATES:
- existing_acl_interfaces_facts = self.get_acl_interfaces_facts()
- else:
- existing_acl_interfaces_facts = []
- if self.state in self.ACTION_STATES or self.state == 'rendered':
- commands.extend(self.set_config(existing_acl_interfaces_facts))
- if commands and self.state in self.ACTION_STATES:
- if not self._module.check_mode:
- self._connection.edit_config(commands)
- changed = True
- if changed:
- 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_acl_interfaces_facts = self.get_acl_interfaces_facts()
- elif self.state == 'rendered':
- result['rendered'] = commands
- elif self.state == 'parsed':
- if not self._module.params['running_config']:
- self._module.fail_json(msg="Value of running_config parameter must not be empty for state parsed")
- result['parsed'] = self.get_acl_interfaces_facts(data=self._module.params['running_config'])
- else:
- changed_acl_interfaces_facts = []
- if self.state in self.ACTION_STATES:
- result['before'] = existing_acl_interfaces_facts
- if result['changed']:
- result['after'] = changed_acl_interfaces_facts
- elif self.state == 'gathered':
- result['gathered'] = changed_acl_interfaces_facts
-
- result['warnings'] = warnings
- return result
-
- def set_config(self, existing_acl_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_acl_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 ('merged', 'replaced', 'overridden') and not want:
- self._module.fail_json(msg='value of config parameter must not be empty for state {0}'.format(self.state))
- state = self._module.params['state']
- if state == 'overridden':
- commands = self._state_overridden(want, have)
- elif state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged' or self.state == '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
- """
- commandset = []
- want_interface = []
- for w in want:
- commands = []
- diff_access_group = []
- want_interface.append(w['name'])
- obj_in_have = search_obj_in_list(w['name'], have, 'name')
- if not obj_in_have or 'access_groups' not in obj_in_have.keys():
- commands.append(add_commands(w['access_groups'], w['name']))
- else:
- if 'access_groups' in obj_in_have.keys():
- obj = self.get_acl_diff(obj_in_have, w)
- if obj[0]:
- to_delete = {'access_groups': [{'acls': obj[0], 'afi': 'ipv4'}]}
- commands.append(remove_commands(to_delete, w['name']))
- if obj[1]:
- to_delete = {'access_groups': [{'acls': obj[1], 'afi': 'ipv6'}]}
- commands.append(remove_commands(to_delete, w['name']))
- diff = self.get_acl_diff(w, obj_in_have)
- if diff[0]:
- diff_access_group.append({'afi': 'ipv4', 'acls': diff[0]})
- if diff[1]:
- diff_access_group.append({'afi': 'ipv6', 'acls': diff[1]})
- if diff_access_group:
- commands.append(add_commands(diff_access_group, w['name']))
- if commands:
- intf_command = ["interface " + w['name']]
- commands = list(itertools.chain(*commands))
- commandset.append(intf_command)
- commandset.append(commands)
-
- if commandset:
- commandset = list(itertools.chain(*commandset))
- return commandset
-
- 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
- """
- commandset = []
- want_interface = []
- for w in want:
- commands = []
- diff_access_group = []
- want_interface.append(w['name'])
- obj_in_have = search_obj_in_list(w['name'], have, 'name')
- if not obj_in_have or 'access_groups' not in obj_in_have.keys():
- commands.append(add_commands(w['access_groups'], w['name']))
- else:
- if 'access_groups' in obj_in_have.keys():
- obj = self.get_acl_diff(obj_in_have, w)
- if obj[0]:
- to_delete = {'access_groups': [{'acls': obj[0], 'afi': 'ipv4'}]}
- commands.append(remove_commands(to_delete, w['name']))
- if obj[1]:
- to_delete = {'access_groups': [{'acls': obj[1], 'afi': 'ipv6'}]}
- commands.append(remove_commands(to_delete, w['name']))
- diff = self.get_acl_diff(w, obj_in_have)
- if diff[0]:
- diff_access_group.append({'afi': 'ipv4', 'acls': diff[0]})
- if diff[1]:
- diff_access_group.append({'afi': 'ipv6', 'acls': diff[1]})
- if diff_access_group:
- commands.append(add_commands(diff_access_group, w['name']))
- if commands:
- intf_command = ["interface " + w['name']]
- commands = list(itertools.chain(*commands))
- commandset.append(intf_command)
- commandset.append(commands)
- for h in have:
- commands = []
- if 'access_groups' in h.keys() and h['access_groups']:
- if h['name'] not in want_interface:
- for h_group in h['access_groups']:
- to_delete = {'access_groups': [h_group]}
- commands.append(remove_commands(to_delete, h['name']))
- if commands:
- intf_command = ["interface " + h['name']]
- commands = list(itertools.chain(*commands))
- commandset.append(intf_command)
- commandset.append(commands)
-
- if commandset:
- commandset = list(itertools.chain(*commandset))
-
- return commandset
-
- 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
- """
- commandset = []
- for w in want:
- commands = []
- diff_access_group = []
- obj_in_have = search_obj_in_list(w['name'], have, 'name')
- if not obj_in_have:
- commands = add_commands(w['access_groups'], w['name'])
- else:
- if 'access_groups' in obj_in_have.keys():
- diff = self.get_acl_diff(w, obj_in_have)
- if diff[0]:
- diff_access_group.append({'afi': 'ipv4', 'acls': diff[0]})
- if diff[1]:
- diff_access_group.append({'afi': 'ipv6', 'acls': diff[1]})
- if diff_access_group:
- commands = add_commands(diff_access_group, w['name'])
- else:
- commands = add_commands(w['access_groups'], w['name'])
- if commands:
- intf_command = ["interface " + w['name']]
- commandset.append(intf_command)
- commandset.append(commands)
- if commandset:
- commandset = list(itertools.chain(*commandset))
- return commandset
-
- 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
- """
- commandset = []
- for w in want:
- commands = []
- intf_command = ["interface " + w['name']]
- obj_in_have = search_obj_in_list(w['name'], have, 'name')
- if 'access_groups' not in w.keys() or not w['access_groups']:
- commands = remove_commands(obj_in_have, w['name'])
- if w['access_groups']:
- for w_grp in w['access_groups']:
- if 'acls' not in w_grp.keys() or not w_grp['acls']:
- obj = self.get_acls_from_afi(w['name'], w_grp['afi'], have)
- to_delete = {'access_groups': [{'acls': obj, 'afi': w_grp['afi']}]}
- commands = remove_commands(to_delete, w['name'])
- else:
- if 'access_groups' not in obj_in_have.keys() or not obj_in_have['access_groups']:
- continue
- group = {'access_groups': [w_grp]}
- obj = self.get_acl_diff(group, obj_in_have, True)
- if obj[0]:
- to_delete = {'access_groups': [{'acls': obj[0], 'afi': 'ipv4'}]}
- commands.append(remove_commands(to_delete, w['name']))
- if obj[1]:
- to_delete = {'access_groups': [{'acls': obj[1], 'afi': 'ipv6'}]}
- commands.append(remove_commands(to_delete, w['name']))
- if commands:
- commands = list(itertools.chain(*commands))
- if commands:
- commandset.append(intf_command)
- commandset.append(commands)
-
- if commandset:
- commandset = list(itertools.chain(*commandset))
- return commandset
-
- def get_acl_diff(self, w, h, intersection=False):
- diff_v4 = []
- diff_v6 = []
- w_acls_v4 = []
- w_acls_v6 = []
- h_acls_v4 = []
- h_acls_v6 = []
- for w_group in w['access_groups']:
- if w_group['afi'] == 'ipv4':
- w_acls_v4 = w_group['acls']
- if w_group['afi'] == 'ipv6':
- w_acls_v6 = w_group['acls']
- for h_group in h['access_groups']:
- if h_group['afi'] == 'ipv4':
- h_acls_v4 = h_group['acls']
- if h_group['afi'] == 'ipv6':
- h_acls_v6 = h_group['acls']
- for item in w_acls_v4:
- match = list(filter(lambda x: x['name'] == item['name'], h_acls_v4))
- if match:
- if item['direction'] == match[0]['direction']:
- if intersection:
- diff_v4.append(item)
- else:
- if not intersection:
- diff_v4.append(item)
- else:
- if not intersection:
- diff_v4.append(item)
- for item in w_acls_v6:
- match = list(filter(lambda x: x['name'] == item['name'], h_acls_v6))
- if match:
- if item['direction'] == match[0]['direction']:
- if intersection:
- diff_v6.append(item)
- else:
- if not intersection:
- diff_v6.append(item)
- else:
- if not intersection:
- diff_v6.append(item)
- return diff_v4, diff_v6
-
- def get_acls_from_afi(self, interface, afi, have):
- config = []
- for h in have:
- if h['name'] == interface:
- if 'access_groups' not in h.keys() or not h['access_groups']:
- continue
- if h['access_groups']:
- for h_grp in h['access_groups']:
- if h_grp['afi'] == afi:
- config = h_grp['acls']
- return config
-
-
-def add_commands(want, interface):
- commands = []
-
- for w in want:
- # This module was verified on an ios device since vEOS doesnot support
- # acl_interfaces cnfiguration. In ios, ipv6 acl is configured as
- # traffic-filter and in eos it is access-group
-
- # a_cmd = "traffic-filter" if w['afi'] == 'ipv6' else "access-group"
- a_cmd = "access-group"
- afi = 'ip' if w['afi'] == 'ipv4' else w['afi']
- if 'acls' in w.keys():
- for acl in w['acls']:
- commands.append(afi + " " + a_cmd + " " + acl['name'] + " " + acl['direction'])
- return commands
-
-
-def remove_commands(want, interface):
- commands = []
- if 'access_groups' not in want.keys() or not want['access_groups']:
- return commands
- for w in want['access_groups']:
- # This module was verified on an ios device since vEOS doesnot support
- # acl_interfaces cnfiguration. In ios, ipv6 acl is configured as
- # traffic-filter and in eos it is access-group
-
- # a_cmd = "traffic-filter" if w['afi'] == 'ipv6' else "access-group"
- a_cmd = "access-group"
-
- afi = 'ip' if w['afi'] == 'ipv4' else w['afi']
- if 'acls' in w.keys():
- for acl in w['acls']:
- commands.append("no " + afi + " " + a_cmd + " " + acl['name'] + " " + acl['direction'])
- return commands
diff --git a/lib/ansible/module_utils/network/eos/config/acls/acls.py b/lib/ansible/module_utils/network/eos/config/acls/acls.py
deleted file mode 100644
index 90fee80b04..0000000000
--- a/lib/ansible/module_utils/network/eos/config/acls/acls.py
+++ /dev/null
@@ -1,483 +0,0 @@
-#
-# -*- 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 eos_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
-
-import socket
-import re
-import itertools
-
-from ansible.module_utils.network.common.cfg.base import ConfigBase
-from ansible.module_utils.network.common.utils import to_list
-from ansible.module_utils.network.common.utils import remove_empties, dict_diff
-from ansible.module_utils.network.eos.facts.facts import Facts
-
-
-class Acls(ConfigBase):
- """
- The eos_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()
- changed = False
-
- 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)
- changed = True
- if changed:
- 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':
- commands = list(itertools.chain(*commands))
- result['rendered'] = commands
- elif self.state == 'parsed':
- if not self._module.params['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=self._module.params['running_config'])
- else:
- changed_acls_facts = []
- 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
- """
- config = self._module.params.get('config')
- want = []
- onbox_configs = []
- for h in existing_acls_facts:
- have_configs = add_commands(remove_empties(h))
- onbox_configs.append(have_configs)
- if config:
- for w in config:
- want.append(remove_empties(w))
- have = existing_acls_facts
- resp = self.set_state(want, have)
- if self.state == 'merged':
- to_config = self.compare_configs(onbox_configs, to_list(resp))
- else:
- to_config = resp
- return to_config
-
- def compare_configs(self, have, want):
- commands = []
- want = list(itertools.chain(*want))
- have = list(itertools.chain(*have))
- h_index = 0
- config = list(want)
- for w in want:
- access_list = re.findall(r'(ip.*) access-list (.*)', w)
- if access_list:
- if w in have:
- h_index = have.index(w)
- else:
- for num, h in enumerate(have, start=h_index + 1):
- if "access-list" not in h:
- seq_num = re.search(r'(\d+) (.*)', w)
- if seq_num:
- have_seq_num = re.search(r'(\d+) (.*)', h)
- if seq_num.group(1) == have_seq_num.group(1) and have_seq_num.group(2) != seq_num.group(2):
- negate_cmd = "no " + seq_num.group(1)
- config.insert(config.index(w), negate_cmd)
- if w in h:
- config.pop(config.index(w))
- break
- for c in config:
- access_list = re.findall(r'(ip.*) access-list (.*)', c)
- if access_list:
- acl_index = config.index(c)
- else:
- if config[acl_index] not in commands:
- commands.append(config[acl_index])
- commands.append(c)
- return commands
-
- 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 ('merged', 'replaced', 'overridden', 'rendered') and not want:
- self._module.fail_json(msg='value of config parameter must not be empty for state {0}'.format(self.state))
- state = self._module.params['state']
- if state == 'overridden':
- commands = self._state_overridden(want, have)
- elif state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged' or self.state == 'rendered':
- commands = self._state_merged(want, have)
- elif state == 'replaced':
- commands = self._state_replaced(want, 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 = []
- have_commands = []
- remove_cmds = []
- diff = {}
- present = False
- diff_present = False
- for w in want:
- afi = "ipv6" if w["afi"] == "ipv6" else "ipv4"
- for acl in w["acls"]:
- name = acl["name"]
- want_ace = acl["aces"]
- for h in have:
- if h["afi"] == afi:
- for h_acl in h["acls"]:
- if h_acl["name"] == name:
- present = True
- h = {"afi": afi, "acls": [{"name": name}]}
- for h_ace in h_acl['aces']:
- diff = get_ace_diff(h_ace, want_ace)
- if diff:
- diff_present = True
- h = {"afi": afi, "acls": [{"name": name, "aces": [h_ace]}]}
- remove_cmds.append(del_commands(h, have))
- if diff_present or not present:
- config_cmds = set_commands(want, have)
- config_cmds = list(itertools.chain(*config_cmds))
- for cmd in have:
- have_configs = add_commands(cmd)
- have_commands.append(have_configs)
- have_commands = list(itertools.chain(*have_commands))
- if remove_cmds:
- remove_cmds = list(itertools.chain(*remove_cmds))
- commands.append(remove_cmds)
- commands.append(config_cmds)
- commands = list(itertools.chain(*commands))
- commandset = []
- [commandset.append(cmd) for cmd in commands if cmd not in commandset]
- return commandset
-
- @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 = []
- ace_diff = {}
- h_afi_list = []
- w_afi_list = []
- diff = False
- for h in have:
- h_afi_list.append(h["afi"])
- for w in want:
- w_afi_list.append(w["afi"])
- for hafi in h_afi_list:
- if hafi not in w_afi_list:
- h = {"afi": hafi}
- remove_cmds = del_commands(h, have)
- commands.append(remove_cmds)
- for w in want:
- w_names = []
- for h in have:
- h_names = []
- if w["afi"] == h["afi"]:
- for w_acl in w["acls"]:
- w_names.append(w_acl["name"])
- for h_acl in h["acls"]:
- h_names.append(h_acl["name"])
- if h_acl["name"] == w_acl["name"]:
- for w_ace in w_acl['aces']:
- ace_diff = get_ace_diff(w_ace, h_acl["aces"])
- if ace_diff:
- diff = True
- h = {"afi": h["afi"], "acls": [{"name": h_acl["name"], "aces": h_acl["aces"]}]}
- remove_cmds = del_commands(h, have)
- commands.append(remove_cmds)
- for hname in h_names:
- if hname not in w_names:
- h = {"afi": h["afi"], "acls": [{"name": hname}]}
- remove_cmds = del_commands(h, have)
- if remove_cmds not in commands:
- commands.append(remove_cmds)
-
- if diff:
- config_cmds = set_commands(want, have)
- config_cmds = list(itertools.chain(*config_cmds))
- commands.append(config_cmds)
- if commands:
- commands = list(itertools.chain(*commands))
- 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
- """
- return set_commands(want, have)
-
- @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 = []
- if not want:
- for h in have:
- return_command = add_commands(h)
- for command in return_command:
- command = "no " + command
- commands.append(command)
- else:
- for w in want:
- return_command = del_commands(w, have)
- commands.append(return_command)
- commands = list(itertools.chain(*commands))
- return commands
-
-
-def set_commands(want, have):
- commands = []
- for w in want:
- wace_updated = []
- for h in have:
- if w['afi'] == h['afi']:
- for wacl in w["acls"]:
- for hacl in h["acls"]:
- if wacl['name'] == hacl['name']:
- want_aces = wacl['aces']
- for wace in wacl['aces']:
- for hace in hacl['aces']:
- if 'sequence' in wace.keys() and 'sequence' in hace.keys():
- if wace['sequence'] == hace['sequence']:
- wace_updated = get_updated_ace(wace, hace)
- if wace_updated:
- want_aces.pop(want_aces.index(wace))
- want_aces.append(wace_updated)
- return_command = add_commands(w)
- commands.append(return_command)
- return commands
-
-
-def get_updated_ace(w, h):
- # gives the ace to be updated in case of merge update.
- w_updated = w.copy()
- for hkey in h.keys():
- if hkey not in w.keys():
- w_updated.update({hkey: h[hkey]})
- else:
- w_updated.update({hkey: w[hkey]})
- return w_updated
-
-
-def add_commands(want):
- commandset = []
- protocol_name = {"51": "ahp", "47": "gre", "1": "icmp", "2": "igmp",
- "4": "ip", "89": "ospf", "103": "pim", "6": "tcp",
- "17": "udp", "112": "vrrp"}
- if not want:
- return commandset
- command = ""
- afi = "ip" if want["afi"] == "ipv4" else "ipv6"
- for acl in want["acls"]:
- if "standard" in acl.keys() and acl["standard"]:
- command = afi + " access-list standard " + acl["name"]
- else:
- command = afi + " access-list " + acl["name"]
- commandset.append(command)
- if "aces" not in acl.keys():
- continue
- for ace in acl["aces"]:
- command = ""
- if "sequence" in ace.keys():
- command = str(ace["sequence"])
- if "remark" in ace.keys():
- command = command + " remark " + ace["remark"]
- if "fragment_rules" in ace.keys() and ace["fragment_rules"]:
- command = command + " fragment-rules"
- if "grant" in ace.keys():
- command = command + " " + ace["grant"]
- if "vlan" in ace.keys():
- command = command + " vlan " + ace["vlan"]
- if "protocol" in ace.keys():
- protocol = ace["protocol"]
- if protocol.isdigit():
- if protocol in protocol_name.keys():
- protocol = protocol_name[protocol]
- command = command + " " + protocol
- if "source" in ace.keys():
- if "any" in ace["source"].keys():
- command = command + " any"
- elif "subnet_address" in ace["source"].keys():
- command = command + " " + ace["source"]["subnet_address"]
- elif "host" in ace["source"].keys():
- command = command + " host " + ace["source"]["host"]
- elif "address" in ace["source"].keys():
- command = command + " " + ace["source"]["address"] + " " + ace["source"]["wildcard_bits"]
- if "port_protocol" in ace["source"].keys():
- for op, val in ace["source"]["port_protocol"].items():
- if val.isdigit():
- val = socket.getservbyport(int(val))
- command = command + " " + op + " " + val
- if "destination" in ace.keys():
- if "any" in ace["destination"].keys():
- command = command + " any"
- elif "subnet_address" in ace["destination"].keys():
- command = command + " " + ace["destination"]["subnet_address"]
- elif "host" in ace["destination"].keys():
- command = command + " host " + ace["destination"]["host"]
- elif "address" in ace["destination"].keys():
- command = command + " " + ace["destination"]["address"] + " " + ace["destination"]["wildcard_bits"]
- if "port_protocol" in ace["destination"].keys():
- for op in ace["destination"]["port_protocol"].keys():
- command = command + " " + op + " " + ace["destination"]["port_protocol"][op]
- if "protocol_options" in ace.keys():
- for proto in ace["protocol_options"].keys():
- if proto == "icmp" or proto == "icmpv6":
- for icmp_msg in ace["protocol_options"][proto].keys():
- command = command + " " + icmp_msg
- elif proto == "ip" or proto == "ipv6":
- command = command + " nexthop-group " + ace["protocol_options"][proto]["nexthop_group"]
- elif proto == "tcp":
- for flag, val in ace["prtocol_options"][proto]["flags"].items():
- command = command + " " + val
- if "hop_limit" in ace.keys():
- for op, val in ace["hop_limit"].items():
- command = command + " hop-limit " + op + " " + val
- if "tracked" in ace.keys() and ace["tracked"]:
- command = command + " tracked"
- if "ttl" in ace.keys():
- for op, val in ace["ttl"].items():
- command = command + " ttl " + op + " " + str(val)
- if "fragments" in ace.keys():
- command = command + " fragments"
- if "log" in ace.keys():
- command = command + " log"
- commandset.append(command.strip())
- return commandset
-
-
-def del_commands(want, have):
- commandset = []
- command = ""
- have_command = []
- for h in have:
- have_configs = add_commands(h)
- have_command.append(have_configs)
- have_command = list(itertools.chain(*have_command))
- afi = "ip" if want["afi"] == "ipv4" else "ipv6"
- if "acls" not in want.keys():
- for have_cmd in have_command:
- access_list = re.search(r'(ip.*)\s+access-list .*', have_cmd)
- if access_list and access_list.group(1) == afi:
- commandset.append("no " + have_cmd)
- return commandset
-
- for acl in want["acls"]:
- ace_present = True
- if "standard" in acl.keys() and acl["standard"]:
- command = afi + " access-list standard " + acl["name"]
- else:
- command = afi + " access-list " + acl["name"]
- if "aces" not in acl.keys():
- ace_present = False
- commandset.append("no " + command)
- if ace_present:
- return_command = add_commands(want)
- for cmd in return_command:
- if "access-list" in cmd:
- commandset.append(cmd)
- continue
- seq = re.search(r'(\d+) (permit|deny|fragment-rules|remark) .*', cmd)
- if seq:
- commandset.append("no " + seq.group(1))
- else:
- commandset.append("no " + cmd)
- return commandset
-
-
-def get_ace_diff(want_ace, have_ace):
- # gives the diff of the aces passed.
- for h_a in have_ace:
- d = dict_diff(want_ace, h_a)
- if not d:
- break
- return d
diff --git a/lib/ansible/module_utils/network/eos/config/interfaces/interfaces.py b/lib/ansible/module_utils/network/eos/config/interfaces/interfaces.py
deleted file mode 100644
index 7687ae296f..0000000000
--- a/lib/ansible/module_utils/network/eos/config/interfaces/interfaces.py
+++ /dev/null
@@ -1,236 +0,0 @@
-# -*- 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 eos_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.network.common.cfg.base import ConfigBase
-from ansible.module_utils.network.common.utils import to_list, dict_diff, param_list_to_dict
-from ansible.module_utils.network.eos.facts.facts import Facts
-from ansible.module_utils.network.eos.utils.utils import normalize_interface
-
-
-class Interfaces(ConfigBase):
- """
- The eos_interfaces class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'interfaces',
- ]
-
- def get_interfaces_facts(self):
- """ 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)
- 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}
- commands = list()
- warnings = list()
-
- existing_interfaces_facts = self.get_interfaces_facts()
- commands.extend(self.set_config(existing_interfaces_facts))
- if commands:
- if not self._module.check_mode:
- self._connection.edit_config(commands)
- result['changed'] = True
- result['commands'] = commands
-
- changed_interfaces_facts = self.get_interfaces_facts()
-
- result['before'] = existing_interfaces_facts
- if result['changed']:
- result['after'] = 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
- """
- state = self._module.params['state']
- want = param_list_to_dict(want)
- have = param_list_to_dict(have)
- if state == 'overridden':
- commands = self._state_overridden(want, have)
- elif state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged':
- commands = self._state_merged(want, have)
- elif state == 'replaced':
- commands = self._state_replaced(want, 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 = []
- for key, desired in want.items():
- interface_name = normalize_interface(key)
- if interface_name in have:
- extant = have[interface_name]
- else:
- extant = dict()
-
- add_config = dict_diff(extant, desired)
- del_config = dict_diff(desired, extant)
-
- commands.extend(generate_commands(key, add_config, del_config))
-
- 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 key, extant in have.items():
- if key in want:
- desired = want[key]
- else:
- desired = dict()
-
- add_config = dict_diff(extant, desired)
- del_config = dict_diff(desired, extant)
-
- commands.extend(generate_commands(key, add_config, del_config))
-
- 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 = []
- for key, desired in want.items():
- interface_name = normalize_interface(key)
- if interface_name in have:
- extant = have[interface_name]
- else:
- extant = dict()
-
- add_config = dict_diff(extant, desired)
-
- commands.extend(generate_commands(key, add_config, {}))
-
- 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 in want:
- desired = dict()
- if key in have:
- extant = have[key]
- else:
- continue
-
- del_config = dict_diff(desired, extant)
-
- commands.extend(generate_commands(key, {}, del_config))
-
- return commands
-
-
-def generate_commands(interface, to_set, to_remove):
- commands = []
- for key, value in to_set.items():
- if value is None:
- continue
-
- if key == "enabled":
- commands.append('{0}shutdown'.format('no ' if value else ''))
- elif key == "speed":
- if value == "auto":
- commands.append("{0} {1}".format(key, value))
- else:
- commands.append('speed {0}{1}'.format(value, to_set['duplex']))
- elif key == "duplex":
- # duplex is handled with speed
- continue
- else:
- commands.append("{0} {1}".format(key, value))
-
- # Don't try to also remove the same key, if present in to_remove
- to_remove.pop(key, None)
-
- for key in to_remove.keys():
- if key == "enabled":
- commands.append('no shutdown')
- elif key == "speed":
- commands.append("speed auto")
- elif key == "duplex":
- # duplex is handled with speed
- continue
- else:
- commands.append("no {0}".format(key))
-
- if commands:
- commands.insert(0, "interface {0}".format(interface))
-
- return commands
diff --git a/lib/ansible/module_utils/network/eos/config/l2_interfaces/l2_interfaces.py b/lib/ansible/module_utils/network/eos/config/l2_interfaces/l2_interfaces.py
deleted file mode 100644
index 32e4c62306..0000000000
--- a/lib/ansible/module_utils/network/eos/config/l2_interfaces/l2_interfaces.py
+++ /dev/null
@@ -1,250 +0,0 @@
-# -*- 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 eos_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.module_utils.network.common.cfg.base import ConfigBase
-from ansible.module_utils.network.common.utils import to_list, param_list_to_dict
-from ansible.module_utils.network.eos.facts.facts import Facts
-from ansible.module_utils.network.eos.utils.utils import normalize_interface
-
-
-class L2_interfaces(ConfigBase):
- """
- The eos_l2_interfaces class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'l2_interfaces',
- ]
-
- def get_l2_interfaces_facts(self):
- """ 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)
- 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}
- commands = list()
- warnings = list()
-
- existing_l2_interfaces_facts = self.get_l2_interfaces_facts()
- commands.extend(self.set_config(existing_l2_interfaces_facts))
- if commands:
- if not self._module.check_mode:
- self._connection.edit_config(commands)
- result['changed'] = True
- result['commands'] = commands
-
- changed_l2_interfaces_facts = self.get_l2_interfaces_facts()
-
- result['before'] = existing_l2_interfaces_facts
- if result['changed']:
- result['after'] = 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
- """
- state = self._module.params['state']
- want = param_list_to_dict(want)
- have = param_list_to_dict(have)
- if state == 'overridden':
- commands = self._state_overridden(want, have)
- elif state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged':
- commands = self._state_merged(want, have)
- elif state == 'replaced':
- commands = self._state_replaced(want, 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 = []
- for key, desired in want.items():
- interface_name = normalize_interface(key)
- if interface_name in have:
- extant = have[interface_name]
- else:
- extant = dict()
-
- intf_commands = set_interface(desired, extant)
- intf_commands.extend(clear_interface(desired, extant))
-
- if intf_commands:
- commands.append("interface {0}".format(interface_name))
- commands.extend(intf_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 key, extant in have.items():
- if key in want:
- desired = want[key]
- else:
- desired = dict()
-
- intf_commands = set_interface(desired, extant)
- intf_commands.extend(clear_interface(desired, extant))
-
- if intf_commands:
- commands.append("interface {0}".format(key))
- commands.extend(intf_commands)
-
- 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 = []
- for key, desired in want.items():
- interface_name = normalize_interface(key)
- if interface_name in have:
- extant = have[interface_name]
- else:
- extant = dict()
-
- intf_commands = set_interface(desired, extant)
-
- if intf_commands:
- commands.append("interface {0}".format(interface_name))
- commands.extend(intf_commands)
-
- 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 in want:
- desired = dict()
- if key in have:
- extant = have[key]
- else:
- continue
-
- intf_commands = clear_interface(desired, extant)
-
- if intf_commands:
- commands.append("interface {0}".format(key))
- commands.extend(intf_commands)
-
- return commands
-
-
-def set_interface(want, have):
- commands = []
-
- want_mode = want.get("mode")
- if want_mode and want_mode != have.get("mode"):
- commands.append("switchport mode {0}".format(want_mode))
-
- wants_access = want.get("access")
- if wants_access:
- access_vlan = wants_access.get("vlan")
- if access_vlan and access_vlan != have.get("access", {}).get("vlan"):
- commands.append("switchport access vlan {0}".format(access_vlan))
-
- wants_trunk = want.get("trunk")
- if wants_trunk:
- has_trunk = have.get("trunk", {})
- native_vlan = wants_trunk.get("native_vlan")
- if native_vlan and native_vlan != has_trunk.get("native_vlan"):
- commands.append("switchport trunk native vlan {0}".format(native_vlan))
-
- allowed_vlans = want['trunk'].get("trunk_allowed_vlans")
- if allowed_vlans:
- allowed_vlans = ','.join(allowed_vlans)
- commands.append("switchport trunk allowed vlan {0}".format(allowed_vlans))
- return commands
-
-
-def clear_interface(want, have):
- commands = []
-
- if 'mode' in have and want.get('mode') is None:
- commands.append("no switchport mode")
-
- if "access" in have and not want.get('access'):
- commands.append("no switchport access vlan")
-
- has_trunk = have.get("trunk") or {}
- wants_trunk = want.get("trunk") or {}
- if "trunk_allowed_vlans" in has_trunk and "trunk_allowed_vlans" not in wants_trunk:
- commands.append("no switchport trunk allowed vlan")
- if "native_vlan" in has_trunk and "native_vlan" not in wants_trunk:
- commands.append("no switchport trunk native vlan")
- return commands
diff --git a/lib/ansible/module_utils/network/eos/config/l3_interfaces/l3_interfaces.py b/lib/ansible/module_utils/network/eos/config/l3_interfaces/l3_interfaces.py
deleted file mode 100644
index d32743fa86..0000000000
--- a/lib/ansible/module_utils/network/eos/config/l3_interfaces/l3_interfaces.py
+++ /dev/null
@@ -1,263 +0,0 @@
-# -*- 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 eos_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.module_utils.network.common.cfg.base import ConfigBase
-from ansible.module_utils.network.common.utils import to_list, param_list_to_dict
-from ansible.module_utils.network.eos.facts.facts import Facts
-from ansible.module_utils.network.eos.utils.utils import normalize_interface
-
-
-class L3_interfaces(ConfigBase):
- """
- The eos_l3_interfaces class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'l3_interfaces',
- ]
-
- def get_l3_interfaces_facts(self):
- """ 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)
- 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}
- commands = list()
- warnings = list()
-
- existing_l3_interfaces_facts = self.get_l3_interfaces_facts()
- commands.extend(self.set_config(existing_l3_interfaces_facts))
- if commands:
- if not self._module.check_mode:
- self._connection.edit_config(commands)
- result['changed'] = True
- result['commands'] = commands
-
- changed_l3_interfaces_facts = self.get_l3_interfaces_facts()
-
- result['before'] = existing_l3_interfaces_facts
- if result['changed']:
- result['after'] = 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
- """
- state = self._module.params['state']
- want = param_list_to_dict(want)
- have = param_list_to_dict(have)
- if state == 'overridden':
- commands = self._state_overridden(want, have)
- elif state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged':
- commands = self._state_merged(want, have)
- elif state == 'replaced':
- commands = self._state_replaced(want, 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 = []
- for key, desired in want.items():
- interface_name = normalize_interface(key)
- if interface_name in have:
- extant = have[interface_name]
- else:
- extant = dict()
- intf_commands = set_interface(desired, extant)
- intf_commands.extend(clear_interface(desired, extant))
-
- if intf_commands:
- commands.append("interface {0}".format(interface_name))
- commands.extend(intf_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 key, extant in have.items():
- if key in want:
- desired = want[key]
- else:
- desired = dict()
- if desired.get("ipv4"):
- for ipv4 in desired["ipv4"]:
- if ipv4["secondary"] is None:
- del ipv4["secondary"]
-
- intf_commands = set_interface(desired, extant)
- intf_commands.extend(clear_interface(desired, extant))
-
- if intf_commands:
- commands.append("interface {0}".format(key))
- commands.extend(intf_commands)
-
- 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 = []
- for key, desired in want.items():
- interface_name = normalize_interface(key)
- if interface_name in have:
- extant = have[interface_name]
- else:
- extant = dict()
-
- intf_commands = set_interface(desired, extant)
- if intf_commands:
- commands.append("interface {0}".format(interface_name))
- commands.extend(intf_commands)
-
- 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 in want:
- desired = dict()
- if key in have:
- extant = have[key]
- else:
- continue
-
- intf_commands = clear_interface(desired, extant)
-
- if intf_commands:
- commands.append("interface {0}".format(key))
- commands.extend(intf_commands)
-
- return commands
-
-
-def set_interface(want, have):
- commands = []
-
- want_ipv4 = set(tuple(address.items()) for address in want.get("ipv4") or [])
- have_ipv4 = set(tuple(address.items()) for address in have.get("ipv4") or [])
- for address in want_ipv4 - have_ipv4:
- address = dict(address)
- if "secondary" in address and not address["secondary"]:
- del address["secondary"]
- if tuple(address.items()) in have_ipv4:
- continue
-
- address_cmd = "ip address {0}".format(address["address"])
- if address.get("secondary"):
- address_cmd += " secondary"
- commands.append(address_cmd)
-
- want_ipv6 = set(tuple(address.items()) for address in want.get("ipv6") or [])
- have_ipv6 = set(tuple(address.items()) for address in have.get("ipv6") or [])
- for address in want_ipv6 - have_ipv6:
- address = dict(address)
- commands.append("ipv6 address {0}".format(address["address"]))
- return commands
-
-
-def clear_interface(want, have):
- commands = []
-
- want_ipv4 = set(tuple(address.items()) for address in want.get("ipv4") or [])
- have_ipv4 = set(tuple(address.items()) for address in have.get("ipv4") or [])
- if not want_ipv4 and have_ipv4:
- commands.append("no ip address")
- else:
- for address in have_ipv4 - want_ipv4:
- address = dict(address)
- if "secondary" not in address:
- address["secondary"] = False
- if tuple(address.items()) in want_ipv4:
- continue
-
- if address.get("secondary"):
- address_cmd = " {0} secondary".format(address["address"])
- commands.append(address_cmd)
-
- if "secondary" not in address:
- # Removing non-secondary removes all other interfaces
- break
-
- want_ipv6 = set(tuple(address.items()) for address in want.get("ipv6") or [])
- have_ipv6 = set(tuple(address.items()) for address in have.get("ipv6") or [])
- for address in have_ipv6 - want_ipv6:
- address = dict(address)
- commands.append("no ipv6 address {0}".format(address["address"]))
- return commands
diff --git a/lib/ansible/module_utils/network/eos/config/lacp/lacp.py b/lib/ansible/module_utils/network/eos/config/lacp/lacp.py
deleted file mode 100644
index 38d368238a..0000000000
--- a/lib/ansible/module_utils/network/eos/config/lacp/lacp.py
+++ /dev/null
@@ -1,161 +0,0 @@
-# -*- 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 eos_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.network.common.cfg.base import ConfigBase
-from ansible.module_utils.network.common.utils import to_list, dict_diff
-from ansible.module_utils.network.eos.facts.facts import Facts
-
-
-class Lacp(ConfigBase):
- """
- The eos_lacp class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'lacp',
- ]
-
- def get_lacp_facts(self):
- """ 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)
- 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()
-
- existing_lacp_facts = self.get_lacp_facts()
- commands.extend(self.set_config(existing_lacp_facts))
- if commands:
- if not self._module.check_mode:
- self._connection.edit_config(commands)
- result['changed'] = True
- result['commands'] = commands
-
- changed_lacp_facts = self.get_lacp_facts()
-
- result['before'] = existing_lacp_facts
- if result['changed']:
- result['after'] = 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['config'] or {}
- 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
- """
- state = self._module.params['state']
- if state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged':
- commands = self._state_merged(want, have)
- elif state == 'replaced':
- commands = self._state_replaced(want, 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 = []
- to_set = dict_diff(have, want)
- if 'system' in to_set:
- system = to_set['system']
- if 'priority' in system:
- commands.append('lacp system-priority {0}'.format(system['priority']))
-
- to_del = dict_diff(want, have)
- if 'system' in to_del:
- system = to_del['system']
- system_set = to_set.get('system', {})
- if 'priority' in system and 'priority' not in system_set:
- commands.append('no lacp system-priority')
-
- 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 = []
- to_set = dict_diff(have, want)
- if 'system' in to_set:
- system = to_set['system']
- if 'priority' in system:
- commands.append('lacp system-priority {0}'.format(system['priority']))
-
- 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 = []
- to_del = dict_diff(want, have)
- if 'system' in to_del:
- system = to_del['system']
- if 'priority' in system:
- commands.append('no lacp system-priority')
-
- return commands
diff --git a/lib/ansible/module_utils/network/eos/config/lacp_interfaces/lacp_interfaces.py b/lib/ansible/module_utils/network/eos/config/lacp_interfaces/lacp_interfaces.py
deleted file mode 100644
index ffd2f36676..0000000000
--- a/lib/ansible/module_utils/network/eos/config/lacp_interfaces/lacp_interfaces.py
+++ /dev/null
@@ -1,214 +0,0 @@
-# -*- 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 eos_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.network.common.cfg.base import ConfigBase
-from ansible.module_utils.network.common.utils import to_list, dict_diff, param_list_to_dict
-from ansible.module_utils.network.eos.facts.facts import Facts
-from ansible.module_utils.network.eos.utils.utils import normalize_interface
-
-
-class Lacp_interfaces(ConfigBase):
- """
- The eos_lacp_interfaces class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'lacp_interfaces',
- ]
-
- def get_lacp_interfaces_facts(self):
- """ 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)
- 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}
- warnings = list()
- commands = list()
-
- existing_lacp_interfaces_facts = self.get_lacp_interfaces_facts()
- commands.extend(self.set_config(existing_lacp_interfaces_facts))
- if commands:
- if not self._module.check_mode:
- self._connection.edit_config(commands)
- result['changed'] = True
- result['commands'] = commands
-
- changed_lacp_interfaces_facts = self.get_lacp_interfaces_facts()
-
- result['before'] = existing_lacp_interfaces_facts
- if result['changed']:
- result['after'] = 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
- """
- state = self._module.params['state']
- want = param_list_to_dict(want)
- have = param_list_to_dict(have)
- if state == 'overridden':
- commands = self._state_overridden(want, have)
- elif state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged':
- commands = self._state_merged(want, have)
- elif state == 'replaced':
- commands = self._state_replaced(want, 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 = []
- for key, desired in want.items():
- interface_name = normalize_interface(key)
- if interface_name in have:
- extant = have[interface_name]
- else:
- extant = dict()
-
- add_config = dict_diff(extant, desired)
- del_config = dict_diff(desired, extant)
-
- commands.extend(generate_commands(key, add_config, del_config))
-
- 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 key, extant in have.items():
- if key in want:
- desired = want[key]
- else:
- desired = dict()
-
- add_config = dict_diff(extant, desired)
- del_config = dict_diff(desired, extant)
-
- commands.extend(generate_commands(key, add_config, del_config))
-
- 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 = []
- for key, desired in want.items():
- interface_name = normalize_interface(key)
- if interface_name in have:
- extant = have[interface_name]
- else:
- extant = dict()
-
- add_config = dict_diff(extant, desired)
-
- commands.extend(generate_commands(key, add_config, {}))
-
- 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 in want:
- desired = dict()
- if key in have:
- extant = have[key]
- else:
- continue
-
- del_config = dict_diff(desired, extant)
-
- commands.extend(generate_commands(key, {}, del_config))
-
- return commands
-
-
-def generate_commands(interface, to_set, to_remove):
- commands = []
- for key in to_remove.keys():
- commands.append("no lacp {0}".format(key.replace("_", "-")))
-
- for key, value in to_set.items():
- if value is None:
- continue
-
- commands.append("lacp {0} {1}".format(key.replace("_", "-"), value))
-
- if commands:
- commands.insert(0, "interface {0}".format(interface))
-
- return commands
diff --git a/lib/ansible/module_utils/network/eos/config/lag_interfaces/lag_interfaces.py b/lib/ansible/module_utils/network/eos/config/lag_interfaces/lag_interfaces.py
deleted file mode 100644
index f9affa404a..0000000000
--- a/lib/ansible/module_utils/network/eos/config/lag_interfaces/lag_interfaces.py
+++ /dev/null
@@ -1,225 +0,0 @@
-# -*- 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 eos_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 ansible.module_utils.network.common.utils import to_list, dict_diff
-
-from ansible.module_utils.network.common.cfg.base import ConfigBase
-from ansible.module_utils.network.eos.facts.facts import Facts
-from ansible.module_utils.network.eos.utils.utils import normalize_interface
-
-
-class Lag_interfaces(ConfigBase):
- """
- The eos_lag_interfaces class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'lag_interfaces',
- ]
-
- def get_lag_interfaces_facts(self):
- """ 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)
- 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}
- commands = list()
- warnings = list()
-
- existing_lag_interfaces_facts = self.get_lag_interfaces_facts()
- commands.extend(self.set_config(existing_lag_interfaces_facts))
- if commands:
- if not self._module.check_mode:
- self._connection.edit_config(commands)
- result['changed'] = True
- result['commands'] = commands
-
- changed_lag_interfaces_facts = self.get_lag_interfaces_facts()
-
- result['before'] = existing_lag_interfaces_facts
- if result['changed']:
- result['after'] = 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']
- 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']
- if state == 'overridden':
- commands = self._state_overridden(want, have)
- elif state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged':
- commands = self._state_merged(want, have)
- elif state == 'replaced':
- commands = self._state_replaced(want, 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 = []
- for interface in want:
- interface_name = normalize_interface(interface["name"])
- for extant in have:
- if extant["name"] == interface_name:
- break
- else:
- extant = dict(name=interface_name)
-
- commands.extend(set_config(interface, extant))
- commands.extend(remove_config(interface, extant))
-
- 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 extant in have:
- for interface in want:
- if normalize_interface(interface["name"]) == extant["name"]:
- break
- else:
- interface = dict(name=extant["name"])
- commands.extend(remove_config(interface, extant))
-
- for interface in want:
- interface_name = normalize_interface(interface["name"])
- for extant in have:
- if extant["name"] == interface_name:
- break
- else:
- extant = dict(name=interface_name)
- commands.extend(set_config(interface, extant))
-
- 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 = []
- for interface in want:
- interface_name = normalize_interface(interface["name"])
- for extant in have:
- if extant["name"] == interface_name:
- break
- else:
- extant = dict(name=interface_name)
-
- commands.extend(set_config(interface, extant))
-
- 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 interface in want:
- interface_name = normalize_interface(interface["name"])
- for extant in have:
- if extant["name"] == interface_name:
- break
- else:
- extant = dict(name=interface_name)
-
- # Clearing all args, send empty dictionary
- interface = dict(name=interface_name)
- commands.extend(remove_config(interface, extant))
-
- return commands
-
-
-def set_config(want, have):
- commands = []
- to_set = dict_diff(have, want)
- for member in to_set.get("members", []):
- channel_id = want["name"][12:]
- commands.extend([
- "interface {0}".format(member["member"]),
- "channel-group {0} mode {1}".format(channel_id, member["mode"]),
- ])
-
- return commands
-
-
-def remove_config(want, have):
- commands = []
- if not want.get("members"):
- return ["no interface {0}".format(want["name"])]
-
- to_remove = dict_diff(want, have)
- for member in to_remove.get("members", []):
- commands.extend([
- "interface {0}".format(member["member"]),
- "no channel-group",
- ])
-
- return commands
diff --git a/lib/ansible/module_utils/network/eos/config/lldp_global/lldp_global.py b/lib/ansible/module_utils/network/eos/config/lldp_global/lldp_global.py
deleted file mode 100644
index 94f00087c2..0000000000
--- a/lib/ansible/module_utils/network/eos/config/lldp_global/lldp_global.py
+++ /dev/null
@@ -1,166 +0,0 @@
-#
-# -*- 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 eos_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.network.common.cfg.base import ConfigBase
-from ansible.module_utils.network.common.utils import dict_diff, to_list
-from ansible.module_utils.network.eos.facts.facts import Facts
-
-
-class Lldp_global(ConfigBase):
- """
- The eos_lldp_global 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):
- """ 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)
- lldp_global_facts = facts['ansible_network_resources'].get('lldp_global')
- if not lldp_global_facts:
- return {}
- return lldp_global_facts
-
- def execute_module(self):
- """ Execute the module
-
- :rtype: A dictionary
- :returns: The result from module execution
- """
- result = {'changed': False}
- warnings = list()
- commands = list()
-
- existing_lldp_global_facts = self.get_lldp_global_facts()
- commands.extend(self.set_config(existing_lldp_global_facts))
- if commands:
- if not self._module.check_mode:
- self._connection.edit_config(commands)
- result['changed'] = True
- result['commands'] = commands
-
- changed_lldp_global_facts = self.get_lldp_global_facts()
-
- result['before'] = existing_lldp_global_facts
- if result['changed']:
- result['after'] = 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'] or {}
- 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 == 'deleted':
- commands = state_deleted(want, have)
- elif state == 'merged':
- commands = state_merged(want, have)
- elif state == 'replaced':
- commands = state_replaced(want, have)
- return commands
-
-
-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 = set()
- # merged and deleted are likely to emit duplicate tlv-select commands
- commands.update(state_merged(want, have))
- commands.update(state_deleted(want, have))
-
- return list(commands)
-
-
-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 = []
- to_set = dict_diff(have, want)
- tlv_options = to_set.pop("tlv_select", {})
- for key, value in to_set.items():
- commands.append("lldp {0} {1}".format(key, value))
- for key, value in tlv_options.items():
- device_option = key.replace("_", "-")
- if value is True:
- commands.append("lldp tlv-select {0}".format(device_option))
- elif value is False:
- commands.append("no lldp tlv-select {0}".format(device_option))
-
- return commands
-
-
-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 = []
- to_remove = dict_diff(want, have)
- tlv_options = to_remove.pop("tlv_select", {})
- for key in to_remove:
- commands.append("no lldp {0}".format(key))
- for key, value in tlv_options.items():
- device_option = key.replace("_", "-")
- if value is False:
- commands.append("lldp tlv-select {0}".format(device_option))
- elif value is True:
- commands.append("no lldp tlv-select {0}".format(device_option))
-
- return commands
diff --git a/lib/ansible/module_utils/network/eos/config/lldp_interfaces/lldp_interfaces.py b/lib/ansible/module_utils/network/eos/config/lldp_interfaces/lldp_interfaces.py
deleted file mode 100644
index 93dcd8db9d..0000000000
--- a/lib/ansible/module_utils/network/eos/config/lldp_interfaces/lldp_interfaces.py
+++ /dev/null
@@ -1,216 +0,0 @@
-# -*- 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 eos_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.network.common.cfg.base import ConfigBase
-from ansible.module_utils.network.common.utils import to_list, dict_diff, param_list_to_dict
-from ansible.module_utils.network.eos.facts.facts import Facts
-from ansible.module_utils.network.eos.utils.utils import normalize_interface
-
-
-class Lldp_interfaces(ConfigBase):
- """
- The eos_lldp_interfaces class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'lldp_interfaces',
- ]
-
- def get_lldp_interfaces_facts(self):
- """ 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)
- 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()
-
- existing_lldp_interfaces_facts = self.get_lldp_interfaces_facts()
- commands.extend(self.set_config(existing_lldp_interfaces_facts))
- if commands:
- if not self._module.check_mode:
- self._connection.edit_config(commands)
- result['changed'] = True
- result['commands'] = commands
-
- changed_lldp_interfaces_facts = self.get_lldp_interfaces_facts()
-
- result['before'] = existing_lldp_interfaces_facts
- if result['changed']:
- result['after'] = 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']
- want = param_list_to_dict(want, remove_key=False)
- have = param_list_to_dict(have, remove_key=False)
- if state == 'overridden':
- commands = self._state_overridden(want, have)
- elif state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged':
- commands = self._state_merged(want, have)
- elif state == 'replaced':
- commands = self._state_replaced(want, 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 = []
- for key, desired in want.items():
- interface_name = normalize_interface(key)
- if interface_name in have:
- extant = have[interface_name]
- else:
- extant = dict(name=interface_name)
-
- add_config = dict_diff(extant, desired)
- del_config = dict_diff(desired, extant)
-
- commands.extend(generate_commands(interface_name, add_config, del_config))
-
- 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 key, extant in have.items():
- if key in want:
- desired = want[key]
- else:
- desired = dict(name=key)
-
- add_config = dict_diff(extant, desired)
- del_config = dict_diff(desired, extant)
-
- commands.extend(generate_commands(key, add_config, del_config))
-
- 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 = []
- for key, desired in want.items():
- interface_name = normalize_interface(key)
- if interface_name in have:
- extant = have[interface_name]
- else:
- extant = dict(name=interface_name)
-
- add_config = dict_diff(extant, desired)
-
- commands.extend(generate_commands(interface_name, add_config, {}))
-
- 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 in want.keys():
- interface_name = normalize_interface(key)
- desired = dict(name=interface_name)
- if interface_name in have:
- extant = have[interface_name]
- else:
- continue
-
- del_config = dict_diff(desired, extant)
-
- commands.extend(generate_commands(interface_name, {}, del_config))
-
- return commands
-
-
-def generate_commands(name, to_set, to_remove):
- commands = []
- for key, value in to_set.items():
- if value is None:
- continue
-
- prefix = "" if value else "no "
- commands.append("{0}lldp {1}".format(prefix, key))
-
- for key in to_remove:
- commands.append("lldp {0}".format(key))
-
- if commands:
- commands.insert(0, "interface {0}".format(name))
-
- return commands
diff --git a/lib/ansible/module_utils/network/eos/config/static_routes/static_routes.py b/lib/ansible/module_utils/network/eos/config/static_routes/static_routes.py
deleted file mode 100644
index ae3e4609c1..0000000000
--- a/lib/ansible/module_utils/network/eos/config/static_routes/static_routes.py
+++ /dev/null
@@ -1,390 +0,0 @@
-#
-# -*- 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 eos_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
-
-import re
-from ansible.module_utils.network.common.cfg.base import ConfigBase
-from ansible.module_utils.network.common.utils import remove_empties
-from ansible.module_utils.network.eos.facts.facts import Facts
-
-
-class Static_routes(ConfigBase):
- """
- The eos_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:
- for command in commands:
- self._connection.edit_config(command)
- 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':
- if not self._module.params['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=self._module.params['running_config'])
- else:
- changed_static_routes_facts = []
-
- 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
- """
- commands = []
- onbox_configs = []
- for h in existing_static_routes_facts:
- return_command = add_commands(h)
- for command in return_command:
- onbox_configs.append(command)
- config = self._module.params.get('config')
- want = []
- if config:
- for w in config:
- want.append(remove_empties(w))
- have = existing_static_routes_facts
- resp = self.set_state(want, have)
- for want_config in resp:
- if want_config not in onbox_configs:
- commands.append(want_config)
- return commands
-
- 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 ('merged', 'replaced', 'overridden') and not want:
- self._module.fail_json(msg='value of config parameter must not be empty for state {0}'.format(self.state))
- state = self._module.params['state']
- if state == 'overridden':
- commands = self._state_overridden(want, have)
- elif state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged' or self.state == 'rendered':
- commands = self._state_merged(want, have)
- elif state == 'replaced':
- commands = self._state_replaced(want, 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 = []
- haveconfigs = []
- vrf = get_vrf(want)
- dest = get_dest(want)
- for h in have:
- return_command = add_commands(h)
- for command in return_command:
- for d in dest:
- if d in command:
- if vrf is None:
- if "vrf" not in command:
- haveconfigs.append(command)
- else:
- if vrf in command:
- haveconfigs.append(command)
- wantconfigs = set_commands(want, have)
-
- removeconfigs = list(set(haveconfigs) - set(wantconfigs))
- for command in removeconfigs:
- commands.append("no " + command)
- for wantcmd in wantconfigs:
- commands.append(wantcmd)
- 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 = []
- haveconfigs = []
- for h in have:
- return_command = add_commands(h)
- for command in return_command:
- haveconfigs.append(command)
- wantconfigs = set_commands(want, have)
- idempotentconfigs = list(set(haveconfigs) - set(wantconfigs))
- if not idempotentconfigs:
- return idempotentconfigs
- removeconfigs = list(set(haveconfigs) - set(wantconfigs))
- for command in removeconfigs:
- commands.append("no " + command)
- for wantcmd in wantconfigs:
- commands.append(wantcmd)
- 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
- """
- return set_commands(want, have)
-
- @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 = []
- if not want:
- for h in have:
- return_command = add_commands(h)
- for command in return_command:
- command = "no " + command
- commands.append(command)
- else:
- for w in want:
- return_command = del_commands(w, have)
- for command in return_command:
- commands.append(command)
- return commands
-
-
-def set_commands(want, have):
- commands = []
- for w in want:
- return_command = add_commands(w)
- for command in return_command:
- commands.append(command)
- return commands
-
-
-def add_commands(want):
- commandset = []
- if not want:
- return commandset
- vrf = want["vrf"] if "vrf" in want.keys() and want["vrf"] is not None else None
- for address_family in want["address_families"]:
- for route in address_family["routes"]:
- for next_hop in route["next_hops"]:
- commands = []
- if address_family["afi"] == "ipv4":
- commands.append('ip route')
- else:
- commands.append('ipv6 route')
- if vrf:
- commands.append(' vrf ' + vrf)
- if not re.search(r'/', route["dest"]):
- mask = route["dest"].split()[1]
- cidr = get_net_size(mask)
- commands.append(' ' + route["dest"].split()[0] + '/' + cidr)
- else:
- commands.append(' ' + route["dest"])
- if "interface" in next_hop.keys():
- commands.append(' ' + next_hop["interface"])
- if "nexthop_grp" in next_hop.keys():
- commands.append(' Nexthop-Group' + ' ' + next_hop["nexthop_grp"])
- if "forward_router_address" in next_hop.keys():
- commands.append(' ' + next_hop["forward_router_address"])
- if "mpls_label" in next_hop.keys():
- commands.append(' label ' + str(next_hop["mpls_label"]))
- if "track" in next_hop.keys():
- commands.append(' track ' + next_hop["track"])
- if "admin_distance" in next_hop.keys():
- commands.append(' ' + str(next_hop["admin_distance"]))
- if "description" in next_hop.keys():
- commands.append(' name ' + str(next_hop["description"]))
- if "tag" in next_hop.keys():
- commands.append(' tag ' + str(next_hop["tag"]))
-
- config_commands = "".join(commands)
- commandset.append(config_commands)
- return commandset
-
-
-def del_commands(want, have):
- commandset = []
- haveconfigs = []
- for h in have:
- return_command = add_commands(h)
- for command in return_command:
- command = "no " + command
- haveconfigs.append(command)
- if want is None or "address_families" not in want.keys():
- commandset = haveconfigs
- if "address_families" not in want.keys() and "vrf" in want.keys():
- commandset = []
- for command in haveconfigs:
- if want["vrf"] in command:
- commandset.append(command)
- elif want is not None and "vrf" not in want.keys() and "address_families" not in want.keys():
- commandset = []
- for command in haveconfigs:
- if "vrf" not in command:
- commandset.append(command)
-
- elif want["address_families"]:
- vrf = want["vrf"] if "vrf" in want.keys() and want["vrf"] else None
- for address_family in want["address_families"]:
- if "routes" not in address_family.keys():
- for command in haveconfigs:
- afi = "ip " if address_family["afi"] == "ipv4" else "ipv6"
- if afi in command:
- if vrf:
- if vrf in command:
- commandset.append(command)
- else:
- commandset.append(command)
- else:
- for route in address_family["routes"]:
- if not re.search(r'/', route["dest"]):
- mask = route["dest"].split()[1]
- cidr = get_net_size(mask)
- destination = route["dest"].split()[0] + '/' + cidr
- else:
- destination = route["dest"]
- if "next_hops" not in route.keys():
- for command in haveconfigs:
- if destination in command:
- if vrf:
- if vrf in command:
- commandset.append(command)
- else:
- commandset.append(command)
- else:
- for next_hop in route["next_hops"]:
- commands = []
- if address_family["afi"] == "ipv4":
- commands.append('no ip route')
- else:
- commands.append('no ipv6 route')
- if vrf:
- commands.append(' vrf ' + vrf)
- commands.append(' ' + destination)
- if "interface" in next_hop.keys():
- commands.append(' ' + next_hop["interface"])
- if "nexhop_grp" in next_hop.keys():
- commands.append(' Nexthop-Group' + ' ' + next_hop["nexthop_grp"])
- if "forward_router_address" in next_hop.keys():
- commands.append(' ' + next_hop["forward_router_address"])
- if "mpls_label" in next_hop.keys():
- commands.append(' label ' + str(next_hop["mpls_label"]))
- if "track" in next_hop.keys():
- commands.append(' track ' + next_hop["track"])
- if "admin_distance" in next_hop.keys():
- commands.append(' ' + str(next_hop["admin_distance"]))
- if "description" in next_hop.keys():
- commands.append(' name ' + str(next_hop["description"]))
- if "tag" in next_hop.keys():
- commands.append(' tag ' + str(next_hop["tag"]))
-
- config_commands = "".join(commands)
- commandset.append(config_commands)
- return commandset
-
-
-def get_net_size(netmask):
- binary_str = ''
- netmask = netmask.split('.')
- for octet in netmask:
- binary_str += bin(int(octet))[2:].zfill(8)
- return str(len(binary_str.rstrip('0')))
-
-
-def get_vrf(config):
- vrf = ""
- for c in config:
- vrf = c["vrf"] if "vrf" in c.keys() and c["vrf"] else None
- return vrf
-
-
-def get_dest(config):
- dest = []
- for c in config:
- for address_family in c["address_families"]:
- for route in address_family["routes"]:
- dest.append(route['dest'])
- return dest
diff --git a/lib/ansible/module_utils/network/eos/config/vlans/vlans.py b/lib/ansible/module_utils/network/eos/config/vlans/vlans.py
deleted file mode 100644
index c2a701637d..0000000000
--- a/lib/ansible/module_utils/network/eos/config/vlans/vlans.py
+++ /dev/null
@@ -1,224 +0,0 @@
-# -*- 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 eos_vlans 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.network.common.cfg.base import ConfigBase
-from ansible.module_utils.network.common.utils import to_list, dict_diff, param_list_to_dict
-from ansible.module_utils.network.eos.facts.facts import Facts
-
-
-class Vlans(ConfigBase):
- """
- The eos_vlans class
- """
-
- gather_subset = [
- '!all',
- '!min',
- ]
-
- gather_network_resources = [
- 'vlans',
- ]
-
- def get_vlans_facts(self):
- """ 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)
- vlans_facts = facts['ansible_network_resources'].get('vlans')
- if not vlans_facts:
- return []
- return vlans_facts
-
- def execute_module(self):
- """ Execute the module
-
- :rtype: A dictionary
- :returns: The result from module execution
- """
- result = {'changed': False}
- warnings = list()
- commands = list()
-
- existing_vlans_facts = self.get_vlans_facts()
- commands.extend(self.set_config(existing_vlans_facts))
- if commands:
- if not self._module.check_mode:
- self._connection.edit_config(commands)
- result['changed'] = True
- result['commands'] = commands
-
- changed_vlans_facts = self.get_vlans_facts()
-
- result['before'] = existing_vlans_facts
- if result['changed']:
- result['after'] = changed_vlans_facts
-
- result['warnings'] = warnings
- return result
-
- def set_config(self, existing_vlans_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_vlans_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']
- want = param_list_to_dict(want, "vlan_id", remove_key=False)
- have = param_list_to_dict(have, "vlan_id", remove_key=False)
- if state == 'overridden':
- commands = self._state_overridden(want, have)
- elif state == 'deleted':
- commands = self._state_deleted(want, have)
- elif state == 'merged':
- commands = self._state_merged(want, have)
- elif state == 'replaced':
- commands = self._state_replaced(want, 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 = []
- for vlan_id, desired in want.items():
- if vlan_id in have:
- extant = have[vlan_id]
- else:
- extant = dict()
-
- add_config = dict_diff(extant, desired)
- del_config = dict_diff(desired, extant)
-
- commands.extend(generate_commands(vlan_id, add_config, del_config))
-
- 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 vlan_id, extant in have.items():
- if vlan_id in want:
- desired = want[vlan_id]
- else:
- desired = dict()
-
- add_config = dict_diff(extant, desired)
- del_config = dict_diff(desired, extant)
-
- commands.extend(generate_commands(vlan_id, add_config, del_config))
-
- # Handle vlans not already in config
- new_vlans = [vlan_id for vlan_id in want if vlan_id not in have]
- for vlan_id in new_vlans:
- desired = want[vlan_id]
- extant = dict(vlan_id=vlan_id)
- add_config = dict_diff(extant, desired)
-
- commands.extend(generate_commands(vlan_id, add_config, {}))
-
- 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 = []
- for vlan_id, desired in want.items():
- if vlan_id in have:
- extant = have[vlan_id]
- else:
- extant = dict()
-
- add_config = dict_diff(extant, desired)
-
- commands.extend(generate_commands(vlan_id, add_config, {}))
-
- 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 vlan_id in want:
- desired = dict()
- if vlan_id in have:
- extant = have[vlan_id]
- else:
- continue
-
- del_config = dict_diff(desired, extant)
-
- commands.extend(generate_commands(vlan_id, {}, del_config))
-
- return commands
-
-
-def generate_commands(vlan_id, to_set, to_remove):
- commands = []
- if "vlan_id" in to_remove:
- return ["no vlan {0}".format(vlan_id)]
-
- for key in to_remove:
- if key in to_set.keys():
- continue
- commands.append("no {0}".format(key))
-
- for key, value in to_set.items():
- if key == "vlan_id" or value is None:
- continue
-
- commands.append("{0} {1}".format(key, value))
-
- if commands:
- commands.insert(0, "vlan {0}".format(vlan_id))
- return commands
diff --git a/lib/ansible/module_utils/network/eos/eos.py b/lib/ansible/module_utils/network/eos/eos.py
deleted file mode 100644
index 22c675153e..0000000000
--- a/lib/ansible/module_utils/network/eos/eos.py
+++ /dev/null
@@ -1,630 +0,0 @@
-#
-# 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.
-#
-# (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.
-#
-import json
-import os
-import time
-
-from ansible.module_utils._text import to_text
-from ansible.module_utils.basic import env_fallback
-from ansible.module_utils.connection import Connection, ConnectionError
-from ansible.module_utils.network.common.config import NetworkConfig, dumps
-from ansible.module_utils.network.common.utils import to_list, ComplexList
-from ansible.module_utils.urls import fetch_url
-
-_DEVICE_CONNECTION = None
-
-eos_provider_spec = {
- 'host': dict(),
- 'port': dict(type='int'),
- 'username': dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
- 'password': dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), no_log=True),
- 'ssh_keyfile': dict(fallback=(env_fallback, ['ANSIBLE_NET_SSH_KEYFILE']), type='path'),
-
- 'authorize': dict(fallback=(env_fallback, ['ANSIBLE_NET_AUTHORIZE']), type='bool'),
- 'auth_pass': dict(no_log=True, fallback=(env_fallback, ['ANSIBLE_NET_AUTH_PASS'])),
-
- 'use_ssl': dict(default=True, type='bool'),
- 'use_proxy': dict(default=True, type='bool'),
- 'validate_certs': dict(default=True, type='bool'),
- 'timeout': dict(type='int'),
-
- 'transport': dict(default='cli', choices=['cli', 'eapi'])
-}
-eos_argument_spec = {
- 'provider': dict(type='dict', options=eos_provider_spec, removed_in_version=2.14),
-}
-
-
-def get_provider_argspec():
- return eos_provider_spec
-
-
-def get_connection(module):
- global _DEVICE_CONNECTION
- if not _DEVICE_CONNECTION:
- if is_local_eapi(module):
- conn = LocalEapi(module)
- else:
- connection_proxy = Connection(module._socket_path)
- cap = json.loads(connection_proxy.get_capabilities())
- if cap['network_api'] == 'cliconf':
- conn = Cli(module)
- elif cap['network_api'] == 'eapi':
- conn = HttpApi(module)
- _DEVICE_CONNECTION = conn
- return _DEVICE_CONNECTION
-
-
-class Cli:
-
- def __init__(self, module):
- self._module = module
- self._device_configs = {}
- self._session_support = None
- self._connection = None
-
- @property
- def supports_sessions(self):
- if self._session_support is None:
- self._session_support = self._get_connection().supports_sessions()
- return self._session_support
-
- def _get_connection(self):
- if self._connection:
- return self._connection
- self._connection = Connection(self._module._socket_path)
-
- return self._connection
-
- def get_config(self, flags=None):
- """Retrieves the current config from the device or cache
- """
- flags = [] if flags is None else flags
-
- cmd = 'show running-config '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- try:
- return self._device_configs[cmd]
- except KeyError:
- conn = self._get_connection()
- try:
- out = conn.get_config(flags=flags)
- except ConnectionError as exc:
- self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
-
- cfg = to_text(out, errors='surrogate_then_replace').strip()
- self._device_configs[cmd] = cfg
- return cfg
-
- def run_commands(self, commands, check_rc=True):
- """Run list of commands on remote device and return results
- """
- connection = self._get_connection()
- try:
- response = connection.run_commands(commands=commands, check_rc=check_rc)
- except ConnectionError as exc:
- self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- return response
-
- def load_config(self, commands, commit=False, replace=False):
- """Loads the config commands onto the remote device
- """
- conn = self._get_connection()
- try:
- response = conn.edit_config(commands, commit, replace)
- except ConnectionError as exc:
- message = getattr(exc, 'err', to_text(exc))
- if "check mode is not supported without configuration session" in message:
- self._module.warn("EOS can not check config without config session")
- response = {'changed': True}
- else:
- self._module.fail_json(msg="%s" % message, data=to_text(message, errors='surrogate_then_replace'))
-
- return response
-
- def get_diff(self, candidate=None, running=None, diff_match='line', diff_ignore_lines=None, path=None, diff_replace='line'):
- conn = self._get_connection()
- try:
- diff = conn.get_diff(candidate=candidate, running=running, diff_match=diff_match, diff_ignore_lines=diff_ignore_lines, path=path,
- diff_replace=diff_replace)
- except ConnectionError as exc:
- self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- return diff
-
- def get_capabilities(self):
- """Returns platform info of the remove device
- """
- if hasattr(self._module, '_capabilities'):
- return self._module._capabilities
-
- connection = self._get_connection()
- try:
- capabilities = connection.get_capabilities()
- except ConnectionError as exc:
- self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
- self._module._capabilities = json.loads(capabilities)
- return self._module._capabilities
-
-
-class LocalEapi:
-
- def __init__(self, module):
- self._module = module
- self._enable = None
- self._session_support = None
- self._device_configs = {}
-
- provider = module.params.get("provider") or {}
- host = provider.get('host')
- port = provider.get('port')
-
- self._module.params['url_username'] = provider.get('username')
- self._module.params['url_password'] = provider.get('password')
-
- if provider.get('use_ssl'):
- proto = 'https'
- else:
- proto = 'http'
-
- module.params['validate_certs'] = provider.get('validate_certs')
-
- self._url = '%s://%s:%s/command-api' % (proto, host, port)
-
- if provider.get("auth_pass"):
- self._enable = {'cmd': 'enable', 'input': provider.get('auth_pass')}
- else:
- self._enable = 'enable'
-
- @property
- def supports_sessions(self):
- if self._session_support is None:
- response = self.send_request(['show configuration sessions'])
- self._session_support = 'error' not in response
- return self._session_support
-
- def _request_builder(self, commands, output, reqid=None):
- params = dict(version=1, cmds=commands, format=output)
- return dict(jsonrpc='2.0', id=reqid, method='runCmds', params=params)
-
- def send_request(self, commands, output='text'):
- commands = to_list(commands)
-
- if self._enable:
- commands.insert(0, self._enable)
-
- body = self._request_builder(commands, output)
- data = self._module.jsonify(body)
-
- headers = {'Content-Type': 'application/json-rpc'}
- timeout = self._module.params['provider']['timeout']
- use_proxy = self._module.params['provider']['use_proxy']
-
- response, headers = fetch_url(
- self._module, self._url, data=data, headers=headers,
- method='POST', timeout=timeout, use_proxy=use_proxy
- )
-
- if headers['status'] != 200:
- self._module.fail_json(**headers)
-
- try:
- data = response.read()
- response = self._module.from_json(to_text(data, errors='surrogate_then_replace'))
- except ValueError:
- self._module.fail_json(msg='unable to load response from device', data=data)
-
- if self._enable and 'result' in response:
- response['result'].pop(0)
-
- return response
-
- def run_commands(self, commands, check_rc=True):
- """Runs list of commands on remote device and returns results
- """
- output = None
- queue = list()
- responses = list()
-
- def _send(commands, output):
- response = self.send_request(commands, output=output)
- if 'error' in response:
- err = response['error']
- self._module.fail_json(msg=err['message'], code=err['code'])
- return response['result']
-
- for item in to_list(commands):
- if is_json(item['command']):
- item['command'] = str(item['command']).replace('| json', '')
- item['output'] = 'json'
-
- if output and output != item['output']:
- responses.extend(_send(queue, output))
- queue = list()
-
- output = item['output'] or 'json'
- queue.append(item['command'])
-
- if queue:
- responses.extend(_send(queue, output))
-
- for index, item in enumerate(commands):
- try:
- responses[index] = responses[index]['output'].strip()
- except KeyError:
- pass
-
- return responses
-
- def get_config(self, flags=None):
- """Retrieves the current config from the device or cache
- """
- flags = [] if flags is None else flags
-
- cmd = 'show running-config '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- try:
- return self._device_configs[cmd]
- except KeyError:
- out = self.send_request(cmd)
- cfg = str(out['result'][0]['output']).strip()
- self._device_configs[cmd] = cfg
- return cfg
-
- def configure(self, commands):
- """Sends the ordered set of commands to the device
- """
- cmds = ['configure terminal']
- cmds.extend(commands)
-
- responses = self.send_request(commands)
- if 'error' in responses:
- err = responses['error']
- self._module.fail_json(msg=err['message'], code=err['code'])
-
- return responses[1:]
-
- def load_config(self, config, commit=False, replace=False):
- """Loads the configuration onto the remote devices
-
- If the device doesn't support configuration sessions, this will
- fallback to using configure() to load the commands. If that happens,
- there will be no returned diff or session values
- """
- use_session = os.getenv('ANSIBLE_EOS_USE_SESSIONS', True)
- try:
- use_session = int(use_session)
- except ValueError:
- pass
-
- if not all((bool(use_session), self.supports_sessions)):
- if commit:
- return self.configure(config)
- else:
- self._module.warn("EOS can not check config without config session")
- result = {'changed': True}
- return result
-
- session = 'ansible_%s' % int(time.time())
- result = {'session': session}
- commands = ['configure session %s' % session]
-
- if replace:
- commands.append('rollback clean-config')
-
- commands.extend(config)
-
- response = self.send_request(commands)
- if 'error' in response:
- commands = ['configure session %s' % session, 'abort']
- self.send_request(commands)
- err = response['error']
- error_text = []
- for data in err['data']:
- error_text.extend(data.get('errors', []))
- error_text = '\n'.join(error_text) or err['message']
- self._module.fail_json(msg=error_text, code=err['code'])
-
- commands = ['configure session %s' % session, 'show session-config diffs']
- if commit:
- commands.append('commit')
- else:
- commands.append('abort')
-
- response = self.send_request(commands, output='text')
- diff = response['result'][1]['output']
- if len(diff) > 0:
- result['diff'] = diff
-
- return result
-
- # get_diff added here to support connection=local and transport=eapi scenario
- def get_diff(self, candidate, running=None, diff_match='line', diff_ignore_lines=None, path=None, diff_replace='line'):
- diff = {}
-
- # prepare candidate configuration
- candidate_obj = NetworkConfig(indent=3)
- candidate_obj.load(candidate)
-
- if running and diff_match != 'none' and diff_replace != 'config':
- # running configuration
- running_obj = NetworkConfig(indent=3, contents=running, ignore_lines=diff_ignore_lines)
- configdiffobjs = candidate_obj.difference(running_obj, path=path, match=diff_match, replace=diff_replace)
-
- else:
- configdiffobjs = candidate_obj.items
-
- configdiff = dumps(configdiffobjs, 'commands') if configdiffobjs else ''
- diff['config_diff'] = configdiff if configdiffobjs else {}
- return diff
-
- def get_capabilities(self):
- # Implement the bare minimum to support eos_facts
- return dict(
- device_info=dict(
- network_os="eos",
- ),
- network_api="eapi",
- )
-
-
-class HttpApi:
- def __init__(self, module):
- self._module = module
- self._device_configs = {}
- self._session_support = None
- self._connection_obj = None
-
- @property
- def _connection(self):
- if not self._connection_obj:
- self._connection_obj = Connection(self._module._socket_path)
-
- return self._connection_obj
-
- @property
- def supports_sessions(self):
- if self._session_support is None:
- self._session_support = self._connection.supports_sessions()
- return self._session_support
-
- def run_commands(self, commands, check_rc=True):
- """Runs list of commands on remote device and returns results
- """
- output = None
- queue = list()
- responses = list()
-
- def run_queue(queue, output):
- try:
- response = to_list(self._connection.send_request(queue, output=output))
- except ConnectionError as exc:
- if check_rc:
- raise
- return to_list(to_text(exc))
-
- if output == 'json':
- response = [json.loads(item) for item in response]
- return response
-
- for item in to_list(commands):
- cmd_output = 'text'
- if isinstance(item, dict):
- command = item['command']
- if 'output' in item:
- cmd_output = item['output']
- else:
- command = item
-
- # Emulate '| json' from CLI
- if is_json(command):
- command = command.rsplit('|', 1)[0]
- cmd_output = 'json'
-
- if output and output != cmd_output:
- responses.extend(run_queue(queue, output))
- queue = list()
-
- output = cmd_output
- queue.append(command)
-
- if queue:
- responses.extend(run_queue(queue, output))
-
- return responses
-
- def get_config(self, flags=None):
- """Retrieves the current config from the device or cache
- """
- flags = [] if flags is None else flags
-
- cmd = 'show running-config '
- cmd += ' '.join(flags)
- cmd = cmd.strip()
-
- try:
- return self._device_configs[cmd]
- except KeyError:
- try:
- out = self._connection.send_request(cmd)
- except ConnectionError as exc:
- self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
-
- cfg = to_text(out).strip()
- self._device_configs[cmd] = cfg
- return cfg
-
- def get_diff(self, candidate=None, running=None, diff_match='line', diff_ignore_lines=None, path=None, diff_replace='line'):
- diff = {}
-
- # prepare candidate configuration
- candidate_obj = NetworkConfig(indent=3)
- candidate_obj.load(candidate)
-
- if running and diff_match != 'none' and diff_replace != 'config':
- # running configuration
- running_obj = NetworkConfig(indent=3, contents=running, ignore_lines=diff_ignore_lines)
- 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 load_config(self, config, commit=False, replace=False):
- """Loads the configuration onto the remote devices
-
- If the device doesn't support configuration sessions, this will
- fallback to using configure() to load the commands. If that happens,
- there will be no returned diff or session values
- """
- return self.edit_config(config, commit, replace)
-
- def edit_config(self, config, commit=False, replace=False):
- """Loads the configuration onto the remote devices
-
- If the device doesn't support configuration sessions, this will
- fallback to using configure() to load the commands. If that happens,
- there will be no returned diff or session values
- """
- session = 'ansible_%s' % int(time.time())
- result = {'session': session}
- banner_cmd = None
- banner_input = []
-
- commands = ['configure session %s' % session]
- if replace:
- commands.append('rollback clean-config')
-
- for command in config:
- if command.startswith('banner'):
- banner_cmd = command
- banner_input = []
- elif banner_cmd:
- if command == 'EOF':
- command = {'cmd': banner_cmd, 'input': '\n'.join(banner_input)}
- banner_cmd = None
- commands.append(command)
- else:
- banner_input.append(command)
- continue
- else:
- commands.append(command)
-
- try:
- response = self._connection.send_request(commands)
- except Exception:
- commands = ['configure session %s' % session, 'abort']
- response = self._connection.send_request(commands, output='text')
- raise
-
- commands = ['configure session %s' % session, 'show session-config diffs']
- if commit:
- commands.append('commit')
- else:
- commands.append('abort')
-
- response = self._connection.send_request(commands, output='text')
- diff = response[1].strip()
- if diff:
- result['diff'] = diff
-
- return result
-
- def get_capabilities(self):
- """Returns platform info of the remove device
- """
- try:
- capabilities = self._connection.get_capabilities()
- except ConnectionError as exc:
- self._module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))
-
- return json.loads(capabilities)
-
-
-def is_json(cmd):
- return to_text(cmd, errors='surrogate_then_replace').endswith('| json')
-
-
-def is_local_eapi(module):
- provider = module.params.get('provider')
- if provider:
- return provider.get('transport') == 'eapi'
- return False
-
-
-def to_command(module, commands):
- if is_local_eapi(module):
- default_output = 'json'
- else:
- default_output = 'text'
-
- transform = ComplexList(dict(
- command=dict(key=True),
- output=dict(default=default_output),
- prompt=dict(type='list'),
- answer=dict(type='list'),
- newline=dict(type='bool', default=True),
- sendonly=dict(type='bool', default=False),
- check_all=dict(type='bool', default=False),
- ), module)
-
- return transform(to_list(commands))
-
-
-def get_config(module, flags=None):
- flags = None if flags is None else flags
-
- conn = get_connection(module)
- return conn.get_config(flags)
-
-
-def run_commands(module, commands, check_rc=True):
- conn = get_connection(module)
- return conn.run_commands(to_command(module, commands), check_rc=check_rc)
-
-
-def load_config(module, config, commit=False, replace=False):
- conn = get_connection(module)
- return conn.load_config(config, commit, replace)
-
-
-def get_diff(self, candidate=None, running=None, diff_match='line', diff_ignore_lines=None, path=None, diff_replace='line'):
- conn = self.get_connection()
- return conn.get_diff(candidate=candidate, running=running, diff_match=diff_match, diff_ignore_lines=diff_ignore_lines, path=path, diff_replace=diff_replace)
-
-
-def get_capabilities(module):
- conn = get_connection(module)
- return conn.get_capabilities()
diff --git a/lib/ansible/module_utils/network/eos/facts/acl_interfaces/acl_interfaces.py b/lib/ansible/module_utils/network/eos/facts/acl_interfaces/acl_interfaces.py
deleted file mode 100644
index 89c3336a62..0000000000
--- a/lib/ansible/module_utils/network/eos/facts/acl_interfaces/acl_interfaces.py
+++ /dev/null
@@ -1,133 +0,0 @@
-#
-# -*- 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 eos 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
-
-
-import re
-from copy import deepcopy
-
-from ansible.module_utils.network.common import utils
-from ansible.module_utils.network.eos.argspec.acl_interfaces.acl_interfaces import Acl_interfacesArgs
-
-
-class Acl_interfacesFacts(object):
- """ The eos 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_device_data(self, connection):
- return connection.get('show running-config | include interface | access-group | traffic-filter')
-
- 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_device_data(connection)
- # split the config into instances of the resource
- resource_delim = 'interface'
- find_pattern = r'(?:^|\n)%s.*?(?=(?:^|\n)%s|$)' % (resource_delim,
- resource_delim)
- resources = [p.strip() for p in re.findall(find_pattern,
- data,
- re.DOTALL)]
- objs = []
- for resource in resources:
- if resource:
- obj = self.render_config(self.generated_spec, resource)
- if obj:
- objs.append(obj)
-
- ansible_facts['ansible_network_resources'].pop('acl_interfaces', None)
- facts = {}
- if objs:
- params = utils.validate_config(self.argument_spec, {'config': objs})
- facts['acl_interfaces'] = [utils.remove_empties(cfg) for cfg in 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)
- access_group_list = []
- access_group_v6_list = []
- acls_list = []
- group_list = []
- group_dict = {}
- config['name'] = utils.parse_conf_arg(conf, 'interface')
- conf_lines = conf.split('\n')
- for line in conf_lines:
- if config['name'] in line:
- continue
- access_group = utils.parse_conf_arg(line, 'ip access-group')
- # This module was verified on an ios device since vEOS doesnot support
- # acl_interfaces cnfiguration. In ios, ipv6 acl is configured as
- # traffic-filter and in eos it is access-group
-
- # access_group_v6 = utils.parse_conf_arg(line, 'ipv6 traffic-filter')
- access_group_v6 = utils.parse_conf_arg(line, 'ipv6 access-group')
- if access_group:
- access_group_list.append(access_group)
- if access_group_v6:
- access_group_v6_list.append(access_group_v6)
- if access_group_list:
- for acl in access_group_list:
- a_name = acl.split()[0]
- a_dir = acl.split()[1]
- acls_dict = {"name": a_name, "direction": a_dir}
- acls_list.append(acls_dict)
- group_dict = {"afi": "ipv4", "acls": acls_list}
- group_list.append(group_dict)
- acls_list = []
- if group_list:
- config['access_groups'] = group_list
- if access_group_v6_list:
- for acl in access_group_v6_list:
- a_name = acl.split()[0]
- a_dir = acl.split()[1]
- acls_dict = {"name": a_name, "direction": a_dir}
- acls_list.append(acls_dict)
- group_dict = {"acls": acls_list, "afi": "ipv6"}
- group_list.append(group_dict)
- acls_list = []
- if group_list:
- config['access_groups'] = group_list
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/eos/facts/acls/acls.py b/lib/ansible/module_utils/network/eos/facts/acls/acls.py
deleted file mode 100644
index edd7752c13..0000000000
--- a/lib/ansible/module_utils/network/eos/facts/acls/acls.py
+++ /dev/null
@@ -1,300 +0,0 @@
-#
-# -*- 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 eos 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 copy import deepcopy
-
-from ansible.module_utils.network.common import utils
-from ansible.module_utils.network.eos.argspec.acls.acls import AclsArgs
-
-
-class AclsFacts(object):
- """ The eos 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 running-config | section access-list')
-
- 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)
-
- # split the config into instances of the resource
- find_pattern = r'(?:^|\n)(?:ip|ipv6) access\-list.*?(?=(?:^|\n)(?:ip|ipv6) access\-list|$)'
- resources = [p for p in re.findall(find_pattern,
- data,
- re.DOTALL)]
-
- objs = []
- ipv4list = []
- ipv6list = []
- for resource in resources:
- if "ipv6" in resource:
- ipv6list.append(resource)
- else:
- ipv4list.append(resource)
- ipv4list = ["\n".join(ipv4list)]
- ipv6list = ["\n".join(ipv6list)]
- for resource in ipv4list:
- if resource:
- obj = self.render_config(self.generated_spec, resource)
- if obj:
- objs.append(obj)
- for resource in ipv6list:
- if resource:
- obj = self.render_config(self.generated_spec, resource)
- if obj:
- objs.append(obj)
-
- ansible_facts['ansible_network_resources'].pop('acls', None)
- facts = {}
- if objs:
- 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)
- afi_list = []
- acls_list = []
- name_dict = {}
- standard = 0
- operator = ['eq', 'lt', 'neq', 'range', 'gt']
- flags = ['ack', 'established', 'fin', 'psh', 'rst', 'syn', 'urg']
- others = ['hop_limit', 'log', 'ttl', 'fragments', 'tracked']
- for dev_config in conf.split('\n'):
- ace_dict = {}
- if not dev_config:
- continue
- if dev_config == '!':
- continue
- dev_config = dev_config.strip()
- matches = re.findall(r'(ip.*?) access-list (.*)', dev_config)
- if matches:
- afi = "ipv4" if matches[0][0] == "ip" else "ipv6"
- ace_list = []
- if bool(name_dict):
- acls_list.append(name_dict.copy())
- name_dict = {}
- if afi not in afi_list:
- afi_list.append(afi)
- config.update({"afi": afi})
- if "standard" in matches[0][1]:
- standard = 1
- name = matches[0][1].split()
- name_dict.update({"name": name[1]})
- name_dict.update({"standard": True})
- else:
- name_dict.update({"name": matches[0][1]})
- else:
- source_dict = {}
- dest_dict = {}
- dev_config = re.sub('-', '_', dev_config)
- dev_config_remainder = dev_config.split()
- if "fragment_rules" in dev_config:
- ace_dict.update({"sequence": dev_config_remainder.pop(0)})
- ace_dict.update({"fragment_rules": True})
- if "remark" in dev_config:
- ace_dict.update({"sequence": dev_config_remainder.pop(0)})
- ace_dict.update({"remark": ' '.join(dev_config_remainder[1:])})
- seq = re.search(r'\d+ (permit|deny) .*', dev_config)
- if seq:
- ace_dict.update({"sequence": dev_config_remainder.pop(0)})
- ace_dict.update({"grant": dev_config_remainder.pop(0)})
- if dev_config_remainder[0] == "vlan":
- vlan_str = ""
- dev_config_remainder.pop(0)
- if dev_config_remainder[0] == "inner":
- vlan_str = dev_config_remainder.pop(0) + " "
- vlan_str = dev_config_remainder.pop(0) + " " + dev_config_remainder.pop(0)
- ace_dict.update({"vlan": vlan_str})
- if not standard:
- protocol = dev_config_remainder[0]
- ace_dict.update({"protocol": dev_config_remainder.pop(0)})
- src_prefix = re.search(r'/', dev_config_remainder[0])
- src_address = re.search(r'[a-z\d:\.]+', dev_config_remainder[0])
- if dev_config_remainder[0] == "host":
- source_dict.update({"host": dev_config_remainder.pop(1)})
- dev_config_remainder.pop(0)
- elif dev_config_remainder[0] == "any":
- source_dict.update({"any": True})
- dev_config_remainder.pop(0)
- elif src_prefix:
- source_dict.update({"subnet_address": dev_config_remainder.pop(0)})
- elif src_address:
- source_dict.update({"address": dev_config_remainder.pop(0)})
- source_dict.update({"wildcard_bits": dev_config_remainder.pop(0)})
- if dev_config_remainder:
- if dev_config_remainder[0] in operator:
- port_dict = {}
- src_port = ""
- src_opr = dev_config_remainder.pop(0)
- portlist = dev_config_remainder[:]
- for config_remainder in portlist:
- addr = re.search(r'[\.\:]', config_remainder)
- if config_remainder == "any" or config_remainder == "host" or addr:
- break
- else:
- src_port = src_port + " " + config_remainder
- dev_config_remainder.pop(0)
- src_port = src_port.strip()
- port_dict.update({src_opr: src_port})
- source_dict.update({"port_protocol": port_dict})
- ace_dict.update({"source": source_dict})
- if not dev_config_remainder or standard:
- if dev_config_remainder and "log" in dev_config_remainder:
- ace_dict.update({"log": True})
- if bool(ace_dict):
- ace_list.append(ace_dict.copy())
- if len(ace_list):
- name_dict = name_dict.copy()
- name_dict.update({"aces": ace_list[:]})
- # acls_list.append(name_dict)
- continue
- dest_prefix = re.search(r'/', dev_config_remainder[0])
- dest_address = re.search(r'[a-z\d:\.]+', dev_config_remainder[0])
- if dev_config_remainder[0] == "host":
- dest_dict.update({"host": dev_config_remainder.pop(1)})
- dev_config_remainder.pop(0)
- elif dev_config_remainder[0] == "any":
- dest_dict.update({"any": True})
- dev_config_remainder.pop(0)
- elif dest_prefix:
- dest_dict.update({"subnet_address": dev_config_remainder.pop(0)})
- elif dest_address:
- dest_dict.update({"address": dev_config_remainder.pop(0)})
- dest_dict.update({"wildcard_bits": dev_config_remainder.pop(0)})
- if dev_config_remainder:
- if dev_config_remainder[0] in operator:
- port_dict = {}
- dest_port = ""
- dest_opr = dev_config_remainder.pop(0)
- portlist = dev_config_remainder[:]
- for config_remainder in portlist:
- if config_remainder in operator or config_remainder in others:
- break
- else:
- dest_port = dest_port + " " + config_remainder
- dev_config_remainder.pop(0)
- dest_port = dest_port.strip()
- port_dict.update({dest_opr: dest_port})
- dest_dict.update({"port_protocol": port_dict})
- ace_dict.update({"destination": dest_dict})
- protocol_option_dict = {}
- tcp_dict = {}
- icmp_dict = {}
- ip_dict = {}
- if not dev_config_remainder:
- if bool(ace_dict):
- ace_list.append(ace_dict.copy())
- if len(ace_list):
- name_dict = name_dict.copy()
- name_dict.update({"aces": ace_list[:]})
- # acls_list.append(name_dict)
- continue
- if protocol == "tcp" or "6":
- protocol = "tcp"
- flags_dict = {}
- if dev_config_remainder[0] in flags:
- flaglist = dev_config_remainder.copy()
- for config_remainder in flaglist:
- if config_remainder not in flags:
- break
- else:
- flags_dict.update({config_remainder: True})
- dev_config_remainder.pop(0)
- if bool(flags_dict):
- tcp_dict.update({"flags": flags_dict})
- if bool(tcp_dict):
- protocol_option_dict.update({"tcp": tcp_dict})
- if protocol == "icmp" or protocol == "icmpv6" \
- or protocol == "1" or protocol == "58":
- if protocol == "1":
- protocol = "icmp"
- elif protocol == "58":
- protocol = "icmpv6"
- if dev_config_remainder[0] not in others:
- icmp_dict.update({dev_config_remainder[0]: True})
- dev_config_remainder.pop(0)
- if bool(icmp_dict):
- protocol_option_dict.update({protocol: icmp_dict})
- if protocol == "ip" or "ipv6":
- if dev_config_remainder[0] == "nexthop_group":
- dev_config_remainder.pop(0)
- ip_dict.update({"nexthop_group": dev_config_remainder.pop(0)})
- if bool(ip_dict):
- protocol_option_dict.update({protocol: ip_dict})
- if bool(protocol_option_dict):
- ace_dict.update({"protocol_options": protocol_option_dict})
- if dev_config_remainder[0] == "ttl":
- dev_config_remainder.pop(0)
- op = dev_config_remainder.pop(0)
- ttl_dict = {op: dev_config_remainder.pop(0)}
- ace_dict.update({"ttl": ttl_dict})
- for config_remainder in dev_config_remainder:
- if config_remainder in others:
- if config_remainder == "hop_limit":
- hop_index = dev_config_remainder.index(config_remainder)
- hoplimit_dict = {dev_config_remainder[hop_index + 1]: dev_config_remainder[hop_index + 2]}
- ace_dict.update({"hop_limit": hoplimit_dict})
- dev_config_remainder.pop(0)
- continue
- ace_dict.update({config_remainder: True})
- dev_config_remainder.pop(0)
- if dev_config_remainder:
- config.update({"line": dev_config})
- return utils.remove_empties(config)
- if bool(ace_dict):
- ace_list.append(ace_dict.copy())
- if len(ace_list):
- name_dict = name_dict.copy()
- name_dict.update({"aces": ace_list[:]})
- acls_list.append(name_dict.copy())
- config.update({"acls": acls_list})
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/eos/facts/facts.py b/lib/ansible/module_utils/network/eos/facts/facts.py
deleted file mode 100644
index 4ff7d87150..0000000000
--- a/lib/ansible/module_utils/network/eos/facts/facts.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# -*- 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 eos
-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.module_utils.network.common.facts.facts import FactsBase
-from ansible.module_utils.network.eos.facts.interfaces.interfaces import InterfacesFacts
-from ansible.module_utils.network.eos.facts.l2_interfaces.l2_interfaces import L2_interfacesFacts
-from ansible.module_utils.network.eos.facts.l3_interfaces.l3_interfaces import L3_interfacesFacts
-from ansible.module_utils.network.eos.facts.lacp.lacp import LacpFacts
-from ansible.module_utils.network.eos.facts.lacp_interfaces.lacp_interfaces import Lacp_interfacesFacts
-from ansible.module_utils.network.eos.facts.lag_interfaces.lag_interfaces import Lag_interfacesFacts
-from ansible.module_utils.network.eos.facts.lldp_global.lldp_global import Lldp_globalFacts
-from ansible.module_utils.network.eos.facts.lldp_interfaces.lldp_interfaces import Lldp_interfacesFacts
-from ansible.module_utils.network.eos.facts.vlans.vlans import VlansFacts
-from ansible.module_utils.network.eos.facts.legacy.base import Default, Hardware, Config, Interfaces
-from ansible.module_utils.network.eos.facts.acl_interfaces.acl_interfaces import Acl_interfacesFacts
-from ansible.module_utils.network.eos.facts.acls.acls import AclsFacts
-from ansible.module_utils.network.eos.facts.static_routes.static_routes import Static_routesFacts
-
-
-FACT_LEGACY_SUBSETS = dict(
- default=Default,
- hardware=Hardware,
- interfaces=Interfaces,
- config=Config,
-)
-FACT_RESOURCE_SUBSETS = dict(
- interfaces=InterfacesFacts,
- l2_interfaces=L2_interfacesFacts,
- l3_interfaces=L3_interfacesFacts,
- lacp=LacpFacts,
- lacp_interfaces=Lacp_interfacesFacts,
- lag_interfaces=Lag_interfacesFacts,
- lldp_global=Lldp_globalFacts,
- lldp_interfaces=Lldp_interfacesFacts,
- vlans=VlansFacts,
- acl_interfaces=Acl_interfacesFacts,
- acls=AclsFacts,
- static_routes=Static_routesFacts,
-)
-
-
-class Facts(FactsBase):
- """ The fact class for eos
- """
-
- VALID_LEGACY_GATHER_SUBSETS = frozenset(FACT_LEGACY_SUBSETS.keys())
- VALID_RESOURCE_SUBSETS = frozenset(FACT_RESOURCE_SUBSETS.keys())
-
- def get_facts(self, legacy_facts_type=None, resource_facts_type=None, data=None):
- """ Collect the facts for eos
- :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/lib/ansible/module_utils/network/eos/facts/interfaces/interfaces.py b/lib/ansible/module_utils/network/eos/facts/interfaces/interfaces.py
deleted file mode 100644
index c3c515e6f5..0000000000
--- a/lib/ansible/module_utils/network/eos/facts/interfaces/interfaces.py
+++ /dev/null
@@ -1,107 +0,0 @@
-# -*- 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 eos interfaces fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-from copy import deepcopy
-import re
-
-from ansible.module_utils.network.common import utils
-from ansible.module_utils.network.eos.argspec.interfaces.interfaces import InterfacesArgs
-
-
-class InterfacesFacts(object):
- """ The eos 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_device_data(self, connection):
- return connection.get('show running-config | section ^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 configuration
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- data = self.get_device_data(connection)
-
- # operate on a collection of resource x
- config = data.split('interface ')
- objs = []
- for conf in config:
- if conf:
- obj = self.render_config(self.generated_spec, conf)
- if obj:
- objs.append(obj)
- facts = {'interfaces': []}
- if objs:
- 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)
-
- # populate the facts from the configuration
- config['name'] = re.match(r'(\S+)', conf).group(1)
- description = utils.parse_conf_arg(conf, 'description')
- if description is not None:
- config['description'] = description.replace('"', '')
- shutdown = utils.parse_conf_cmd_arg(conf, 'shutdown', False)
- config['enabled'] = shutdown if shutdown is False else True
- config['mtu'] = utils.parse_conf_arg(conf, 'mtu')
-
- speed_pair = utils.parse_conf_arg(conf, 'speed')
- if speed_pair:
- state = speed_pair.split()
- if state[0] == 'forced':
- state = state[1]
- else:
- state = state[0]
-
- if state == 'auto':
- config['duplex'] = state
- else:
- # remaining options are all e.g., 10half or 40gfull
- config['speed'] = state[:-4]
- config['duplex'] = state[-4:]
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/eos/facts/l2_interfaces/l2_interfaces.py b/lib/ansible/module_utils/network/eos/facts/l2_interfaces/l2_interfaces.py
deleted file mode 100644
index 86e8109864..0000000000
--- a/lib/ansible/module_utils/network/eos/facts/l2_interfaces/l2_interfaces.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# -*- 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 eos l2_interfaces fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-from copy import deepcopy
-import re
-
-from ansible.module_utils.network.common import utils
-from ansible.module_utils.network.eos.argspec.l2_interfaces.l2_interfaces import L2_interfacesArgs
-
-
-class L2_interfacesFacts(object):
- """ The eos 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_device_data(self, connection):
- return connection.get('show running-config | section ^interface')
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for l2_interfaces
-
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected configuration
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- data = self.get_device_data(connection)
-
- # operate on a collection of resource x
- config = data.split('interface ')
- objs = []
- for conf in config:
- if conf:
- obj = self.render_config(self.generated_spec, conf)
- if obj:
- objs.append(obj)
- facts = {}
- if objs:
- params = utils.validate_config(self.argument_spec, {'config': objs})
- facts['l2_interfaces'] = [utils.remove_empties(cfg) for cfg in 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)
-
- # populate the facts from the configuration
- config['name'] = re.match(r'(\S+)', conf).group(1).replace('"', '')
- has_mode = re.search(r"switchport mode (\S+)", conf)
- if has_mode:
- config["mode"] = has_mode.group(1)
-
- has_access = re.search(r"switchport access vlan (\d+)", conf)
- if has_access:
- config["access"] = {"vlan": int(has_access.group(1))}
-
- has_trunk = re.findall(r"switchport trunk (.+)", conf)
- if has_trunk:
- trunk = {}
- for match in has_trunk:
- has_native = re.match(r"native vlan (\d+)", match)
- if has_native:
- trunk["native_vlan"] = int(has_native.group(1))
- continue
-
- has_allowed = re.match(r"allowed vlan (\S+)", match)
- if has_allowed:
- # TODO: listify?
- trunk["trunk_allowed_vlans"] = has_allowed.group(1)
- continue
- config['trunk'] = trunk
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/eos/facts/l3_interfaces/l3_interfaces.py b/lib/ansible/module_utils/network/eos/facts/l3_interfaces/l3_interfaces.py
deleted file mode 100644
index 67041729df..0000000000
--- a/lib/ansible/module_utils/network/eos/facts/l3_interfaces/l3_interfaces.py
+++ /dev/null
@@ -1,101 +0,0 @@
-# -*- 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 eos l3_interfaces fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-from copy import deepcopy
-import re
-
-from ansible.module_utils.network.common import utils
-from ansible.module_utils.network.eos.argspec.l3_interfaces.l3_interfaces import L3_interfacesArgs
-
-
-class L3_interfacesFacts(object):
- """ The eos l3_interfaces fact class
- """
-
- def __init__(self, module, subspec='config', options='options'):
- self._module = module
- self.argument_spec = L3_interfacesArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for l3_interfaces
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected configuration
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- data = connection.get('show running-config | section ^interface')
-
- # split the config into instances of the resource
- resource_delim = 'interface'
- find_pattern = r'(?:^|\n)%s.*?(?=(?:^|\n)%s|$)' % (resource_delim, resource_delim)
- resources = [p.strip() for p in re.findall(find_pattern, data, re.DOTALL)]
-
- objs = []
- for resource in resources:
- if resource:
- obj = self.render_config(self.generated_spec, resource)
- if obj:
- objs.append(obj)
- facts = {}
- if objs:
- params = utils.validate_config(self.argument_spec, {'config': objs})
- facts['l3_interfaces'] = [utils.remove_empties(cfg) for cfg in 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)
-
- config['name'] = utils.parse_conf_arg(conf, 'interface')
-
- matches = re.findall(r'.*ip address (.+)$', conf, re.MULTILINE)
- if matches:
- config["ipv4"] = []
- for match in matches:
- address, dummy, remainder = match.partition(" ")
- ipv4 = {"address": address}
- if remainder == "secondary":
- ipv4["secondary"] = True
- config['ipv4'].append(ipv4)
-
- matches = re.findall(r'.*ipv6 address (.+)$', conf, re.MULTILINE)
- if matches:
- config["ipv6"] = []
- for match in matches:
- address, dummy, remainder = match.partition(" ")
- ipv6 = {"address": address}
- config['ipv6'].append(ipv6)
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/eos/facts/lacp/lacp.py b/lib/ansible/module_utils/network/eos/facts/lacp/lacp.py
deleted file mode 100644
index 370cb9df67..0000000000
--- a/lib/ansible/module_utils/network/eos/facts/lacp/lacp.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# -*- 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 eos 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
-
-import re
-from copy import deepcopy
-
-from ansible.module_utils.network.common import utils
-from ansible.module_utils.network.eos.argspec.lacp.lacp import LacpArgs
-
-
-class LacpFacts(object):
- """ The eos 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_device_data(self, connection):
- return connection.get('show running-config | section ^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 configuration
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- data = self.get_device_data(connection)
-
- # split the config into instances of the resource
- resource_delim = 'lacp'
- find_pattern = r'(?:^|\n)%s.*?(?=(?:^|\n)%s|$)' % (resource_delim,
- resource_delim)
- resources = [p.strip() for p in re.findall(find_pattern, data, re.DOTALL)]
-
- objs = {}
- for resource in resources:
- if resource:
- obj = self.render_config(self.generated_spec, resource)
- if obj:
- objs.update(obj)
-
- ansible_facts['ansible_network_resources'].pop('lacp', None)
- facts = {'lacp': {}}
- if objs:
- params = utils.validate_config(self.argument_spec, {'config': objs})
- 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)
- config['system']['priority'] = utils.parse_conf_arg(conf, 'system-priority')
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/eos/facts/lacp_interfaces/lacp_interfaces.py b/lib/ansible/module_utils/network/eos/facts/lacp_interfaces/lacp_interfaces.py
deleted file mode 100644
index 6f0560fe3b..0000000000
--- a/lib/ansible/module_utils/network/eos/facts/lacp_interfaces/lacp_interfaces.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# -*- 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 eos 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.network.common import utils
-from ansible.module_utils.network.eos.argspec.lacp_interfaces.lacp_interfaces import Lacp_interfacesArgs
-
-
-class Lacp_interfacesFacts(object):
- """ The eos 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_device_data(self, connection):
- return connection.get('show running-config | section lacp')
-
- 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 configuration
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- data = self.get_device_data(connection)
-
- # split the config into instances of the resource
- resource_delim = 'interface'
- find_pattern = r'(?:^|\n)%s.*?(?=(?:^|\n)%s|$)' % (resource_delim, resource_delim)
- resources = [p.strip() for p in re.findall(find_pattern, data, re.DOTALL)]
-
- objs = []
- for resource in resources:
- if resource:
- obj = self.render_config(self.generated_spec, resource)
- if obj:
- objs.append(obj)
-
- ansible_facts['ansible_network_resources'].pop('lacp_interfaces', None)
- facts = {}
- if objs:
- params = utils.validate_config(self.argument_spec, {'config': objs})
- facts['lacp_interfaces'] = [utils.remove_empties(cfg) for cfg in 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)
- config['name'] = utils.parse_conf_arg(conf, 'interface')
- config['port_priority'] = utils.parse_conf_arg(conf, 'port-priority')
- config['rate'] = utils.parse_conf_arg(conf, 'rate')
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/eos/facts/lag_interfaces/lag_interfaces.py b/lib/ansible/module_utils/network/eos/facts/lag_interfaces/lag_interfaces.py
deleted file mode 100644
index d93152a01b..0000000000
--- a/lib/ansible/module_utils/network/eos/facts/lag_interfaces/lag_interfaces.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# -*- 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 eos 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
-
-from copy import deepcopy
-import re
-
-from ansible.module_utils.network.common import utils
-from ansible.module_utils.network.eos.argspec.lag_interfaces.lag_interfaces import Lag_interfacesArgs
-
-
-class Lag_interfacesFacts(object):
- """ The eos lag_interfaces fact class
- """
-
- def __init__(self, module, subspec='config', options='options'):
- self._module = module
- self.argument_spec = Lag_interfacesArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for lag_interfaces
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected configuration
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- data = connection.get('show running-config | section ^interface')
-
- # split the config into instances of the resource
- resource_delim = 'interface'
- find_pattern = r'(?:^|\n)%s.*?(?=(?:^|\n)%s|$)' % (resource_delim,
- resource_delim)
- resources = [p.strip() for p in re.findall(find_pattern,
- data,
- re.DOTALL)]
-
- objs = {}
- for resource in resources:
- if resource:
- obj = self.render_config(self.generated_spec, resource)
- if obj:
- group_name = obj['name']
- if group_name in objs and "members" in obj:
- config = objs[group_name]
- if "members" not in config:
- config["members"] = []
- objs[group_name]['members'].extend(obj['members'])
- else:
- objs[group_name] = obj
- objs = list(objs.values())
- facts = {'lag_interfaces': []}
- if objs:
- params = utils.validate_config(self.argument_spec, {'config': objs})
- facts['lag_interfaces'] = [utils.remove_empties(cfg) for cfg in 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)
- interface_name = utils.parse_conf_arg(conf, 'interface')
- if interface_name.startswith("Port-Channel"):
- config["name"] = interface_name
- return utils.remove_empties(config)
-
- interface = {'member': interface_name}
- match = re.match(r'.*channel-group (\d+) mode (\S+)', conf, re.MULTILINE | re.DOTALL)
- if match:
- config['name'], interface['mode'] = match.groups()
- config["name"] = "Port-Channel" + config["name"]
- config['members'] = [interface]
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/eos/facts/legacy/base.py b/lib/ansible/module_utils/network/eos/facts/legacy/base.py
deleted file mode 100644
index 50bb82e849..0000000000
--- a/lib/ansible/module_utils/network/eos/facts/legacy/base.py
+++ /dev/null
@@ -1,182 +0,0 @@
-# -*- 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)
-
-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.network.eos.eos import run_commands, get_capabilities
-
-
-class FactsBase(object):
-
- COMMANDS = frozenset()
-
- def __init__(self, module):
- self.module = module
- self.warnings = list()
- self.facts = dict()
- self.responses = None
-
- def populate(self):
- self.responses = run_commands(self.module, list(self.COMMANDS), check_rc=False)
-
-
-class Default(FactsBase):
-
- SYSTEM_MAP = {
- 'serialNumber': 'serialnum',
- }
-
- COMMANDS = [
- 'show version | json',
- 'show hostname | json',
- ]
-
- def populate(self):
- super(Default, self).populate()
- data = self.responses[0]
- for key, value in iteritems(self.SYSTEM_MAP):
- if key in data:
- self.facts[value] = data[key]
-
- self.facts.update(self.responses[1])
- 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-filesystems',
- 'show version | json'
- ]
-
- def populate(self):
- super(Hardware, self).populate()
- self.facts.update(self.populate_filesystems())
- self.facts.update(self.populate_memory())
-
- def populate_filesystems(self):
- data = self.responses[0]
-
- if isinstance(data, dict):
- data = data['messages'][0]
-
- fs = re.findall(r'^Directory of (.+)/', data, re.M)
- return dict(filesystems=fs)
-
- def populate_memory(self):
- values = self.responses[1]
- return dict(
- memfree_mb=int(values['memFree']) / 1024,
- memtotal_mb=int(values['memTotal']) / 1024
- )
-
-
-class Config(FactsBase):
-
- COMMANDS = ['show running-config']
-
- def populate(self):
- super(Config, self).populate()
- self.facts['config'] = self.responses[0]
-
-
-class Interfaces(FactsBase):
-
- INTERFACE_MAP = {
- 'description': 'description',
- 'physicalAddress': 'macaddress',
- 'mtu': 'mtu',
- 'bandwidth': 'bandwidth',
- 'duplex': 'duplex',
- 'lineProtocolStatus': 'lineprotocol',
- 'interfaceStatus': 'operstatus',
- 'forwardingModel': 'type'
- }
-
- COMMANDS = [
- 'show interfaces | json',
- 'show lldp neighbors | json'
- ]
-
- def populate(self):
- super(Interfaces, self).populate()
-
- self.facts['all_ipv4_addresses'] = list()
- self.facts['all_ipv6_addresses'] = list()
-
- data = self.responses[0]
- self.facts['interfaces'] = self.populate_interfaces(data)
-
- data = self.responses[1]
- if data:
- self.facts['neighbors'] = self.populate_neighbors(data['lldpNeighbors'])
-
- def populate_interfaces(self, data):
- facts = dict()
- for key, value in iteritems(data['interfaces']):
- intf = dict()
-
- for remote, local in iteritems(self.INTERFACE_MAP):
- if remote in value:
- intf[local] = value[remote]
-
- if 'interfaceAddress' in value:
- intf['ipv4'] = dict()
- for entry in value['interfaceAddress']:
- intf['ipv4']['address'] = entry['primaryIp']['address']
- intf['ipv4']['masklen'] = entry['primaryIp']['maskLen']
- self.add_ip_address(entry['primaryIp']['address'], 'ipv4')
-
- if 'interfaceAddressIp6' in value:
- intf['ipv6'] = dict()
- for entry in value['interfaceAddressIp6']['globalUnicastIp6s']:
- intf['ipv6']['address'] = entry['address']
- intf['ipv6']['subnet'] = entry['subnet']
- self.add_ip_address(entry['address'], 'ipv6')
-
- facts[key] = intf
-
- return facts
-
- 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 populate_neighbors(self, neighbors):
- facts = dict()
- for value in neighbors:
- port = value['port']
- if port not in facts:
- facts[port] = list()
- lldp = dict()
- lldp['host'] = value['neighborDevice']
- lldp['port'] = value['neighborPort']
- facts[port].append(lldp)
- return facts
diff --git a/lib/ansible/module_utils/network/eos/facts/lldp_global/lldp_global.py b/lib/ansible/module_utils/network/eos/facts/lldp_global/lldp_global.py
deleted file mode 100644
index b74469d700..0000000000
--- a/lib/ansible/module_utils/network/eos/facts/lldp_global/lldp_global.py
+++ /dev/null
@@ -1,86 +0,0 @@
-#
-# -*- 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 eos lldp_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 __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-import re
-from copy import deepcopy
-
-from ansible.module_utils.network.common import utils
-from ansible.module_utils.network.eos.argspec.lldp_global.lldp_global import Lldp_globalArgs
-
-
-class Lldp_globalFacts(object):
- """ The eos lldp_global fact class
- """
-
- def __init__(self, module, subspec='config', options='options'):
- self._module = module
- self.argument_spec = Lldp_globalArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for lldp_global
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- data = connection.get('show running-config | section lldp')
-
- obj = {}
- if data:
- obj.update(self.render_config(self.generated_spec, data))
-
- ansible_facts['ansible_network_resources'].pop('lldp_global', None)
- facts = {}
- if obj:
- params = utils.validate_config(self.argument_spec, {'config': obj})
- facts['lldp_global'] = utils.remove_empties(params['config'])
- else:
- facts['lldp_global'] = {}
-
- 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['holdtime'] = utils.parse_conf_arg(conf, 'holdtime')
- config['reinit'] = utils.parse_conf_arg(conf, 'reinit')
- config['timer'] = utils.parse_conf_arg(conf, 'timer')
-
- for match in re.findall(r'^(no)? lldp tlv-select (\S+)', conf, re.MULTILINE):
- tlv_option = match[1].replace("-", "_")
- config['tlv_select'][tlv_option] = bool(match[0] != "no")
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/eos/facts/lldp_interfaces/lldp_interfaces.py b/lib/ansible/module_utils/network/eos/facts/lldp_interfaces/lldp_interfaces.py
deleted file mode 100644
index 8fa02697f6..0000000000
--- a/lib/ansible/module_utils/network/eos/facts/lldp_interfaces/lldp_interfaces.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# -*- 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 eos 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.module_utils.network.common import utils
-from ansible.module_utils.network.eos.argspec.lldp_interfaces.lldp_interfaces import Lldp_interfacesArgs
-
-
-class Lldp_interfacesFacts(object):
- """ The eos lldp_interfaces fact class
- """
-
- def __init__(self, module, subspec='config', options='options'):
- self._module = module
- self.argument_spec = Lldp_interfacesArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for lldp_interfaces
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected configuration
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- data = connection.get('show running-config | section lldp')
-
- # split the config into instances of the resource
- resource_delim = 'interface'
- find_pattern = r'(?:^|\n)%s.*?(?=(?:^|\n)%s|$)' % (resource_delim,
- resource_delim)
- resources = [p.strip() for p in re.findall(find_pattern,
- data,
- re.DOTALL)]
-
- objs = []
- for resource in resources:
- if resource:
- obj = self.render_config(self.generated_spec, resource)
- if obj:
- objs.append(obj)
-
- ansible_facts['ansible_network_resources'].pop('lldp_interfaces', None)
- facts = {}
- if objs:
- params = utils.validate_config(self.argument_spec, {'config': objs})
- facts['lldp_interfaces'] = [utils.remove_empties(cfg) for cfg in 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)
- config['name'] = utils.parse_conf_arg(conf, 'interface')
-
- matches = re.findall(r'(no )?lldp (\S+)', conf)
- for match in matches:
- config[match[1]] = not bool(match[0])
-
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/eos/facts/static_routes/static_routes.py b/lib/ansible/module_utils/network/eos/facts/static_routes/static_routes.py
deleted file mode 100644
index 810b2bfa0e..0000000000
--- a/lib/ansible/module_utils/network/eos/facts/static_routes/static_routes.py
+++ /dev/null
@@ -1,202 +0,0 @@
-#
-# -*- 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 eos 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.module_utils.network.common import utils
-from ansible.module_utils.network.eos.argspec.static_routes.static_routes import Static_routesArgs
-
-
-class Static_routesFacts(object):
- """ The eos 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('show running-config | grep route')
-
- 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)
-
- # split the config into instances of the resource
- resource_delim = 'ip.* route'
- find_pattern = r'(?:^|\n)%s.*?(?=(?:^|\n)%s|$)' % (resource_delim,
- resource_delim)
- resources = [p.strip() for p in re.findall(find_pattern, data)]
- resources_without_vrf = []
- resource_vrf = {}
- for resource in resources:
- if resource and "vrf" not in resource:
- resources_without_vrf.append(resource)
- else:
- vrf = re.search(r'ip(v6)* route vrf (.*?) .*', resource)
- if vrf.group(2) in resource_vrf.keys():
- vrf_val = resource_vrf[vrf.group(2)]
- vrf_val.append(resource)
- resource_vrf.update({vrf.group(2): vrf_val})
- else:
- resource_vrf.update({vrf.group(2): [resource]})
- resources_without_vrf = ["\n".join(resources_without_vrf)]
- for vrf in resource_vrf.keys():
- vrflist = ["\n".join(resource_vrf[vrf])]
- resource_vrf.update({vrf: vrflist})
- objs = []
- for resource in resources_without_vrf:
- if resource:
- obj = self.render_config(self.generated_spec, resource)
- if obj:
- objs.append(obj)
- for resource in resource_vrf.keys():
- if resource:
- obj = self.render_config(self.generated_spec, resource_vrf[resource][0])
- if obj:
- objs.append(obj)
- ansible_facts['ansible_network_resources'].pop('static_routes', None)
- facts = {}
- if objs:
- 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)
- address_family_dict = {}
- route_dict = {}
- dest_list = []
- afi_list = []
- vrf_list = []
- routes = []
- config["address_families"] = []
- next_hops = {}
- interface_list = ["Ethernet", "Loopback", "Management",
- "Port-Channel", "Tunnel", "Vlan", "Vxlan", "vtep"]
- conf_list = conf.split('\n')
- for conf_elem in conf_list:
- matches = re.findall(r'(ip|ipv6) route ([\d\.\/:]+|vrf) (.+)$', conf_elem)
- if matches:
- remainder = matches[0][2].split()
- route_update = False
- if matches[0][1] == "vrf":
- vrf = remainder.pop(0)
- # new vrf
- if vrf not in vrf_list and vrf_list:
- route_dict.update({"next_hops": next_hops})
- routes.append(route_dict)
- address_family_dict.update({"routes": routes})
- config["address_families"].append(address_family_dict)
- route_update = True
- config.update({"vrf": vrf})
- vrf_list.append(vrf)
- dest = remainder.pop(0)
- else:
- config["vrf"] = None
- dest = matches[0][1]
- afi = "ipv4" if matches[0][0] == "ip" else "ipv6"
- if afi not in afi_list:
- if afi_list and not route_update:
- # new afi and not the first updating all prev configs
- route_dict.update({"next_hops": next_hops})
- routes.append(route_dict)
- address_family_dict.update({"routes": routes})
- config["address_families"].append(address_family_dict)
- route_update = True
- address_family_dict = {}
- address_family_dict.update({"afi": afi})
- routes = []
- afi_list.append(afi)
- # To check the format of the dest
- prefix = re.search(r'/', dest)
- if not prefix:
- dest = dest + ' ' + remainder.pop(0)
- if dest not in dest_list:
- # For new dest and not the first dest
- if dest_list and not route_update:
- route_dict.update({"next_hops": next_hops})
- routes.append(route_dict)
- dest_list.append(dest)
- next_hops = []
- route_dict = {}
- route_dict.update({"dest": dest})
- nexthops = {}
- nxthop_addr = re.search(r'[\.\:]', remainder[0])
- if nxthop_addr:
- nexthops.update({"interface": remainder.pop(0)})
- if remainder and remainder[0] == "label":
- nexthops.update({"mpls_label": remainder.pop(1)})
- remainder.pop(0)
- elif re.search(r'Nexthop-Group', remainder[0]):
- nexthops.update({"nexthop_grp": remainder.pop(1)})
- remainder.pop(0)
- else:
- interface = remainder.pop(0)
- if interface in interface_list:
- interface = interface + " " + remainder.pop(0)
- nexthops.update({"interface": interface})
- for attribute in remainder:
- forward_addr = re.search(r'([\dA-Fa-f]+[:\.]+)+[\dA-Fa-f]+', attribute)
- if forward_addr:
- nexthops.update({"forward_router_address": remainder.pop(remainder.index(attribute))})
- for attribute in remainder:
- for params in ["tag", "name", "track"]:
- if attribute == params:
- keyname = params
- if attribute == "name":
- keyname = "description"
- nexthops.update({keyname: remainder.pop(remainder.index(attribute) + 1)})
- remainder.pop(remainder.index(attribute))
- if remainder:
- metric = re.search(r'\d+', remainder[0])
- if metric:
- nexthops.update({"admin_distance": remainder.pop(0)})
- next_hops.append(nexthops)
- route_dict.update({"next_hops": next_hops})
- routes.append(route_dict)
- address_family_dict.update({"routes": routes})
- config["address_families"].append(address_family_dict)
- return utils.remove_empties(config)
diff --git a/lib/ansible/module_utils/network/eos/facts/vlans/vlans.py b/lib/ansible/module_utils/network/eos/facts/vlans/vlans.py
deleted file mode 100644
index 0e01b6c216..0000000000
--- a/lib/ansible/module_utils/network/eos/facts/vlans/vlans.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# -*- 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 eos vlans fact class
-It is in this file the configuration is collected from the device
-for a given resource, parsed, and the facts tree is populated
-based on the configuration.
-"""
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-from copy import deepcopy
-import re
-
-from ansible.module_utils.network.common import utils
-from ansible.module_utils.network.eos.argspec.vlans.vlans import VlansArgs
-
-
-class VlansFacts(object):
- """ The eos vlans fact class
- """
-
- def __init__(self, module, subspec='config', options='options'):
- self._module = module
- self.argument_spec = VlansArgs.argument_spec
- spec = deepcopy(self.argument_spec)
- if subspec:
- if options:
- facts_argument_spec = spec[subspec][options]
- else:
- facts_argument_spec = spec[subspec]
- else:
- facts_argument_spec = spec
-
- self.generated_spec = utils.generate_dict(facts_argument_spec)
-
- def populate_facts(self, connection, ansible_facts, data=None):
- """ Populate the facts for vlans
- :param connection: the device connection
- :param ansible_facts: Facts dictionary
- :param data: previously collected conf
- :rtype: dictionary
- :returns: facts
- """
- if not data:
- data = connection.get('show running-config | section ^vlan')
-
- # split the config into instances of the resource
- resource_delim = 'vlan'
- find_pattern = r'(?:^|\n)%s.*?(?=(?:^|\n)%s|$)' % (resource_delim,
- resource_delim)
- resources = [p.strip() for p in re.findall(find_pattern,
- data,
- re.DOTALL)]
-
- objs = []
- for resource in resources:
- if resource:
- obj = self.render_config(self.generated_spec, resource)
- if obj:
- objs.extend(obj)
-
- ansible_facts['ansible_network_resources'].pop('vlans', None)
- facts = {}
- if objs:
- params = utils.validate_config(self.argument_spec, {'config': objs})
- facts['vlans'] = [utils.remove_empties(cfg) for cfg in 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)
- vlans = []
-
- vlan_list = vlan_to_list(utils.parse_conf_arg(conf, 'vlan'))
- for vlan in vlan_list:
- config['vlan_id'] = vlan
- config['name'] = utils.parse_conf_arg(conf, 'name')
- config['state'] = utils.parse_conf_arg(conf, 'state')
-
- vlans.append(utils.remove_empties(config))
-
- return vlans
-
-
-def vlan_to_list(vlan_str):
- vlans = []
- for vlan in vlan_str.split(','):
- if '-' in vlan:
- start, stop = vlan.split('-')
- vlans.extend(range(int(start), int(stop) + 1))
- else:
- vlans.append(int(vlan))
-
- return vlans
diff --git a/lib/ansible/module_utils/network/eos/providers/cli/config/bgp/address_family.py b/lib/ansible/module_utils/network/eos/providers/cli/config/bgp/address_family.py
deleted file mode 100644
index 0e50f6d518..0000000000
--- a/lib/ansible/module_utils/network/eos/providers/cli/config/bgp/address_family.py
+++ /dev/null
@@ -1,129 +0,0 @@
-#
-# (c) 2019, Ansible by Red Hat, inc
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-import re
-
-from ansible.module_utils.six import iteritems
-from ansible.module_utils.network.common.utils import to_list
-from ansible.module_utils.network.eos.providers.providers import CliProvider
-from ansible.module_utils.network.eos.providers.cli.config.bgp.neighbors import AFNeighbors
-
-
-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' % item['afi']
- context_commands = list()
-
- if config:
- context_path = [router_context, context]
- context_config = self.get_config_context(config, context_path, indent=2)
-
- 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 self.params['operation'] == 'replace':
- 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_auto_summary(self, item, config=None):
- cmd = 'auto-summary'
- if item['auto_summary'] is False:
- cmd = 'no %s' % cmd
- if not config or cmd not in config:
- return cmd
-
- def _render_synchronization(self, item, config=None):
- cmd = 'synchronization'
- if item['synchronization'] is False:
- cmd = 'no %s' % cmd
- if not config or cmd not in config:
- return cmd
-
- 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-map %s' % entry['route_map']
-
- if not config or cmd not in config:
- commands.append(cmd)
-
- if self.params['operation'] == 'replace':
- if config:
- 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['route_map']:
- cmd += ' route-map %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
-
- def _render_neighbors(self, item, config):
- """ generate bgp neighbor configuration
- """
- return AFNeighbors(self.params).render(config, nbr_list=item['neighbors'])
diff --git a/lib/ansible/module_utils/network/eos/providers/cli/config/bgp/neighbors.py b/lib/ansible/module_utils/network/eos/providers/cli/config/bgp/neighbors.py
deleted file mode 100644
index 329916b69f..0000000000
--- a/lib/ansible/module_utils/network/eos/providers/cli/config/bgp/neighbors.py
+++ /dev/null
@@ -1,173 +0,0 @@
-#
-# (c) 2019, Ansible by Red Hat, inc
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-import re
-
-from ansible.module_utils.six import iteritems
-from ansible.module_utils.network.common.utils import to_list
-from ansible.module_utils.network.eos.providers.providers import CliProvider
-
-
-class Neighbors(CliProvider):
-
- def render(self, config=None, nbr_list=None):
- commands = list()
- safe_list = list()
- if not nbr_list:
- nbr_list = self.get_value('config.neighbors')
-
- for item in nbr_list:
- neighbor_commands = list()
- context = 'neighbor %s' % item['neighbor']
- cmd = '%s remote-as %s' % (context, item['remote_as'])
-
- if not config or cmd not in config:
- neighbor_commands.append(cmd)
-
- for key, value in iteritems(item):
- if value is not None:
- meth = getattr(self, '_render_%s' % key, None)
- if meth:
- resp = meth(item, config)
- if resp:
- neighbor_commands.extend(to_list(resp))
-
- commands.extend(neighbor_commands)
- safe_list.append(context)
-
- if self.params['operation'] == 'replace':
- 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_description(self, item, config=None):
- cmd = 'neighbor %s description %s' % (item['neighbor'], item['description'])
- if not config or cmd not in config:
- return cmd
-
- def _render_enabled(self, item, config=None):
- cmd = 'neighbor %s shutdown' % item['neighbor']
- if item['enabled'] is True:
- if not config or cmd in config:
- cmd = 'no %s' % cmd
- return cmd
- elif not config or cmd not in config:
- return cmd
-
- def _render_update_source(self, item, config=None):
- cmd = 'neighbor %s update-source %s' % (item['neighbor'], item['update_source'])
- if not config or cmd not in config:
- return cmd
-
- def _render_password(self, item, config=None):
- cmd = 'neighbor %s password %s' % (item['neighbor'], item['password'])
- if not config or cmd not in config:
- return cmd
-
- def _render_ebgp_multihop(self, item, config=None):
- cmd = 'neighbor %s ebgp-multihop %s' % (item['neighbor'], item['ebgp_multihop'])
- if not config or cmd not in config:
- return cmd
-
- def _render_peer_group(self, item, config=None):
- cmd = 'neighbor %s peer-group %s' % (item['neighbor'], item['peer_group'])
- if not config or cmd not in config:
- return cmd
-
- def _render_route_reflector_client(self, item, config=None):
- cmd = 'neighbor %s route-reflector-client' % item['neighbor']
- if item['route_reflector_client'] is False:
- if not config or cmd in config:
- cmd = 'no %s' % cmd
- return cmd
- elif not config or cmd not in config:
- return cmd
-
- def _render_maximum_prefix(self, item, config=None):
- cmd = 'neighbor %s maximum-routes %s' % (item['neighbor'], item['maximum_prefix'])
- if not config or cmd not in config:
- return cmd
-
- def _render_remove_private_as(self, item, config=None):
- cmd = 'neighbor %s remove-private-AS' % item['neighbor']
- if item['remove_private_as'] is False:
- if not config or cmd in config:
- cmd = 'no %s' % cmd
- return cmd
- elif 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']
- neighbor = item['neighbor']
-
- if keepalive and holdtime:
- cmd = 'neighbor %s timers %s %s' % (neighbor, keepalive, holdtime)
- if not config or cmd not in config:
- return cmd
-
-
-class AFNeighbors(CliProvider):
-
- def render(self, config=None, nbr_list=None):
- commands = list()
- if not nbr_list:
- return
-
- for item in nbr_list:
- neighbor_commands = list()
- for key, value in iteritems(item):
- if value is not None:
- meth = getattr(self, '_render_%s' % key, None)
- if meth:
- resp = meth(item, config)
- if resp:
- neighbor_commands.extend(to_list(resp))
-
- commands.extend(neighbor_commands)
-
- return commands
-
- def _render_activate(self, item, config=None):
- cmd = 'neighbor %s activate' % item['neighbor']
- if item['activate'] is False:
- if not config or cmd in config:
- cmd = 'no %s' % cmd
- return cmd
- elif not config or cmd not in config:
- return cmd
-
- def _render_default_originate(self, item, config=None):
- cmd = 'neighbor %s default-originate' % item['neighbor']
- if item['activate'] is False:
- if not config or cmd in config:
- cmd = 'no %s' % cmd
- return cmd
- elif not config or cmd not in config:
- return cmd
-
- def _render_graceful_restart(self, item, config=None):
- cmd = 'neighbor %s graceful-restart' % item['neighbor']
- if item['activate'] is False:
- if not config or cmd in config:
- cmd = 'no %s' % cmd
- return cmd
- elif not config or cmd not in config:
- return cmd
-
- def _render_weight(self, item, config=None):
- cmd = 'neighbor %s weight %s' % (item['neighbor'], item['weight'])
- if not config or cmd not in config:
- return cmd
diff --git a/lib/ansible/module_utils/network/eos/providers/cli/config/bgp/process.py b/lib/ansible/module_utils/network/eos/providers/cli/config/bgp/process.py
deleted file mode 100644
index a2f40affae..0000000000
--- a/lib/ansible/module_utils/network/eos/providers/cli/config/bgp/process.py
+++ /dev/null
@@ -1,163 +0,0 @@
-#
-# (c) 2019, Ansible by Red Hat, inc
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-import re
-
-from ansible.module_utils.six import iteritems
-from ansible.module_utils.network.common.utils import to_list
-from ansible.module_utils.network.eos.providers.providers import register_provider
-from ansible.module_utils.network.eos.providers.providers import CliProvider
-from ansible.module_utils.network.eos.providers.cli.config.bgp.neighbors import Neighbors
-from ansible.module_utils.network.eos.providers.cli.config.bgp.address_family import AddressFamily
-
-REDISTRIBUTE_PROTOCOLS = frozenset(['ospf', 'ospf3', 'rip', 'isis', 'static', 'connected'])
-
-
-@register_provider('eos', 'eos_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:
- self._validate_input(config)
- if operation == 'replace':
- if existing_as and int(existing_as) != self.get_value('config.bgp_as'):
- commands.append('no router bgp %s' % existing_as)
- config = None
-
- elif operation == 'override':
- if existing_as:
- commands.append('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 = '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 cmd
- elif log_neighbor_changes is False:
- if config and cmd in config:
- return 'no %s' % cmd
-
- def _render_networks(self, config=None):
- commands = list()
- safe_list = list()
-
- for entry in self.get_value('config.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-map %s' % entry['route_map']
-
- if not config or cmd not in config:
- commands.append(cmd)
-
- if self.params['operation'] == 'replace':
- if config:
- 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, config=None):
- commands = list()
- safe_list = list()
-
- for entry in self.get_value('config.redistribute'):
- option = entry['protocol']
-
- cmd = 'redistribute %s' % entry['protocol']
-
- if entry['route_map']:
- cmd += ' route-map %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
-
- 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)
-
- def _validate_input(self, config):
- def device_has_AF(config):
- return re.search(r'address-family (?:.*)', config)
-
- address_family = self.get_value('config.address_family')
- root_networks = self.get_value('config.networks')
- operation = self.params['operation']
-
- if operation == 'replace' and root_networks:
- if address_family:
- for item in address_family:
- if item['networks']:
- raise ValueError('operation is replace but provided both root level networks and networks under %s address family'
- % item['afi'])
-
- if config and device_has_AF(config):
- raise ValueError('operation is replace and device has one or more address family activated but root level network(s) provided')
diff --git a/lib/ansible/module_utils/network/eos/providers/module.py b/lib/ansible/module_utils/network/eos/providers/module.py
deleted file mode 100644
index 2d8fd67ebc..0000000000
--- a/lib/ansible/module_utils/network/eos/providers/module.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#
-# (c) 2019, Ansible by Red Hat, inc
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-from ansible.module_utils.basic import AnsibleModule
-from ansible.module_utils.connection import Connection
-from ansible.module_utils.network.eos.providers import providers
-from ansible.module_utils._text import to_text
-
-
-class NetworkModule(AnsibleModule):
-
- fail_on_missing_provider = True
-
- def __init__(self, connection=None, *args, **kwargs):
- super(NetworkModule, self).__init__(*args, **kwargs)
-
- if connection is None:
- connection = Connection(self._socket_path)
-
- self.connection = connection
-
- @property
- def provider(self):
- if not hasattr(self, '_provider'):
- capabilities = self.from_json(self.connection.get_capabilities())
-
- network_os = capabilities['device_info']['network_os']
- network_api = capabilities['network_api']
-
- if network_api == 'cliconf':
- connection_type = 'network_cli'
-
- cls = providers.get(network_os, self._name.split('.')[-1], connection_type)
-
- if not cls:
- msg = 'unable to find suitable provider for network os %s' % network_os
- if self.fail_on_missing_provider:
- self.fail_json(msg=msg)
- else:
- self.warn(msg)
-
- obj = cls(self.params, self.connection, self.check_mode)
-
- setattr(self, '_provider', obj)
-
- return getattr(self, '_provider')
-
- def get_facts(self, subset=None):
- try:
- self.provider.get_facts(subset)
- except Exception as exc:
- self.fail_json(msg=to_text(exc))
-
- def edit_config(self, config_filter=None):
- current_config = self.connection.get_config(flags=config_filter)
- try:
- commands = self.provider.edit_config(current_config)
- changed = bool(commands)
- return {'commands': commands, 'changed': changed}
- except Exception as exc:
- self.fail_json(msg=to_text(exc))
diff --git a/lib/ansible/module_utils/network/eos/providers/providers.py b/lib/ansible/module_utils/network/eos/providers/providers.py
deleted file mode 100644
index be429dc0f8..0000000000
--- a/lib/ansible/module_utils/network/eos/providers/providers.py
+++ /dev/null
@@ -1,120 +0,0 @@
-#
-# (c) 2019, Ansible by Red Hat, inc
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-#
-import json
-
-from threading import RLock
-
-from ansible.module_utils.six import itervalues
-from ansible.module_utils.network.common.utils import to_list
-from ansible.module_utils.network.common.config import NetworkConfig
-
-
-_registered_providers = {}
-_provider_lock = RLock()
-
-
-def register_provider(network_os, module_name):
- def wrapper(cls):
- _provider_lock.acquire()
- try:
- if network_os not in _registered_providers:
- _registered_providers[network_os] = {}
- for ct in cls.supported_connections:
- if ct not in _registered_providers[network_os]:
- _registered_providers[network_os][ct] = {}
- for item in to_list(module_name):
- for entry in itervalues(_registered_providers[network_os]):
- entry[item] = cls
- finally:
- _provider_lock.release()
- return cls
- return wrapper
-
-
-def get(network_os, module_name, connection_type):
- network_os_providers = _registered_providers.get(network_os)
- if network_os_providers is None:
- raise ValueError('unable to find a suitable provider for this module')
- if connection_type not in network_os_providers:
- raise ValueError('provider does not support this connection type')
- elif module_name not in network_os_providers[connection_type]:
- raise ValueError('could not find a suitable provider for this module')
- return network_os_providers[connection_type][module_name]
-
-
-class ProviderBase(object):
-
- supported_connections = ()
-
- def __init__(self, params, connection=None, check_mode=False):
- self.params = params
- self.connection = connection
- self.check_mode = check_mode
-
- @property
- def capabilities(self):
- if not hasattr(self, '_capabilities'):
- resp = self.from_json(self.connection.get_capabilities())
- setattr(self, '_capabilities', resp)
- return getattr(self, '_capabilities')
-
- def get_value(self, path):
- params = self.params.copy()
- for key in path.split('.'):
- params = params[key]
- return params
-
- def get_facts(self, subset=None):
- raise NotImplementedError(self.__class__.__name__)
-
- def edit_config(self):
- raise NotImplementedError(self.__class__.__name__)
-
-
-class CliProvider(ProviderBase):
-
- supported_connections = ('network_cli',)
-
- @property
- def capabilities(self):
- if not hasattr(self, '_capabilities'):
- resp = self.from_json(self.connection.get_capabilities())
- setattr(self, '_capabilities', resp)
- return getattr(self, '_capabilities')
-
- def get_config_context(self, config, path, indent=2):
- 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/lib/ansible/module_utils/network/eos/utils/utils.py b/lib/ansible/module_utils/network/eos/utils/utils.py
deleted file mode 100644
index beb3a6fd2e..0000000000
--- a/lib/ansible/module_utils/network/eos/utils/utils.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# -*- 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
-
-
-def get_interface_number(name):
- digits = ''
- for char in name:
- if char.isdigit() or char in '/.':
- digits += char
- return digits
-
-
-def normalize_interface(name):
- """Return the normalized interface name
- """
- if not name:
- return None
-
- if name.lower().startswith('et'):
- if_type = 'Ethernet'
- elif name.lower().startswith('lo'):
- if_type = 'Loopback'
- elif name.lower().startswith('ma'):
- if_type = 'Management'
- elif name.lower().startswith('po'):
- if_type = 'Port-Channel'
- elif name.lower().startswith('tu'):
- if_type = 'Tunnel'
- elif name.lower().startswith('vl'):
- if_type = 'Vlan'
- elif name.lower().startswith('vx'):
- if_type = 'Vxlan'
- else:
- if_type = None
-
- number_list = name.split(' ')
- if len(number_list) == 2:
- number = number_list[-1].strip()
- else:
- number = get_interface_number(name)
-
- if if_type:
- proper_interface = if_type + number
- else:
- proper_interface = name
-
- return proper_interface